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
);
1566 /// Low level functions for the BigInteger
1568 private sealed class Kernel
{
1570 #region Addition/Subtraction
1573 /// Adds two numbers with the same sign.
1575 /// <param name="bi1">A BigInteger</param>
1576 /// <param name="bi2">A BigInteger</param>
1577 /// <returns>bi1 + bi2</returns>
1578 public static BigInteger
AddSameSign (BigInteger bi1
, BigInteger bi2
)
1581 uint yMax
, xMax
, i
= 0;
1583 // x should be bigger
1584 if (bi1
.length
< bi2
.length
) {
1596 BigInteger result
= new BigInteger (Sign
.Positive
, xMax
+ 1);
1598 uint [] r
= result
.data
;
1602 // Add common parts of both numbers
1604 sum
= ((ulong)x
[i
]) + ((ulong)y
[i
]) + sum
;
1607 } while (++i
< yMax
);
1609 // Copy remainder of longer number while carry propagation is required
1610 bool carry
= (sum
!= 0);
1616 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1617 while (++i
< xMax
&& carry
);
1622 result
.length
= ++i
;
1634 result
.Normalize ();
1638 public static BigInteger
Subtract (BigInteger big
, BigInteger small
)
1640 BigInteger result
= new BigInteger (Sign
.Positive
, big
.length
);
1642 uint [] r
= result
.data
, b
= big
.data
, s
= small
.data
;
1648 if (((x
+= c
) < c
) | ((r
[i
] = b
[i
] - x
) > ~x
))
1653 } while (++i
< small
.length
);
1655 if (i
== big
.length
) goto fixup
;
1660 while (b
[i
++] == 0 && i
< big
.length
);
1662 if (i
== big
.length
) goto fixup
;
1667 while (++i
< big
.length
);
1671 result
.Normalize ();
1675 public static void MinusEq (BigInteger big
, BigInteger small
)
1677 uint [] b
= big
.data
, s
= small
.data
;
1682 if (((x
+= c
) < c
) | ((b
[i
] -= x
) > ~x
))
1686 } while (++i
< small
.length
);
1688 if (i
== big
.length
) goto fixup
;
1693 while (b
[i
++] == 0 && i
< big
.length
);
1699 while (big
.length
> 0 && big
.data
[big
.length
-1] == 0) big
.length
--;
1702 if (big
.length
== 0)
1707 public static void PlusEq (BigInteger bi1
, BigInteger bi2
)
1710 uint yMax
, xMax
, i
= 0;
1713 // x should be bigger
1714 if (bi1
.length
< bi2
.length
){
1727 uint [] r
= bi1
.data
;
1731 // Add common parts of both numbers
1733 sum
+= ((ulong)x
[i
]) + ((ulong)y
[i
]);
1736 } while (++i
< yMax
);
1738 // Copy remainder of longer number while carry propagation is required
1739 bool carry
= (sum
!= 0);
1745 carry
= ((r
[i
] = x
[i
] + 1) == 0);
1746 while (++i
< xMax
&& carry
);
1757 if (flag
&& i
< xMax
- 1) {
1763 bi1
.length
= xMax
+ 1;
1772 /// Compares two BigInteger
1774 /// <param name="bi1">A BigInteger</param>
1775 /// <param name="bi2">A BigInteger</param>
1776 /// <returns>The sign of bi1 - bi2</returns>
1777 public static Sign
Compare (BigInteger bi1
, BigInteger bi2
)
1780 // Step 1. Compare the lengths
1782 uint l1
= bi1
.length
, l2
= bi2
.length
;
1784 while (l1
> 0 && bi1
.data
[l1
-1] == 0) l1
--;
1785 while (l2
> 0 && bi2
.data
[l2
-1] == 0) l2
--;
1787 if (l1
== 0 && l2
== 0) return Sign
.Zero
;
1789 // bi1 len < bi2 len
1790 if (l1
< l2
) return Sign
.Negative
;
1791 // bi1 len > bi2 len
1792 else if (l1
> l2
) return Sign
.Positive
;
1795 // Step 2. Compare the bits
1800 while (pos
!= 0 && bi1
.data
[pos
] == bi2
.data
[pos
]) pos
--;
1802 if (bi1
.data
[pos
] < bi2
.data
[pos
])
1803 return Sign
.Negative
;
1804 else if (bi1
.data
[pos
] > bi2
.data
[pos
])
1805 return Sign
.Positive
;
1817 /// Performs n / d and n % d in one operation.
1819 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1820 /// <param name="d">The divisor</param>
1821 /// <returns>n % d</returns>
1822 public static uint SingleByteDivideInPlace (BigInteger n
, uint d
)
1830 n
.data
[i
] = (uint)(r
/ d
);
1838 public static uint DwordMod (BigInteger n
, uint d
)
1852 public static BigInteger
DwordDiv (BigInteger n
, uint d
)
1854 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1862 ret
.data
[i
] = (uint)(r
/ d
);
1870 public static BigInteger
[] DwordDivMod (BigInteger n
, uint d
)
1872 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
);
1880 ret
.data
[i
] = (uint)(r
/ d
);
1885 BigInteger rem
= (uint)r
;
1887 return new BigInteger
[] {ret, rem}
;
1894 public static BigInteger
[] multiByteDivide (BigInteger bi1
, BigInteger bi2
)
1896 if (Kernel
.Compare (bi1
, bi2
) == Sign
.Negative
)
1897 return new BigInteger
[2] { 0, new BigInteger (bi1) }
;
1899 bi1
.Normalize (); bi2
.Normalize ();
1901 if (bi2
.length
== 1)
1902 return DwordDivMod (bi1
, bi2
.data
[0]);
1904 uint remainderLen
= bi1
.length
+ 1;
1905 int divisorLen
= (int)bi2
.length
+ 1;
1907 uint mask
= 0x80000000;
1908 uint val
= bi2
.data
[bi2
.length
- 1];
1910 int resultPos
= (int)bi1
.length
- (int)bi2
.length
;
1912 while (mask
!= 0 && (val
& mask
) == 0) {
1913 shift
++; mask
>>= 1;
1916 BigInteger quot
= new BigInteger (Sign
.Positive
, bi1
.length
- bi2
.length
+ 1);
1917 BigInteger rem
= (bi1
<< shift
);
1919 uint [] remainder
= rem
.data
;
1923 int j
= (int)(remainderLen
- bi2
.length
);
1924 int pos
= (int)remainderLen
- 1;
1926 uint firstDivisorByte
= bi2
.data
[bi2
.length
-1];
1927 ulong secondDivisorByte
= bi2
.data
[bi2
.length
-2];
1930 ulong dividend
= ((ulong)remainder
[pos
] << 32) + (ulong)remainder
[pos
-1];
1932 ulong q_hat
= dividend
/ (ulong)firstDivisorByte
;
1933 ulong r_hat
= dividend
% (ulong)firstDivisorByte
;
1937 if (q_hat
== 0x100000000 ||
1938 (q_hat
* secondDivisorByte
) > ((r_hat
<< 32) + remainder
[pos
-2])) {
1940 r_hat
+= (ulong)firstDivisorByte
;
1942 if (r_hat
< 0x100000000)
1949 // At this point, q_hat is either exact, or one too large
1950 // (more likely to be exact) so, we attempt to multiply the
1951 // divisor by q_hat, if we get a borrow, we just subtract
1952 // one from q_hat and add the divisor back.
1957 int nPos
= pos
- divisorLen
+ 1;
1959 uint uint_q_hat
= (uint)q_hat
;
1961 mc
+= (ulong)bi2
.data
[dPos
] * (ulong)uint_q_hat
;
1962 t
= remainder
[nPos
];
1963 remainder
[nPos
] -= (uint)mc
;
1965 if (remainder
[nPos
] > t
) mc
++;
1967 } while (dPos
< divisorLen
);
1969 nPos
= pos
- divisorLen
+ 1;
1978 sum
= ((ulong)remainder
[nPos
]) + ((ulong)bi2
.data
[dPos
]) + sum
;
1979 remainder
[nPos
] = (uint)sum
;
1982 } while (dPos
< divisorLen
);
1986 quot
.data
[resultPos
--] = (uint)uint_q_hat
;
1994 BigInteger
[] ret
= new BigInteger
[2] { quot, rem }
;
2007 public static BigInteger
LeftShift (BigInteger bi
, int n
)
2009 if (n
== 0) return new BigInteger (bi
, bi
.length
+ 1);
2012 n
&= ((1 << 5) - 1);
2014 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
+ 1 + (uint)w
);
2016 uint i
= 0, l
= bi
.length
;
2021 ret
.data
[i
+ w
] = (x
<< n
) | carry
;
2022 carry
= x
>> (32 - n
);
2025 ret
.data
[i
+ w
] = carry
;
2028 ret
.data
[i
+ w
] = bi
.data
[i
];
2037 public static BigInteger
RightShift (BigInteger bi
, int n
)
2039 if (n
== 0) return new BigInteger (bi
);
2042 int s
= n
& ((1 << 5) - 1);
2044 BigInteger ret
= new BigInteger (Sign
.Positive
, bi
.length
- (uint)w
+ 1);
2045 uint l
= (uint)ret
.data
.Length
- 1;
2052 x
= bi
.data
[l
+ w
];
2053 ret
.data
[l
] = (x
>> n
) | carry
;
2054 carry
= x
<< (32 - n
);
2058 ret
.data
[l
] = bi
.data
[l
+ w
];
2069 public static BigInteger
MultiplyByDword (BigInteger n
, uint f
)
2071 BigInteger ret
= new BigInteger (Sign
.Positive
, n
.length
+ 1);
2077 c
+= (ulong)n
.data
[i
] * (ulong)f
;
2078 ret
.data
[i
] = (uint)c
;
2080 } while (++i
< n
.length
);
2081 ret
.data
[i
] = (uint)c
;
2088 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2089 /// y [yOffset:yOffset+yLen] and puts it into
2090 /// d [dOffset:dOffset+xLen+yLen].
2093 /// This code is unsafe! It is the caller's responsibility to make
2094 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2095 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
2097 public static unsafe void Multiply (uint [] x
, uint xOffset
, uint xLen
, uint [] y
, uint yOffset
, uint yLen
, uint [] d
, uint dOffset
)
2099 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2100 uint* xP
= xx
+ xOffset
,
2106 for (; xP
< xE
; xP
++, dB
++) {
2108 if (*xP
== 0) continue;
2113 for (uint* yP
= yB
; yP
< yE
; yP
++, dP
++) {
2114 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2127 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2128 /// y [yOffset:yOffset+yLen] and puts the low mod words into
2129 /// d [dOffset:dOffset+mod].
2132 /// This code is unsafe! It is the caller's responsibility to make
2133 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2134 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
2136 public static unsafe void MultiplyMod2p32pmod (uint [] x
, int xOffset
, int xLen
, uint [] y
, int yOffest
, int yLen
, uint [] d
, int dOffset
, int mod
)
2138 fixed (uint* xx
= x
, yy
= y
, dd
= d
) {
2139 uint* xP
= xx
+ xOffset
,
2146 for (; xP
< xE
; xP
++, dB
++) {
2148 if (*xP
== 0) continue;
2152 for (uint* yP
= yB
; yP
< yE
&& dP
< dE
; yP
++, dP
++) {
2153 mcarry
+= ((ulong)*xP
* (ulong)*yP
) + (ulong)*dP
;
2159 if (mcarry
!= 0 && dP
< dE
)
2165 public static unsafe void SquarePositive (BigInteger bi
, ref uint [] wkSpace
)
2167 uint [] t
= wkSpace
;
2169 uint [] d
= bi
.data
;
2170 uint dl
= bi
.length
;
2173 fixed (uint* dd
= d
, tt
= t
) {
2175 uint* ttE
= tt
+ t
.Length
;
2177 for (uint* ttt
= tt
; ttt
< ttE
; ttt
++)
2180 uint* dP
= dd
, tP
= tt
;
2182 for (uint i
= 0; i
< dl
; i
++, dP
++) {
2189 uint* dP2
= dP
+ 1, tP2
= tP
+ 2*i
+ 1;
2191 for (uint j
= i
+ 1; j
< dl
; j
++, tP2
++, dP2
++) {
2193 mcarry
+= ((ulong)bi1val
* (ulong)*dP2
) + *tP2
;
2195 *tP2
= (uint)mcarry
;
2200 *tP2
= (uint)mcarry
;
2203 // Double t. Inlined for speed.
2210 *tP
= (x
<< 1) | carry
;
2211 carry
= x
>> (32 - 1);
2214 if (carry
!= 0) *tP
= carry
;
2216 // Add in the diagnals
2220 for (uint* dE
= dP
+ dl
; (dP
< dE
); dP
++, tP
++) {
2221 ulong val
= (ulong)*dP
* (ulong)*dP
+ *tP
;
2224 *(++tP
) += (uint)val
;
2225 if (*tP
< (uint)val
) {
2227 // Account for the first carry
2230 // Keep adding until no carry
2231 while ((*tP3
++) == 0)
2240 while (tt
[bi
.length
-1] == 0 && bi
.length
> 1) bi
.length
--;
2246 * Never called in BigInteger (and part of a private class)
2247 * public static bool Double (uint [] u, int l)
2253 u [i] = (x << 1) | carry;
2254 carry = x >> (32 - 1);
2257 if (carry != 0) u [l] = carry;
2263 #region Number Theory
2265 public static BigInteger
gcd (BigInteger a
, BigInteger b
)
2272 while (x
.length
> 1) {
2278 if (x
== 0) return g
;
2280 // TODO: should we have something here if we can convert to long?
2283 // Now we can just do it with single precision. I am using the binary gcd method,
2284 // as it should be faster.
2287 uint yy
= x
.data
[0];
2292 while (((xx
| yy
) & 1) == 0) {
2293 xx
>>= 1; yy
>>= 1; t
++;
2296 while ((xx
& 1) == 0) xx
>>= 1;
2297 while ((yy
& 1) == 0) yy
>>= 1;
2299 xx
= (xx
- yy
) >> 1;
2301 yy
= (yy
- xx
) >> 1;
2307 public static uint modInverse (BigInteger bi
, uint modulus
)
2309 uint a
= modulus
, b
= bi
% modulus
;
2310 uint p0
= 0, p1
= 1;
2330 public static BigInteger
modInverse (BigInteger bi
, BigInteger modulus
)
2332 if (modulus
.length
== 1) return modInverse (bi
, modulus
.data
[0]);
2334 BigInteger
[] p
= { 0, 1 }
;
2335 BigInteger
[] q
= new BigInteger
[2]; // quotients
2336 BigInteger
[] r
= { 0, 0 }
; // remainders
2340 BigInteger a
= modulus
;
2343 ModulusRing mr
= new ModulusRing (modulus
);
2349 BigInteger pval
= mr
.Difference (p
[0], p
[1] * q
[0]);
2350 p
[0] = p
[1]; p
[1] = pval
;
2353 BigInteger
[] divret
= multiByteDivide (a
, b
);
2355 q
[0] = q
[1]; q
[1] = divret
[0];
2356 r
[0] = r
[1]; r
[1] = divret
[1];
2364 throw (new ArithmeticException ("No inverse!"));
2366 return mr
.Difference (p
[0], p
[1] * q
[0]);