2 // BigInteger.cs - Big Integer implementation
7 // Sebastien Pouliot (spouliot@motus.com)
9 // Copyright (c) 2003 Ben Maurer
10 // All rights reserved
12 // Copyright (c) 2002 Chew Keong TAN
13 // All rights reserved.
16 using System.Security.Cryptography;
17 using Mono.Math.Prime.Generator;
18 using Mono.Math.Prime;
23 public class BigInteger {
28 /// The Length of this BigInteger
33 /// The data for this BigInteger
42 /// Default length of a BigInteger in bytes
44 const uint DEFAULT_LEN = 20;
47 /// Table of primes below 2000.
51 /// This table was generated using Mathematica 4.1 using the following function:
55 /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
60 public static readonly uint [] smallPrimes = {
61 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
62 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
63 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
64 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
65 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
66 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
67 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
68 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
69 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
70 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
71 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
73 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
74 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
75 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
76 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
77 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
78 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
79 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
80 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
81 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
82 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
83 1979, 1987, 1993, 1997, 1999,
85 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
86 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
87 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
88 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
89 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
90 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
91 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
92 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
93 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
94 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
96 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
97 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
98 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
99 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
100 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
101 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
102 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
103 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
104 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
107 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
108 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
109 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
110 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
111 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
112 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
113 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
114 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
115 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
118 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
119 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
120 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
121 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
122 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
123 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
124 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
125 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
126 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
129 public enum Sign : int {
135 #region Exception Messages
136 const string WouldReturnNegVal = "Operation would return a negative value";
145 data = new uint [DEFAULT_LEN];
148 public BigInteger (Sign sign, uint len)
150 this.data = new uint [len];
154 public BigInteger (BigInteger bi)
156 this.data = (uint [])bi.data.Clone ();
157 this.length = bi.length;
160 public BigInteger (BigInteger bi, uint len)
163 this.data = new uint [len];
165 for (uint i = 0; i < bi.length; i++)
166 this.data [i] = bi.data [i];
168 this.length = bi.length;
175 public BigInteger (byte [] inData)
177 length = (uint)inData.Length >> 2;
178 int leftOver = inData.Length & 0x3;
180 // length not multiples of 4
181 if (leftOver != 0) length++;
183 data = new uint [length];
185 for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++) {
187 (inData [i-3] << (3*8)) |
188 (inData [i-2] << (2*8)) |
189 (inData [i-1] << (1*8)) |
190 (inData [i-0] << (0*8))
195 case 1: data [length-1] = (uint)inData [0]; break;
196 case 2: data [length-1] = (uint)((inData [0] << 8) | inData [1]); break;
197 case 3: data [length-1] = (uint)((inData [0] << 16) | (inData [1] << 8) | inData [2]); break;
203 public BigInteger (uint [] inData)
205 length = (uint)inData.Length;
207 data = new uint [length];
209 for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
210 data [j] = inData [i];
215 public BigInteger (uint ui)
217 data = new uint [] {ui};
220 public BigInteger (ulong ul)
222 data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
228 public static implicit operator BigInteger (uint value)
230 return (new BigInteger (value));
233 public static implicit operator BigInteger (int value)
235 if (value < 0) throw new ArgumentOutOfRangeException ("value");
236 return (new BigInteger ((uint)value));
239 public static implicit operator BigInteger (ulong value)
241 return (new BigInteger (value));
248 public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
251 return new BigInteger (bi2);
253 return new BigInteger (bi1);
255 return Kernel.AddSameSign (bi1, bi2);
258 public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
261 return new BigInteger (bi1);
264 throw new ArithmeticException (WouldReturnNegVal);
266 switch (Kernel.Compare (bi1, bi2)) {
272 return Kernel.Subtract (bi1, bi2);
275 throw new ArithmeticException (WouldReturnNegVal);
277 throw new Exception ();
281 public static int operator % (BigInteger bi, int i)
284 return (int)Kernel.DwordMod (bi, (uint)i);
286 return -(int)Kernel.DwordMod (bi, (uint)-i);
289 public static uint operator % (BigInteger bi, uint ui)
291 return Kernel.DwordMod (bi, (uint)ui);
294 public static BigInteger operator % (BigInteger bi1, BigInteger bi2)
296 return Kernel.multiByteDivide (bi1, bi2)[1];
299 public static BigInteger operator / (BigInteger bi, int i)
302 return Kernel.DwordDiv (bi, (uint)i);
304 throw new ArithmeticException (WouldReturnNegVal);
307 public static BigInteger operator / (BigInteger bi1, BigInteger bi2)
309 return Kernel.multiByteDivide (bi1, bi2)[0];
312 public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
314 if (bi1 == 0 || bi2 == 0) return 0;
319 if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
320 if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");
322 BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);
324 Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
330 public static BigInteger operator * (BigInteger bi, int i)
332 if (i < 0) throw new ArithmeticException (WouldReturnNegVal);
333 if (i == 0) return 0;
334 if (i == 1) return new BigInteger (bi);
336 return Kernel.MultiplyByDword (bi, (uint)i);
339 public static BigInteger operator << (BigInteger bi1, int shiftVal)
341 return Kernel.LeftShift (bi1, shiftVal);
344 public static BigInteger operator >> (BigInteger bi1, int shiftVal)
346 return Kernel.RightShift (bi1, shiftVal);
352 private static RandomNumberGenerator rng;
353 private static RandomNumberGenerator Rng {
356 rng = RandomNumberGenerator.Create ();
362 /// Generates a new, random BigInteger of the specified length.
364 /// <param name="bits">The number of bits for the new number.</param>
365 /// <param name="rng">A random number generator to use to obtain the bits.</param>
366 /// <returns>A random number of the specified length.</returns>
367 public static BigInteger genRandom (int bits, RandomNumberGenerator rng)
369 int dwords = bits >> 5;
370 int remBits = bits & 0x1F;
375 BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
376 byte [] random = new byte [dwords << 2];
378 rng.GetBytes (random);
379 Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);
382 uint mask = (uint)(0x01 << (remBits-1));
383 ret.data [dwords-1] |= mask;
385 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
386 ret.data [dwords-1] &= mask;
389 ret.data [dwords-1] |= 0x80000000;
396 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
398 /// <param name="bits">The number of bits for the new number.</param>
399 /// <returns>A random number of the specified length.</returns>
400 public static BigInteger genRandom (int bits)
402 return genRandom (bits, Rng);
406 /// Randomizes the bits in "this" from the specified RNG.
408 /// <param name="rng">A RNG.</param>
409 public void randomize (RandomNumberGenerator rng)
411 int bits = this.bitCount ();
412 int dwords = bits >> 5;
413 int remBits = bits & 0x1F;
418 byte [] random = new byte [dwords << 2];
420 rng.GetBytes (random);
421 Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
424 uint mask = (uint)(0x01 << (remBits-1));
425 data [dwords-1] |= mask;
427 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
428 data [dwords-1] &= mask;
432 data [dwords-1] |= 0x80000000;
438 /// Randomizes the bits in "this" from the default RNG.
440 public void randomize ()
449 public int bitCount ()
453 uint value = data [length - 1];
454 uint mask = 0x80000000;
457 while (bits > 0 && (value & mask) == 0) {
461 bits += ((length - 1) << 5);
467 /// Tests if the specified bit is 1.
469 /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
470 /// <returns>True if bitNum is set to 1, else false.</returns>
471 public bool testBit (uint bitNum)
473 uint bytePos = bitNum >> 5; // divide by 32
474 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
476 uint mask = (uint)1 << bitPos;
477 return ((this.data [bytePos] & mask) != 0);
480 public bool testBit (int bitNum)
482 if (bitNum < 0) throw new IndexOutOfRangeException ("bitNum out of range");
484 uint bytePos = (uint)bitNum >> 5; // divide by 32
485 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
487 uint mask = (uint)1 << bitPos;
488 return ((this.data [bytePos] | mask) == this.data [bytePos]);
491 public void setBit (uint bitNum)
493 setBit (bitNum, true);
495 public void clearBit (uint bitNum)
497 setBit (bitNum, false);
500 public void setBit (uint bitNum, bool val)
502 uint bytePos = bitNum >> 5; // divide by 32
504 if (bytePos < this.length) {
505 uint mask = (uint)1 << (int)(bitNum & 0x1F);
507 this.data [bytePos] |= mask;
509 this.data [bytePos] &= ~mask;
513 public int LowestSetBit ()
515 if (this == 0) return -1;
517 while (!testBit (i)) i++;
521 public byte [] getBytes ()
523 if (this == 0) return new byte [1];
525 int numBits = bitCount ();
526 int numBytes = numBits >> 3;
527 if ((numBits & 0x7) != 0)
530 byte [] result = new byte [numBytes];
532 int numBytesInWord = numBytes & 0x3;
533 if (numBytesInWord == 0) numBytesInWord = 4;
536 for (int i = (int)length - 1; i >= 0; i--) {
538 for (int j = numBytesInWord - 1; j >= 0; j--) {
539 result [pos+j] = (byte)(val & 0xFF);
542 pos += numBytesInWord;
552 public static bool operator == (BigInteger bi1, uint ui)
554 if (bi1.length != 1) bi1.Normalize ();
555 return bi1.length == 1 && bi1.data [0] == ui;
558 public static bool operator != (BigInteger bi1, uint ui)
560 if (bi1.length != 1) bi1.Normalize ();
561 return !(bi1.length == 1 && bi1.data [0] == ui);
564 public static bool operator == (BigInteger bi1, BigInteger bi2)
566 // we need to compare with null
567 if ((bi1 as object) == (bi2 as object))
569 if (null == bi1 || null == bi2)
571 return Kernel.Compare (bi1, bi2) == 0;
574 public static bool operator != (BigInteger bi1, BigInteger bi2)
576 // we need to compare with null
577 if ((bi1 as object) == (bi2 as object))
579 if (null == bi1 || null == bi2)
581 return Kernel.Compare (bi1, bi2) != 0;
584 public static bool operator > (BigInteger bi1, BigInteger bi2)
586 return Kernel.Compare (bi1, bi2) > 0;
589 public static bool operator < (BigInteger bi1, BigInteger bi2)
591 return Kernel.Compare (bi1, bi2) < 0;
594 public static bool operator >= (BigInteger bi1, BigInteger bi2)
596 return Kernel.Compare (bi1, bi2) >= 0;
599 public static bool operator <= (BigInteger bi1, BigInteger bi2)
601 return Kernel.Compare (bi1, bi2) <= 0;
604 public Sign Compare (BigInteger bi)
606 return Kernel.Compare (this, bi);
613 public string ToString (uint radix)
615 return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
618 public string ToString (uint radix, string charSet)
620 if (charSet.Length < radix)
621 throw new ArgumentException ("charSet length less than radix", "charSet");
623 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
625 if (this == 0) return "0";
626 if (this == 1) return "1";
630 BigInteger a = new BigInteger (this);
633 uint rem = Kernel.SingleByteDivideInPlace (a, radix);
634 result = charSet [ (int)rem] + result;
645 /// Normalizes this by setting the length to the actual number of
646 /// uints used in data and by setting the sign to Sign.Zero if the
647 /// value of this is 0.
649 private void Normalize ()
652 while (length > 0 && data [length-1] == 0) length--;
661 for (int i=0; i < length; i++)
669 public override int GetHashCode ()
673 for (uint i = 0; i < this.length; i++)
674 val ^= this.data [i];
679 public override string ToString ()
681 return ToString (10);
684 public override bool Equals (object o)
686 if (o == null) return false;
687 if (o is int) return (int)o >= 0 && this == (uint)o;
689 return Kernel.Compare (this, (BigInteger)o) == 0;
694 #region Number Theory
696 public BigInteger gcd (BigInteger bi)
698 return Kernel.gcd (this, bi);
701 public BigInteger modInverse (BigInteger mod)
703 return Kernel.modInverse (this, mod);
706 public BigInteger modPow (BigInteger exp, BigInteger n)
708 ModulusRing mr = new ModulusRing (n);
709 return mr.Pow (this, exp);
714 #region Prime Testing
716 public bool isProbablePrime ()
719 for (int p = 0; p < smallPrimes.Length; p++) {
720 if (this % smallPrimes [p] == 0)
725 PrimalityTests.SmallPrimeSppTest (this, Prime.ConfidenceFactor.Medium);
729 public bool isProbablePrime (int notUsed)
732 for (int p = 0; p < smallPrimes.Length; p++) {
733 if (this % smallPrimes [p] == 0)
738 PrimalityTests.SmallPrimeSppTest (this, Prime.ConfidenceFactor.Medium);
743 #region Prime Number Generation
746 /// Generates the smallest prime >= bi
748 /// <param name="bi">A BigInteger</param>
749 /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
750 public static BigInteger NextHightestPrime (BigInteger bi)
752 NextPrimeFinder npf = new NextPrimeFinder ();
753 return npf.GenerateNewPrime (0, bi);
756 public static BigInteger genPseudoPrime (int bits)
758 SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase ();
759 return sspg.GenerateNewPrime (bits);
763 /// Increments this by two
771 // If there was no carry, nothing to do
774 // Account for the first carry
777 // Keep adding until no carry
778 while (data [i++] == 0x0)
781 // See if we increased the data length
782 if (length == (uint)i)
789 public sealed class ModulusRing {
791 BigInteger mod, constant;
793 public ModulusRing (BigInteger mod)
797 // calculate constant = b^ (2k) / m
798 uint i = mod.length << 1;
800 constant = new BigInteger (Sign.Positive, i + 1);
801 constant.data [i] = 0x00000001;
803 constant = constant / mod;
806 public void BarrettReduction (BigInteger x)
813 // x < mod, so nothing to do.
814 if (x.length < k) return;
821 if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");
824 // q2 = q1 * constant
825 // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
827 // TODO: We should the method in HAC p 604 to do this (14.45)
828 q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
829 Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
831 // r1 = x mod b^ (k+1)
832 // i.e. keep the lowest (k+1) words
834 uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
836 x.length = lengthToCopy;
839 // r2 = (q3 * n) mod b^ (k+1)
840 // partial multiplication of q3 and n
842 BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
843 Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
848 Kernel.MinusEq (x, r2);
850 BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
851 val.data [kPlusOne] = 0x00000001;
853 Kernel.MinusEq (val, r2);
854 Kernel.PlusEq (x, val);
858 Kernel.MinusEq (x, n);
861 public BigInteger Multiply (BigInteger a, BigInteger b)
863 if (a == 0 || b == 0) return 0;
865 if (a.length >= mod.length << 1)
868 if (b.length >= mod.length << 1)
871 if (a.length >= mod.length)
872 BarrettReduction (a);
874 if (b.length >= mod.length)
875 BarrettReduction (b);
877 BigInteger ret = new BigInteger (a * b);
878 BarrettReduction (ret);
883 public BigInteger Difference (BigInteger a, BigInteger b)
885 Sign cmp = Kernel.Compare (a, b);
896 throw new Exception ();
900 if (diff.length >= mod.length << 1)
903 BarrettReduction (diff);
905 if (cmp == Sign.Negative)
910 public BigInteger Pow (BigInteger b, BigInteger exp)
912 if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
913 else return EvenPow (b, exp);
916 public BigInteger EvenPow (BigInteger b, BigInteger exp)
918 BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
919 BigInteger tempNum = new BigInteger (b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
921 uint totalBits = (uint)exp.bitCount ();
923 uint [] wkspace = new uint [mod.length << 1];
925 // perform squaring and multiply exponentiation
926 for (uint pos = 0; pos < totalBits; pos++) {
927 if (exp.testBit (pos)) {
929 Array.Clear (wkspace, 0, wkspace.Length);
930 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
931 resultNum.length += tempNum.length;
933 wkspace = resultNum.data;
936 BarrettReduction (resultNum);
939 Kernel.SquarePositive (tempNum, ref wkspace);
940 BarrettReduction (tempNum);
950 private BigInteger OddPow (BigInteger b, BigInteger exp)
952 BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
953 BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
954 uint mPrime = Montgomery.Inverse (mod.data [0]);
955 uint totalBits = (uint)exp.bitCount ();
957 uint [] wkspace = new uint [mod.length << 1];
959 // perform squaring and multiply exponentiation
960 for (uint pos = 0; pos < totalBits; pos++) {
961 if (exp.testBit (pos)) {
963 Array.Clear (wkspace, 0, wkspace.Length);
964 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
965 resultNum.length += tempNum.length;
967 wkspace = resultNum.data;
970 Montgomery.Reduce (resultNum, mod, mPrime);
973 Kernel.SquarePositive (tempNum, ref wkspace);
974 Montgomery.Reduce (tempNum, mod, mPrime);
977 Montgomery.Reduce (resultNum, mod, mPrime);
981 #region Pow Small Base
983 // TODO: Make tests for this, not really needed b/c prime stuff
984 // checks it, but still would be nice
985 public BigInteger Pow (uint b, BigInteger exp)
988 if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
989 else return EvenPow (b, exp);
991 if ((mod.data [0] & 1) == 1) return OddModTwoPow (exp);
992 else return EvenModTwoPow (exp);
996 private unsafe BigInteger OddPow (uint b, BigInteger exp)
999 uint [] wkspace = new uint [mod.length << 1 + 1];
1001 BigInteger resultNum = Montgomery.ToMont ((BigInteger)b, this.mod);
1002 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1004 uint mPrime = Montgomery.Inverse (mod.data [0]);
1006 uint pos = (uint)exp.bitCount () - 2;
1009 // We know that the first itr will make the val b
1016 Kernel.SquarePositive (resultNum, ref wkspace);
1017 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1019 if (exp.testBit (pos)) {
1025 // TODO: Is Unsafe really speeding things up?
1026 fixed (uint* u = resultNum.data) {
1032 mc += (ulong)u [i] * (ulong)b;
1035 } while (++i < resultNum.length);
1037 if (resultNum.length < mod.length) {
1041 while (resultNum >= mod)
1042 Kernel.MinusEq (resultNum, mod);
1044 } else if (mc != 0) {
1047 // First, we estimate the quotient by dividing
1048 // the first part of each of the numbers. Then
1049 // we correct this, if necessary, with a subtraction.
1054 // We would rather have this estimate overshoot,
1055 // so we add one to the divisor
1056 uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1057 (mod.data [mod.length-1] + 1));
1064 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1068 if (u [i] > t) mc++;
1070 } while (i < resultNum.length);
1076 uint [] s = mod.data;
1079 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1082 } while (j < resultNum.length);
1085 while (resultNum >= mod)
1086 Kernel.MinusEq (resultNum, mod);
1088 while (resultNum >= mod)
1089 Kernel.MinusEq (resultNum, mod);
1093 } while (pos-- > 0);
1095 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1100 private unsafe BigInteger EvenPow (uint b, BigInteger exp)
1103 uint [] wkspace = new uint [mod.length << 1 + 1];
1104 BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);
1106 uint pos = (uint)exp.bitCount () - 2;
1109 // We know that the first itr will make the val b
1116 Kernel.SquarePositive (resultNum, ref wkspace);
1117 if (!(resultNum.length < mod.length))
1118 BarrettReduction (resultNum);
1120 if (exp.testBit (pos)) {
1126 // TODO: Is Unsafe really speeding things up?
1127 fixed (uint* u = resultNum.data) {
1133 mc += (ulong)u [i] * (ulong)b;
1136 } while (++i < resultNum.length);
1138 if (resultNum.length < mod.length) {
1142 while (resultNum >= mod)
1143 Kernel.MinusEq (resultNum, mod);
1145 } else if (mc != 0) {
1148 // First, we estimate the quotient by dividing
1149 // the first part of each of the numbers. Then
1150 // we correct this, if necessary, with a subtraction.
1155 // We would rather have this estimate overshoot,
1156 // so we add one to the divisor
1157 uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1158 (mod.data [mod.length-1] + 1));
1165 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1169 if (u [i] > t) mc++;
1171 } while (i < resultNum.length);
1177 uint [] s = mod.data;
1180 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1183 } while (j < resultNum.length);
1186 while (resultNum >= mod)
1187 Kernel.MinusEq (resultNum, mod);
1189 while (resultNum >= mod)
1190 Kernel.MinusEq (resultNum, mod);
1194 } while (pos-- > 0);
1199 private unsafe BigInteger EvenModTwoPow (BigInteger exp)
1202 uint [] wkspace = new uint [mod.length << 1 + 1];
1204 BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
1206 uint value = exp.data [exp.length - 1];
1207 uint mask = 0x80000000;
1209 // Find the first bit of the exponent
1210 while ((value & mask) == 0)
1214 // We know that the first itr will make the val 2,
1215 // so eat one bit of the exponent
1219 uint wPos = exp.length - 1;
1222 value = exp.data [wPos];
1224 Kernel.SquarePositive (resultNum, ref wkspace);
1225 if (resultNum.length >= mod.length)
1226 BarrettReduction (resultNum);
1228 if ((value & mask) != 0) {
1230 // resultNum = (resultNum * 2) % mod
1233 fixed (uint* u = resultNum.data) {
1238 uint* uuE = u + resultNum.length;
1242 *uu = (x << 1) | carry;
1243 carry = x >> (32 - 1);
1247 // subtraction inlined because we know it is square
1248 if (carry != 0 || resultNum >= mod) {
1251 uint [] s = mod.data;
1255 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1264 } while ((mask >>= 1) > 0);
1266 } while (wPos-- > 0);
1271 private unsafe BigInteger OddModTwoPow (BigInteger exp)
1274 uint [] wkspace = new uint [mod.length << 1 + 1];
1276 BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
1277 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1279 uint mPrime = Montgomery.Inverse (mod.data [0]);
1282 // TODO: eat small bits, the ones we can do with no modular reduction
1284 uint pos = (uint)exp.bitCount () - 2;
1287 Kernel.SquarePositive (resultNum, ref wkspace);
1288 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1290 if (exp.testBit (pos)) {
1292 // resultNum = (resultNum * 2) % mod
1295 fixed (uint* u = resultNum.data) {
1300 uint* uuE = u + resultNum.length;
1304 *uu = (x << 1) | carry;
1305 carry = x >> (32 - 1);
1309 // subtraction inlined because we know it is square
1310 if (carry != 0 || resultNum >= mod) {
1311 fixed (uint* s = mod.data) {
1317 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1326 } while (pos-- > 0);
1328 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1335 public sealed class Montgomery {
1336 public static uint Inverse (uint n)
1340 while ((z = n * y) != 1)
1346 public static BigInteger ToMont (BigInteger n, BigInteger m)
1348 n.Normalize (); m.Normalize ();
1350 n <<= (int)m.length * 32;
1355 public static unsafe BigInteger Reduce (BigInteger n, BigInteger m, uint mPrime)
1358 fixed (uint* a = A.data, mm = m.data) {
1359 for (uint i = 0; i < m.length; i++) {
1360 // The mod here is taken care of by the CPU,
1361 // since the multiply will overflow.
1362 uint u_i = a [0] * mPrime /* % 2^32 */;
1369 // mP = Position in mod
1370 // aSP = the source of bits from a
1371 // aDP = destination for bits
1372 uint* mP = mm, aSP = a, aDP = a;
1374 ulong c = (ulong)u_i * (ulong)*(mP++) + *(aSP++);
1379 for (; j < m.length; j++) {
1380 c += (ulong)u_i * (ulong)*(mP++) + *(aSP++);
1385 // Account for carry
1386 // TODO: use a better loop here, we dont need the ulong stuff
1387 for (; j < A.length; j++) {
1391 if (c == 0) {j++; break;}
1394 for (; j < A.length; j++) {
1395 *(aDP++) = *(aSP++);
1401 while (A.length > 1 && a [A.length-1] == 0) A.length--;
1404 if (A >= m) Kernel.MinusEq (A, m);
1409 public static BigInteger Reduce (BigInteger n, BigInteger m)
1411 return Reduce (n, m, Inverse (m.data [0]));
1416 /// Low level functions for the BigInteger
1418 private sealed class Kernel {
1420 #region Addition/Subtraction
1423 /// Adds two numbers with the same sign.
1425 /// <param name="bi1">A BigInteger</param>
1426 /// <param name="bi2">A BigInteger</param>
1427 /// <returns>bi1 + bi2</returns>
1428 public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
1431 uint yMax, xMax, i = 0;
1433 // x should be bigger
1434 if (bi1.length < bi2.length) {
1446 BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
1448 uint [] r = result.data;
1452 // Add common parts of both numbers
1454 sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
1457 } while (++i < yMax);
1459 // Copy remainder of longer number while carry propagation is required
1460 bool carry = (sum != 0);
1466 carry = ((r [i] = x [i] + 1) == 0);
1467 while (++i < xMax && carry);
1472 result.length = ++i;
1484 result.Normalize ();
1488 public static BigInteger Subtract (BigInteger big, BigInteger small)
1490 BigInteger result = new BigInteger (Sign.Positive, big.length);
1492 uint [] r = result.data, b = big.data, s = small.data;
1498 if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
1503 } while (++i < small.length);
1505 if (i == big.length) goto fixup;
1510 while (b [i++] == 0 && i < big.length);
1512 if (i == big.length) goto fixup;
1517 while (++i < big.length);
1521 result.Normalize ();
1525 public static void MinusEq (BigInteger big, BigInteger small)
1527 uint [] b = big.data, s = small.data;
1532 if (((x += c) < c) | ((b [i] -= x) > ~x))
1536 } while (++i < small.length);
1538 if (i == big.length) goto fixup;
1543 while (b [i++] == 0 && i < big.length);
1549 while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
1552 if (big.length == 0)
1557 public static void PlusEq (BigInteger bi1, BigInteger bi2)
1560 uint yMax, xMax, i = 0;
1563 // x should be bigger
1564 if (bi1.length < bi2.length){
1577 uint [] r = bi1.data;
1581 // Add common parts of both numbers
1583 sum += ((ulong)x [i]) + ((ulong)y [i]);
1586 } while (++i < yMax);
1588 // Copy remainder of longer number while carry propagation is required
1589 bool carry = (sum != 0);
1595 carry = ((r [i] = x [i] + 1) == 0);
1596 while (++i < xMax && carry);
1607 if (flag && i < xMax - 1) {
1613 bi1.length = xMax + 1;
1622 /// Compares two BigInteger
1624 /// <param name="bi1">A BigInteger</param>
1625 /// <param name="bi2">A BigInteger</param>
1626 /// <returns>The sign of bi1 - bi2</returns>
1627 public static Sign Compare (BigInteger bi1, BigInteger bi2)
1630 // Step 1. Compare the lengths
1632 uint l1 = bi1.length, l2 = bi2.length;
1634 while (l1 > 0 && bi1.data [l1-1] == 0) l1--;
1635 while (l2 > 0 && bi2.data [l2-1] == 0) l2--;
1637 if (l1 == 0 && l2 == 0) return Sign.Zero;
1639 // bi1 len < bi2 len
1640 if (l1 < l2) return Sign.Negative;
1641 // bi1 len > bi2 len
1642 else if (l1 > l2) return Sign.Positive;
1645 // Step 2. Compare the bits
1650 while (pos != 0 && bi1.data [pos] == bi2.data [pos]) pos--;
1652 if (bi1.data [pos] < bi2.data [pos])
1653 return Sign.Negative;
1654 else if (bi1.data [pos] > bi2.data [pos])
1655 return Sign.Positive;
1667 /// Performs n / d and n % d in one operation.
1669 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1670 /// <param name="d">The divisor</param>
1671 /// <returns>n % d</returns>
1672 public static uint SingleByteDivideInPlace (BigInteger n, uint d)
1680 n.data [i] = (uint)(r / d);
1688 public static uint DwordMod (BigInteger n, uint d)
1702 public static BigInteger DwordDiv (BigInteger n, uint d)
1704 BigInteger ret = new BigInteger (Sign.Positive, n.length);
1712 ret.data [i] = (uint)(r / d);
1720 public static BigInteger [] DwordDivMod (BigInteger n, uint d)
1722 BigInteger ret = new BigInteger (Sign.Positive , n.length);
1730 ret.data [i] = (uint)(r / d);
1735 BigInteger rem = (uint)r;
1737 return new BigInteger [] {ret, rem};
1744 public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
1746 if (Kernel.Compare (bi1, bi2) == Sign.Negative)
1747 return new BigInteger [2] { 0, new BigInteger (bi1) };
1749 bi1.Normalize (); bi2.Normalize ();
1751 if (bi2.length == 1)
1752 return DwordDivMod (bi1, bi2.data [0]);
1754 uint remainderLen = bi1.length + 1;
1755 int divisorLen = (int)bi2.length + 1;
1757 uint mask = 0x80000000;
1758 uint val = bi2.data [bi2.length - 1];
1760 int resultPos = (int)bi1.length - (int)bi2.length;
1762 while (mask != 0 && (val & mask) == 0) {
1763 shift++; mask >>= 1;
1766 BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
1767 BigInteger rem = (bi1 << shift);
1769 uint [] remainder = rem.data;
1773 int j = (int)(remainderLen - bi2.length);
1774 int pos = (int)remainderLen - 1;
1776 uint firstDivisorByte = bi2.data [bi2.length-1];
1777 ulong secondDivisorByte = bi2.data [bi2.length-2];
1780 ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
1782 ulong q_hat = dividend / (ulong)firstDivisorByte;
1783 ulong r_hat = dividend % (ulong)firstDivisorByte;
1787 if (q_hat == 0x100000000 ||
1788 (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
1790 r_hat += (ulong)firstDivisorByte;
1792 if (r_hat < 0x100000000)
1799 // At this point, q_hat is either exact, or one too large
1800 // (more likely to be exact) so, we attempt to multiply the
1801 // divisor by q_hat, if we get a borrow, we just subtract
1802 // one from q_hat and add the divisor back.
1807 int nPos = pos - divisorLen + 1;
1809 uint uint_q_hat = (uint)q_hat;
1811 mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
1812 t = remainder [nPos];
1813 remainder [nPos] -= (uint)mc;
1815 if (remainder [nPos] > t) mc++;
1817 } while (dPos < divisorLen);
1819 nPos = pos - divisorLen + 1;
1828 sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
1829 remainder [nPos] = (uint)sum;
1832 } while (dPos < divisorLen);
1836 quot.data [resultPos--] = (uint)uint_q_hat;
1844 BigInteger [] ret = new BigInteger [2] { quot, rem };
1857 public static BigInteger LeftShift (BigInteger bi, int n)
1859 if (n == 0) return new BigInteger (bi, bi.length + 1);
1862 n &= ((1 << 5) - 1);
1864 BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
1866 uint i = 0, l = bi.length;
1871 ret.data [i + w] = (x << n) | carry;
1872 carry = x >> (32 - n);
1875 ret.data [i + w] = carry;
1878 ret.data [i + w] = bi.data [i];
1887 public static BigInteger RightShift (BigInteger bi, int n)
1889 if (n == 0) return new BigInteger (bi);
1892 int s = n & ((1 << 5) - 1);
1894 BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
1895 uint l = (uint)ret.data.Length - 1;
1902 x = bi.data [l + w];
1903 ret.data [l] = (x >> n) | carry;
1904 carry = x << (32 - n);
1908 ret.data [l] = bi.data [l + w];
1919 public static BigInteger MultiplyByDword (BigInteger n, uint f)
1921 BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
1927 c += (ulong)n.data [i] * (ulong)f;
1928 ret.data [i] = (uint)c;
1930 } while (++i < n.length);
1931 ret.data [i] = (uint)c;
1938 /// Multiplies the data in x [xOffset:xOffset+xLen] by
1939 /// y [yOffset:yOffset+yLen] and puts it into
1940 /// d [dOffset:dOffset+xLen+yLen].
1943 /// This code is unsafe! It is the caller's responsibility to make
1944 /// sure that it is safe to access x [xOffset:xOffset+xLen],
1945 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
1947 public static unsafe void Multiply (uint [] x, uint xOffset, uint xLen, uint [] y, uint yOffset, uint yLen, uint [] d, uint dOffset)
1949 fixed (uint* xx = x, yy = y, dd = d) {
1950 uint* xP = xx + xOffset,
1956 for (; xP < xE; xP++, dB++) {
1958 if (*xP == 0) continue;
1963 for (uint* yP = yB; yP < yE; yP++, dP++) {
1964 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
1977 /// Multiplies the data in x [xOffset:xOffset+xLen] by
1978 /// y [yOffset:yOffset+yLen] and puts the low mod words into
1979 /// d [dOffset:dOffset+mod].
1982 /// This code is unsafe! It is the caller's responsibility to make
1983 /// sure that it is safe to access x [xOffset:xOffset+xLen],
1984 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
1986 public static unsafe void MultiplyMod2p32pmod (uint [] x, int xOffset, int xLen, uint [] y, int yOffest, int yLen, uint [] d, int dOffset, int mod)
1988 fixed (uint* xx = x, yy = y, dd = d) {
1989 uint* xP = xx + xOffset,
1996 for (; xP < xE; xP++, dB++) {
1998 if (*xP == 0) continue;
2002 for (uint* yP = yB; yP < yE && dP < dE; yP++, dP++) {
2003 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2009 if (mcarry != 0 && dP < dE)
2015 public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
2017 uint [] t = wkSpace;
2019 uint [] d = bi.data;
2020 uint dl = bi.length;
2023 fixed (uint* dd = d, tt = t) {
2025 uint* ttE = tt + t.Length;
2027 for (uint* ttt = tt; ttt < ttE; ttt++)
2030 uint* dP = dd, tP = tt;
2032 for (uint i = 0; i < dl; i++, dP++) {
2039 uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
2041 for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
2043 mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
2045 *tP2 = (uint)mcarry;
2050 *tP2 = (uint)mcarry;
2053 // Double t. Inlined for speed.
2060 *tP = (x << 1) | carry;
2061 carry = x >> (32 - 1);
2064 if (carry != 0) *tP = carry;
2066 // Add in the diagnals
2070 for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
2071 ulong val = (ulong)*dP * (ulong)*dP + *tP;
2074 *(++tP) += (uint)val;
2075 if (*tP < (uint)val) {
2077 // Account for the first carry
2080 // Keep adding until no carry
2081 while ((*tP3++) == 0x0)
2090 while (tt [bi.length-1] == 0 && bi.length > 1) bi.length--;
2095 public static bool Double (uint [] u, int l)
2101 u [i] = (x << 1) | carry;
2102 carry = x >> (32 - 1);
2105 if (carry != 0) u [l] = carry;
2111 #region Number Theory
2113 public static BigInteger gcd (BigInteger a, BigInteger b)
2120 while (x.length > 1) {
2126 if (x == 0) return g;
2128 // TODO: should we have something here if we can convert to long?
2131 // Now we can just do it with single precision. I am using the binary gcd method,
2132 // as it should be faster.
2135 uint yy = x.data [0];
2140 while (((xx | yy) & 1) == 0) {
2141 xx >>= 1; yy >>= 1; t++;
2144 while ((xx & 1) == 0) xx >>= 1;
2145 while ((yy & 1) == 0) yy >>= 1;
2147 xx = (xx - yy) >> 1;
2149 yy = (yy - xx) >> 1;
2155 public static uint modInverse (BigInteger bi, uint modulus)
2157 uint a = modulus, b = bi % modulus;
2158 uint p0 = 0, p1 = 1;
2178 public static BigInteger modInverse (BigInteger bi, BigInteger modulus)
2180 if (modulus.length == 1) return modInverse (bi, modulus.data [0]);
2182 BigInteger [] p = { 0, 1 };
2183 BigInteger [] q = new BigInteger [2]; // quotients
2184 BigInteger [] r = { 0, 0 }; // remainders
2188 BigInteger a = modulus;
2191 ModulusRing mr = new ModulusRing (modulus);
2197 BigInteger pval = mr.Difference (p [0], p [1] * q [0]);
2198 p [0] = p [1]; p [1] = pval;
2201 BigInteger [] divret = multiByteDivide (a, b);
2203 q [0] = q [1]; q [1] = divret [0];
2204 r [0] = r [1]; r [1] = divret [1];
2212 throw (new ArithmeticException ("No inverse!"));
2214 return mr.Difference (p [0], p [1] * q [0]);