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 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
19 // Permission is hereby granted, free of charge, to any person obtaining
20 // a copy of this software and associated documentation files (the
21 // "Software"), to deal in the Software without restriction, including
22 // without limitation the rights to use, copy, modify, merge, publish,
23 // distribute, sublicense, and/or sell copies of the Software, and to
24 // permit persons to whom the Software is furnished to do so, subject to
25 // the following conditions:
27 // The above copyright notice and this permission notice shall be
28 // included in all copies or substantial portions of the Software.
30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 using System
.Security
.Cryptography
;
41 using Mono
.Math
.Prime
.Generator
;
42 using Mono
.Math
.Prime
;
56 /// The Length of this BigInteger
61 /// The data for this BigInteger
70 /// Default length of a BigInteger in bytes
72 const uint DEFAULT_LEN
= 20;
75 /// Table of primes below 2000.
79 /// This table was generated using Mathematica 4.1 using the following function:
83 /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
88 internal static readonly uint [] smallPrimes
= {
89 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
90 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
91 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
92 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
93 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
94 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
95 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
96 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
97 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
98 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
99 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
101 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
102 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
103 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
104 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
105 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
106 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
107 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
108 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
109 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
110 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
111 1979, 1987, 1993, 1997, 1999,
113 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
114 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
115 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
116 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
117 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
118 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
119 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
120 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
121 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
122 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
124 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
125 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
126 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
127 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
128 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
129 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
130 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
131 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
132 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
135 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
136 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
137 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
138 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
139 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
140 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
141 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
142 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
143 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
146 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
147 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
148 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
149 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
150 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
151 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
152 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
153 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
154 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
157 public enum Sign
: int {
163 #region Exception Messages
164 const string WouldReturnNegVal
= "Operation would return a negative value";
173 data
= new uint [DEFAULT_LEN
];
174 this.length
= DEFAULT_LEN
;
178 [CLSCompliant (false)]
180 public BigInteger (Sign sign
, uint len
)
182 this.data
= new uint [len
];
186 public BigInteger (BigInteger bi
)
188 this.data
= (uint [])bi
.data
.Clone ();
189 this.length
= bi
.length
;
193 [CLSCompliant (false)]
195 public BigInteger (BigInteger bi
, uint len
)
198 this.data
= new uint [len
];
200 for (uint i
= 0; i
< bi
.length
; i
++)
201 this.data
[i
] = bi
.data
[i
];
203 this.length
= bi
.length
;
210 public BigInteger (byte [] inData
)
212 length
= (uint)inData
.Length
>> 2;
213 int leftOver
= inData
.Length
& 0x3;
215 // length not multiples of 4
216 if (leftOver
!= 0) length
++;
218 data
= new uint [length
];
220 for (int i
= inData
.Length
- 1, j
= 0; i
>= 3; i
-= 4, j
++) {
222 (inData
[i
-3] << (3*8)) |
223 (inData
[i
-2] << (2*8)) |
224 (inData
[i
-1] << (1*8)) |
230 case 1: data
[length
-1] = (uint)inData
[0]; break;
231 case 2: data
[length
-1] = (uint)((inData
[0] << 8) | inData
[1]); break;
232 case 3: data
[length
-1] = (uint)((inData
[0] << 16) | (inData
[1] << 8) | inData
[2]); break;
239 [CLSCompliant (false)]
241 public BigInteger (uint [] inData
)
243 length
= (uint)inData
.Length
;
245 data
= new uint [length
];
247 for (int i
= (int)length
- 1, j
= 0; i
>= 0; i
--, j
++)
248 data
[j
] = inData
[i
];
254 [CLSCompliant (false)]
256 public BigInteger (uint ui
)
258 data
= new uint [] {ui}
;
262 [CLSCompliant (false)]
264 public BigInteger (ulong ul
)
266 data
= new uint [2] { (uint)ul, (uint)(ul >> 32)}
;
273 [CLSCompliant (false)]
275 public static implicit operator BigInteger (uint value)
277 return (new BigInteger (value));
280 public static implicit operator BigInteger (int value)
282 if (value < 0) throw new ArgumentOutOfRangeException ("value");
283 return (new BigInteger ((uint)value));
287 [CLSCompliant (false)]
289 public static implicit operator BigInteger (ulong value)
291 return (new BigInteger (value));
294 /* This is the BigInteger.Parse method I use. This method works
295 because BigInteger.ToString returns the input I gave to Parse. */
296 public static BigInteger
Parse (string number
)
299 throw new ArgumentNullException ("number");
301 int i
= 0, len
= number
.Length
;
303 bool digits_seen
= false;
304 BigInteger val
= new BigInteger (0);
305 if (number
[i
] == '+') {
308 else if (number
[i
] == '-') {
309 throw new FormatException (WouldReturnNegVal
);
312 for (; i
< len
; i
++) {
318 if (c
>= '0' && c
<= '9') {
319 val
= val
* 10 + (c
- '0');
323 if (Char
.IsWhiteSpace (c
)) {
324 for (i
++; i
< len
; i
++) {
325 if (!Char
.IsWhiteSpace (number
[i
]))
326 throw new FormatException ();
331 throw new FormatException ();
335 throw new FormatException ();
343 public static BigInteger
operator + (BigInteger bi1
, BigInteger bi2
)
346 return new BigInteger (bi2
);
348 return new BigInteger (bi1
);
350 return Kernel
.AddSameSign (bi1
, bi2
);
353 public static BigInteger
operator - (BigInteger bi1
, BigInteger bi2
)
356 return new BigInteger (bi1
);
359 throw new ArithmeticException (WouldReturnNegVal
);
361 switch (Kernel
.Compare (bi1
, bi2
)) {
367 return Kernel
.Subtract (bi1
, bi2
);
370 throw new ArithmeticException (WouldReturnNegVal
);
372 throw new Exception ();
376 public static int operator % (BigInteger bi
, int i
)
379 return (int)Kernel
.DwordMod (bi
, (uint)i
);
381 return -(int)Kernel
.DwordMod (bi
, (uint)-i
);
385 [CLSCompliant (false)]
387 public static uint operator % (BigInteger bi
, uint ui
)
389 return Kernel
.DwordMod (bi
, (uint)ui
);
392 public static BigInteger
operator % (BigInteger bi1
, BigInteger bi2
)
394 return Kernel
.multiByteDivide (bi1
, bi2
)[1];
397 public static BigInteger
operator / (BigInteger bi
, int i
)
400 return Kernel
.DwordDiv (bi
, (uint)i
);
402 throw new ArithmeticException (WouldReturnNegVal
);
405 public static BigInteger
operator / (BigInteger bi1
, BigInteger bi2
)
407 return Kernel
.multiByteDivide (bi1
, bi2
)[0];
410 public static BigInteger
operator * (BigInteger bi1
, BigInteger bi2
)
412 if (bi1
== 0 || bi2
== 0) return 0;
417 if (bi1
.data
.Length
< bi1
.length
) throw new IndexOutOfRangeException ("bi1 out of range");
418 if (bi2
.data
.Length
< bi2
.length
) throw new IndexOutOfRangeException ("bi2 out of range");
420 BigInteger ret
= new BigInteger (Sign
.Positive
, bi1
.length
+ bi2
.length
);
422 Kernel
.Multiply (bi1
.data
, 0, bi1
.length
, bi2
.data
, 0, bi2
.length
, ret
.data
, 0);
428 public static BigInteger
operator * (BigInteger bi
, int i
)
430 if (i
< 0) throw new ArithmeticException (WouldReturnNegVal
);
431 if (i
== 0) return 0;
432 if (i
== 1) return new BigInteger (bi
);
434 return Kernel
.MultiplyByDword (bi
, (uint)i
);
437 public static BigInteger
operator << (BigInteger bi1
, int shiftVal
)
439 return Kernel
.LeftShift (bi1
, shiftVal
);
442 public static BigInteger
operator >> (BigInteger bi1
, int shiftVal
)
444 return Kernel
.RightShift (bi1
, shiftVal
);
449 #region Friendly names for operators
451 // with names suggested by FxCop 1.30
453 public static BigInteger
Add (BigInteger bi1
, BigInteger bi2
)
458 public static BigInteger
Subtract (BigInteger bi1
, BigInteger bi2
)
463 public static int Modulus (BigInteger bi
, int i
)
469 [CLSCompliant (false)]
471 public static uint Modulus (BigInteger bi
, uint ui
)
476 public static BigInteger
Modulus (BigInteger bi1
, BigInteger bi2
)
481 public static BigInteger
Divid (BigInteger bi
, int i
)
486 public static BigInteger
Divid (BigInteger bi1
, BigInteger bi2
)
491 public static BigInteger
Multiply (BigInteger bi1
, BigInteger bi2
)
496 public static BigInteger
Multiply (BigInteger bi
, int i
)
504 private static RandomNumberGenerator rng
;
505 private static RandomNumberGenerator Rng
{
508 rng
= RandomNumberGenerator
.Create ();
514 /// Generates a new, random BigInteger of the specified length.
516 /// <param name="bits">The number of bits for the new number.</param>
517 /// <param name="rng">A random number generator to use to obtain the bits.</param>
518 /// <returns>A random number of the specified length.</returns>
519 public static BigInteger
GenerateRandom (int bits
, RandomNumberGenerator rng
)
521 int dwords
= bits
>> 5;
522 int remBits
= bits
& 0x1F;
527 BigInteger ret
= new BigInteger (Sign
.Positive
, (uint)dwords
+ 1);
528 byte [] random
= new byte [dwords
<< 2];
530 rng
.GetBytes (random
);
531 Buffer
.BlockCopy (random
, 0, ret
.data
, 0, (int)dwords
<< 2);
534 uint mask
= (uint)(0x01 << (remBits
-1));
535 ret
.data
[dwords
-1] |= mask
;
537 mask
= (uint)(0xFFFFFFFF >> (32 - remBits
));
538 ret
.data
[dwords
-1] &= mask
;
541 ret
.data
[dwords
-1] |= 0x80000000;
548 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
550 /// <param name="bits">The number of bits for the new number.</param>
551 /// <returns>A random number of the specified length.</returns>
552 public static BigInteger
GenerateRandom (int bits
)
554 return GenerateRandom (bits
, Rng
);
558 /// Randomizes the bits in "this" from the specified RNG.
560 /// <param name="rng">A RNG.</param>
561 public void Randomize (RandomNumberGenerator rng
)
566 int bits
= this.BitCount ();
567 int dwords
= bits
>> 5;
568 int remBits
= bits
& 0x1F;
573 byte [] random
= new byte [dwords
<< 2];
575 rng
.GetBytes (random
);
576 Buffer
.BlockCopy (random
, 0, data
, 0, (int)dwords
<< 2);
579 uint mask
= (uint)(0x01 << (remBits
-1));
580 data
[dwords
-1] |= mask
;
582 mask
= (uint)(0xFFFFFFFF >> (32 - remBits
));
583 data
[dwords
-1] &= mask
;
587 data
[dwords
-1] |= 0x80000000;
593 /// Randomizes the bits in "this" from the default RNG.
595 public void Randomize ()
604 public int BitCount ()
608 uint value = data
[length
- 1];
609 uint mask
= 0x80000000;
612 while (bits
> 0 && (value & mask
) == 0) {
616 bits
+= ((length
- 1) << 5);
622 /// Tests if the specified bit is 1.
624 /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
625 /// <returns>True if bitNum is set to 1, else false.</returns>
627 [CLSCompliant (false)]
629 public bool TestBit (uint bitNum
)
631 uint bytePos
= bitNum
>> 5; // divide by 32
632 byte bitPos
= (byte)(bitNum
& 0x1F); // get the lowest 5 bits
634 uint mask
= (uint)1 << bitPos
;
635 return ((this.data
[bytePos
] & mask
) != 0);
638 public bool TestBit (int bitNum
)
640 if (bitNum
< 0) throw new IndexOutOfRangeException ("bitNum out of range");
642 uint bytePos
= (uint)bitNum
>> 5; // divide by 32
643 byte bitPos
= (byte)(bitNum
& 0x1F); // get the lowest 5 bits
645 uint mask
= (uint)1 << bitPos
;
646 return ((this.data
[bytePos
] | mask
) == this.data
[bytePos
]);
650 [CLSCompliant (false)]
652 public void SetBit (uint bitNum
)
654 SetBit (bitNum
, true);
658 [CLSCompliant (false)]
660 public void ClearBit (uint bitNum
)
662 SetBit (bitNum
, false);
666 [CLSCompliant (false)]
668 public void SetBit (uint bitNum
, bool value)
670 uint bytePos
= bitNum
>> 5; // divide by 32
672 if (bytePos
< this.length
) {
673 uint mask
= (uint)1 << (int)(bitNum
& 0x1F);
675 this.data
[bytePos
] |= mask
;
677 this.data
[bytePos
] &= ~mask
;
681 public int LowestSetBit ()
683 if (this == 0) return -1;
685 while (!TestBit (i
)) i
++;
689 public byte[] GetBytes ()
691 if (this == 0) return new byte [1];
693 int numBits
= BitCount ();
694 int numBytes
= numBits
>> 3;
695 if ((numBits
& 0x7) != 0)
698 byte [] result
= new byte [numBytes
];
700 int numBytesInWord
= numBytes
& 0x3;
701 if (numBytesInWord
== 0) numBytesInWord
= 4;
704 for (int i
= (int)length
- 1; i
>= 0; i
--) {
706 for (int j
= numBytesInWord
- 1; j
>= 0; j
--) {
707 result
[pos
+j
] = (byte)(val
& 0xFF);
710 pos
+= numBytesInWord
;
721 [CLSCompliant (false)]
723 public static bool operator == (BigInteger bi1
, uint ui
)
725 if (bi1
.length
!= 1) bi1
.Normalize ();
726 return bi1
.length
== 1 && bi1
.data
[0] == ui
;
730 [CLSCompliant (false)]
732 public static bool operator != (BigInteger bi1
, uint ui
)
734 if (bi1
.length
!= 1) bi1
.Normalize ();
735 return !(bi1
.length
== 1 && bi1
.data
[0] == ui
);
738 public static bool operator == (BigInteger bi1
, BigInteger bi2
)
740 // we need to compare with null
741 if ((bi1
as object) == (bi2
as object))
743 if (null == bi1
|| null == bi2
)
745 return Kernel
.Compare (bi1
, bi2
) == 0;
748 public static bool operator != (BigInteger bi1
, BigInteger bi2
)
750 // we need to compare with null
751 if ((bi1
as object) == (bi2
as object))
753 if (null == bi1
|| null == bi2
)
755 return Kernel
.Compare (bi1
, bi2
) != 0;
758 public static bool operator > (BigInteger bi1
, BigInteger bi2
)
760 return Kernel
.Compare (bi1
, bi2
) > 0;
763 public static bool operator < (BigInteger bi1
, BigInteger bi2
)
765 return Kernel
.Compare (bi1
, bi2
) < 0;
768 public static bool operator >= (BigInteger bi1
, BigInteger bi2
)
770 return Kernel
.Compare (bi1
, bi2
) >= 0;
773 public static bool operator <= (BigInteger bi1
, BigInteger bi2
)
775 return Kernel
.Compare (bi1
, bi2
) <= 0;
778 public Sign
Compare (BigInteger bi
)
780 return Kernel
.Compare (this, bi
);
788 [CLSCompliant (false)]
790 public string ToString (uint radix
)
792 return ToString (radix
, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
796 [CLSCompliant (false)]
798 public string ToString (uint radix
, string characterSet
)
800 if (characterSet
.Length
< radix
)
801 throw new ArgumentException ("charSet length less than radix", "characterSet");
803 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
805 if (this == 0) return "0";
806 if (this == 1) return "1";
810 BigInteger a
= new BigInteger (this);
813 uint rem
= Kernel
.SingleByteDivideInPlace (a
, radix
);
814 result
= characterSet
[(int) rem
] + result
;
825 /// Normalizes this by setting the length to the actual number of
826 /// uints used in data and by setting the sign to Sign.Zero if the
827 /// value of this is 0.
829 private void Normalize ()
832 while (length
> 0 && data
[length
-1] == 0) length
--;
841 for (int i
=0; i
< length
; i
++)
849 public override int GetHashCode ()
853 for (uint i
= 0; i
< this.length
; i
++)
854 val ^
= this.data
[i
];
859 public override string ToString ()
861 return ToString (10);
864 public override bool Equals (object o
)
866 if (o
== null) return false;
867 if (o
is int) return (int)o
>= 0 && this == (uint)o
;
869 return Kernel
.Compare (this, (BigInteger
)o
) == 0;
874 #region Number Theory
876 public BigInteger
GCD (BigInteger bi
)
878 return Kernel
.gcd (this, bi
);
881 public BigInteger
ModInverse (BigInteger modulus
)
883 return Kernel
.modInverse (this, modulus
);
886 public BigInteger
ModPow (BigInteger exp
, BigInteger n
)
888 ModulusRing mr
= new ModulusRing (n
);
889 return mr
.Pow (this, exp
);
894 #region Prime Testing
896 public bool IsProbablePrime ()
898 if (this < smallPrimes
[smallPrimes
.Length
- 1]) {
899 for (int p
= 0; p
< smallPrimes
.Length
; p
++) {
900 if (this == smallPrimes
[p
])
905 for (int p
= 0; p
< smallPrimes
.Length
; p
++) {
906 if (this % smallPrimes
[p
] == 0)
910 return PrimalityTests
.RabinMillerTest (this, Prime
.ConfidenceFactor
.Medium
);
915 #region Prime Number Generation
918 /// Generates the smallest prime >= bi
920 /// <param name="bi">A BigInteger</param>
921 /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
922 public static BigInteger
NextHighestPrime (BigInteger bi
)
924 NextPrimeFinder npf
= new NextPrimeFinder ();
925 return npf
.GenerateNewPrime (0, bi
);
928 public static BigInteger
GeneratePseudoPrime (int bits
)
930 SequentialSearchPrimeGeneratorBase sspg
= new SequentialSearchPrimeGeneratorBase ();
931 return sspg
.GenerateNewPrime (bits
);
935 /// Increments this by two
943 // If there was no carry, nothing to do
946 // Account for the first carry
949 // Keep adding until no carry
950 while (data
[i
++] == 0x0)
953 // See if we increased the data length
954 if (length
== (uint)i
)
966 sealed class ModulusRing
{
968 BigInteger mod
, constant
;
970 public ModulusRing (BigInteger modulus
)
974 // calculate constant = b^ (2k) / m
975 uint i
= mod
.length
<< 1;
977 constant
= new BigInteger (Sign
.Positive
, i
+ 1);
978 constant
.data
[i
] = 0x00000001;
980 constant
= constant
/ mod
;
983 public void BarrettReduction (BigInteger x
)
990 // x < mod, so nothing to do.
991 if (x
.length
< k
) return;
998 if (x
.data
.Length
< x
.length
) throw new IndexOutOfRangeException ("x out of range");
1000 // q1 = x / b^ (k-1)
1001 // q2 = q1 * constant
1002 // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
1004 // TODO: We should the method in HAC p 604 to do this (14.45)
1005 q3
= new BigInteger (Sign
.Positive
, x
.length
- kMinusOne
+ constant
.length
);
1006 Kernel
.Multiply (x
.data
, kMinusOne
, x
.length
- kMinusOne
, constant
.data
, 0, constant
.length
, q3
.data
, 0);
1008 // r1 = x mod b^ (k+1)
1009 // i.e. keep the lowest (k+1) words
1011 uint lengthToCopy
= (x
.length
> kPlusOne
) ? kPlusOne
: x
.length
;
1013 x
.length
= lengthToCopy
;
1016 // r2 = (q3 * n) mod b^ (k+1)
1017 // partial multiplication of q3 and n
1019 BigInteger r2
= new BigInteger (Sign
.Positive
, kPlusOne
);
1020 Kernel
.MultiplyMod2p32pmod (q3
.data
, (int)kPlusOne
, (int)q3
.length
- (int)kPlusOne
, n
.data
, 0, (int)n
.length
, r2
.data
, 0, (int)kPlusOne
);
1025 Kernel
.MinusEq (x
, r2
);
1027 BigInteger val
= new BigInteger (Sign
.Positive
, kPlusOne
+ 1);
1028 val
.data
[kPlusOne
] = 0x00000001;
1030 Kernel
.MinusEq (val
, r2
);
1031 Kernel
.PlusEq (x
, val
);
1035 Kernel
.MinusEq (x
, n
);
1038 public BigInteger
Multiply (BigInteger a
, BigInteger b
)
1040 if (a
== 0 || b
== 0) return 0;
1042 if (a
.length
>= mod
.length
<< 1)
1045 if (b
.length
>= mod
.length
<< 1)
1048 if (a
.length
>= mod
.length
)
1049 BarrettReduction (a
);
1051 if (b
.length
>= mod
.length
)
1052 BarrettReduction (b
);
1054 BigInteger ret
= new BigInteger (a
* b
);
1055 BarrettReduction (ret
);
1060 public BigInteger
Difference (BigInteger a
, BigInteger b
)
1062 Sign cmp
= Kernel
.Compare (a
, b
);
1069 diff
= a
- b
; break;
1071 diff
= b
- a
; break;
1073 throw new Exception ();
1077 if (diff
.length
>= mod
.length
<< 1)
1080 BarrettReduction (diff
);
1082 if (cmp
== Sign
.Negative
)
1087 public BigInteger
Pow (BigInteger b
, BigInteger exp
)
1089 if ((mod
.data
[0] & 1) == 1) return OddPow (b
, exp
);
1090 else return EvenPow (b
, exp
);
1093 public BigInteger
EvenPow (BigInteger b
, BigInteger exp
)
1095 BigInteger resultNum
= new BigInteger ((BigInteger
)1, mod
.length
<< 1);
1096 BigInteger tempNum
= new BigInteger (b
% mod
, mod
.length
<< 1); // ensures (tempNum * tempNum) < b^ (2k)
1098 uint totalBits
= (uint)exp
.BitCount ();
1100 uint [] wkspace
= new uint [mod
.length
<< 1];
1102 // perform squaring and multiply exponentiation
1103 for (uint pos
= 0; pos
< totalBits
; pos
++) {
1104 if (exp
.TestBit (pos
)) {
1106 Array
.Clear (wkspace
, 0, wkspace
.Length
);
1107 Kernel
.Multiply (resultNum
.data
, 0, resultNum
.length
, tempNum
.data
, 0, tempNum
.length
, wkspace
, 0);
1108 resultNum
.length
+= tempNum
.length
;
1109 uint [] t
= wkspace
;
1110 wkspace
= resultNum
.data
;
1113 BarrettReduction (resultNum
);
1116 Kernel
.SquarePositive (tempNum
, ref wkspace
);
1117 BarrettReduction (tempNum
);
1127 private BigInteger
OddPow (BigInteger b
, BigInteger exp
)
1129 BigInteger resultNum
= new BigInteger (Montgomery
.ToMont (1, mod
), mod
.length
<< 1);
1130 BigInteger tempNum
= new BigInteger (Montgomery
.ToMont (b
, mod
), mod
.length
<< 1); // ensures (tempNum * tempNum) < b^ (2k)
1131 uint mPrime
= Montgomery
.Inverse (mod
.data
[0]);
1132 uint totalBits
= (uint)exp
.BitCount ();
1134 uint [] wkspace
= new uint [mod
.length
<< 1];
1136 // perform squaring and multiply exponentiation
1137 for (uint pos
= 0; pos
< totalBits
; pos
++) {
1138 if (exp
.TestBit (pos
)) {
1140 Array
.Clear (wkspace
, 0, wkspace
.Length
);
1141 Kernel
.Multiply (resultNum
.data
, 0, resultNum
.length
, tempNum
.data
, 0, tempNum
.length
, wkspace
, 0);
1142 resultNum
.length
+= tempNum
.length
;
1143 uint [] t
= wkspace
;
1144 wkspace
= resultNum
.data
;
1147 Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1150 Kernel
.SquarePositive (tempNum
, ref wkspace
);
1151 Montgomery
.Reduce (tempNum
, mod
, mPrime
);
1154 Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1158 #region Pow Small Base
1160 // TODO: Make tests for this, not really needed b/c prime stuff
1161 // checks it, but still would be nice
1163 [CLSCompliant (false)]
1165 public BigInteger
Pow (uint b
, BigInteger exp
)
1168 if ((mod
.data
[0] & 1) == 1)
1169 return OddPow (b
, exp
);
1171 return EvenPow (b
, exp
);
1172 /* buggy in some cases (like the well tested primes)
1174 if ((mod.data [0] & 1) == 1)
1175 return OddModTwoPow (exp);
1177 return EvenModTwoPow (exp);
1181 private unsafe BigInteger
OddPow (uint b
, BigInteger exp
)
1184 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1186 BigInteger resultNum
= Montgomery
.ToMont ((BigInteger
)b
, this.mod
);
1187 resultNum
= new BigInteger (resultNum
, mod
.length
<< 1 +1);
1189 uint mPrime
= Montgomery
.Inverse (mod
.data
[0]);
1191 uint pos
= (uint)exp
.BitCount () - 2;
1194 // We know that the first itr will make the val b
1201 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1202 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1204 if (exp
.TestBit (pos
)) {
1210 // TODO: Is Unsafe really speeding things up?
1211 fixed (uint* u
= resultNum
.data
) {
1217 mc
+= (ulong)u
[i
] * (ulong)b
;
1220 } while (++i
< resultNum
.length
);
1222 if (resultNum
.length
< mod
.length
) {
1226 while (resultNum
>= mod
)
1227 Kernel
.MinusEq (resultNum
, mod
);
1229 } else if (mc
!= 0) {
1232 // First, we estimate the quotient by dividing
1233 // the first part of each of the numbers. Then
1234 // we correct this, if necessary, with a subtraction.
1239 // We would rather have this estimate overshoot,
1240 // so we add one to the divisor
1242 if (mod
.data
[mod
.length
- 1] < UInt32
.MaxValue
) {
1243 divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1244 (mod
.data
[mod
.length
-1] + 1));
1247 // guess but don't divide by 0
1248 divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1249 (mod
.data
[mod
.length
-1]));
1257 mc
+= (ulong)mod
.data
[i
] * (ulong)divEstimate
;
1261 if (u
[i
] > t
) mc
++;
1263 } while (i
< resultNum
.length
);
1269 uint [] s
= mod
.data
;
1272 if (((a
+= sc
) < sc
) | ((u
[j
] -= a
) > ~a
)) sc
= 1;
1275 } while (j
< resultNum
.length
);
1278 while (resultNum
>= mod
)
1279 Kernel
.MinusEq (resultNum
, mod
);
1281 while (resultNum
>= mod
)
1282 Kernel
.MinusEq (resultNum
, mod
);
1286 } while (pos
-- > 0);
1288 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1293 private unsafe BigInteger
EvenPow (uint b
, BigInteger exp
)
1296 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1297 BigInteger resultNum
= new BigInteger ((BigInteger
)b
, mod
.length
<< 1 + 1);
1299 uint pos
= (uint)exp
.BitCount () - 2;
1302 // We know that the first itr will make the val b
1309 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1310 if (!(resultNum
.length
< mod
.length
))
1311 BarrettReduction (resultNum
);
1313 if (exp
.TestBit (pos
)) {
1319 // TODO: Is Unsafe really speeding things up?
1320 fixed (uint* u
= resultNum
.data
) {
1326 mc
+= (ulong)u
[i
] * (ulong)b
;
1329 } while (++i
< resultNum
.length
);
1331 if (resultNum
.length
< mod
.length
) {
1335 while (resultNum
>= mod
)
1336 Kernel
.MinusEq (resultNum
, mod
);
1338 } else if (mc
!= 0) {
1341 // First, we estimate the quotient by dividing
1342 // the first part of each of the numbers. Then
1343 // we correct this, if necessary, with a subtraction.
1348 // We would rather have this estimate overshoot,
1349 // so we add one to the divisor
1350 uint divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1351 (mod
.data
[mod
.length
-1] + 1));
1358 mc
+= (ulong)mod
.data
[i
] * (ulong)divEstimate
;
1362 if (u
[i
] > t
) mc
++;
1364 } while (i
< resultNum
.length
);
1370 uint [] s
= mod
.data
;
1373 if (((a
+= sc
) < sc
) | ((u
[j
] -= a
) > ~a
)) sc
= 1;
1376 } while (j
< resultNum
.length
);
1379 while (resultNum
>= mod
)
1380 Kernel
.MinusEq (resultNum
, mod
);
1382 while (resultNum
>= mod
)
1383 Kernel
.MinusEq (resultNum
, mod
);
1387 } while (pos
-- > 0);
1392 /* known to be buggy in some cases
1393 private unsafe BigInteger EvenModTwoPow (BigInteger exp)
1396 uint [] wkspace = new uint [mod.length << 1 + 1];
1398 BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
1400 uint value = exp.data [exp.length - 1];
1401 uint mask = 0x80000000;
1403 // Find the first bit of the exponent
1404 while ((value & mask) == 0)
1408 // We know that the first itr will make the val 2,
1409 // so eat one bit of the exponent
1413 uint wPos = exp.length - 1;
1416 value = exp.data [wPos];
1418 Kernel.SquarePositive (resultNum, ref wkspace);
1419 if (resultNum.length >= mod.length)
1420 BarrettReduction (resultNum);
1422 if ((value & mask) != 0) {
1424 // resultNum = (resultNum * 2) % mod
1427 fixed (uint* u = resultNum.data) {
1432 uint* uuE = u + resultNum.length;
1436 *uu = (x << 1) | carry;
1437 carry = x >> (32 - 1);
1441 // subtraction inlined because we know it is square
1442 if (carry != 0 || resultNum >= mod) {
1445 uint [] s = mod.data;
1449 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1458 } while ((mask >>= 1) > 0);
1460 } while (wPos-- > 0);
1465 private unsafe BigInteger OddModTwoPow (BigInteger exp)
1468 uint [] wkspace = new uint [mod.length << 1 + 1];
1470 BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
1471 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1473 uint mPrime = Montgomery.Inverse (mod.data [0]);
1476 // TODO: eat small bits, the ones we can do with no modular reduction
1478 uint pos = (uint)exp.BitCount () - 2;
1481 Kernel.SquarePositive (resultNum, ref wkspace);
1482 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1484 if (exp.TestBit (pos)) {
1486 // resultNum = (resultNum * 2) % mod
1489 fixed (uint* u = resultNum.data) {
1494 uint* uuE = u + resultNum.length;
1498 *uu = (x << 1) | carry;
1499 carry = x >> (32 - 1);
1503 // subtraction inlined because we know it is square
1504 if (carry != 0 || resultNum >= mod) {
1505 fixed (uint* s = mod.data) {
1511 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1520 } while (pos-- > 0);
1522 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1529 internal sealed class Montgomery
{
1531 private Montgomery ()
1535 public static uint Inverse (uint n
)
1539 while ((z
= n
* y
) != 1)
1545 public static BigInteger
ToMont (BigInteger n
, BigInteger m
)
1547 n
.Normalize (); m
.Normalize ();
1549 n
<<= (int)m
.length
* 32;
1554 public static unsafe BigInteger
Reduce (BigInteger n
, BigInteger m
, uint mPrime
)
1557 fixed (uint* a
= A
.data
, mm
= m
.data
) {
1558 for (uint i
= 0; i
< m
.length
; i
++) {
1559 // The mod here is taken care of by the CPU,
1560 // since the multiply will overflow.
1561 uint u_i
= a
[0] * mPrime
/* % 2^32 */;
1568 // mP = Position in mod
1569 // aSP = the source of bits from a
1570 // aDP = destination for bits
1571 uint* mP
= mm
, aSP
= a
, aDP
= a
;
1573 ulong c
= (ulong)u_i
* ((ulong)*(mP
++)) + *(aSP
++);
1578 for (; j
< m
.length
; j
++) {
1579 c
+= (ulong)u_i
* (ulong)*(mP
++) + *(aSP
++);
1584 // Account for carry
1585 // TODO: use a better loop here, we dont need the ulong stuff
1586 for (; j
< A
.length
; j
++) {
1590 if (c
== 0) {j++; break;}
1593 for (; j
< A
.length
; j
++) {
1594 *(aDP
++) = *(aSP
++);
1600 while (A
.length
> 1 && a
[A
.length
-1] == 0) A
.length
--;
1603 if (A
>= m
) Kernel
.MinusEq (A
, m
);
1608 public static BigInteger
Reduce (BigInteger n
, BigInteger m
)
1610 return Reduce (n
, m
, Inverse (m
.data
[0]));
1616 /// Low level functions for the BigInteger
1618 private sealed class Kernel
{
1620 #region Addition/Subtraction
1623 /// Adds two numbers with the same sign.
1625 /// <param name="bi1">A BigInteger</param>
1626 /// <param name="bi2">A BigInteger</param>
1627 /// <returns>bi1 + bi2</returns>
1628 public static BigInteger
AddSameSign (BigInteger bi1
, BigInteger bi2
)
1631 uint yMax
, xMax
, i
= 0;
1633 // x should be bigger
1634 if (bi1
.length
< bi2
.length
) {
1646 BigInteger result
= new BigInteger (Sign
.Positive
, xMax
+ 1);
1648 uint [] r
= result
.data
;
1652 // Add common parts of both numbers
1654 sum
= ((ulong)x
[i
]) + ((ulong)y
[i
]) + sum
;
1657 } while (++i
< yMax
);
1659 // Copy remainder of longer number while carry propagation is required
1660 bool carry
= (sum
!= 0);
1666 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1667 while (++i
< xMax
&& carry
);
1672 result
.length
= ++i
;
1684 result
.Normalize ();
1688 public static BigInteger
Subtract (BigInteger big
, BigInteger small
)
1690 BigInteger result
= new BigInteger (Sign
.Positive
, big
.length
);
1692 uint [] r
= result
.data
, b
= big
.data
, s
= small
.data
;
1698 if (((x
+= c
) < c
) | ((r
[i
] = b
[i
] - x
) > ~x
))
1703 } while (++i
< small
.length
);
1705 if (i
== big
.length
) goto fixup
;
1710 while (b
[i
++] == 0 && i
< big
.length
);
1712 if (i
== big
.length
) goto fixup
;
1717 while (++i
< big
.length
);
1721 result
.Normalize ();
1725 public static void MinusEq (BigInteger big
, BigInteger small
)
1727 uint [] b
= big
.data
, s
= small
.data
;
1732 if (((x
+= c
) < c
) | ((b
[i
] -= x
) > ~x
))
1736 } while (++i
< small
.length
);
1738 if (i
== big
.length
) goto fixup
;
1743 while (b
[i
++] == 0 && i
< big
.length
);
1749 while (big
.length
> 0 && big
.data
[big
.length
-1] == 0) big
.length
--;
1752 if (big
.length
== 0)
1757 public static void PlusEq (BigInteger bi1
, BigInteger bi2
)
1760 uint yMax
, xMax
, i
= 0;
1763 // x should be bigger
1764 if (bi1
.length
< bi2
.length
){
1777 uint [] r
= bi1
.data
;
1781 // Add common parts of both numbers
1783 sum
+= ((ulong)x
[i
]) + ((ulong)y
[i
]);
1786 } while (++i
< yMax
);
1788 // Copy remainder of longer number while carry propagation is required
1789 bool carry
= (sum
!= 0);
1795 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1796 while (++i
< xMax
&& carry
);
1807 if (flag
&& i
< xMax
- 1) {
1813 bi1
.length
= xMax
+ 1;
1822 /// Compares two BigInteger
1824 /// <param name="bi1">A BigInteger</param>
1825 /// <param name="bi2">A BigInteger</param>
1826 /// <returns>The sign of bi1 - bi2</returns>
1827 public static Sign
Compare (BigInteger bi1
, BigInteger bi2
)
1830 // Step 1. Compare the lengths
1832 uint l1
= bi1
.length
, l2
= bi2
.length
;
1834 while (l1
> 0 && bi1
.data
[l1
-1] == 0) l1
--;
1835 while (l2
> 0 && bi2
.data
[l2
-1] == 0) l2
--;
1837 if (l1
== 0 && l2
== 0) return Sign
.Zero
;
1839 // bi1 len < bi2 len
1840 if (l1
< l2
) return Sign
.Negative
;
1841 // bi1 len > bi2 len
1842 else if (l1
> l2
) return Sign
.Positive
;
1845 // Step 2. Compare the bits
1850 while (pos
!= 0 && bi1
.data
[pos
] == bi2
.data
[pos
]) pos
--;
1852 if (bi1
.data
[pos
] < bi2
.data
[pos
])
1853 return Sign
.Negative
;
1854 else if (bi1
.data
[pos
] > bi2
.data
[pos
])
1855 return Sign
.Positive
;
1867 /// Performs n / d and n % d in one operation.
1869 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1870 /// <param name="d">The divisor</param>
1871 /// <returns>n % d</returns>
1872 public static uint SingleByteDivideInPlace (BigInteger n
, uint d
)
1880 n
.data
[i
] = (uint)(r
/ d
);
1888 public static uint DwordMod (BigInteger n
, uint d
)
1902 public static BigInteger
DwordDiv (BigInteger n
, uint d
)
1904 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1912 ret
.data
[i
] = (uint)(r
/ d
);
1920 public static BigInteger
[] DwordDivMod (BigInteger n
, uint d
)
1922 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1930 ret
.data
[i
] = (uint)(r
/ d
);
1935 BigInteger rem
= (uint)r
;
1937 return new BigInteger
[] {ret, rem}
;
1944 public static BigInteger
[] multiByteDivide (BigInteger bi1
, BigInteger bi2
)
1946 if (Kernel
.Compare (bi1
, bi2
) == Sign
.Negative
)
1947 return new BigInteger
[2] { 0, new BigInteger (bi1) }
;
1949 bi1
.Normalize (); bi2
.Normalize ();
1951 if (bi2
.length
== 1)
1952 return DwordDivMod (bi1
, bi2
.data
[0]);
1954 uint remainderLen
= bi1
.length
+ 1;
1955 int divisorLen
= (int)bi2
.length
+ 1;
1957 uint mask
= 0x80000000;
1958 uint val
= bi2
.data
[bi2
.length
- 1];
1960 int resultPos
= (int)bi1
.length
- (int)bi2
.length
;
1962 while (mask
!= 0 && (val
& mask
) == 0) {
1963 shift
++; mask
>>= 1;
1966 BigInteger quot
= new BigInteger (Sign
.Positive
, bi1
.length
- bi2
.length
+ 1);
1967 BigInteger rem
= (bi1
<< shift
);
1969 uint [] remainder
= rem
.data
;
1973 int j
= (int)(remainderLen
- bi2
.length
);
1974 int pos
= (int)remainderLen
- 1;
1976 uint firstDivisorByte
= bi2
.data
[bi2
.length
-1];
1977 ulong secondDivisorByte
= bi2
.data
[bi2
.length
-2];
1980 ulong dividend
= ((ulong)remainder
[pos
] << 32) + (ulong)remainder
[pos
-1];
1982 ulong q_hat
= dividend
/ (ulong)firstDivisorByte
;
1983 ulong r_hat
= dividend
% (ulong)firstDivisorByte
;
1987 if (q_hat
== 0x100000000 ||
1988 (q_hat
* secondDivisorByte
) > ((r_hat
<< 32) + remainder
[pos
-2])) {
1990 r_hat
+= (ulong)firstDivisorByte
;
1992 if (r_hat
< 0x100000000)
1999 // At this point, q_hat is either exact, or one too large
2000 // (more likely to be exact) so, we attempt to multiply the
2001 // divisor by q_hat, if we get a borrow, we just subtract
2002 // one from q_hat and add the divisor back.
2007 int nPos
= pos
- divisorLen
+ 1;
2009 uint uint_q_hat
= (uint)q_hat
;
2011 mc
+= (ulong)bi2
.data
[dPos
] * (ulong)uint_q_hat
;
2012 t
= remainder
[nPos
];
2013 remainder
[nPos
] -= (uint)mc
;
2015 if (remainder
[nPos
] > t
) mc
++;
2017 } while (dPos
< divisorLen
);
2019 nPos
= pos
- divisorLen
+ 1;
2028 sum
= ((ulong)remainder
[nPos
]) + ((ulong)bi2
.data
[dPos
]) + sum
;
2029 remainder
[nPos
] = (uint)sum
;
2032 } while (dPos
< divisorLen
);
2036 quot
.data
[resultPos
--] = (uint)uint_q_hat
;
2044 BigInteger
[] ret
= new BigInteger
[2] { quot, rem }
;
2057 public static BigInteger
LeftShift (BigInteger bi
, int n
)
2059 if (n
== 0) return new BigInteger (bi
, bi
.length
+ 1);
2062 n
&= ((1 << 5) - 1);
2064 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
+ 1 + (uint)w
);
2066 uint i
= 0, l
= bi
.length
;
2071 ret
.data
[i
+ w
] = (x
<< n
) | carry
;
2072 carry
= x
>> (32 - n
);
2075 ret
.data
[i
+ w
] = carry
;
2078 ret
.data
[i
+ w
] = bi
.data
[i
];
2087 public static BigInteger
RightShift (BigInteger bi
, int n
)
2089 if (n
== 0) return new BigInteger (bi
);
2092 int s
= n
& ((1 << 5) - 1);
2094 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
- (uint)w
+ 1);
2095 uint l
= (uint)ret
.data
.Length
- 1;
2102 x
= bi
.data
[l
+ w
];
2103 ret
.data
[l
] = (x
>> n
) | carry
;
2104 carry
= x
<< (32 - n
);
2108 ret
.data
[l
] = bi
.data
[l
+ w
];
2119 public static BigInteger
MultiplyByDword (BigInteger n
, uint f
)
2121 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
+ 1);
2127 c
+= (ulong)n
.data
[i
] * (ulong)f
;
2128 ret
.data
[i
] = (uint)c
;
2130 } while (++i
< n
.length
);
2131 ret
.data
[i
] = (uint)c
;
2138 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2139 /// y [yOffset:yOffset+yLen] and puts it into
2140 /// d [dOffset:dOffset+xLen+yLen].
2143 /// This code is unsafe! It is the caller's responsibility to make
2144 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2145 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
2147 public static unsafe void Multiply (uint [] x
, uint xOffset
, uint xLen
, uint [] y
, uint yOffset
, uint yLen
, uint [] d
, uint dOffset
)
2149 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2150 uint* xP
= xx
+ xOffset
,
2156 for (; xP
< xE
; xP
++, dB
++) {
2158 if (*xP
== 0) continue;
2163 for (uint* yP
= yB
; yP
< yE
; yP
++, dP
++) {
2164 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2177 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2178 /// y [yOffset:yOffset+yLen] and puts the low mod words into
2179 /// d [dOffset:dOffset+mod].
2182 /// This code is unsafe! It is the caller's responsibility to make
2183 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2184 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
2186 public static unsafe void MultiplyMod2p32pmod (uint [] x
, int xOffset
, int xLen
, uint [] y
, int yOffest
, int yLen
, uint [] d
, int dOffset
, int mod
)
2188 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2189 uint* xP
= xx
+ xOffset
,
2196 for (; xP
< xE
; xP
++, dB
++) {
2198 if (*xP
== 0) continue;
2202 for (uint* yP
= yB
; yP
< yE
&& dP
< dE
; yP
++, dP
++) {
2203 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2209 if (mcarry
!= 0 && dP
< dE
)
2215 public static unsafe void SquarePositive (BigInteger bi
, ref uint [] wkSpace
)
2217 uint [] t
= wkSpace
;
2219 uint [] d
= bi
.data
;
2220 uint dl
= bi
.length
;
2223 fixed (uint* dd
= d
, tt
= t
) {
2225 uint* ttE
= tt
+ t
.Length
;
2227 for (uint* ttt
= tt
; ttt
< ttE
; ttt
++)
2230 uint* dP
= dd
, tP
= tt
;
2232 for (uint i
= 0; i
< dl
; i
++, dP
++) {
2239 uint* dP2
= dP
+ 1, tP2
= tP
+ 2*i
+ 1;
2241 for (uint j
= i
+ 1; j
< dl
; j
++, tP2
++, dP2
++) {
2243 mcarry
+= ((ulong)bi1val
* (ulong)*dP2
) + *tP2
;
2245 *tP2
= (uint)mcarry
;
2250 *tP2
= (uint)mcarry
;
2253 // Double t. Inlined for speed.
2260 *tP
= (x
<< 1) | carry
;
2261 carry
= x
>> (32 - 1);
2264 if (carry
!= 0) *tP
= carry
;
2266 // Add in the diagnals
2270 for (uint* dE
= dP
+ dl
; (dP
< dE
); dP
++, tP
++) {
2271 ulong val
= (ulong)*dP
* (ulong)*dP
+ *tP
;
2274 *(++tP
) += (uint)val
;
2275 if (*tP
< (uint)val
) {
2277 // Account for the first carry
2280 // Keep adding until no carry
2281 while ((*tP3
++) == 0)
2290 while (tt
[bi
.length
-1] == 0 && bi
.length
> 1) bi
.length
--;
2296 * Never called in BigInteger (and part of a private class)
2297 * public static bool Double (uint [] u, int l)
2303 u [i] = (x << 1) | carry;
2304 carry = x >> (32 - 1);
2307 if (carry != 0) u [l] = carry;
2313 #region Number Theory
2315 public static BigInteger
gcd (BigInteger a
, BigInteger b
)
2322 while (x
.length
> 1) {
2328 if (x
== 0) return g
;
2330 // TODO: should we have something here if we can convert to long?
2333 // Now we can just do it with single precision. I am using the binary gcd method,
2334 // as it should be faster.
2337 uint yy
= x
.data
[0];
2342 while (((xx
| yy
) & 1) == 0) {
2343 xx
>>= 1; yy
>>= 1; t
++;
2346 while ((xx
& 1) == 0) xx
>>= 1;
2347 while ((yy
& 1) == 0) yy
>>= 1;
2349 xx
= (xx
- yy
) >> 1;
2351 yy
= (yy
- xx
) >> 1;
2357 public static uint modInverse (BigInteger bi
, uint modulus
)
2359 uint a
= modulus
, b
= bi
% modulus
;
2360 uint p0
= 0, p1
= 1;
2380 public static BigInteger
modInverse (BigInteger bi
, BigInteger modulus
)
2382 if (modulus
.length
== 1) return modInverse (bi
, modulus
.data
[0]);
2384 BigInteger
[] p
= { 0, 1 }
;
2385 BigInteger
[] q
= new BigInteger
[2]; // quotients
2386 BigInteger
[] r
= { 0, 0 }
; // remainders
2390 BigInteger a
= modulus
;
2393 ModulusRing mr
= new ModulusRing (modulus
);
2399 BigInteger pval
= mr
.Difference (p
[0], p
[1] * q
[0]);
2400 p
[0] = p
[1]; p
[1] = pval
;
2403 BigInteger
[] divret
= multiByteDivide (a
, b
);
2405 q
[0] = q
[1]; q
[1] = divret
[0];
2406 r
[0] = r
[1]; r
[1] = divret
[1];
2414 throw (new ArithmeticException ("No inverse!"));
2416 return mr
.Difference (p
[0], p
[1] * q
[0]);