2 // BigInteger.cs - Big Integer implementation
7 // Sebastien Pouliot <sebastien@ximian.com>
8 // Pieter Philippaerts <Pieter@mentalis.org>
10 // Copyright (c) 2003 Ben Maurer
11 // All rights reserved
13 // Copyright (c) 2002 Chew Keong TAN
14 // All rights reserved.
17 using System.Security.Cryptography;
18 using Mono.Math.Prime.Generator;
19 using Mono.Math.Prime;
33 /// The Length of this BigInteger
38 /// The data for this BigInteger
47 /// Default length of a BigInteger in bytes
49 const uint DEFAULT_LEN = 20;
52 /// Table of primes below 2000.
56 /// This table was generated using Mathematica 4.1 using the following function:
60 /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
65 internal static readonly uint [] smallPrimes = {
66 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
67 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
68 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
69 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
70 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
71 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
72 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
73 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
74 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
75 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
76 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
78 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
79 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
80 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
81 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
82 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
83 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
84 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
85 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
86 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
87 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
88 1979, 1987, 1993, 1997, 1999,
90 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
91 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
92 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
93 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
94 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
95 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
96 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
97 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
98 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
99 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
101 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
102 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
103 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
104 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
105 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
106 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
107 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
108 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
109 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
112 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
113 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
114 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
115 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
116 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
117 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
118 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
119 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
120 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
123 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
124 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
125 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
126 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
127 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
128 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
129 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
130 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
131 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
134 public enum Sign : int {
140 #region Exception Messages
141 const string WouldReturnNegVal = "Operation would return a negative value";
150 data = new uint [DEFAULT_LEN];
153 [CLSCompliant (false)]
154 public BigInteger (Sign sign, uint len)
156 this.data = new uint [len];
160 public BigInteger (BigInteger bi)
162 this.data = (uint [])bi.data.Clone ();
163 this.length = bi.length;
166 [CLSCompliant (false)]
167 public BigInteger (BigInteger bi, uint len)
170 this.data = new uint [len];
172 for (uint i = 0; i < bi.length; i++)
173 this.data [i] = bi.data [i];
175 this.length = bi.length;
182 public BigInteger (byte [] inData)
184 length = (uint)inData.Length >> 2;
185 int leftOver = inData.Length & 0x3;
187 // length not multiples of 4
188 if (leftOver != 0) length++;
190 data = new uint [length];
192 for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++) {
194 (inData [i-3] << (3*8)) |
195 (inData [i-2] << (2*8)) |
196 (inData [i-1] << (1*8)) |
202 case 1: data [length-1] = (uint)inData [0]; break;
203 case 2: data [length-1] = (uint)((inData [0] << 8) | inData [1]); break;
204 case 3: data [length-1] = (uint)((inData [0] << 16) | (inData [1] << 8) | inData [2]); break;
210 [CLSCompliant (false)]
211 public BigInteger (uint [] inData)
213 length = (uint)inData.Length;
215 data = new uint [length];
217 for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
218 data [j] = inData [i];
223 [CLSCompliant (false)]
224 public BigInteger (uint ui)
226 data = new uint [] {ui};
229 [CLSCompliant (false)]
230 public BigInteger (ulong ul)
232 data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
238 [CLSCompliant (false)]
239 public static implicit operator BigInteger (uint value)
241 return (new BigInteger (value));
244 public static implicit operator BigInteger (int value)
246 if (value < 0) throw new ArgumentOutOfRangeException ("value");
247 return (new BigInteger ((uint)value));
250 [CLSCompliant (false)]
251 public static implicit operator BigInteger (ulong value)
253 return (new BigInteger (value));
256 /* This is the BigInteger.Parse method I use. This method works
257 because BigInteger.ToString returns the input I gave to Parse. */
258 public static BigInteger Parse (string number)
261 throw new ArgumentNullException ("number");
263 int i = 0, len = number.Length;
265 bool digits_seen = false;
266 BigInteger val = new BigInteger (0);
267 if (number [i] == '+') {
270 else if (number [i] == '-') {
271 throw new FormatException (WouldReturnNegVal);
274 for (; i < len; i++) {
280 if (c >= '0' && c <= '9') {
281 val = val * 10 + (c - '0');
285 if (Char.IsWhiteSpace (c)) {
286 for (i++; i < len; i++) {
287 if (!Char.IsWhiteSpace (number [i]))
288 throw new FormatException ();
293 throw new FormatException ();
297 throw new FormatException ();
305 public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
308 return new BigInteger (bi2);
310 return new BigInteger (bi1);
312 return Kernel.AddSameSign (bi1, bi2);
315 public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
318 return new BigInteger (bi1);
321 throw new ArithmeticException (WouldReturnNegVal);
323 switch (Kernel.Compare (bi1, bi2)) {
329 return Kernel.Subtract (bi1, bi2);
332 throw new ArithmeticException (WouldReturnNegVal);
334 throw new Exception ();
338 public static int operator % (BigInteger bi, int i)
341 return (int)Kernel.DwordMod (bi, (uint)i);
343 return -(int)Kernel.DwordMod (bi, (uint)-i);
346 [CLSCompliant (false)]
347 public static uint operator % (BigInteger bi, uint ui)
349 return Kernel.DwordMod (bi, (uint)ui);
352 public static BigInteger operator % (BigInteger bi1, BigInteger bi2)
354 return Kernel.multiByteDivide (bi1, bi2)[1];
357 public static BigInteger operator / (BigInteger bi, int i)
360 return Kernel.DwordDiv (bi, (uint)i);
362 throw new ArithmeticException (WouldReturnNegVal);
365 public static BigInteger operator / (BigInteger bi1, BigInteger bi2)
367 return Kernel.multiByteDivide (bi1, bi2)[0];
370 public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
372 if (bi1 == 0 || bi2 == 0) return 0;
377 if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
378 if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");
380 BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);
382 Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
388 public static BigInteger operator * (BigInteger bi, int i)
390 if (i < 0) throw new ArithmeticException (WouldReturnNegVal);
391 if (i == 0) return 0;
392 if (i == 1) return new BigInteger (bi);
394 return Kernel.MultiplyByDword (bi, (uint)i);
397 public static BigInteger operator << (BigInteger bi1, int shiftVal)
399 return Kernel.LeftShift (bi1, shiftVal);
402 public static BigInteger operator >> (BigInteger bi1, int shiftVal)
404 return Kernel.RightShift (bi1, shiftVal);
409 #region Friendly names for operators
411 // with names suggested by FxCop 1.30
413 public static BigInteger Add (BigInteger bi1, BigInteger bi2)
418 public static BigInteger Subtract (BigInteger bi1, BigInteger bi2)
423 public static int Modulus (BigInteger bi, int i)
428 [CLSCompliant (false)]
429 public static uint Modulus (BigInteger bi, uint ui)
434 public static BigInteger Modulus (BigInteger bi1, BigInteger bi2)
439 public static BigInteger Divid (BigInteger bi, int i)
444 public static BigInteger Divid (BigInteger bi1, BigInteger bi2)
449 public static BigInteger Multiply (BigInteger bi1, BigInteger bi2)
454 public static BigInteger Multiply (BigInteger bi, int i)
462 private static RandomNumberGenerator rng;
463 private static RandomNumberGenerator Rng {
466 rng = RandomNumberGenerator.Create ();
472 /// Generates a new, random BigInteger of the specified length.
474 /// <param name="bits">The number of bits for the new number.</param>
475 /// <param name="rng">A random number generator to use to obtain the bits.</param>
476 /// <returns>A random number of the specified length.</returns>
477 public static BigInteger GenerateRandom (int bits, RandomNumberGenerator rng)
479 int dwords = bits >> 5;
480 int remBits = bits & 0x1F;
485 BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
486 byte [] random = new byte [dwords << 2];
488 rng.GetBytes (random);
489 Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);
492 uint mask = (uint)(0x01 << (remBits-1));
493 ret.data [dwords-1] |= mask;
495 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
496 ret.data [dwords-1] &= mask;
499 ret.data [dwords-1] |= 0x80000000;
506 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
508 /// <param name="bits">The number of bits for the new number.</param>
509 /// <returns>A random number of the specified length.</returns>
510 public static BigInteger GenerateRandom (int bits)
512 return GenerateRandom (bits, Rng);
516 /// Randomizes the bits in "this" from the specified RNG.
518 /// <param name="rng">A RNG.</param>
519 public void Randomize (RandomNumberGenerator rng)
521 int bits = this.BitCount ();
522 int dwords = bits >> 5;
523 int remBits = bits & 0x1F;
528 byte [] random = new byte [dwords << 2];
530 rng.GetBytes (random);
531 Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
534 uint mask = (uint)(0x01 << (remBits-1));
535 data [dwords-1] |= mask;
537 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
538 data [dwords-1] &= mask;
542 data [dwords-1] |= 0x80000000;
548 /// Randomizes the bits in "this" from the default RNG.
550 public void Randomize ()
559 public int BitCount ()
563 uint value = data [length - 1];
564 uint mask = 0x80000000;
567 while (bits > 0 && (value & mask) == 0) {
571 bits += ((length - 1) << 5);
577 /// Tests if the specified bit is 1.
579 /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
580 /// <returns>True if bitNum is set to 1, else false.</returns>
581 [CLSCompliant (false)]
582 public bool TestBit (uint bitNum)
584 uint bytePos = bitNum >> 5; // divide by 32
585 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
587 uint mask = (uint)1 << bitPos;
588 return ((this.data [bytePos] & mask) != 0);
591 public bool TestBit (int bitNum)
593 if (bitNum < 0) throw new IndexOutOfRangeException ("bitNum out of range");
595 uint bytePos = (uint)bitNum >> 5; // divide by 32
596 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
598 uint mask = (uint)1 << bitPos;
599 return ((this.data [bytePos] | mask) == this.data [bytePos]);
602 [CLSCompliant (false)]
603 public void SetBit (uint bitNum)
605 SetBit (bitNum, true);
608 [CLSCompliant (false)]
609 public void ClearBit (uint bitNum)
611 SetBit (bitNum, false);
614 [CLSCompliant (false)]
615 public void SetBit (uint bitNum, bool value)
617 uint bytePos = bitNum >> 5; // divide by 32
619 if (bytePos < this.length) {
620 uint mask = (uint)1 << (int)(bitNum & 0x1F);
622 this.data [bytePos] |= mask;
624 this.data [bytePos] &= ~mask;
628 public int LowestSetBit ()
630 if (this == 0) return -1;
632 while (!TestBit (i)) i++;
636 public byte[] GetBytes ()
638 if (this == 0) return new byte [1];
640 int numBits = BitCount ();
641 int numBytes = numBits >> 3;
642 if ((numBits & 0x7) != 0)
645 byte [] result = new byte [numBytes];
647 int numBytesInWord = numBytes & 0x3;
648 if (numBytesInWord == 0) numBytesInWord = 4;
651 for (int i = (int)length - 1; i >= 0; i--) {
653 for (int j = numBytesInWord - 1; j >= 0; j--) {
654 result [pos+j] = (byte)(val & 0xFF);
657 pos += numBytesInWord;
667 [CLSCompliant (false)]
668 public static bool operator == (BigInteger bi1, uint ui)
670 if (bi1.length != 1) bi1.Normalize ();
671 return bi1.length == 1 && bi1.data [0] == ui;
674 [CLSCompliant (false)]
675 public static bool operator != (BigInteger bi1, uint ui)
677 if (bi1.length != 1) bi1.Normalize ();
678 return !(bi1.length == 1 && bi1.data [0] == ui);
681 public static bool operator == (BigInteger bi1, BigInteger bi2)
683 // we need to compare with null
684 if ((bi1 as object) == (bi2 as object))
686 if (null == bi1 || null == bi2)
688 return Kernel.Compare (bi1, bi2) == 0;
691 public static bool operator != (BigInteger bi1, BigInteger bi2)
693 // we need to compare with null
694 if ((bi1 as object) == (bi2 as object))
696 if (null == bi1 || null == bi2)
698 return Kernel.Compare (bi1, bi2) != 0;
701 public static bool operator > (BigInteger bi1, BigInteger bi2)
703 return Kernel.Compare (bi1, bi2) > 0;
706 public static bool operator < (BigInteger bi1, BigInteger bi2)
708 return Kernel.Compare (bi1, bi2) < 0;
711 public static bool operator >= (BigInteger bi1, BigInteger bi2)
713 return Kernel.Compare (bi1, bi2) >= 0;
716 public static bool operator <= (BigInteger bi1, BigInteger bi2)
718 return Kernel.Compare (bi1, bi2) <= 0;
721 public Sign Compare (BigInteger bi)
723 return Kernel.Compare (this, bi);
730 [CLSCompliant (false)]
731 public string ToString (uint radix)
733 return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
736 [CLSCompliant (false)]
737 public string ToString (uint radix, string characterSet)
739 if (characterSet.Length < radix)
740 throw new ArgumentException ("charSet length less than radix", "characterSet");
742 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
744 if (this == 0) return "0";
745 if (this == 1) return "1";
749 BigInteger a = new BigInteger (this);
752 uint rem = Kernel.SingleByteDivideInPlace (a, radix);
753 result = characterSet [(int) rem] + result;
764 /// Normalizes this by setting the length to the actual number of
765 /// uints used in data and by setting the sign to Sign.Zero if the
766 /// value of this is 0.
768 private void Normalize ()
771 while (length > 0 && data [length-1] == 0) length--;
780 for (int i=0; i < length; i++)
788 public override int GetHashCode ()
792 for (uint i = 0; i < this.length; i++)
793 val ^= this.data [i];
798 public override string ToString ()
800 return ToString (10);
803 public override bool Equals (object o)
805 if (o == null) return false;
806 if (o is int) return (int)o >= 0 && this == (uint)o;
808 return Kernel.Compare (this, (BigInteger)o) == 0;
813 #region Number Theory
815 public BigInteger GCD (BigInteger bi)
817 return Kernel.gcd (this, bi);
820 public BigInteger ModInverse (BigInteger modulus)
822 return Kernel.modInverse (this, modulus);
825 public BigInteger ModPow (BigInteger exp, BigInteger n)
827 ModulusRing mr = new ModulusRing (n);
828 return mr.Pow (this, exp);
833 #region Prime Testing
835 public bool IsProbablePrime ()
837 for (int p = 0; p < smallPrimes.Length; p++) {
838 if (this == smallPrimes [p])
840 if (this % smallPrimes [p] == 0)
843 return PrimalityTests.RabinMillerTest (this, Prime.ConfidenceFactor.Medium);
848 #region Prime Number Generation
851 /// Generates the smallest prime >= bi
853 /// <param name="bi">A BigInteger</param>
854 /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
855 public static BigInteger NextHighestPrime (BigInteger bi)
857 NextPrimeFinder npf = new NextPrimeFinder ();
858 return npf.GenerateNewPrime (0, bi);
861 public static BigInteger GeneratePseudoPrime (int bits)
863 SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase ();
864 return sspg.GenerateNewPrime (bits);
868 /// Increments this by two
876 // If there was no carry, nothing to do
879 // Account for the first carry
882 // Keep adding until no carry
883 while (data [i++] == 0x0)
886 // See if we increased the data length
887 if (length == (uint)i)
899 sealed class ModulusRing {
901 BigInteger mod, constant;
903 public ModulusRing (BigInteger modulus)
907 // calculate constant = b^ (2k) / m
908 uint i = mod.length << 1;
910 constant = new BigInteger (Sign.Positive, i + 1);
911 constant.data [i] = 0x00000001;
913 constant = constant / mod;
916 public void BarrettReduction (BigInteger x)
923 // x < mod, so nothing to do.
924 if (x.length < k) return;
931 if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");
934 // q2 = q1 * constant
935 // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
937 // TODO: We should the method in HAC p 604 to do this (14.45)
938 q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
939 Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
941 // r1 = x mod b^ (k+1)
942 // i.e. keep the lowest (k+1) words
944 uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
946 x.length = lengthToCopy;
949 // r2 = (q3 * n) mod b^ (k+1)
950 // partial multiplication of q3 and n
952 BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
953 Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
958 Kernel.MinusEq (x, r2);
960 BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
961 val.data [kPlusOne] = 0x00000001;
963 Kernel.MinusEq (val, r2);
964 Kernel.PlusEq (x, val);
968 Kernel.MinusEq (x, n);
971 public BigInteger Multiply (BigInteger a, BigInteger b)
973 if (a == 0 || b == 0) return 0;
975 if (a.length >= mod.length << 1)
978 if (b.length >= mod.length << 1)
981 if (a.length >= mod.length)
982 BarrettReduction (a);
984 if (b.length >= mod.length)
985 BarrettReduction (b);
987 BigInteger ret = new BigInteger (a * b);
988 BarrettReduction (ret);
993 public BigInteger Difference (BigInteger a, BigInteger b)
995 Sign cmp = Kernel.Compare (a, b);
1002 diff = a - b; break;
1004 diff = b - a; break;
1006 throw new Exception ();
1010 if (diff.length >= mod.length << 1)
1013 BarrettReduction (diff);
1015 if (cmp == Sign.Negative)
1020 public BigInteger Pow (BigInteger b, BigInteger exp)
1022 if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
1023 else return EvenPow (b, exp);
1026 public BigInteger EvenPow (BigInteger b, BigInteger exp)
1028 BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
1029 BigInteger tempNum = new BigInteger (b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
1031 uint totalBits = (uint)exp.BitCount ();
1033 uint [] wkspace = new uint [mod.length << 1];
1035 // perform squaring and multiply exponentiation
1036 for (uint pos = 0; pos < totalBits; pos++) {
1037 if (exp.TestBit (pos)) {
1039 Array.Clear (wkspace, 0, wkspace.Length);
1040 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
1041 resultNum.length += tempNum.length;
1042 uint [] t = wkspace;
1043 wkspace = resultNum.data;
1046 BarrettReduction (resultNum);
1049 Kernel.SquarePositive (tempNum, ref wkspace);
1050 BarrettReduction (tempNum);
1060 private BigInteger OddPow (BigInteger b, BigInteger exp)
1062 BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
1063 BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
1064 uint mPrime = Montgomery.Inverse (mod.data [0]);
1065 uint totalBits = (uint)exp.BitCount ();
1067 uint [] wkspace = new uint [mod.length << 1];
1069 // perform squaring and multiply exponentiation
1070 for (uint pos = 0; pos < totalBits; pos++) {
1071 if (exp.TestBit (pos)) {
1073 Array.Clear (wkspace, 0, wkspace.Length);
1074 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
1075 resultNum.length += tempNum.length;
1076 uint [] t = wkspace;
1077 wkspace = resultNum.data;
1080 Montgomery.Reduce (resultNum, mod, mPrime);
1083 Kernel.SquarePositive (tempNum, ref wkspace);
1084 Montgomery.Reduce (tempNum, mod, mPrime);
1087 Montgomery.Reduce (resultNum, mod, mPrime);
1091 #region Pow Small Base
1093 // TODO: Make tests for this, not really needed b/c prime stuff
1094 // checks it, but still would be nice
1095 [CLSCompliant (false)]
1096 public BigInteger Pow (uint b, BigInteger exp)
1099 if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
1100 else return EvenPow (b, exp);
1102 if ((mod.data [0] & 1) == 1) return OddModTwoPow (exp);
1103 else return EvenModTwoPow (exp);
1107 [CLSCompliant (false)]
1108 private unsafe BigInteger OddPow (uint b, BigInteger exp)
1111 uint [] wkspace = new uint [mod.length << 1 + 1];
1113 BigInteger resultNum = Montgomery.ToMont ((BigInteger)b, this.mod);
1114 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1116 uint mPrime = Montgomery.Inverse (mod.data [0]);
1118 uint pos = (uint)exp.BitCount () - 2;
1121 // We know that the first itr will make the val b
1128 Kernel.SquarePositive (resultNum, ref wkspace);
1129 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1131 if (exp.TestBit (pos)) {
1137 // TODO: Is Unsafe really speeding things up?
1138 fixed (uint* u = resultNum.data) {
1144 mc += (ulong)u [i] * (ulong)b;
1147 } while (++i < resultNum.length);
1149 if (resultNum.length < mod.length) {
1153 while (resultNum >= mod)
1154 Kernel.MinusEq (resultNum, mod);
1156 } else if (mc != 0) {
1159 // First, we estimate the quotient by dividing
1160 // the first part of each of the numbers. Then
1161 // we correct this, if necessary, with a subtraction.
1166 // We would rather have this estimate overshoot,
1167 // so we add one to the divisor
1168 uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1169 (mod.data [mod.length-1] + 1));
1176 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1180 if (u [i] > t) mc++;
1182 } while (i < resultNum.length);
1188 uint [] s = mod.data;
1191 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1194 } while (j < resultNum.length);
1197 while (resultNum >= mod)
1198 Kernel.MinusEq (resultNum, mod);
1200 while (resultNum >= mod)
1201 Kernel.MinusEq (resultNum, mod);
1205 } while (pos-- > 0);
1207 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1212 private unsafe BigInteger EvenPow (uint b, BigInteger exp)
1215 uint [] wkspace = new uint [mod.length << 1 + 1];
1216 BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);
1218 uint pos = (uint)exp.BitCount () - 2;
1221 // We know that the first itr will make the val b
1228 Kernel.SquarePositive (resultNum, ref wkspace);
1229 if (!(resultNum.length < mod.length))
1230 BarrettReduction (resultNum);
1232 if (exp.TestBit (pos)) {
1238 // TODO: Is Unsafe really speeding things up?
1239 fixed (uint* u = resultNum.data) {
1245 mc += (ulong)u [i] * (ulong)b;
1248 } while (++i < resultNum.length);
1250 if (resultNum.length < mod.length) {
1254 while (resultNum >= mod)
1255 Kernel.MinusEq (resultNum, mod);
1257 } else if (mc != 0) {
1260 // First, we estimate the quotient by dividing
1261 // the first part of each of the numbers. Then
1262 // we correct this, if necessary, with a subtraction.
1267 // We would rather have this estimate overshoot,
1268 // so we add one to the divisor
1269 uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1270 (mod.data [mod.length-1] + 1));
1277 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1281 if (u [i] > t) mc++;
1283 } while (i < resultNum.length);
1289 uint [] s = mod.data;
1292 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1295 } while (j < resultNum.length);
1298 while (resultNum >= mod)
1299 Kernel.MinusEq (resultNum, mod);
1301 while (resultNum >= mod)
1302 Kernel.MinusEq (resultNum, mod);
1306 } while (pos-- > 0);
1311 private unsafe BigInteger EvenModTwoPow (BigInteger exp)
1314 uint [] wkspace = new uint [mod.length << 1 + 1];
1316 BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
1318 uint value = exp.data [exp.length - 1];
1319 uint mask = 0x80000000;
1321 // Find the first bit of the exponent
1322 while ((value & mask) == 0)
1326 // We know that the first itr will make the val 2,
1327 // so eat one bit of the exponent
1331 uint wPos = exp.length - 1;
1334 value = exp.data [wPos];
1336 Kernel.SquarePositive (resultNum, ref wkspace);
1337 if (resultNum.length >= mod.length)
1338 BarrettReduction (resultNum);
1340 if ((value & mask) != 0) {
1342 // resultNum = (resultNum * 2) % mod
1345 fixed (uint* u = resultNum.data) {
1350 uint* uuE = u + resultNum.length;
1354 *uu = (x << 1) | carry;
1355 carry = x >> (32 - 1);
1359 // subtraction inlined because we know it is square
1360 if (carry != 0 || resultNum >= mod) {
1363 uint [] s = mod.data;
1367 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1376 } while ((mask >>= 1) > 0);
1378 } while (wPos-- > 0);
1383 private unsafe BigInteger OddModTwoPow (BigInteger exp)
1386 uint [] wkspace = new uint [mod.length << 1 + 1];
1388 BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
1389 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1391 uint mPrime = Montgomery.Inverse (mod.data [0]);
1394 // TODO: eat small bits, the ones we can do with no modular reduction
1396 uint pos = (uint)exp.BitCount () - 2;
1399 Kernel.SquarePositive (resultNum, ref wkspace);
1400 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1402 if (exp.TestBit (pos)) {
1404 // resultNum = (resultNum * 2) % mod
1407 fixed (uint* u = resultNum.data) {
1412 uint* uuE = u + resultNum.length;
1416 *uu = (x << 1) | carry;
1417 carry = x >> (32 - 1);
1421 // subtraction inlined because we know it is square
1422 if (carry != 0 || resultNum >= mod) {
1423 fixed (uint* s = mod.data) {
1429 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1438 } while (pos-- > 0);
1440 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1447 internal sealed class Montgomery {
1449 private Montgomery ()
1453 [CLSCompliant (false)]
1454 public static uint Inverse (uint n)
1458 while ((z = n * y) != 1)
1464 public static BigInteger ToMont (BigInteger n, BigInteger m)
1466 n.Normalize (); m.Normalize ();
1468 n <<= (int)m.length * 32;
1473 [CLSCompliant (false)]
1474 public static unsafe BigInteger Reduce (BigInteger n, BigInteger m, uint mPrime)
1477 fixed (uint* a = A.data, mm = m.data) {
1478 for (uint i = 0; i < m.length; i++) {
1479 // The mod here is taken care of by the CPU,
1480 // since the multiply will overflow.
1481 uint u_i = a [0] * mPrime /* % 2^32 */;
1488 // mP = Position in mod
1489 // aSP = the source of bits from a
1490 // aDP = destination for bits
1491 uint* mP = mm, aSP = a, aDP = a;
1493 ulong c = (ulong)u_i * ((ulong)*(mP++)) + *(aSP++);
1498 for (; j < m.length; j++) {
1499 c += (ulong)u_i * (ulong)*(mP++) + *(aSP++);
1504 // Account for carry
1505 // TODO: use a better loop here, we dont need the ulong stuff
1506 for (; j < A.length; j++) {
1510 if (c == 0) {j++; break;}
1513 for (; j < A.length; j++) {
1514 *(aDP++) = *(aSP++);
1520 while (A.length > 1 && a [A.length-1] == 0) A.length--;
1523 if (A >= m) Kernel.MinusEq (A, m);
1528 public static BigInteger Reduce (BigInteger n, BigInteger m)
1530 return Reduce (n, m, Inverse (m.data [0]));
1536 /// Low level functions for the BigInteger
1538 private sealed class Kernel {
1540 #region Addition/Subtraction
1543 /// Adds two numbers with the same sign.
1545 /// <param name="bi1">A BigInteger</param>
1546 /// <param name="bi2">A BigInteger</param>
1547 /// <returns>bi1 + bi2</returns>
1548 public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
1551 uint yMax, xMax, i = 0;
1553 // x should be bigger
1554 if (bi1.length < bi2.length) {
1566 BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
1568 uint [] r = result.data;
1572 // Add common parts of both numbers
1574 sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
1577 } while (++i < yMax);
1579 // Copy remainder of longer number while carry propagation is required
1580 bool carry = (sum != 0);
1586 carry = ((r [i] = x [i] + 1) == 0);
1587 while (++i < xMax && carry);
1592 result.length = ++i;
1604 result.Normalize ();
1608 public static BigInteger Subtract (BigInteger big, BigInteger small)
1610 BigInteger result = new BigInteger (Sign.Positive, big.length);
1612 uint [] r = result.data, b = big.data, s = small.data;
1618 if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
1623 } while (++i < small.length);
1625 if (i == big.length) goto fixup;
1630 while (b [i++] == 0 && i < big.length);
1632 if (i == big.length) goto fixup;
1637 while (++i < big.length);
1641 result.Normalize ();
1645 public static void MinusEq (BigInteger big, BigInteger small)
1647 uint [] b = big.data, s = small.data;
1652 if (((x += c) < c) | ((b [i] -= x) > ~x))
1656 } while (++i < small.length);
1658 if (i == big.length) goto fixup;
1663 while (b [i++] == 0 && i < big.length);
1669 while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
1672 if (big.length == 0)
1677 public static void PlusEq (BigInteger bi1, BigInteger bi2)
1680 uint yMax, xMax, i = 0;
1683 // x should be bigger
1684 if (bi1.length < bi2.length){
1697 uint [] r = bi1.data;
1701 // Add common parts of both numbers
1703 sum += ((ulong)x [i]) + ((ulong)y [i]);
1706 } while (++i < yMax);
1708 // Copy remainder of longer number while carry propagation is required
1709 bool carry = (sum != 0);
1715 carry = ((r [i] = x [i] + 1) == 0);
1716 while (++i < xMax && carry);
1727 if (flag && i < xMax - 1) {
1733 bi1.length = xMax + 1;
1742 /// Compares two BigInteger
1744 /// <param name="bi1">A BigInteger</param>
1745 /// <param name="bi2">A BigInteger</param>
1746 /// <returns>The sign of bi1 - bi2</returns>
1747 public static Sign Compare (BigInteger bi1, BigInteger bi2)
1750 // Step 1. Compare the lengths
1752 uint l1 = bi1.length, l2 = bi2.length;
1754 while (l1 > 0 && bi1.data [l1-1] == 0) l1--;
1755 while (l2 > 0 && bi2.data [l2-1] == 0) l2--;
1757 if (l1 == 0 && l2 == 0) return Sign.Zero;
1759 // bi1 len < bi2 len
1760 if (l1 < l2) return Sign.Negative;
1761 // bi1 len > bi2 len
1762 else if (l1 > l2) return Sign.Positive;
1765 // Step 2. Compare the bits
1770 while (pos != 0 && bi1.data [pos] == bi2.data [pos]) pos--;
1772 if (bi1.data [pos] < bi2.data [pos])
1773 return Sign.Negative;
1774 else if (bi1.data [pos] > bi2.data [pos])
1775 return Sign.Positive;
1787 /// Performs n / d and n % d in one operation.
1789 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1790 /// <param name="d">The divisor</param>
1791 /// <returns>n % d</returns>
1792 public static uint SingleByteDivideInPlace (BigInteger n, uint d)
1800 n.data [i] = (uint)(r / d);
1808 public static uint DwordMod (BigInteger n, uint d)
1822 public static BigInteger DwordDiv (BigInteger n, uint d)
1824 BigInteger ret = new BigInteger (Sign.Positive, n.length);
1832 ret.data [i] = (uint)(r / d);
1840 public static BigInteger [] DwordDivMod (BigInteger n, uint d)
1842 BigInteger ret = new BigInteger (Sign.Positive , n.length);
1850 ret.data [i] = (uint)(r / d);
1855 BigInteger rem = (uint)r;
1857 return new BigInteger [] {ret, rem};
1864 public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
1866 if (Kernel.Compare (bi1, bi2) == Sign.Negative)
1867 return new BigInteger [2] { 0, new BigInteger (bi1) };
1869 bi1.Normalize (); bi2.Normalize ();
1871 if (bi2.length == 1)
1872 return DwordDivMod (bi1, bi2.data [0]);
1874 uint remainderLen = bi1.length + 1;
1875 int divisorLen = (int)bi2.length + 1;
1877 uint mask = 0x80000000;
1878 uint val = bi2.data [bi2.length - 1];
1880 int resultPos = (int)bi1.length - (int)bi2.length;
1882 while (mask != 0 && (val & mask) == 0) {
1883 shift++; mask >>= 1;
1886 BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
1887 BigInteger rem = (bi1 << shift);
1889 uint [] remainder = rem.data;
1893 int j = (int)(remainderLen - bi2.length);
1894 int pos = (int)remainderLen - 1;
1896 uint firstDivisorByte = bi2.data [bi2.length-1];
1897 ulong secondDivisorByte = bi2.data [bi2.length-2];
1900 ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
1902 ulong q_hat = dividend / (ulong)firstDivisorByte;
1903 ulong r_hat = dividend % (ulong)firstDivisorByte;
1907 if (q_hat == 0x100000000 ||
1908 (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
1910 r_hat += (ulong)firstDivisorByte;
1912 if (r_hat < 0x100000000)
1919 // At this point, q_hat is either exact, or one too large
1920 // (more likely to be exact) so, we attempt to multiply the
1921 // divisor by q_hat, if we get a borrow, we just subtract
1922 // one from q_hat and add the divisor back.
1927 int nPos = pos - divisorLen + 1;
1929 uint uint_q_hat = (uint)q_hat;
1931 mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
1932 t = remainder [nPos];
1933 remainder [nPos] -= (uint)mc;
1935 if (remainder [nPos] > t) mc++;
1937 } while (dPos < divisorLen);
1939 nPos = pos - divisorLen + 1;
1948 sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
1949 remainder [nPos] = (uint)sum;
1952 } while (dPos < divisorLen);
1956 quot.data [resultPos--] = (uint)uint_q_hat;
1964 BigInteger [] ret = new BigInteger [2] { quot, rem };
1977 public static BigInteger LeftShift (BigInteger bi, int n)
1979 if (n == 0) return new BigInteger (bi, bi.length + 1);
1982 n &= ((1 << 5) - 1);
1984 BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
1986 uint i = 0, l = bi.length;
1991 ret.data [i + w] = (x << n) | carry;
1992 carry = x >> (32 - n);
1995 ret.data [i + w] = carry;
1998 ret.data [i + w] = bi.data [i];
2007 public static BigInteger RightShift (BigInteger bi, int n)
2009 if (n == 0) return new BigInteger (bi);
2012 int s = n & ((1 << 5) - 1);
2014 BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
2015 uint l = (uint)ret.data.Length - 1;
2022 x = bi.data [l + w];
2023 ret.data [l] = (x >> n) | carry;
2024 carry = x << (32 - n);
2028 ret.data [l] = bi.data [l + w];
2039 public static BigInteger MultiplyByDword (BigInteger n, uint f)
2041 BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
2047 c += (ulong)n.data [i] * (ulong)f;
2048 ret.data [i] = (uint)c;
2050 } while (++i < n.length);
2051 ret.data [i] = (uint)c;
2058 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2059 /// y [yOffset:yOffset+yLen] and puts it into
2060 /// d [dOffset:dOffset+xLen+yLen].
2063 /// This code is unsafe! It is the caller's responsibility to make
2064 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2065 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
2067 public static unsafe void Multiply (uint [] x, uint xOffset, uint xLen, uint [] y, uint yOffset, uint yLen, uint [] d, uint dOffset)
2069 fixed (uint* xx = x, yy = y, dd = d) {
2070 uint* xP = xx + xOffset,
2076 for (; xP < xE; xP++, dB++) {
2078 if (*xP == 0) continue;
2083 for (uint* yP = yB; yP < yE; yP++, dP++) {
2084 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2097 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2098 /// y [yOffset:yOffset+yLen] and puts the low mod words into
2099 /// d [dOffset:dOffset+mod].
2102 /// This code is unsafe! It is the caller's responsibility to make
2103 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2104 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
2106 public static unsafe void MultiplyMod2p32pmod (uint [] x, int xOffset, int xLen, uint [] y, int yOffest, int yLen, uint [] d, int dOffset, int mod)
2108 fixed (uint* xx = x, yy = y, dd = d) {
2109 uint* xP = xx + xOffset,
2116 for (; xP < xE; xP++, dB++) {
2118 if (*xP == 0) continue;
2122 for (uint* yP = yB; yP < yE && dP < dE; yP++, dP++) {
2123 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2129 if (mcarry != 0 && dP < dE)
2135 public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
2137 uint [] t = wkSpace;
2139 uint [] d = bi.data;
2140 uint dl = bi.length;
2143 fixed (uint* dd = d, tt = t) {
2145 uint* ttE = tt + t.Length;
2147 for (uint* ttt = tt; ttt < ttE; ttt++)
2150 uint* dP = dd, tP = tt;
2152 for (uint i = 0; i < dl; i++, dP++) {
2159 uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
2161 for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
2163 mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
2165 *tP2 = (uint)mcarry;
2170 *tP2 = (uint)mcarry;
2173 // Double t. Inlined for speed.
2180 *tP = (x << 1) | carry;
2181 carry = x >> (32 - 1);
2184 if (carry != 0) *tP = carry;
2186 // Add in the diagnals
2190 for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
2191 ulong val = (ulong)*dP * (ulong)*dP + *tP;
2194 *(++tP) += (uint)val;
2195 if (*tP < (uint)val) {
2197 // Account for the first carry
2200 // Keep adding until no carry
2201 while ((*tP3++) == 0)
2210 while (tt [bi.length-1] == 0 && bi.length > 1) bi.length--;
2216 * Never called in BigInteger (and part of a private class)
2217 * public static bool Double (uint [] u, int l)
2223 u [i] = (x << 1) | carry;
2224 carry = x >> (32 - 1);
2227 if (carry != 0) u [l] = carry;
2233 #region Number Theory
2235 public static BigInteger gcd (BigInteger a, BigInteger b)
2242 while (x.length > 1) {
2248 if (x == 0) return g;
2250 // TODO: should we have something here if we can convert to long?
2253 // Now we can just do it with single precision. I am using the binary gcd method,
2254 // as it should be faster.
2257 uint yy = x.data [0];
2262 while (((xx | yy) & 1) == 0) {
2263 xx >>= 1; yy >>= 1; t++;
2266 while ((xx & 1) == 0) xx >>= 1;
2267 while ((yy & 1) == 0) yy >>= 1;
2269 xx = (xx - yy) >> 1;
2271 yy = (yy - xx) >> 1;
2277 public static uint modInverse (BigInteger bi, uint modulus)
2279 uint a = modulus, b = bi % modulus;
2280 uint p0 = 0, p1 = 1;
2300 public static BigInteger modInverse (BigInteger bi, BigInteger modulus)
2302 if (modulus.length == 1) return modInverse (bi, modulus.data [0]);
2304 BigInteger [] p = { 0, 1 };
2305 BigInteger [] q = new BigInteger [2]; // quotients
2306 BigInteger [] r = { 0, 0 }; // remainders
2310 BigInteger a = modulus;
2313 ModulusRing mr = new ModulusRing (modulus);
2319 BigInteger pval = mr.Difference (p [0], p [1] * q [0]);
2320 p [0] = p [1]; p [1] = pval;
2323 BigInteger [] divret = multiByteDivide (a, b);
2325 q [0] = q [1]; q [1] = divret [0];
2326 r [0] = r [1]; r [1] = divret [1];
2334 throw (new ArithmeticException ("No inverse!"));
2336 return mr.Difference (p [0], p [1] * q [0]);