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.
16 // Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 using System
.Security
.Cryptography
;
40 using Mono
.Math
.Prime
.Generator
;
41 using Mono
.Math
.Prime
;
55 /// The Length of this BigInteger
60 /// The data for this BigInteger
69 /// Default length of a BigInteger in bytes
71 const uint DEFAULT_LEN
= 20;
74 /// Table of primes below 2000.
78 /// This table was generated using Mathematica 4.1 using the following function:
82 /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
87 internal static readonly uint [] smallPrimes
= {
88 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
89 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
90 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
91 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
92 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
93 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
94 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
95 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
96 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
97 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
98 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
100 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
101 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
102 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
103 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
104 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
105 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
106 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
107 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
108 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
109 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
110 1979, 1987, 1993, 1997, 1999,
112 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
113 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
114 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
115 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
116 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
117 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
118 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
119 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
120 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
121 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
123 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
124 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
125 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
126 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
127 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
128 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
129 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
130 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
131 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
134 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
135 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
136 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
137 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
138 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
139 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
140 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
141 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
142 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
145 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
146 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
147 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
148 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
149 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
150 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
151 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
152 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
153 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
156 public enum Sign
: int {
162 #region Exception Messages
163 const string WouldReturnNegVal
= "Operation would return a negative value";
172 data
= new uint [DEFAULT_LEN
];
173 this.length
= DEFAULT_LEN
;
177 [CLSCompliant (false)]
179 public BigInteger (Sign sign
, uint len
)
181 this.data
= new uint [len
];
185 public BigInteger (BigInteger bi
)
187 this.data
= (uint [])bi
.data
.Clone ();
188 this.length
= bi
.length
;
192 [CLSCompliant (false)]
194 public BigInteger (BigInteger bi
, uint len
)
197 this.data
= new uint [len
];
199 for (uint i
= 0; i
< bi
.length
; i
++)
200 this.data
[i
] = bi
.data
[i
];
202 this.length
= bi
.length
;
209 public BigInteger (byte [] inData
)
211 if (inData
.Length
== 0)
212 inData
= new byte [1];
213 length
= (uint)inData
.Length
>> 2;
214 int leftOver
= inData
.Length
& 0x3;
216 // length not multiples of 4
217 if (leftOver
!= 0) length
++;
219 data
= new uint [length
];
221 for (int i
= inData
.Length
- 1, j
= 0; i
>= 3; i
-= 4, j
++) {
223 (inData
[i
-3] << (3*8)) |
224 (inData
[i
-2] << (2*8)) |
225 (inData
[i
-1] << (1*8)) |
231 case 1: data
[length
-1] = (uint)inData
[0]; break;
232 case 2: data
[length
-1] = (uint)((inData
[0] << 8) | inData
[1]); break;
233 case 3: data
[length
-1] = (uint)((inData
[0] << 16) | (inData
[1] << 8) | inData
[2]); break;
240 [CLSCompliant (false)]
242 public BigInteger (uint [] inData
)
244 if (inData
.Length
== 0)
245 inData
= new uint [1];
246 length
= (uint)inData
.Length
;
248 data
= new uint [length
];
250 for (int i
= (int)length
- 1, j
= 0; i
>= 0; i
--, j
++)
251 data
[j
] = inData
[i
];
257 [CLSCompliant (false)]
259 public BigInteger (uint ui
)
261 data
= new uint [] {ui}
;
265 [CLSCompliant (false)]
267 public BigInteger (ulong ul
)
269 data
= new uint [2] { (uint)ul, (uint)(ul >> 32)}
;
276 [CLSCompliant (false)]
278 public static implicit operator BigInteger (uint value)
280 return (new BigInteger (value));
283 public static implicit operator BigInteger (int value)
285 if (value < 0) throw new ArgumentOutOfRangeException ("value");
286 return (new BigInteger ((uint)value));
290 [CLSCompliant (false)]
292 public static implicit operator BigInteger (ulong value)
294 return (new BigInteger (value));
297 /* This is the BigInteger.Parse method I use. This method works
298 because BigInteger.ToString returns the input I gave to Parse. */
299 public static BigInteger
Parse (string number
)
302 throw new ArgumentNullException ("number");
304 int i
= 0, len
= number
.Length
;
306 bool digits_seen
= false;
307 BigInteger val
= new BigInteger (0);
308 if (number
[i
] == '+') {
311 else if (number
[i
] == '-') {
312 throw new FormatException (WouldReturnNegVal
);
315 for (; i
< len
; i
++) {
321 if (c
>= '0' && c
<= '9') {
322 val
= val
* 10 + (c
- '0');
326 if (Char
.IsWhiteSpace (c
)) {
327 for (i
++; i
< len
; i
++) {
328 if (!Char
.IsWhiteSpace (number
[i
]))
329 throw new FormatException ();
334 throw new FormatException ();
338 throw new FormatException ();
346 public static BigInteger
operator + (BigInteger bi1
, BigInteger bi2
)
349 return new BigInteger (bi2
);
351 return new BigInteger (bi1
);
353 return Kernel
.AddSameSign (bi1
, bi2
);
356 public static BigInteger
operator - (BigInteger bi1
, BigInteger bi2
)
359 return new BigInteger (bi1
);
362 throw new ArithmeticException (WouldReturnNegVal
);
364 switch (Kernel
.Compare (bi1
, bi2
)) {
370 return Kernel
.Subtract (bi1
, bi2
);
373 throw new ArithmeticException (WouldReturnNegVal
);
375 throw new Exception ();
379 public static int operator % (BigInteger bi
, int i
)
382 return (int)Kernel
.DwordMod (bi
, (uint)i
);
384 return -(int)Kernel
.DwordMod (bi
, (uint)-i
);
388 [CLSCompliant (false)]
390 public static uint operator % (BigInteger bi
, uint ui
)
392 return Kernel
.DwordMod (bi
, (uint)ui
);
395 public static BigInteger
operator % (BigInteger bi1
, BigInteger bi2
)
397 return Kernel
.multiByteDivide (bi1
, bi2
)[1];
400 public static BigInteger
operator / (BigInteger bi
, int i
)
403 return Kernel
.DwordDiv (bi
, (uint)i
);
405 throw new ArithmeticException (WouldReturnNegVal
);
408 public static BigInteger
operator / (BigInteger bi1
, BigInteger bi2
)
410 return Kernel
.multiByteDivide (bi1
, bi2
)[0];
413 public static BigInteger
operator * (BigInteger bi1
, BigInteger bi2
)
415 if (bi1
== 0 || bi2
== 0) return 0;
420 if (bi1
.data
.Length
< bi1
.length
) throw new IndexOutOfRangeException ("bi1 out of range");
421 if (bi2
.data
.Length
< bi2
.length
) throw new IndexOutOfRangeException ("bi2 out of range");
423 BigInteger ret
= new BigInteger (Sign
.Positive
, bi1
.length
+ bi2
.length
);
425 Kernel
.Multiply (bi1
.data
, 0, bi1
.length
, bi2
.data
, 0, bi2
.length
, ret
.data
, 0);
431 public static BigInteger
operator * (BigInteger bi
, int i
)
433 if (i
< 0) throw new ArithmeticException (WouldReturnNegVal
);
434 if (i
== 0) return 0;
435 if (i
== 1) return new BigInteger (bi
);
437 return Kernel
.MultiplyByDword (bi
, (uint)i
);
440 public static BigInteger
operator << (BigInteger bi1
, int shiftVal
)
442 return Kernel
.LeftShift (bi1
, shiftVal
);
445 public static BigInteger
operator >> (BigInteger bi1
, int shiftVal
)
447 return Kernel
.RightShift (bi1
, shiftVal
);
452 #region Friendly names for operators
454 // with names suggested by FxCop 1.30
456 public static BigInteger
Add (BigInteger bi1
, BigInteger bi2
)
461 public static BigInteger
Subtract (BigInteger bi1
, BigInteger bi2
)
466 public static int Modulus (BigInteger bi
, int i
)
472 [CLSCompliant (false)]
474 public static uint Modulus (BigInteger bi
, uint ui
)
479 public static BigInteger
Modulus (BigInteger bi1
, BigInteger bi2
)
484 public static BigInteger
Divid (BigInteger bi
, int i
)
489 public static BigInteger
Divid (BigInteger bi1
, BigInteger bi2
)
494 public static BigInteger
Multiply (BigInteger bi1
, BigInteger bi2
)
499 public static BigInteger
Multiply (BigInteger bi
, int i
)
507 private static RandomNumberGenerator rng
;
508 private static RandomNumberGenerator Rng
{
511 rng
= RandomNumberGenerator
.Create ();
517 /// Generates a new, random BigInteger of the specified length.
519 /// <param name="bits">The number of bits for the new number.</param>
520 /// <param name="rng">A random number generator to use to obtain the bits.</param>
521 /// <returns>A random number of the specified length.</returns>
522 public static BigInteger
GenerateRandom (int bits
, RandomNumberGenerator rng
)
524 int dwords
= bits
>> 5;
525 int remBits
= bits
& 0x1F;
530 BigInteger ret
= new BigInteger (Sign
.Positive
, (uint)dwords
+ 1);
531 byte [] random
= new byte [dwords
<< 2];
533 rng
.GetBytes (random
);
534 Buffer
.BlockCopy (random
, 0, ret
.data
, 0, (int)dwords
<< 2);
537 uint mask
= (uint)(0x01 << (remBits
-1));
538 ret
.data
[dwords
-1] |= mask
;
540 mask
= (uint)(0xFFFFFFFF >> (32 - remBits
));
541 ret
.data
[dwords
-1] &= mask
;
544 ret
.data
[dwords
-1] |= 0x80000000;
551 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
553 /// <param name="bits">The number of bits for the new number.</param>
554 /// <returns>A random number of the specified length.</returns>
555 public static BigInteger
GenerateRandom (int bits
)
557 return GenerateRandom (bits
, Rng
);
561 /// Randomizes the bits in "this" from the specified RNG.
563 /// <param name="rng">A RNG.</param>
564 public void Randomize (RandomNumberGenerator rng
)
569 int bits
= this.BitCount ();
570 int dwords
= bits
>> 5;
571 int remBits
= bits
& 0x1F;
576 byte [] random
= new byte [dwords
<< 2];
578 rng
.GetBytes (random
);
579 Buffer
.BlockCopy (random
, 0, data
, 0, (int)dwords
<< 2);
582 uint mask
= (uint)(0x01 << (remBits
-1));
583 data
[dwords
-1] |= mask
;
585 mask
= (uint)(0xFFFFFFFF >> (32 - remBits
));
586 data
[dwords
-1] &= mask
;
590 data
[dwords
-1] |= 0x80000000;
596 /// Randomizes the bits in "this" from the default RNG.
598 public void Randomize ()
607 public int BitCount ()
611 uint value = data
[length
- 1];
612 uint mask
= 0x80000000;
615 while (bits
> 0 && (value & mask
) == 0) {
619 bits
+= ((length
- 1) << 5);
625 /// Tests if the specified bit is 1.
627 /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
628 /// <returns>True if bitNum is set to 1, else false.</returns>
630 [CLSCompliant (false)]
632 public bool TestBit (uint bitNum
)
634 uint bytePos
= bitNum
>> 5; // divide by 32
635 byte bitPos
= (byte)(bitNum
& 0x1F); // get the lowest 5 bits
637 uint mask
= (uint)1 << bitPos
;
638 return ((this.data
[bytePos
] & mask
) != 0);
641 public bool TestBit (int bitNum
)
643 if (bitNum
< 0) throw new IndexOutOfRangeException ("bitNum out of range");
645 uint bytePos
= (uint)bitNum
>> 5; // divide by 32
646 byte bitPos
= (byte)(bitNum
& 0x1F); // get the lowest 5 bits
648 uint mask
= (uint)1 << bitPos
;
649 return ((this.data
[bytePos
] | mask
) == this.data
[bytePos
]);
653 [CLSCompliant (false)]
655 public void SetBit (uint bitNum
)
657 SetBit (bitNum
, true);
661 [CLSCompliant (false)]
663 public void ClearBit (uint bitNum
)
665 SetBit (bitNum
, false);
669 [CLSCompliant (false)]
671 public void SetBit (uint bitNum
, bool value)
673 uint bytePos
= bitNum
>> 5; // divide by 32
675 if (bytePos
< this.length
) {
676 uint mask
= (uint)1 << (int)(bitNum
& 0x1F);
678 this.data
[bytePos
] |= mask
;
680 this.data
[bytePos
] &= ~mask
;
684 public int LowestSetBit ()
686 if (this == 0) return -1;
688 while (!TestBit (i
)) i
++;
692 public byte[] GetBytes ()
694 if (this == 0) return new byte [1];
696 int numBits
= BitCount ();
697 int numBytes
= numBits
>> 3;
698 if ((numBits
& 0x7) != 0)
701 byte [] result
= new byte [numBytes
];
703 int numBytesInWord
= numBytes
& 0x3;
704 if (numBytesInWord
== 0) numBytesInWord
= 4;
707 for (int i
= (int)length
- 1; i
>= 0; i
--) {
709 for (int j
= numBytesInWord
- 1; j
>= 0; j
--) {
710 result
[pos
+j
] = (byte)(val
& 0xFF);
713 pos
+= numBytesInWord
;
724 [CLSCompliant (false)]
726 public static bool operator == (BigInteger bi1
, uint ui
)
728 if (bi1
.length
!= 1) bi1
.Normalize ();
729 return bi1
.length
== 1 && bi1
.data
[0] == ui
;
733 [CLSCompliant (false)]
735 public static bool operator != (BigInteger bi1
, uint ui
)
737 if (bi1
.length
!= 1) bi1
.Normalize ();
738 return !(bi1
.length
== 1 && bi1
.data
[0] == ui
);
741 public static bool operator == (BigInteger bi1
, BigInteger bi2
)
743 // we need to compare with null
744 if ((bi1
as object) == (bi2
as object))
746 if (null == bi1
|| null == bi2
)
748 return Kernel
.Compare (bi1
, bi2
) == 0;
751 public static bool operator != (BigInteger bi1
, BigInteger bi2
)
753 // we need to compare with null
754 if ((bi1
as object) == (bi2
as object))
756 if (null == bi1
|| null == bi2
)
758 return Kernel
.Compare (bi1
, bi2
) != 0;
761 public static bool operator > (BigInteger bi1
, BigInteger bi2
)
763 return Kernel
.Compare (bi1
, bi2
) > 0;
766 public static bool operator < (BigInteger bi1
, BigInteger bi2
)
768 return Kernel
.Compare (bi1
, bi2
) < 0;
771 public static bool operator >= (BigInteger bi1
, BigInteger bi2
)
773 return Kernel
.Compare (bi1
, bi2
) >= 0;
776 public static bool operator <= (BigInteger bi1
, BigInteger bi2
)
778 return Kernel
.Compare (bi1
, bi2
) <= 0;
781 public Sign
Compare (BigInteger bi
)
783 return Kernel
.Compare (this, bi
);
791 [CLSCompliant (false)]
793 public string ToString (uint radix
)
795 return ToString (radix
, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
799 [CLSCompliant (false)]
801 public string ToString (uint radix
, string characterSet
)
803 if (characterSet
.Length
< radix
)
804 throw new ArgumentException ("charSet length less than radix", "characterSet");
806 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
808 if (this == 0) return "0";
809 if (this == 1) return "1";
813 BigInteger a
= new BigInteger (this);
816 uint rem
= Kernel
.SingleByteDivideInPlace (a
, radix
);
817 result
= characterSet
[(int) rem
] + result
;
828 /// Normalizes this by setting the length to the actual number of
829 /// uints used in data and by setting the sign to Sign.Zero if the
830 /// value of this is 0.
832 private void Normalize ()
835 while (length
> 0 && data
[length
-1] == 0) length
--;
844 for (int i
=0; i
< length
; i
++)
852 public override int GetHashCode ()
856 for (uint i
= 0; i
< this.length
; i
++)
857 val ^
= this.data
[i
];
862 public override string ToString ()
864 return ToString (10);
867 public override bool Equals (object o
)
872 return (int)o
>= 0 && this == (uint)o
;
874 BigInteger bi
= o
as BigInteger
;
878 return Kernel
.Compare (this, bi
) == 0;
883 #region Number Theory
885 public BigInteger
GCD (BigInteger bi
)
887 return Kernel
.gcd (this, bi
);
890 public BigInteger
ModInverse (BigInteger modulus
)
892 return Kernel
.modInverse (this, modulus
);
895 public BigInteger
ModPow (BigInteger exp
, BigInteger n
)
897 ModulusRing mr
= new ModulusRing (n
);
898 return mr
.Pow (this, exp
);
903 #region Prime Testing
905 public bool IsProbablePrime ()
907 // can we use our small-prime table ?
908 if (this <= smallPrimes
[smallPrimes
.Length
- 1]) {
909 for (int p
= 0; p
< smallPrimes
.Length
; p
++) {
910 if (this == smallPrimes
[p
])
913 // the list is complete, so it's not a prime
917 // otherwise check if we can divide by one of the small primes
918 for (int p
= 0; p
< smallPrimes
.Length
; p
++) {
919 if (this % smallPrimes
[p
] == 0)
922 // the last step is to confirm the "large" prime with the SPP or Miller-Rabin test
923 return PrimalityTests
.Test (this, Prime
.ConfidenceFactor
.Medium
);
928 #region Prime Number Generation
931 /// Generates the smallest prime >= bi
933 /// <param name="bi">A BigInteger</param>
934 /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
935 public static BigInteger
NextHighestPrime (BigInteger bi
)
937 NextPrimeFinder npf
= new NextPrimeFinder ();
938 return npf
.GenerateNewPrime (0, bi
);
941 public static BigInteger
GeneratePseudoPrime (int bits
)
943 SequentialSearchPrimeGeneratorBase sspg
= new SequentialSearchPrimeGeneratorBase ();
944 return sspg
.GenerateNewPrime (bits
);
948 /// Increments this by two
956 // If there was no carry, nothing to do
959 // Account for the first carry
962 // Keep adding until no carry
963 while (data
[i
++] == 0x0)
966 // See if we increased the data length
967 if (length
== (uint)i
)
979 sealed class ModulusRing
{
981 BigInteger mod
, constant
;
983 public ModulusRing (BigInteger modulus
)
987 // calculate constant = b^ (2k) / m
988 uint i
= mod
.length
<< 1;
990 constant
= new BigInteger (Sign
.Positive
, i
+ 1);
991 constant
.data
[i
] = 0x00000001;
993 constant
= constant
/ mod
;
996 public void BarrettReduction (BigInteger x
)
1003 // x < mod, so nothing to do.
1004 if (x
.length
< k
) return;
1009 // Validate pointers
1011 if (x
.data
.Length
< x
.length
) throw new IndexOutOfRangeException ("x out of range");
1013 // q1 = x / b^ (k-1)
1014 // q2 = q1 * constant
1015 // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
1017 // TODO: We should the method in HAC p 604 to do this (14.45)
1018 q3
= new BigInteger (Sign
.Positive
, x
.length
- kMinusOne
+ constant
.length
);
1019 Kernel
.Multiply (x
.data
, kMinusOne
, x
.length
- kMinusOne
, constant
.data
, 0, constant
.length
, q3
.data
, 0);
1021 // r1 = x mod b^ (k+1)
1022 // i.e. keep the lowest (k+1) words
1024 uint lengthToCopy
= (x
.length
> kPlusOne
) ? kPlusOne
: x
.length
;
1026 x
.length
= lengthToCopy
;
1029 // r2 = (q3 * n) mod b^ (k+1)
1030 // partial multiplication of q3 and n
1032 BigInteger r2
= new BigInteger (Sign
.Positive
, kPlusOne
);
1033 Kernel
.MultiplyMod2p32pmod (q3
.data
, (int)kPlusOne
, (int)q3
.length
- (int)kPlusOne
, n
.data
, 0, (int)n
.length
, r2
.data
, 0, (int)kPlusOne
);
1038 Kernel
.MinusEq (x
, r2
);
1040 BigInteger val
= new BigInteger (Sign
.Positive
, kPlusOne
+ 1);
1041 val
.data
[kPlusOne
] = 0x00000001;
1043 Kernel
.MinusEq (val
, r2
);
1044 Kernel
.PlusEq (x
, val
);
1048 Kernel
.MinusEq (x
, n
);
1051 public BigInteger
Multiply (BigInteger a
, BigInteger b
)
1053 if (a
== 0 || b
== 0) return 0;
1061 BigInteger ret
= a
* b
;
1062 BarrettReduction (ret
);
1067 public BigInteger
Difference (BigInteger a
, BigInteger b
)
1069 Sign cmp
= Kernel
.Compare (a
, b
);
1076 diff
= a
- b
; break;
1078 diff
= b
- a
; break;
1080 throw new Exception ();
1084 if (diff
.length
>= mod
.length
<< 1)
1087 BarrettReduction (diff
);
1089 if (cmp
== Sign
.Negative
)
1094 public BigInteger
Pow (BigInteger a
, BigInteger k
)
1096 BigInteger b
= new BigInteger (1);
1104 for (int i
= 1; i
< k
.BitCount (); i
++) {
1105 A
= Multiply (A
, A
);
1107 b
= Multiply (A
, b
);
1112 public BigInteger
Pow (BigInteger b
, BigInteger exp
)
1114 if ((mod
.data
[0] & 1) == 1) return OddPow (b
, exp
);
1115 else return EvenPow (b
, exp
);
1118 public BigInteger
EvenPow (BigInteger b
, BigInteger exp
)
1120 BigInteger resultNum
= new BigInteger ((BigInteger
)1, mod
.length
<< 1);
1121 BigInteger tempNum
= new BigInteger (b
% mod
, mod
.length
<< 1); // ensures (tempNum * tempNum) < b^ (2k)
1123 uint totalBits
= (uint)exp
.BitCount ();
1125 uint [] wkspace
= new uint [mod
.length
<< 1];
1127 // perform squaring and multiply exponentiation
1128 for (uint pos
= 0; pos
< totalBits
; pos
++) {
1129 if (exp
.TestBit (pos
)) {
1131 Array
.Clear (wkspace
, 0, wkspace
.Length
);
1132 Kernel
.Multiply (resultNum
.data
, 0, resultNum
.length
, tempNum
.data
, 0, tempNum
.length
, wkspace
, 0);
1133 resultNum
.length
+= tempNum
.length
;
1134 uint [] t
= wkspace
;
1135 wkspace
= resultNum
.data
;
1138 BarrettReduction (resultNum
);
1141 Kernel
.SquarePositive (tempNum
, ref wkspace
);
1142 BarrettReduction (tempNum
);
1152 private BigInteger
OddPow (BigInteger b
, BigInteger exp
)
1154 BigInteger resultNum
= new BigInteger (Montgomery
.ToMont (1, mod
), mod
.length
<< 1);
1155 BigInteger tempNum
= new BigInteger (Montgomery
.ToMont (b
, mod
), mod
.length
<< 1); // ensures (tempNum * tempNum) < b^ (2k)
1156 uint mPrime
= Montgomery
.Inverse (mod
.data
[0]);
1157 uint totalBits
= (uint)exp
.BitCount ();
1159 uint [] wkspace
= new uint [mod
.length
<< 1];
1161 // perform squaring and multiply exponentiation
1162 for (uint pos
= 0; pos
< totalBits
; pos
++) {
1163 if (exp
.TestBit (pos
)) {
1165 Array
.Clear (wkspace
, 0, wkspace
.Length
);
1166 Kernel
.Multiply (resultNum
.data
, 0, resultNum
.length
, tempNum
.data
, 0, tempNum
.length
, wkspace
, 0);
1167 resultNum
.length
+= tempNum
.length
;
1168 uint [] t
= wkspace
;
1169 wkspace
= resultNum
.data
;
1172 Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1175 // the value of tempNum is required in the last loop
1176 if (pos
< totalBits
- 1) {
1177 Kernel
.SquarePositive (tempNum
, ref wkspace
);
1178 Montgomery
.Reduce (tempNum
, mod
, mPrime
);
1182 Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1186 #region Pow Small Base
1188 // TODO: Make tests for this, not really needed b/c prime stuff
1189 // checks it, but still would be nice
1191 [CLSCompliant (false)]
1194 public BigInteger
Pow (uint b
, BigInteger exp
)
1196 return Pow (new BigInteger (b
), exp
);
1199 public BigInteger
Pow (uint b
, BigInteger exp
)
1202 if ((mod
.data
[0] & 1) == 1)
1203 return OddPow (b
, exp
);
1205 return EvenPow (b
, exp
);
1206 /* buggy in some cases (like the well tested primes)
1208 if ((mod.data [0] & 1) == 1)
1209 return OddModTwoPow (exp);
1211 return EvenModTwoPow (exp);
1215 private unsafe BigInteger
OddPow (uint b
, BigInteger exp
)
1218 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1220 BigInteger resultNum
= Montgomery
.ToMont ((BigInteger
)b
, this.mod
);
1221 resultNum
= new BigInteger (resultNum
, mod
.length
<< 1 +1);
1223 uint mPrime
= Montgomery
.Inverse (mod
.data
[0]);
1225 int bc
= exp
.BitCount () - 2;
1226 uint pos
= (bc
> 1 ? (uint) bc
: 1);
1229 // We know that the first itr will make the val b
1236 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1237 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1239 if (exp
.TestBit (pos
)) {
1245 // TODO: Is Unsafe really speeding things up?
1246 fixed (uint* u
= resultNum
.data
) {
1252 mc
+= (ulong)u
[i
] * (ulong)b
;
1255 } while (++i
< resultNum
.length
);
1257 if (resultNum
.length
< mod
.length
) {
1261 while (resultNum
>= mod
)
1262 Kernel
.MinusEq (resultNum
, mod
);
1264 } else if (mc
!= 0) {
1267 // First, we estimate the quotient by dividing
1268 // the first part of each of the numbers. Then
1269 // we correct this, if necessary, with a subtraction.
1274 // We would rather have this estimate overshoot,
1275 // so we add one to the divisor
1277 if (mod
.data
[mod
.length
- 1] < UInt32
.MaxValue
) {
1278 divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1279 (mod
.data
[mod
.length
-1] + 1));
1282 // guess but don't divide by 0
1283 divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1284 (mod
.data
[mod
.length
-1]));
1292 mc
+= (ulong)mod
.data
[i
] * (ulong)divEstimate
;
1296 if (u
[i
] > t
) mc
++;
1298 } while (i
< resultNum
.length
);
1304 uint [] s
= mod
.data
;
1307 if (((a
+= sc
) < sc
) | ((u
[j
] -= a
) > ~a
)) sc
= 1;
1310 } while (j
< resultNum
.length
);
1313 while (resultNum
>= mod
)
1314 Kernel
.MinusEq (resultNum
, mod
);
1316 while (resultNum
>= mod
)
1317 Kernel
.MinusEq (resultNum
, mod
);
1321 } while (pos
-- > 0);
1323 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1328 private unsafe BigInteger
EvenPow (uint b
, BigInteger exp
)
1331 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1332 BigInteger resultNum
= new BigInteger ((BigInteger
)b
, mod
.length
<< 1 + 1);
1334 uint pos
= (uint)exp
.BitCount () - 2;
1337 // We know that the first itr will make the val b
1344 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1345 if (!(resultNum
.length
< mod
.length
))
1346 BarrettReduction (resultNum
);
1348 if (exp
.TestBit (pos
)) {
1354 // TODO: Is Unsafe really speeding things up?
1355 fixed (uint* u
= resultNum
.data
) {
1361 mc
+= (ulong)u
[i
] * (ulong)b
;
1364 } while (++i
< resultNum
.length
);
1366 if (resultNum
.length
< mod
.length
) {
1370 while (resultNum
>= mod
)
1371 Kernel
.MinusEq (resultNum
, mod
);
1373 } else if (mc
!= 0) {
1376 // First, we estimate the quotient by dividing
1377 // the first part of each of the numbers. Then
1378 // we correct this, if necessary, with a subtraction.
1383 // We would rather have this estimate overshoot,
1384 // so we add one to the divisor
1385 uint divEstimate
= (uint) ((((ulong)cc
<< 32) | (ulong) u
[i
-1]) /
1386 (mod
.data
[mod
.length
-1] + 1));
1393 mc
+= (ulong)mod
.data
[i
] * (ulong)divEstimate
;
1397 if (u
[i
] > t
) mc
++;
1399 } while (i
< resultNum
.length
);
1405 uint [] s
= mod
.data
;
1408 if (((a
+= sc
) < sc
) | ((u
[j
] -= a
) > ~a
)) sc
= 1;
1411 } while (j
< resultNum
.length
);
1414 while (resultNum
>= mod
)
1415 Kernel
.MinusEq (resultNum
, mod
);
1417 while (resultNum
>= mod
)
1418 Kernel
.MinusEq (resultNum
, mod
);
1422 } while (pos
-- > 0);
1427 /* known to be buggy in some cases */
1429 private unsafe BigInteger
EvenModTwoPow (BigInteger exp
)
1432 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1434 BigInteger resultNum
= new BigInteger (2, mod
.length
<< 1 +1);
1436 uint value = exp
.data
[exp
.length
- 1];
1437 uint mask
= 0x80000000;
1439 // Find the first bit of the exponent
1440 while ((value & mask
) == 0)
1444 // We know that the first itr will make the val 2,
1445 // so eat one bit of the exponent
1449 uint wPos
= exp
.length
- 1;
1452 value = exp
.data
[wPos
];
1454 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1455 if (resultNum
.length
>= mod
.length
)
1456 BarrettReduction (resultNum
);
1458 if ((value & mask
) != 0) {
1460 // resultNum = (resultNum * 2) % mod
1463 fixed (uint* u
= resultNum
.data
) {
1468 uint* uuE
= u
+ resultNum
.length
;
1472 *uu
= (x
<< 1) | carry
;
1473 carry
= x
>> (32 - 1);
1477 // subtraction inlined because we know it is square
1478 if (carry
!= 0 || resultNum
>= mod
) {
1481 uint [] s
= mod
.data
;
1485 if (((a
+= c
) < c
) | ((* (uu
++) -= a
) > ~a
))
1494 } while ((mask
>>= 1) > 0);
1496 } while (wPos
-- > 0);
1501 private unsafe BigInteger
OddModTwoPow (BigInteger exp
)
1504 uint [] wkspace
= new uint [mod
.length
<< 1 + 1];
1506 BigInteger resultNum
= Montgomery
.ToMont ((BigInteger
)2, this.mod
);
1507 resultNum
= new BigInteger (resultNum
, mod
.length
<< 1 +1);
1509 uint mPrime
= Montgomery
.Inverse (mod
.data
[0]);
1512 // TODO: eat small bits, the ones we can do with no modular reduction
1514 uint pos
= (uint)exp
.BitCount () - 2;
1517 Kernel
.SquarePositive (resultNum
, ref wkspace
);
1518 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1520 if (exp
.TestBit (pos
)) {
1522 // resultNum = (resultNum * 2) % mod
1525 fixed (uint* u
= resultNum
.data
) {
1530 uint* uuE
= u
+ resultNum
.length
;
1534 *uu
= (x
<< 1) | carry
;
1535 carry
= x
>> (32 - 1);
1539 // subtraction inlined because we know it is square
1540 if (carry
!= 0 || resultNum
>= mod
) {
1541 fixed (uint* s
= mod
.data
) {
1547 if (((a
+= c
) < c
) | ((* (uu
++) -= a
) > ~a
))
1556 } while (pos
-- > 0);
1558 resultNum
= Montgomery
.Reduce (resultNum
, mod
, mPrime
);
1565 internal sealed class Montgomery
{
1567 private Montgomery ()
1571 public static uint Inverse (uint n
)
1575 while ((z
= n
* y
) != 1)
1581 public static BigInteger
ToMont (BigInteger n
, BigInteger m
)
1583 n
.Normalize (); m
.Normalize ();
1585 n
<<= (int)m
.length
* 32;
1590 public static unsafe BigInteger
Reduce (BigInteger n
, BigInteger m
, uint mPrime
)
1593 fixed (uint* a
= A
.data
, mm
= m
.data
) {
1594 for (uint i
= 0; i
< m
.length
; i
++) {
1595 // The mod here is taken care of by the CPU,
1596 // since the multiply will overflow.
1597 uint u_i
= a
[0] * mPrime
/* % 2^32 */;
1604 // mP = Position in mod
1605 // aSP = the source of bits from a
1606 // aDP = destination for bits
1607 uint* mP
= mm
, aSP
= a
, aDP
= a
;
1609 ulong c
= (ulong)u_i
* ((ulong)*(mP
++)) + *(aSP
++);
1614 for (; j
< m
.length
; j
++) {
1615 c
+= (ulong)u_i
* (ulong)*(mP
++) + *(aSP
++);
1620 // Account for carry
1621 // TODO: use a better loop here, we dont need the ulong stuff
1622 for (; j
< A
.length
; j
++) {
1626 if (c
== 0) {j++; break;}
1629 for (; j
< A
.length
; j
++) {
1630 *(aDP
++) = *(aSP
++);
1636 while (A
.length
> 1 && a
[A
.length
-1] == 0) A
.length
--;
1639 if (A
>= m
) Kernel
.MinusEq (A
, m
);
1644 public static BigInteger
Reduce (BigInteger n
, BigInteger m
)
1646 return Reduce (n
, m
, Inverse (m
.data
[0]));
1652 /// Low level functions for the BigInteger
1654 private sealed class Kernel
{
1656 #region Addition/Subtraction
1659 /// Adds two numbers with the same sign.
1661 /// <param name="bi1">A BigInteger</param>
1662 /// <param name="bi2">A BigInteger</param>
1663 /// <returns>bi1 + bi2</returns>
1664 public static BigInteger
AddSameSign (BigInteger bi1
, BigInteger bi2
)
1667 uint yMax
, xMax
, i
= 0;
1669 // x should be bigger
1670 if (bi1
.length
< bi2
.length
) {
1682 BigInteger result
= new BigInteger (Sign
.Positive
, xMax
+ 1);
1684 uint [] r
= result
.data
;
1688 // Add common parts of both numbers
1690 sum
= ((ulong)x
[i
]) + ((ulong)y
[i
]) + sum
;
1693 } while (++i
< yMax
);
1695 // Copy remainder of longer number while carry propagation is required
1696 bool carry
= (sum
!= 0);
1702 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1703 while (++i
< xMax
&& carry
);
1708 result
.length
= ++i
;
1720 result
.Normalize ();
1724 public static BigInteger
Subtract (BigInteger big
, BigInteger small
)
1726 BigInteger result
= new BigInteger (Sign
.Positive
, big
.length
);
1728 uint [] r
= result
.data
, b
= big
.data
, s
= small
.data
;
1734 if (((x
+= c
) < c
) | ((r
[i
] = b
[i
] - x
) > ~x
))
1739 } while (++i
< small
.length
);
1741 if (i
== big
.length
) goto fixup
;
1746 while (b
[i
++] == 0 && i
< big
.length
);
1748 if (i
== big
.length
) goto fixup
;
1753 while (++i
< big
.length
);
1757 result
.Normalize ();
1761 public static void MinusEq (BigInteger big
, BigInteger small
)
1763 uint [] b
= big
.data
, s
= small
.data
;
1768 if (((x
+= c
) < c
) | ((b
[i
] -= x
) > ~x
))
1772 } while (++i
< small
.length
);
1774 if (i
== big
.length
) goto fixup
;
1779 while (b
[i
++] == 0 && i
< big
.length
);
1785 while (big
.length
> 0 && big
.data
[big
.length
-1] == 0) big
.length
--;
1788 if (big
.length
== 0)
1793 public static void PlusEq (BigInteger bi1
, BigInteger bi2
)
1796 uint yMax
, xMax
, i
= 0;
1799 // x should be bigger
1800 if (bi1
.length
< bi2
.length
){
1813 uint [] r
= bi1
.data
;
1817 // Add common parts of both numbers
1819 sum
+= ((ulong)x
[i
]) + ((ulong)y
[i
]);
1822 } while (++i
< yMax
);
1824 // Copy remainder of longer number while carry propagation is required
1825 bool carry
= (sum
!= 0);
1831 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1832 while (++i
< xMax
&& carry
);
1843 if (flag
&& i
< xMax
- 1) {
1849 bi1
.length
= xMax
+ 1;
1858 /// Compares two BigInteger
1860 /// <param name="bi1">A BigInteger</param>
1861 /// <param name="bi2">A BigInteger</param>
1862 /// <returns>The sign of bi1 - bi2</returns>
1863 public static Sign
Compare (BigInteger bi1
, BigInteger bi2
)
1866 // Step 1. Compare the lengths
1868 uint l1
= bi1
.length
, l2
= bi2
.length
;
1870 while (l1
> 0 && bi1
.data
[l1
-1] == 0) l1
--;
1871 while (l2
> 0 && bi2
.data
[l2
-1] == 0) l2
--;
1873 if (l1
== 0 && l2
== 0) return Sign
.Zero
;
1875 // bi1 len < bi2 len
1876 if (l1
< l2
) return Sign
.Negative
;
1877 // bi1 len > bi2 len
1878 else if (l1
> l2
) return Sign
.Positive
;
1881 // Step 2. Compare the bits
1886 while (pos
!= 0 && bi1
.data
[pos
] == bi2
.data
[pos
]) pos
--;
1888 if (bi1
.data
[pos
] < bi2
.data
[pos
])
1889 return Sign
.Negative
;
1890 else if (bi1
.data
[pos
] > bi2
.data
[pos
])
1891 return Sign
.Positive
;
1903 /// Performs n / d and n % d in one operation.
1905 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1906 /// <param name="d">The divisor</param>
1907 /// <returns>n % d</returns>
1908 public static uint SingleByteDivideInPlace (BigInteger n
, uint d
)
1916 n
.data
[i
] = (uint)(r
/ d
);
1924 public static uint DwordMod (BigInteger n
, uint d
)
1938 public static BigInteger
DwordDiv (BigInteger n
, uint d
)
1940 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1948 ret
.data
[i
] = (uint)(r
/ d
);
1956 public static BigInteger
[] DwordDivMod (BigInteger n
, uint d
)
1958 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1966 ret
.data
[i
] = (uint)(r
/ d
);
1971 BigInteger rem
= (uint)r
;
1973 return new BigInteger
[] {ret, rem}
;
1980 public static BigInteger
[] multiByteDivide (BigInteger bi1
, BigInteger bi2
)
1982 if (Kernel
.Compare (bi1
, bi2
) == Sign
.Negative
)
1983 return new BigInteger
[2] { 0, new BigInteger (bi1) }
;
1985 bi1
.Normalize (); bi2
.Normalize ();
1987 if (bi2
.length
== 1)
1988 return DwordDivMod (bi1
, bi2
.data
[0]);
1990 uint remainderLen
= bi1
.length
+ 1;
1991 int divisorLen
= (int)bi2
.length
+ 1;
1993 uint mask
= 0x80000000;
1994 uint val
= bi2
.data
[bi2
.length
- 1];
1996 int resultPos
= (int)bi1
.length
- (int)bi2
.length
;
1998 while (mask
!= 0 && (val
& mask
) == 0) {
1999 shift
++; mask
>>= 1;
2002 BigInteger quot
= new BigInteger (Sign
.Positive
, bi1
.length
- bi2
.length
+ 1);
2003 BigInteger rem
= (bi1
<< shift
);
2005 uint [] remainder
= rem
.data
;
2009 int j
= (int)(remainderLen
- bi2
.length
);
2010 int pos
= (int)remainderLen
- 1;
2012 uint firstDivisorByte
= bi2
.data
[bi2
.length
-1];
2013 ulong secondDivisorByte
= bi2
.data
[bi2
.length
-2];
2016 ulong dividend
= ((ulong)remainder
[pos
] << 32) + (ulong)remainder
[pos
-1];
2018 ulong q_hat
= dividend
/ (ulong)firstDivisorByte
;
2019 ulong r_hat
= dividend
% (ulong)firstDivisorByte
;
2023 if (q_hat
== 0x100000000 ||
2024 (q_hat
* secondDivisorByte
) > ((r_hat
<< 32) + remainder
[pos
-2])) {
2026 r_hat
+= (ulong)firstDivisorByte
;
2028 if (r_hat
< 0x100000000)
2035 // At this point, q_hat is either exact, or one too large
2036 // (more likely to be exact) so, we attempt to multiply the
2037 // divisor by q_hat, if we get a borrow, we just subtract
2038 // one from q_hat and add the divisor back.
2043 int nPos
= pos
- divisorLen
+ 1;
2045 uint uint_q_hat
= (uint)q_hat
;
2047 mc
+= (ulong)bi2
.data
[dPos
] * (ulong)uint_q_hat
;
2048 t
= remainder
[nPos
];
2049 remainder
[nPos
] -= (uint)mc
;
2051 if (remainder
[nPos
] > t
) mc
++;
2053 } while (dPos
< divisorLen
);
2055 nPos
= pos
- divisorLen
+ 1;
2064 sum
= ((ulong)remainder
[nPos
]) + ((ulong)bi2
.data
[dPos
]) + sum
;
2065 remainder
[nPos
] = (uint)sum
;
2068 } while (dPos
< divisorLen
);
2072 quot
.data
[resultPos
--] = (uint)uint_q_hat
;
2080 BigInteger
[] ret
= new BigInteger
[2] { quot, rem }
;
2093 public static BigInteger
LeftShift (BigInteger bi
, int n
)
2095 if (n
== 0) return new BigInteger (bi
, bi
.length
+ 1);
2098 n
&= ((1 << 5) - 1);
2100 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
+ 1 + (uint)w
);
2102 uint i
= 0, l
= bi
.length
;
2107 ret
.data
[i
+ w
] = (x
<< n
) | carry
;
2108 carry
= x
>> (32 - n
);
2111 ret
.data
[i
+ w
] = carry
;
2114 ret
.data
[i
+ w
] = bi
.data
[i
];
2123 public static BigInteger
RightShift (BigInteger bi
, int n
)
2125 if (n
== 0) return new BigInteger (bi
);
2128 int s
= n
& ((1 << 5) - 1);
2130 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
- (uint)w
+ 1);
2131 uint l
= (uint)ret
.data
.Length
- 1;
2138 x
= bi
.data
[l
+ w
];
2139 ret
.data
[l
] = (x
>> n
) | carry
;
2140 carry
= x
<< (32 - n
);
2144 ret
.data
[l
] = bi
.data
[l
+ w
];
2155 public static BigInteger
MultiplyByDword (BigInteger n
, uint f
)
2157 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
+ 1);
2163 c
+= (ulong)n
.data
[i
] * (ulong)f
;
2164 ret
.data
[i
] = (uint)c
;
2166 } while (++i
< n
.length
);
2167 ret
.data
[i
] = (uint)c
;
2174 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2175 /// y [yOffset:yOffset+yLen] and puts it into
2176 /// d [dOffset:dOffset+xLen+yLen].
2179 /// This code is unsafe! It is the caller's responsibility to make
2180 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2181 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
2183 public static unsafe void Multiply (uint [] x
, uint xOffset
, uint xLen
, uint [] y
, uint yOffset
, uint yLen
, uint [] d
, uint dOffset
)
2185 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2186 uint* xP
= xx
+ xOffset
,
2192 for (; xP
< xE
; xP
++, dB
++) {
2194 if (*xP
== 0) continue;
2199 for (uint* yP
= yB
; yP
< yE
; yP
++, dP
++) {
2200 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2213 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2214 /// y [yOffset:yOffset+yLen] and puts the low mod words into
2215 /// d [dOffset:dOffset+mod].
2218 /// This code is unsafe! It is the caller's responsibility to make
2219 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2220 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
2222 public static unsafe void MultiplyMod2p32pmod (uint [] x
, int xOffset
, int xLen
, uint [] y
, int yOffest
, int yLen
, uint [] d
, int dOffset
, int mod
)
2224 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2225 uint* xP
= xx
+ xOffset
,
2232 for (; xP
< xE
; xP
++, dB
++) {
2234 if (*xP
== 0) continue;
2238 for (uint* yP
= yB
; yP
< yE
&& dP
< dE
; yP
++, dP
++) {
2239 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2245 if (mcarry
!= 0 && dP
< dE
)
2251 public static unsafe void SquarePositive (BigInteger bi
, ref uint [] wkSpace
)
2253 uint [] t
= wkSpace
;
2255 uint [] d
= bi
.data
;
2256 uint dl
= bi
.length
;
2259 fixed (uint* dd
= d
, tt
= t
) {
2261 uint* ttE
= tt
+ t
.Length
;
2263 for (uint* ttt
= tt
; ttt
< ttE
; ttt
++)
2266 uint* dP
= dd
, tP
= tt
;
2268 for (uint i
= 0; i
< dl
; i
++, dP
++) {
2275 uint* dP2
= dP
+ 1, tP2
= tP
+ 2*i
+ 1;
2277 for (uint j
= i
+ 1; j
< dl
; j
++, tP2
++, dP2
++) {
2279 mcarry
+= ((ulong)bi1val
* (ulong)*dP2
) + *tP2
;
2281 *tP2
= (uint)mcarry
;
2286 *tP2
= (uint)mcarry
;
2289 // Double t. Inlined for speed.
2296 *tP
= (x
<< 1) | carry
;
2297 carry
= x
>> (32 - 1);
2300 if (carry
!= 0) *tP
= carry
;
2302 // Add in the diagnals
2306 for (uint* dE
= dP
+ dl
; (dP
< dE
); dP
++, tP
++) {
2307 ulong val
= (ulong)*dP
* (ulong)*dP
+ *tP
;
2310 *(++tP
) += (uint)val
;
2311 if (*tP
< (uint)val
) {
2313 // Account for the first carry
2316 // Keep adding until no carry
2317 while ((*tP3
++) == 0)
2326 while (tt
[bi
.length
-1] == 0 && bi
.length
> 1) bi
.length
--;
2332 * Never called in BigInteger (and part of a private class)
2333 * public static bool Double (uint [] u, int l)
2339 u [i] = (x << 1) | carry;
2340 carry = x >> (32 - 1);
2343 if (carry != 0) u [l] = carry;
2349 #region Number Theory
2351 public static BigInteger
gcd (BigInteger a
, BigInteger b
)
2358 while (x
.length
> 1) {
2364 if (x
== 0) return g
;
2366 // TODO: should we have something here if we can convert to long?
2369 // Now we can just do it with single precision. I am using the binary gcd method,
2370 // as it should be faster.
2373 uint yy
= x
.data
[0];
2378 while (((xx
| yy
) & 1) == 0) {
2379 xx
>>= 1; yy
>>= 1; t
++;
2382 while ((xx
& 1) == 0) xx
>>= 1;
2383 while ((yy
& 1) == 0) yy
>>= 1;
2385 xx
= (xx
- yy
) >> 1;
2387 yy
= (yy
- xx
) >> 1;
2393 public static uint modInverse (BigInteger bi
, uint modulus
)
2395 uint a
= modulus
, b
= bi
% modulus
;
2396 uint p0
= 0, p1
= 1;
2416 public static BigInteger
modInverse (BigInteger bi
, BigInteger modulus
)
2418 if (modulus
.length
== 1) return modInverse (bi
, modulus
.data
[0]);
2420 BigInteger
[] p
= { 0, 1 }
;
2421 BigInteger
[] q
= new BigInteger
[2]; // quotients
2422 BigInteger
[] r
= { 0, 0 }
; // remainders
2426 BigInteger a
= modulus
;
2429 ModulusRing mr
= new ModulusRing (modulus
);
2435 BigInteger pval
= mr
.Difference (p
[0], p
[1] * q
[0]);
2436 p
[0] = p
[1]; p
[1] = pval
;
2439 BigInteger
[] divret
= multiByteDivide (a
, b
);
2441 q
[0] = q
[1]; q
[1] = divret
[0];
2442 r
[0] = r
[1]; r
[1] = divret
[1];
2450 throw (new ArithmeticException ("No inverse!"));
2452 return mr
.Difference (p
[0], p
[1] * q
[0]);