2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Mono.Security / Mono.Math / BigInteger.cs
blobc4bb85b04daf8ddf117795fb0548fed9bcb0648e
1 //
2 // BigInteger.cs - Big Integer implementation
3 //
4 // Authors:
5 // Ben Maurer
6 // Chew Keong TAN
7 // Sebastien Pouliot <sebastien@ximian.com>
8 // Pieter Philippaerts <Pieter@mentalis.org>
9 //
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:
25 //
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
28 //
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.
38 using System;
39 using System.Security.Cryptography;
40 using Mono.Math.Prime.Generator;
41 using Mono.Math.Prime;
43 namespace Mono.Math {
45 #if INSIDE_CORLIB
46 internal
47 #else
48 public
49 #endif
50 class BigInteger {
52 #region Data Storage
54 /// <summary>
55 /// The Length of this BigInteger
56 /// </summary>
57 uint length = 1;
59 /// <summary>
60 /// The data for this BigInteger
61 /// </summary>
62 uint [] data;
64 #endregion
66 #region Constants
68 /// <summary>
69 /// Default length of a BigInteger in bytes
70 /// </summary>
71 const uint DEFAULT_LEN = 20;
73 /// <summary>
74 /// Table of primes below 2000.
75 /// </summary>
76 /// <remarks>
77 /// <para>
78 /// This table was generated using Mathematica 4.1 using the following function:
79 /// </para>
80 /// <para>
81 /// <code>
82 /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
83 /// PrimeTable [6000]
84 /// </code>
85 /// </para>
86 /// </remarks>
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,
132 3947, 3967, 3989,
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,
143 4993, 4999,
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 {
157 Negative = -1,
158 Zero = 0,
159 Positive = 1
162 #region Exception Messages
163 const string WouldReturnNegVal = "Operation would return a negative value";
164 #endregion
166 #endregion
168 #region Constructors
170 public BigInteger ()
172 data = new uint [DEFAULT_LEN];
173 this.length = DEFAULT_LEN;
176 #if !INSIDE_CORLIB
177 [CLSCompliant (false)]
178 #endif
179 public BigInteger (Sign sign, uint len)
181 this.data = new uint [len];
182 this.length = len;
185 public BigInteger (BigInteger bi)
187 this.data = (uint [])bi.data.Clone ();
188 this.length = bi.length;
191 #if !INSIDE_CORLIB
192 [CLSCompliant (false)]
193 #endif
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;
205 #endregion
207 #region Conversions
209 public BigInteger (byte [] inData)
211 length = (uint)inData.Length >> 2;
212 int leftOver = inData.Length & 0x3;
214 // length not multiples of 4
215 if (leftOver != 0) length++;
217 data = new uint [length];
219 for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++) {
220 data [j] = (uint)(
221 (inData [i-3] << (3*8)) |
222 (inData [i-2] << (2*8)) |
223 (inData [i-1] << (1*8)) |
224 (inData [i])
228 switch (leftOver) {
229 case 1: data [length-1] = (uint)inData [0]; break;
230 case 2: data [length-1] = (uint)((inData [0] << 8) | inData [1]); break;
231 case 3: data [length-1] = (uint)((inData [0] << 16) | (inData [1] << 8) | inData [2]); break;
234 this.Normalize ();
237 #if !INSIDE_CORLIB
238 [CLSCompliant (false)]
239 #endif
240 public BigInteger (uint [] inData)
242 length = (uint)inData.Length;
244 data = new uint [length];
246 for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
247 data [j] = inData [i];
249 this.Normalize ();
252 #if !INSIDE_CORLIB
253 [CLSCompliant (false)]
254 #endif
255 public BigInteger (uint ui)
257 data = new uint [] {ui};
260 #if !INSIDE_CORLIB
261 [CLSCompliant (false)]
262 #endif
263 public BigInteger (ulong ul)
265 data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
266 length = 2;
268 this.Normalize ();
271 #if !INSIDE_CORLIB
272 [CLSCompliant (false)]
273 #endif
274 public static implicit operator BigInteger (uint value)
276 return (new BigInteger (value));
279 public static implicit operator BigInteger (int value)
281 if (value < 0) throw new ArgumentOutOfRangeException ("value");
282 return (new BigInteger ((uint)value));
285 #if !INSIDE_CORLIB
286 [CLSCompliant (false)]
287 #endif
288 public static implicit operator BigInteger (ulong value)
290 return (new BigInteger (value));
293 /* This is the BigInteger.Parse method I use. This method works
294 because BigInteger.ToString returns the input I gave to Parse. */
295 public static BigInteger Parse (string number)
297 if (number == null)
298 throw new ArgumentNullException ("number");
300 int i = 0, len = number.Length;
301 char c;
302 bool digits_seen = false;
303 BigInteger val = new BigInteger (0);
304 if (number [i] == '+') {
305 i++;
307 else if (number [i] == '-') {
308 throw new FormatException (WouldReturnNegVal);
311 for (; i < len; i++) {
312 c = number [i];
313 if (c == '\0') {
314 i = len;
315 continue;
317 if (c >= '0' && c <= '9') {
318 val = val * 10 + (c - '0');
319 digits_seen = true;
321 else {
322 if (Char.IsWhiteSpace (c)) {
323 for (i++; i < len; i++) {
324 if (!Char.IsWhiteSpace (number [i]))
325 throw new FormatException ();
327 break;
329 else
330 throw new FormatException ();
333 if (!digits_seen)
334 throw new FormatException ();
335 return val;
338 #endregion
340 #region Operators
342 public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
344 if (bi1 == 0)
345 return new BigInteger (bi2);
346 else if (bi2 == 0)
347 return new BigInteger (bi1);
348 else
349 return Kernel.AddSameSign (bi1, bi2);
352 public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
354 if (bi2 == 0)
355 return new BigInteger (bi1);
357 if (bi1 == 0)
358 throw new ArithmeticException (WouldReturnNegVal);
360 switch (Kernel.Compare (bi1, bi2)) {
362 case Sign.Zero:
363 return 0;
365 case Sign.Positive:
366 return Kernel.Subtract (bi1, bi2);
368 case Sign.Negative:
369 throw new ArithmeticException (WouldReturnNegVal);
370 default:
371 throw new Exception ();
375 public static int operator % (BigInteger bi, int i)
377 if (i > 0)
378 return (int)Kernel.DwordMod (bi, (uint)i);
379 else
380 return -(int)Kernel.DwordMod (bi, (uint)-i);
383 #if !INSIDE_CORLIB
384 [CLSCompliant (false)]
385 #endif
386 public static uint operator % (BigInteger bi, uint ui)
388 return Kernel.DwordMod (bi, (uint)ui);
391 public static BigInteger operator % (BigInteger bi1, BigInteger bi2)
393 return Kernel.multiByteDivide (bi1, bi2)[1];
396 public static BigInteger operator / (BigInteger bi, int i)
398 if (i > 0)
399 return Kernel.DwordDiv (bi, (uint)i);
401 throw new ArithmeticException (WouldReturnNegVal);
404 public static BigInteger operator / (BigInteger bi1, BigInteger bi2)
406 return Kernel.multiByteDivide (bi1, bi2)[0];
409 public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
411 if (bi1 == 0 || bi2 == 0) return 0;
414 // Validate pointers
416 if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
417 if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");
419 BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);
421 Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
423 ret.Normalize ();
424 return ret;
427 public static BigInteger operator * (BigInteger bi, int i)
429 if (i < 0) throw new ArithmeticException (WouldReturnNegVal);
430 if (i == 0) return 0;
431 if (i == 1) return new BigInteger (bi);
433 return Kernel.MultiplyByDword (bi, (uint)i);
436 public static BigInteger operator << (BigInteger bi1, int shiftVal)
438 return Kernel.LeftShift (bi1, shiftVal);
441 public static BigInteger operator >> (BigInteger bi1, int shiftVal)
443 return Kernel.RightShift (bi1, shiftVal);
446 #endregion
448 #region Friendly names for operators
450 // with names suggested by FxCop 1.30
452 public static BigInteger Add (BigInteger bi1, BigInteger bi2)
454 return (bi1 + bi2);
457 public static BigInteger Subtract (BigInteger bi1, BigInteger bi2)
459 return (bi1 - bi2);
462 public static int Modulus (BigInteger bi, int i)
464 return (bi % i);
467 #if !INSIDE_CORLIB
468 [CLSCompliant (false)]
469 #endif
470 public static uint Modulus (BigInteger bi, uint ui)
472 return (bi % ui);
475 public static BigInteger Modulus (BigInteger bi1, BigInteger bi2)
477 return (bi1 % bi2);
480 public static BigInteger Divid (BigInteger bi, int i)
482 return (bi / i);
485 public static BigInteger Divid (BigInteger bi1, BigInteger bi2)
487 return (bi1 / bi2);
490 public static BigInteger Multiply (BigInteger bi1, BigInteger bi2)
492 return (bi1 * bi2);
495 public static BigInteger Multiply (BigInteger bi, int i)
497 return (bi * i);
500 #endregion
502 #region Random
503 private static RandomNumberGenerator rng;
504 private static RandomNumberGenerator Rng {
505 get {
506 if (rng == null)
507 rng = RandomNumberGenerator.Create ();
508 return rng;
512 /// <summary>
513 /// Generates a new, random BigInteger of the specified length.
514 /// </summary>
515 /// <param name="bits">The number of bits for the new number.</param>
516 /// <param name="rng">A random number generator to use to obtain the bits.</param>
517 /// <returns>A random number of the specified length.</returns>
518 public static BigInteger GenerateRandom (int bits, RandomNumberGenerator rng)
520 int dwords = bits >> 5;
521 int remBits = bits & 0x1F;
523 if (remBits != 0)
524 dwords++;
526 BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
527 byte [] random = new byte [dwords << 2];
529 rng.GetBytes (random);
530 Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);
532 if (remBits != 0) {
533 uint mask = (uint)(0x01 << (remBits-1));
534 ret.data [dwords-1] |= mask;
536 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
537 ret.data [dwords-1] &= mask;
539 else
540 ret.data [dwords-1] |= 0x80000000;
542 ret.Normalize ();
543 return ret;
546 /// <summary>
547 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
548 /// </summary>
549 /// <param name="bits">The number of bits for the new number.</param>
550 /// <returns>A random number of the specified length.</returns>
551 public static BigInteger GenerateRandom (int bits)
553 return GenerateRandom (bits, Rng);
556 /// <summary>
557 /// Randomizes the bits in "this" from the specified RNG.
558 /// </summary>
559 /// <param name="rng">A RNG.</param>
560 public void Randomize (RandomNumberGenerator rng)
562 if (this == 0)
563 return;
565 int bits = this.BitCount ();
566 int dwords = bits >> 5;
567 int remBits = bits & 0x1F;
569 if (remBits != 0)
570 dwords++;
572 byte [] random = new byte [dwords << 2];
574 rng.GetBytes (random);
575 Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
577 if (remBits != 0) {
578 uint mask = (uint)(0x01 << (remBits-1));
579 data [dwords-1] |= mask;
581 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
582 data [dwords-1] &= mask;
585 else
586 data [dwords-1] |= 0x80000000;
588 Normalize ();
591 /// <summary>
592 /// Randomizes the bits in "this" from the default RNG.
593 /// </summary>
594 public void Randomize ()
596 Randomize (Rng);
599 #endregion
601 #region Bitwise
603 public int BitCount ()
605 this.Normalize ();
607 uint value = data [length - 1];
608 uint mask = 0x80000000;
609 uint bits = 32;
611 while (bits > 0 && (value & mask) == 0) {
612 bits--;
613 mask >>= 1;
615 bits += ((length - 1) << 5);
617 return (int)bits;
620 /// <summary>
621 /// Tests if the specified bit is 1.
622 /// </summary>
623 /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
624 /// <returns>True if bitNum is set to 1, else false.</returns>
625 #if !INSIDE_CORLIB
626 [CLSCompliant (false)]
627 #endif
628 public bool TestBit (uint bitNum)
630 uint bytePos = bitNum >> 5; // divide by 32
631 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
633 uint mask = (uint)1 << bitPos;
634 return ((this.data [bytePos] & mask) != 0);
637 public bool TestBit (int bitNum)
639 if (bitNum < 0) throw new IndexOutOfRangeException ("bitNum out of range");
641 uint bytePos = (uint)bitNum >> 5; // divide by 32
642 byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
644 uint mask = (uint)1 << bitPos;
645 return ((this.data [bytePos] | mask) == this.data [bytePos]);
648 #if !INSIDE_CORLIB
649 [CLSCompliant (false)]
650 #endif
651 public void SetBit (uint bitNum)
653 SetBit (bitNum, true);
656 #if !INSIDE_CORLIB
657 [CLSCompliant (false)]
658 #endif
659 public void ClearBit (uint bitNum)
661 SetBit (bitNum, false);
664 #if !INSIDE_CORLIB
665 [CLSCompliant (false)]
666 #endif
667 public void SetBit (uint bitNum, bool value)
669 uint bytePos = bitNum >> 5; // divide by 32
671 if (bytePos < this.length) {
672 uint mask = (uint)1 << (int)(bitNum & 0x1F);
673 if (value)
674 this.data [bytePos] |= mask;
675 else
676 this.data [bytePos] &= ~mask;
680 public int LowestSetBit ()
682 if (this == 0) return -1;
683 int i = 0;
684 while (!TestBit (i)) i++;
685 return i;
688 public byte[] GetBytes ()
690 if (this == 0) return new byte [1];
692 int numBits = BitCount ();
693 int numBytes = numBits >> 3;
694 if ((numBits & 0x7) != 0)
695 numBytes++;
697 byte [] result = new byte [numBytes];
699 int numBytesInWord = numBytes & 0x3;
700 if (numBytesInWord == 0) numBytesInWord = 4;
702 int pos = 0;
703 for (int i = (int)length - 1; i >= 0; i--) {
704 uint val = data [i];
705 for (int j = numBytesInWord - 1; j >= 0; j--) {
706 result [pos+j] = (byte)(val & 0xFF);
707 val >>= 8;
709 pos += numBytesInWord;
710 numBytesInWord = 4;
712 return result;
715 #endregion
717 #region Compare
719 #if !INSIDE_CORLIB
720 [CLSCompliant (false)]
721 #endif
722 public static bool operator == (BigInteger bi1, uint ui)
724 if (bi1.length != 1) bi1.Normalize ();
725 return bi1.length == 1 && bi1.data [0] == ui;
728 #if !INSIDE_CORLIB
729 [CLSCompliant (false)]
730 #endif
731 public static bool operator != (BigInteger bi1, uint ui)
733 if (bi1.length != 1) bi1.Normalize ();
734 return !(bi1.length == 1 && bi1.data [0] == ui);
737 public static bool operator == (BigInteger bi1, BigInteger bi2)
739 // we need to compare with null
740 if ((bi1 as object) == (bi2 as object))
741 return true;
742 if (null == bi1 || null == bi2)
743 return false;
744 return Kernel.Compare (bi1, bi2) == 0;
747 public static bool operator != (BigInteger bi1, BigInteger bi2)
749 // we need to compare with null
750 if ((bi1 as object) == (bi2 as object))
751 return false;
752 if (null == bi1 || null == bi2)
753 return true;
754 return Kernel.Compare (bi1, bi2) != 0;
757 public static bool operator > (BigInteger bi1, BigInteger bi2)
759 return Kernel.Compare (bi1, bi2) > 0;
762 public static bool operator < (BigInteger bi1, BigInteger bi2)
764 return Kernel.Compare (bi1, bi2) < 0;
767 public static bool operator >= (BigInteger bi1, BigInteger bi2)
769 return Kernel.Compare (bi1, bi2) >= 0;
772 public static bool operator <= (BigInteger bi1, BigInteger bi2)
774 return Kernel.Compare (bi1, bi2) <= 0;
777 public Sign Compare (BigInteger bi)
779 return Kernel.Compare (this, bi);
782 #endregion
784 #region Formatting
786 #if !INSIDE_CORLIB
787 [CLSCompliant (false)]
788 #endif
789 public string ToString (uint radix)
791 return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
794 #if !INSIDE_CORLIB
795 [CLSCompliant (false)]
796 #endif
797 public string ToString (uint radix, string characterSet)
799 if (characterSet.Length < radix)
800 throw new ArgumentException ("charSet length less than radix", "characterSet");
801 if (radix == 1)
802 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
804 if (this == 0) return "0";
805 if (this == 1) return "1";
807 string result = "";
809 BigInteger a = new BigInteger (this);
811 while (a != 0) {
812 uint rem = Kernel.SingleByteDivideInPlace (a, radix);
813 result = characterSet [(int) rem] + result;
816 return result;
819 #endregion
821 #region Misc
823 /// <summary>
824 /// Normalizes this by setting the length to the actual number of
825 /// uints used in data and by setting the sign to Sign.Zero if the
826 /// value of this is 0.
827 /// </summary>
828 private void Normalize ()
830 // Normalize length
831 while (length > 0 && data [length-1] == 0) length--;
833 // Check for zero
834 if (length == 0)
835 length++;
838 public void Clear ()
840 for (int i=0; i < length; i++)
841 data [i] = 0x00;
844 #endregion
846 #region Object Impl
848 public override int GetHashCode ()
850 uint val = 0;
852 for (uint i = 0; i < this.length; i++)
853 val ^= this.data [i];
855 return (int)val;
858 public override string ToString ()
860 return ToString (10);
863 public override bool Equals (object o)
865 if (o == null)
866 return false;
867 if (o is int)
868 return (int)o >= 0 && this == (uint)o;
870 BigInteger bi = o as BigInteger;
871 if (bi == null)
872 return false;
874 return Kernel.Compare (this, bi) == 0;
877 #endregion
879 #region Number Theory
881 public BigInteger GCD (BigInteger bi)
883 return Kernel.gcd (this, bi);
886 public BigInteger ModInverse (BigInteger modulus)
888 return Kernel.modInverse (this, modulus);
891 public BigInteger ModPow (BigInteger exp, BigInteger n)
893 ModulusRing mr = new ModulusRing (n);
894 return mr.Pow (this, exp);
897 #endregion
899 #region Prime Testing
901 public bool IsProbablePrime ()
903 // can we use our small-prime table ?
904 if (this <= smallPrimes[smallPrimes.Length - 1]) {
905 for (int p = 0; p < smallPrimes.Length; p++) {
906 if (this == smallPrimes[p])
907 return true;
909 // the list is complete, so it's not a prime
910 return false;
913 // otherwise check if we can divide by one of the small primes
914 for (int p = 0; p < smallPrimes.Length; p++) {
915 if (this % smallPrimes[p] == 0)
916 return false;
918 // the last step is to confirm the "large" prime with the SPP or Miller-Rabin test
919 return PrimalityTests.Test (this, Prime.ConfidenceFactor.Medium);
922 #endregion
924 #region Prime Number Generation
926 /// <summary>
927 /// Generates the smallest prime >= bi
928 /// </summary>
929 /// <param name="bi">A BigInteger</param>
930 /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
931 public static BigInteger NextHighestPrime (BigInteger bi)
933 NextPrimeFinder npf = new NextPrimeFinder ();
934 return npf.GenerateNewPrime (0, bi);
937 public static BigInteger GeneratePseudoPrime (int bits)
939 SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase ();
940 return sspg.GenerateNewPrime (bits);
943 /// <summary>
944 /// Increments this by two
945 /// </summary>
946 public void Incr2 ()
948 int i = 0;
950 data [0] += 2;
952 // If there was no carry, nothing to do
953 if (data [0] < 2) {
955 // Account for the first carry
956 data [++i]++;
958 // Keep adding until no carry
959 while (data [i++] == 0x0)
960 data [i]++;
962 // See if we increased the data length
963 if (length == (uint)i)
964 length++;
968 #endregion
970 #if INSIDE_CORLIB
971 internal
972 #else
973 public
974 #endif
975 sealed class ModulusRing {
977 BigInteger mod, constant;
979 public ModulusRing (BigInteger modulus)
981 this.mod = modulus;
983 // calculate constant = b^ (2k) / m
984 uint i = mod.length << 1;
986 constant = new BigInteger (Sign.Positive, i + 1);
987 constant.data [i] = 0x00000001;
989 constant = constant / mod;
992 public void BarrettReduction (BigInteger x)
994 BigInteger n = mod;
995 uint k = n.length,
996 kPlusOne = k+1,
997 kMinusOne = k-1;
999 // x < mod, so nothing to do.
1000 if (x.length < k) return;
1002 BigInteger q3;
1005 // Validate pointers
1007 if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");
1009 // q1 = x / b^ (k-1)
1010 // q2 = q1 * constant
1011 // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
1013 // TODO: We should the method in HAC p 604 to do this (14.45)
1014 q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
1015 Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
1017 // r1 = x mod b^ (k+1)
1018 // i.e. keep the lowest (k+1) words
1020 uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
1022 x.length = lengthToCopy;
1023 x.Normalize ();
1025 // r2 = (q3 * n) mod b^ (k+1)
1026 // partial multiplication of q3 and n
1028 BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
1029 Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
1031 r2.Normalize ();
1033 if (r2 <= x) {
1034 Kernel.MinusEq (x, r2);
1035 } else {
1036 BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
1037 val.data [kPlusOne] = 0x00000001;
1039 Kernel.MinusEq (val, r2);
1040 Kernel.PlusEq (x, val);
1043 while (x >= n)
1044 Kernel.MinusEq (x, n);
1047 public BigInteger Multiply (BigInteger a, BigInteger b)
1049 if (a == 0 || b == 0) return 0;
1051 if (a > mod)
1052 a %= mod;
1054 if (b > mod)
1055 b %= mod;
1057 BigInteger ret = new BigInteger (a * b);
1058 BarrettReduction (ret);
1060 return ret;
1063 public BigInteger Difference (BigInteger a, BigInteger b)
1065 Sign cmp = Kernel.Compare (a, b);
1066 BigInteger diff;
1068 switch (cmp) {
1069 case Sign.Zero:
1070 return 0;
1071 case Sign.Positive:
1072 diff = a - b; break;
1073 case Sign.Negative:
1074 diff = b - a; break;
1075 default:
1076 throw new Exception ();
1079 if (diff >= mod) {
1080 if (diff.length >= mod.length << 1)
1081 diff %= mod;
1082 else
1083 BarrettReduction (diff);
1085 if (cmp == Sign.Negative)
1086 diff = mod - diff;
1087 return diff;
1089 #if true
1090 public BigInteger Pow (BigInteger a, BigInteger k)
1092 BigInteger b = new BigInteger (1);
1093 if (k == 0)
1094 return b;
1096 BigInteger A = a;
1097 if (k.TestBit (0))
1098 b = a;
1100 for (int i = 1; i < k.BitCount (); i++) {
1101 A = Multiply (A, A);
1102 if (k.TestBit (i))
1103 b = Multiply (A, b);
1105 return b;
1107 #else
1108 public BigInteger Pow (BigInteger b, BigInteger exp)
1110 if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
1111 else return EvenPow (b, exp);
1114 public BigInteger EvenPow (BigInteger b, BigInteger exp)
1116 BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
1117 BigInteger tempNum = new BigInteger (b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
1119 uint totalBits = (uint)exp.BitCount ();
1121 uint [] wkspace = new uint [mod.length << 1];
1123 // perform squaring and multiply exponentiation
1124 for (uint pos = 0; pos < totalBits; pos++) {
1125 if (exp.TestBit (pos)) {
1127 Array.Clear (wkspace, 0, wkspace.Length);
1128 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
1129 resultNum.length += tempNum.length;
1130 uint [] t = wkspace;
1131 wkspace = resultNum.data;
1132 resultNum.data = t;
1134 BarrettReduction (resultNum);
1137 Kernel.SquarePositive (tempNum, ref wkspace);
1138 BarrettReduction (tempNum);
1140 if (tempNum == 1) {
1141 return resultNum;
1145 return resultNum;
1148 private BigInteger OddPow (BigInteger b, BigInteger exp)
1150 BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
1151 BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
1152 uint mPrime = Montgomery.Inverse (mod.data [0]);
1153 uint totalBits = (uint)exp.BitCount ();
1155 uint [] wkspace = new uint [mod.length << 1];
1157 // perform squaring and multiply exponentiation
1158 for (uint pos = 0; pos < totalBits; pos++) {
1159 if (exp.TestBit (pos)) {
1161 Array.Clear (wkspace, 0, wkspace.Length);
1162 Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
1163 resultNum.length += tempNum.length;
1164 uint [] t = wkspace;
1165 wkspace = resultNum.data;
1166 resultNum.data = t;
1168 Montgomery.Reduce (resultNum, mod, mPrime);
1171 // the value of tempNum is required in the last loop
1172 if (pos < totalBits - 1) {
1173 Kernel.SquarePositive (tempNum, ref wkspace);
1174 Montgomery.Reduce (tempNum, mod, mPrime);
1178 Montgomery.Reduce (resultNum, mod, mPrime);
1179 return resultNum;
1181 #endif
1182 #region Pow Small Base
1184 // TODO: Make tests for this, not really needed b/c prime stuff
1185 // checks it, but still would be nice
1186 #if !INSIDE_CORLIB
1187 [CLSCompliant (false)]
1188 #endif
1189 #if true
1190 public BigInteger Pow (uint b, BigInteger exp)
1192 return Pow (new BigInteger (b), exp);
1194 #else
1195 public BigInteger Pow (uint b, BigInteger exp)
1197 // if (b != 2) {
1198 if ((mod.data [0] & 1) == 1)
1199 return OddPow (b, exp);
1200 else
1201 return EvenPow (b, exp);
1202 /* buggy in some cases (like the well tested primes)
1203 } else {
1204 if ((mod.data [0] & 1) == 1)
1205 return OddModTwoPow (exp);
1206 else
1207 return EvenModTwoPow (exp);
1211 private unsafe BigInteger OddPow (uint b, BigInteger exp)
1213 exp.Normalize ();
1214 uint [] wkspace = new uint [mod.length << 1 + 1];
1216 BigInteger resultNum = Montgomery.ToMont ((BigInteger)b, this.mod);
1217 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1219 uint mPrime = Montgomery.Inverse (mod.data [0]);
1221 int bc = exp.BitCount () - 2;
1222 uint pos = (bc > 1 ? (uint) bc : 1);
1225 // We know that the first itr will make the val b
1228 do {
1230 // r = r ^ 2 % m
1232 Kernel.SquarePositive (resultNum, ref wkspace);
1233 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1235 if (exp.TestBit (pos)) {
1238 // r = r * b % m
1241 // TODO: Is Unsafe really speeding things up?
1242 fixed (uint* u = resultNum.data) {
1244 uint i = 0;
1245 ulong mc = 0;
1247 do {
1248 mc += (ulong)u [i] * (ulong)b;
1249 u [i] = (uint)mc;
1250 mc >>= 32;
1251 } while (++i < resultNum.length);
1253 if (resultNum.length < mod.length) {
1254 if (mc != 0) {
1255 u [i] = (uint)mc;
1256 resultNum.length++;
1257 while (resultNum >= mod)
1258 Kernel.MinusEq (resultNum, mod);
1260 } else if (mc != 0) {
1263 // First, we estimate the quotient by dividing
1264 // the first part of each of the numbers. Then
1265 // we correct this, if necessary, with a subtraction.
1268 uint cc = (uint)mc;
1270 // We would rather have this estimate overshoot,
1271 // so we add one to the divisor
1272 uint divEstimate;
1273 if (mod.data [mod.length - 1] < UInt32.MaxValue) {
1274 divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1275 (mod.data [mod.length-1] + 1));
1277 else {
1278 // guess but don't divide by 0
1279 divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1280 (mod.data [mod.length-1]));
1283 uint t;
1285 i = 0;
1286 mc = 0;
1287 do {
1288 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1289 t = u [i];
1290 u [i] -= (uint)mc;
1291 mc >>= 32;
1292 if (u [i] > t) mc++;
1293 i++;
1294 } while (i < resultNum.length);
1295 cc -= (uint)mc;
1297 if (cc != 0) {
1299 uint sc = 0, j = 0;
1300 uint [] s = mod.data;
1301 do {
1302 uint a = s [j];
1303 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1304 else sc = 0;
1305 j++;
1306 } while (j < resultNum.length);
1307 cc -= sc;
1309 while (resultNum >= mod)
1310 Kernel.MinusEq (resultNum, mod);
1311 } else {
1312 while (resultNum >= mod)
1313 Kernel.MinusEq (resultNum, mod);
1317 } while (pos-- > 0);
1319 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1320 return resultNum;
1324 private unsafe BigInteger EvenPow (uint b, BigInteger exp)
1326 exp.Normalize ();
1327 uint [] wkspace = new uint [mod.length << 1 + 1];
1328 BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);
1330 uint pos = (uint)exp.BitCount () - 2;
1333 // We know that the first itr will make the val b
1336 do {
1338 // r = r ^ 2 % m
1340 Kernel.SquarePositive (resultNum, ref wkspace);
1341 if (!(resultNum.length < mod.length))
1342 BarrettReduction (resultNum);
1344 if (exp.TestBit (pos)) {
1347 // r = r * b % m
1350 // TODO: Is Unsafe really speeding things up?
1351 fixed (uint* u = resultNum.data) {
1353 uint i = 0;
1354 ulong mc = 0;
1356 do {
1357 mc += (ulong)u [i] * (ulong)b;
1358 u [i] = (uint)mc;
1359 mc >>= 32;
1360 } while (++i < resultNum.length);
1362 if (resultNum.length < mod.length) {
1363 if (mc != 0) {
1364 u [i] = (uint)mc;
1365 resultNum.length++;
1366 while (resultNum >= mod)
1367 Kernel.MinusEq (resultNum, mod);
1369 } else if (mc != 0) {
1372 // First, we estimate the quotient by dividing
1373 // the first part of each of the numbers. Then
1374 // we correct this, if necessary, with a subtraction.
1377 uint cc = (uint)mc;
1379 // We would rather have this estimate overshoot,
1380 // so we add one to the divisor
1381 uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1382 (mod.data [mod.length-1] + 1));
1384 uint t;
1386 i = 0;
1387 mc = 0;
1388 do {
1389 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1390 t = u [i];
1391 u [i] -= (uint)mc;
1392 mc >>= 32;
1393 if (u [i] > t) mc++;
1394 i++;
1395 } while (i < resultNum.length);
1396 cc -= (uint)mc;
1398 if (cc != 0) {
1400 uint sc = 0, j = 0;
1401 uint [] s = mod.data;
1402 do {
1403 uint a = s [j];
1404 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1405 else sc = 0;
1406 j++;
1407 } while (j < resultNum.length);
1408 cc -= sc;
1410 while (resultNum >= mod)
1411 Kernel.MinusEq (resultNum, mod);
1412 } else {
1413 while (resultNum >= mod)
1414 Kernel.MinusEq (resultNum, mod);
1418 } while (pos-- > 0);
1420 return resultNum;
1422 #endif
1423 /* known to be buggy in some cases */
1424 #if false
1425 private unsafe BigInteger EvenModTwoPow (BigInteger exp)
1427 exp.Normalize ();
1428 uint [] wkspace = new uint [mod.length << 1 + 1];
1430 BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
1432 uint value = exp.data [exp.length - 1];
1433 uint mask = 0x80000000;
1435 // Find the first bit of the exponent
1436 while ((value & mask) == 0)
1437 mask >>= 1;
1440 // We know that the first itr will make the val 2,
1441 // so eat one bit of the exponent
1443 mask >>= 1;
1445 uint wPos = exp.length - 1;
1447 do {
1448 value = exp.data [wPos];
1449 do {
1450 Kernel.SquarePositive (resultNum, ref wkspace);
1451 if (resultNum.length >= mod.length)
1452 BarrettReduction (resultNum);
1454 if ((value & mask) != 0) {
1456 // resultNum = (resultNum * 2) % mod
1459 fixed (uint* u = resultNum.data) {
1461 // Double
1463 uint* uu = u;
1464 uint* uuE = u + resultNum.length;
1465 uint x, carry = 0;
1466 while (uu < uuE) {
1467 x = *uu;
1468 *uu = (x << 1) | carry;
1469 carry = x >> (32 - 1);
1470 uu++;
1473 // subtraction inlined because we know it is square
1474 if (carry != 0 || resultNum >= mod) {
1475 uu = u;
1476 uint c = 0;
1477 uint [] s = mod.data;
1478 uint i = 0;
1479 do {
1480 uint a = s [i];
1481 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1482 c = 1;
1483 else
1484 c = 0;
1485 i++;
1486 } while (uu < uuE);
1490 } while ((mask >>= 1) > 0);
1491 mask = 0x80000000;
1492 } while (wPos-- > 0);
1494 return resultNum;
1497 private unsafe BigInteger OddModTwoPow (BigInteger exp)
1500 uint [] wkspace = new uint [mod.length << 1 + 1];
1502 BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
1503 resultNum = new BigInteger (resultNum, mod.length << 1 +1);
1505 uint mPrime = Montgomery.Inverse (mod.data [0]);
1508 // TODO: eat small bits, the ones we can do with no modular reduction
1510 uint pos = (uint)exp.BitCount () - 2;
1512 do {
1513 Kernel.SquarePositive (resultNum, ref wkspace);
1514 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1516 if (exp.TestBit (pos)) {
1518 // resultNum = (resultNum * 2) % mod
1521 fixed (uint* u = resultNum.data) {
1523 // Double
1525 uint* uu = u;
1526 uint* uuE = u + resultNum.length;
1527 uint x, carry = 0;
1528 while (uu < uuE) {
1529 x = *uu;
1530 *uu = (x << 1) | carry;
1531 carry = x >> (32 - 1);
1532 uu++;
1535 // subtraction inlined because we know it is square
1536 if (carry != 0 || resultNum >= mod) {
1537 fixed (uint* s = mod.data) {
1538 uu = u;
1539 uint c = 0;
1540 uint* ss = s;
1541 do {
1542 uint a = *ss++;
1543 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1544 c = 1;
1545 else
1546 c = 0;
1547 } while (uu < uuE);
1552 } while (pos-- > 0);
1554 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1555 return resultNum;
1557 #endif
1558 #endregion
1561 internal sealed class Montgomery {
1563 private Montgomery ()
1567 public static uint Inverse (uint n)
1569 uint y = n, z;
1571 while ((z = n * y) != 1)
1572 y *= 2 - z;
1574 return (uint)-y;
1577 public static BigInteger ToMont (BigInteger n, BigInteger m)
1579 n.Normalize (); m.Normalize ();
1581 n <<= (int)m.length * 32;
1582 n %= m;
1583 return n;
1586 public static unsafe BigInteger Reduce (BigInteger n, BigInteger m, uint mPrime)
1588 BigInteger A = n;
1589 fixed (uint* a = A.data, mm = m.data) {
1590 for (uint i = 0; i < m.length; i++) {
1591 // The mod here is taken care of by the CPU,
1592 // since the multiply will overflow.
1593 uint u_i = a [0] * mPrime /* % 2^32 */;
1596 // A += u_i * m;
1597 // A >>= 32
1600 // mP = Position in mod
1601 // aSP = the source of bits from a
1602 // aDP = destination for bits
1603 uint* mP = mm, aSP = a, aDP = a;
1605 ulong c = (ulong)u_i * ((ulong)*(mP++)) + *(aSP++);
1606 c >>= 32;
1607 uint j = 1;
1609 // Multiply and add
1610 for (; j < m.length; j++) {
1611 c += (ulong)u_i * (ulong)*(mP++) + *(aSP++);
1612 *(aDP++) = (uint)c;
1613 c >>= 32;
1616 // Account for carry
1617 // TODO: use a better loop here, we dont need the ulong stuff
1618 for (; j < A.length; j++) {
1619 c += *(aSP++);
1620 *(aDP++) = (uint)c;
1621 c >>= 32;
1622 if (c == 0) {j++; break;}
1624 // Copy the rest
1625 for (; j < A.length; j++) {
1626 *(aDP++) = *(aSP++);
1629 *(aDP++) = (uint)c;
1632 while (A.length > 1 && a [A.length-1] == 0) A.length--;
1635 if (A >= m) Kernel.MinusEq (A, m);
1637 return A;
1639 #if _NOT_USED_
1640 public static BigInteger Reduce (BigInteger n, BigInteger m)
1642 return Reduce (n, m, Inverse (m.data [0]));
1644 #endif
1647 /// <summary>
1648 /// Low level functions for the BigInteger
1649 /// </summary>
1650 private sealed class Kernel {
1652 #region Addition/Subtraction
1654 /// <summary>
1655 /// Adds two numbers with the same sign.
1656 /// </summary>
1657 /// <param name="bi1">A BigInteger</param>
1658 /// <param name="bi2">A BigInteger</param>
1659 /// <returns>bi1 + bi2</returns>
1660 public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
1662 uint [] x, y;
1663 uint yMax, xMax, i = 0;
1665 // x should be bigger
1666 if (bi1.length < bi2.length) {
1667 x = bi2.data;
1668 xMax = bi2.length;
1669 y = bi1.data;
1670 yMax = bi1.length;
1671 } else {
1672 x = bi1.data;
1673 xMax = bi1.length;
1674 y = bi2.data;
1675 yMax = bi2.length;
1678 BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
1680 uint [] r = result.data;
1682 ulong sum = 0;
1684 // Add common parts of both numbers
1685 do {
1686 sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
1687 r [i] = (uint)sum;
1688 sum >>= 32;
1689 } while (++i < yMax);
1691 // Copy remainder of longer number while carry propagation is required
1692 bool carry = (sum != 0);
1694 if (carry) {
1696 if (i < xMax) {
1698 carry = ((r [i] = x [i] + 1) == 0);
1699 while (++i < xMax && carry);
1702 if (carry) {
1703 r [i] = 1;
1704 result.length = ++i;
1705 return result;
1709 // Copy the rest
1710 if (i < xMax) {
1712 r [i] = x [i];
1713 while (++i < xMax);
1716 result.Normalize ();
1717 return result;
1720 public static BigInteger Subtract (BigInteger big, BigInteger small)
1722 BigInteger result = new BigInteger (Sign.Positive, big.length);
1724 uint [] r = result.data, b = big.data, s = small.data;
1725 uint i = 0, c = 0;
1727 do {
1729 uint x = s [i];
1730 if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
1731 c = 1;
1732 else
1733 c = 0;
1735 } while (++i < small.length);
1737 if (i == big.length) goto fixup;
1739 if (c == 1) {
1741 r [i] = b [i] - 1;
1742 while (b [i++] == 0 && i < big.length);
1744 if (i == big.length) goto fixup;
1748 r [i] = b [i];
1749 while (++i < big.length);
1751 fixup:
1753 result.Normalize ();
1754 return result;
1757 public static void MinusEq (BigInteger big, BigInteger small)
1759 uint [] b = big.data, s = small.data;
1760 uint i = 0, c = 0;
1762 do {
1763 uint x = s [i];
1764 if (((x += c) < c) | ((b [i] -= x) > ~x))
1765 c = 1;
1766 else
1767 c = 0;
1768 } while (++i < small.length);
1770 if (i == big.length) goto fixup;
1772 if (c == 1) {
1774 b [i]--;
1775 while (b [i++] == 0 && i < big.length);
1778 fixup:
1780 // Normalize length
1781 while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
1783 // Check for zero
1784 if (big.length == 0)
1785 big.length++;
1789 public static void PlusEq (BigInteger bi1, BigInteger bi2)
1791 uint [] x, y;
1792 uint yMax, xMax, i = 0;
1793 bool flag = false;
1795 // x should be bigger
1796 if (bi1.length < bi2.length){
1797 flag = true;
1798 x = bi2.data;
1799 xMax = bi2.length;
1800 y = bi1.data;
1801 yMax = bi1.length;
1802 } else {
1803 x = bi1.data;
1804 xMax = bi1.length;
1805 y = bi2.data;
1806 yMax = bi2.length;
1809 uint [] r = bi1.data;
1811 ulong sum = 0;
1813 // Add common parts of both numbers
1814 do {
1815 sum += ((ulong)x [i]) + ((ulong)y [i]);
1816 r [i] = (uint)sum;
1817 sum >>= 32;
1818 } while (++i < yMax);
1820 // Copy remainder of longer number while carry propagation is required
1821 bool carry = (sum != 0);
1823 if (carry){
1825 if (i < xMax) {
1827 carry = ((r [i] = x [i] + 1) == 0);
1828 while (++i < xMax && carry);
1831 if (carry) {
1832 r [i] = 1;
1833 bi1.length = ++i;
1834 return;
1838 // Copy the rest
1839 if (flag && i < xMax - 1) {
1841 r [i] = x [i];
1842 while (++i < xMax);
1845 bi1.length = xMax + 1;
1846 bi1.Normalize ();
1849 #endregion
1851 #region Compare
1853 /// <summary>
1854 /// Compares two BigInteger
1855 /// </summary>
1856 /// <param name="bi1">A BigInteger</param>
1857 /// <param name="bi2">A BigInteger</param>
1858 /// <returns>The sign of bi1 - bi2</returns>
1859 public static Sign Compare (BigInteger bi1, BigInteger bi2)
1862 // Step 1. Compare the lengths
1864 uint l1 = bi1.length, l2 = bi2.length;
1866 while (l1 > 0 && bi1.data [l1-1] == 0) l1--;
1867 while (l2 > 0 && bi2.data [l2-1] == 0) l2--;
1869 if (l1 == 0 && l2 == 0) return Sign.Zero;
1871 // bi1 len < bi2 len
1872 if (l1 < l2) return Sign.Negative;
1873 // bi1 len > bi2 len
1874 else if (l1 > l2) return Sign.Positive;
1877 // Step 2. Compare the bits
1880 uint pos = l1 - 1;
1882 while (pos != 0 && bi1.data [pos] == bi2.data [pos]) pos--;
1884 if (bi1.data [pos] < bi2.data [pos])
1885 return Sign.Negative;
1886 else if (bi1.data [pos] > bi2.data [pos])
1887 return Sign.Positive;
1888 else
1889 return Sign.Zero;
1892 #endregion
1894 #region Division
1896 #region Dword
1898 /// <summary>
1899 /// Performs n / d and n % d in one operation.
1900 /// </summary>
1901 /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
1902 /// <param name="d">The divisor</param>
1903 /// <returns>n % d</returns>
1904 public static uint SingleByteDivideInPlace (BigInteger n, uint d)
1906 ulong r = 0;
1907 uint i = n.length;
1909 while (i-- > 0) {
1910 r <<= 32;
1911 r |= n.data [i];
1912 n.data [i] = (uint)(r / d);
1913 r %= d;
1915 n.Normalize ();
1917 return (uint)r;
1920 public static uint DwordMod (BigInteger n, uint d)
1922 ulong r = 0;
1923 uint i = n.length;
1925 while (i-- > 0) {
1926 r <<= 32;
1927 r |= n.data [i];
1928 r %= d;
1931 return (uint)r;
1934 public static BigInteger DwordDiv (BigInteger n, uint d)
1936 BigInteger ret = new BigInteger (Sign.Positive, n.length);
1938 ulong r = 0;
1939 uint i = n.length;
1941 while (i-- > 0) {
1942 r <<= 32;
1943 r |= n.data [i];
1944 ret.data [i] = (uint)(r / d);
1945 r %= d;
1947 ret.Normalize ();
1949 return ret;
1952 public static BigInteger [] DwordDivMod (BigInteger n, uint d)
1954 BigInteger ret = new BigInteger (Sign.Positive , n.length);
1956 ulong r = 0;
1957 uint i = n.length;
1959 while (i-- > 0) {
1960 r <<= 32;
1961 r |= n.data [i];
1962 ret.data [i] = (uint)(r / d);
1963 r %= d;
1965 ret.Normalize ();
1967 BigInteger rem = (uint)r;
1969 return new BigInteger [] {ret, rem};
1972 #endregion
1974 #region BigNum
1976 public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
1978 if (Kernel.Compare (bi1, bi2) == Sign.Negative)
1979 return new BigInteger [2] { 0, new BigInteger (bi1) };
1981 bi1.Normalize (); bi2.Normalize ();
1983 if (bi2.length == 1)
1984 return DwordDivMod (bi1, bi2.data [0]);
1986 uint remainderLen = bi1.length + 1;
1987 int divisorLen = (int)bi2.length + 1;
1989 uint mask = 0x80000000;
1990 uint val = bi2.data [bi2.length - 1];
1991 int shift = 0;
1992 int resultPos = (int)bi1.length - (int)bi2.length;
1994 while (mask != 0 && (val & mask) == 0) {
1995 shift++; mask >>= 1;
1998 BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
1999 BigInteger rem = (bi1 << shift);
2001 uint [] remainder = rem.data;
2003 bi2 = bi2 << shift;
2005 int j = (int)(remainderLen - bi2.length);
2006 int pos = (int)remainderLen - 1;
2008 uint firstDivisorByte = bi2.data [bi2.length-1];
2009 ulong secondDivisorByte = bi2.data [bi2.length-2];
2011 while (j > 0) {
2012 ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
2014 ulong q_hat = dividend / (ulong)firstDivisorByte;
2015 ulong r_hat = dividend % (ulong)firstDivisorByte;
2017 do {
2019 if (q_hat == 0x100000000 ||
2020 (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
2021 q_hat--;
2022 r_hat += (ulong)firstDivisorByte;
2024 if (r_hat < 0x100000000)
2025 continue;
2027 break;
2028 } while (true);
2031 // At this point, q_hat is either exact, or one too large
2032 // (more likely to be exact) so, we attempt to multiply the
2033 // divisor by q_hat, if we get a borrow, we just subtract
2034 // one from q_hat and add the divisor back.
2037 uint t;
2038 uint dPos = 0;
2039 int nPos = pos - divisorLen + 1;
2040 ulong mc = 0;
2041 uint uint_q_hat = (uint)q_hat;
2042 do {
2043 mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
2044 t = remainder [nPos];
2045 remainder [nPos] -= (uint)mc;
2046 mc >>= 32;
2047 if (remainder [nPos] > t) mc++;
2048 dPos++; nPos++;
2049 } while (dPos < divisorLen);
2051 nPos = pos - divisorLen + 1;
2052 dPos = 0;
2054 // Overestimate
2055 if (mc != 0) {
2056 uint_q_hat--;
2057 ulong sum = 0;
2059 do {
2060 sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
2061 remainder [nPos] = (uint)sum;
2062 sum >>= 32;
2063 dPos++; nPos++;
2064 } while (dPos < divisorLen);
2068 quot.data [resultPos--] = (uint)uint_q_hat;
2070 pos--;
2071 j--;
2074 quot.Normalize ();
2075 rem.Normalize ();
2076 BigInteger [] ret = new BigInteger [2] { quot, rem };
2078 if (shift != 0)
2079 ret [1] >>= shift;
2081 return ret;
2084 #endregion
2086 #endregion
2088 #region Shift
2089 public static BigInteger LeftShift (BigInteger bi, int n)
2091 if (n == 0) return new BigInteger (bi, bi.length + 1);
2093 int w = n >> 5;
2094 n &= ((1 << 5) - 1);
2096 BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
2098 uint i = 0, l = bi.length;
2099 if (n != 0) {
2100 uint x, carry = 0;
2101 while (i < l) {
2102 x = bi.data [i];
2103 ret.data [i + w] = (x << n) | carry;
2104 carry = x >> (32 - n);
2105 i++;
2107 ret.data [i + w] = carry;
2108 } else {
2109 while (i < l) {
2110 ret.data [i + w] = bi.data [i];
2111 i++;
2115 ret.Normalize ();
2116 return ret;
2119 public static BigInteger RightShift (BigInteger bi, int n)
2121 if (n == 0) return new BigInteger (bi);
2123 int w = n >> 5;
2124 int s = n & ((1 << 5) - 1);
2126 BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
2127 uint l = (uint)ret.data.Length - 1;
2129 if (s != 0) {
2131 uint x, carry = 0;
2133 while (l-- > 0) {
2134 x = bi.data [l + w];
2135 ret.data [l] = (x >> n) | carry;
2136 carry = x << (32 - n);
2138 } else {
2139 while (l-- > 0)
2140 ret.data [l] = bi.data [l + w];
2143 ret.Normalize ();
2144 return ret;
2147 #endregion
2149 #region Multiply
2151 public static BigInteger MultiplyByDword (BigInteger n, uint f)
2153 BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
2155 uint i = 0;
2156 ulong c = 0;
2158 do {
2159 c += (ulong)n.data [i] * (ulong)f;
2160 ret.data [i] = (uint)c;
2161 c >>= 32;
2162 } while (++i < n.length);
2163 ret.data [i] = (uint)c;
2164 ret.Normalize ();
2165 return ret;
2169 /// <summary>
2170 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2171 /// y [yOffset:yOffset+yLen] and puts it into
2172 /// d [dOffset:dOffset+xLen+yLen].
2173 /// </summary>
2174 /// <remarks>
2175 /// This code is unsafe! It is the caller's responsibility to make
2176 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2177 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
2178 /// </remarks>
2179 public static unsafe void Multiply (uint [] x, uint xOffset, uint xLen, uint [] y, uint yOffset, uint yLen, uint [] d, uint dOffset)
2181 fixed (uint* xx = x, yy = y, dd = d) {
2182 uint* xP = xx + xOffset,
2183 xE = xP + xLen,
2184 yB = yy + yOffset,
2185 yE = yB + yLen,
2186 dB = dd + dOffset;
2188 for (; xP < xE; xP++, dB++) {
2190 if (*xP == 0) continue;
2192 ulong mcarry = 0;
2194 uint* dP = dB;
2195 for (uint* yP = yB; yP < yE; yP++, dP++) {
2196 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2198 *dP = (uint)mcarry;
2199 mcarry >>= 32;
2202 if (mcarry != 0)
2203 *dP = (uint)mcarry;
2208 /// <summary>
2209 /// Multiplies the data in x [xOffset:xOffset+xLen] by
2210 /// y [yOffset:yOffset+yLen] and puts the low mod words into
2211 /// d [dOffset:dOffset+mod].
2212 /// </summary>
2213 /// <remarks>
2214 /// This code is unsafe! It is the caller's responsibility to make
2215 /// sure that it is safe to access x [xOffset:xOffset+xLen],
2216 /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
2217 /// </remarks>
2218 public static unsafe void MultiplyMod2p32pmod (uint [] x, int xOffset, int xLen, uint [] y, int yOffest, int yLen, uint [] d, int dOffset, int mod)
2220 fixed (uint* xx = x, yy = y, dd = d) {
2221 uint* xP = xx + xOffset,
2222 xE = xP + xLen,
2223 yB = yy + yOffest,
2224 yE = yB + yLen,
2225 dB = dd + dOffset,
2226 dE = dB + mod;
2228 for (; xP < xE; xP++, dB++) {
2230 if (*xP == 0) continue;
2232 ulong mcarry = 0;
2233 uint* dP = dB;
2234 for (uint* yP = yB; yP < yE && dP < dE; yP++, dP++) {
2235 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2237 *dP = (uint)mcarry;
2238 mcarry >>= 32;
2241 if (mcarry != 0 && dP < dE)
2242 *dP = (uint)mcarry;
2247 public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
2249 uint [] t = wkSpace;
2250 wkSpace = bi.data;
2251 uint [] d = bi.data;
2252 uint dl = bi.length;
2253 bi.data = t;
2255 fixed (uint* dd = d, tt = t) {
2257 uint* ttE = tt + t.Length;
2258 // Clear the dest
2259 for (uint* ttt = tt; ttt < ttE; ttt++)
2260 *ttt = 0;
2262 uint* dP = dd, tP = tt;
2264 for (uint i = 0; i < dl; i++, dP++) {
2265 if (*dP == 0)
2266 continue;
2268 ulong mcarry = 0;
2269 uint bi1val = *dP;
2271 uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
2273 for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
2274 // k = i + j
2275 mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
2277 *tP2 = (uint)mcarry;
2278 mcarry >>= 32;
2281 if (mcarry != 0)
2282 *tP2 = (uint)mcarry;
2285 // Double t. Inlined for speed.
2287 tP = tt;
2289 uint x, carry = 0;
2290 while (tP < ttE) {
2291 x = *tP;
2292 *tP = (x << 1) | carry;
2293 carry = x >> (32 - 1);
2294 tP++;
2296 if (carry != 0) *tP = carry;
2298 // Add in the diagnals
2300 dP = dd;
2301 tP = tt;
2302 for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
2303 ulong val = (ulong)*dP * (ulong)*dP + *tP;
2304 *tP = (uint)val;
2305 val >>= 32;
2306 *(++tP) += (uint)val;
2307 if (*tP < (uint)val) {
2308 uint* tP3 = tP;
2309 // Account for the first carry
2310 (*++tP3)++;
2312 // Keep adding until no carry
2313 while ((*tP3++) == 0)
2314 (*tP3)++;
2319 bi.length <<= 1;
2321 // Normalize length
2322 while (tt [bi.length-1] == 0 && bi.length > 1) bi.length--;
2328 * Never called in BigInteger (and part of a private class)
2329 * public static bool Double (uint [] u, int l)
2331 uint x, carry = 0;
2332 uint i = 0;
2333 while (i < l) {
2334 x = u [i];
2335 u [i] = (x << 1) | carry;
2336 carry = x >> (32 - 1);
2337 i++;
2339 if (carry != 0) u [l] = carry;
2340 return carry != 0;
2343 #endregion
2345 #region Number Theory
2347 public static BigInteger gcd (BigInteger a, BigInteger b)
2349 BigInteger x = a;
2350 BigInteger y = b;
2352 BigInteger g = y;
2354 while (x.length > 1) {
2355 g = x;
2356 x = y % x;
2357 y = g;
2360 if (x == 0) return g;
2362 // TODO: should we have something here if we can convert to long?
2365 // Now we can just do it with single precision. I am using the binary gcd method,
2366 // as it should be faster.
2369 uint yy = x.data [0];
2370 uint xx = y % yy;
2372 int t = 0;
2374 while (((xx | yy) & 1) == 0) {
2375 xx >>= 1; yy >>= 1; t++;
2377 while (xx != 0) {
2378 while ((xx & 1) == 0) xx >>= 1;
2379 while ((yy & 1) == 0) yy >>= 1;
2380 if (xx >= yy)
2381 xx = (xx - yy) >> 1;
2382 else
2383 yy = (yy - xx) >> 1;
2386 return yy << t;
2389 public static uint modInverse (BigInteger bi, uint modulus)
2391 uint a = modulus, b = bi % modulus;
2392 uint p0 = 0, p1 = 1;
2394 while (b != 0) {
2395 if (b == 1)
2396 return p1;
2397 p0 += (a / b) * p1;
2398 a %= b;
2400 if (a == 0)
2401 break;
2402 if (a == 1)
2403 return modulus-p0;
2405 p1 += (b / a) * p0;
2406 b %= a;
2409 return 0;
2412 public static BigInteger modInverse (BigInteger bi, BigInteger modulus)
2414 if (modulus.length == 1) return modInverse (bi, modulus.data [0]);
2416 BigInteger [] p = { 0, 1 };
2417 BigInteger [] q = new BigInteger [2]; // quotients
2418 BigInteger [] r = { 0, 0 }; // remainders
2420 int step = 0;
2422 BigInteger a = modulus;
2423 BigInteger b = bi;
2425 ModulusRing mr = new ModulusRing (modulus);
2427 while (b != 0) {
2429 if (step > 1) {
2431 BigInteger pval = mr.Difference (p [0], p [1] * q [0]);
2432 p [0] = p [1]; p [1] = pval;
2435 BigInteger [] divret = multiByteDivide (a, b);
2437 q [0] = q [1]; q [1] = divret [0];
2438 r [0] = r [1]; r [1] = divret [1];
2439 a = b;
2440 b = divret [1];
2442 step++;
2445 if (r [0] != 1)
2446 throw (new ArithmeticException ("No inverse!"));
2448 return mr.Difference (p [0], p [1] * q [0]);
2451 #endregion