Merge changes, that were only made in corlib, back into Mono.Security
[mono-project.git] / mcs / class / Mono.Security / Mono.Math / BigInteger.cs
blob0356d0a166487af7ffae6befcd7c59b362d180d0
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 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++) {
222 data [j] = (uint)(
223 (inData [i-3] << (3*8)) |
224 (inData [i-2] << (2*8)) |
225 (inData [i-1] << (1*8)) |
226 (inData [i])
230 switch (leftOver) {
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;
236 this.Normalize ();
239 #if !INSIDE_CORLIB
240 [CLSCompliant (false)]
241 #endif
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];
253 this.Normalize ();
256 #if !INSIDE_CORLIB
257 [CLSCompliant (false)]
258 #endif
259 public BigInteger (uint ui)
261 data = new uint [] {ui};
264 #if !INSIDE_CORLIB
265 [CLSCompliant (false)]
266 #endif
267 public BigInteger (ulong ul)
269 data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
270 length = 2;
272 this.Normalize ();
275 #if !INSIDE_CORLIB
276 [CLSCompliant (false)]
277 #endif
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));
289 #if !INSIDE_CORLIB
290 [CLSCompliant (false)]
291 #endif
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)
301 if (number == null)
302 throw new ArgumentNullException ("number");
304 int i = 0, len = number.Length;
305 char c;
306 bool digits_seen = false;
307 BigInteger val = new BigInteger (0);
308 if (number [i] == '+') {
309 i++;
311 else if (number [i] == '-') {
312 throw new FormatException (WouldReturnNegVal);
315 for (; i < len; i++) {
316 c = number [i];
317 if (c == '\0') {
318 i = len;
319 continue;
321 if (c >= '0' && c <= '9') {
322 val = val * 10 + (c - '0');
323 digits_seen = true;
325 else {
326 if (Char.IsWhiteSpace (c)) {
327 for (i++; i < len; i++) {
328 if (!Char.IsWhiteSpace (number [i]))
329 throw new FormatException ();
331 break;
333 else
334 throw new FormatException ();
337 if (!digits_seen)
338 throw new FormatException ();
339 return val;
342 #endregion
344 #region Operators
346 public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
348 if (bi1 == 0)
349 return new BigInteger (bi2);
350 else if (bi2 == 0)
351 return new BigInteger (bi1);
352 else
353 return Kernel.AddSameSign (bi1, bi2);
356 public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
358 if (bi2 == 0)
359 return new BigInteger (bi1);
361 if (bi1 == 0)
362 throw new ArithmeticException (WouldReturnNegVal);
364 switch (Kernel.Compare (bi1, bi2)) {
366 case Sign.Zero:
367 return 0;
369 case Sign.Positive:
370 return Kernel.Subtract (bi1, bi2);
372 case Sign.Negative:
373 throw new ArithmeticException (WouldReturnNegVal);
374 default:
375 throw new Exception ();
379 public static int operator % (BigInteger bi, int i)
381 if (i > 0)
382 return (int)Kernel.DwordMod (bi, (uint)i);
383 else
384 return -(int)Kernel.DwordMod (bi, (uint)-i);
387 #if !INSIDE_CORLIB
388 [CLSCompliant (false)]
389 #endif
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)
402 if (i > 0)
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;
418 // Validate pointers
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);
427 ret.Normalize ();
428 return ret;
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);
450 #endregion
452 #region Friendly names for operators
454 // with names suggested by FxCop 1.30
456 public static BigInteger Add (BigInteger bi1, BigInteger bi2)
458 return (bi1 + bi2);
461 public static BigInteger Subtract (BigInteger bi1, BigInteger bi2)
463 return (bi1 - bi2);
466 public static int Modulus (BigInteger bi, int i)
468 return (bi % i);
471 #if !INSIDE_CORLIB
472 [CLSCompliant (false)]
473 #endif
474 public static uint Modulus (BigInteger bi, uint ui)
476 return (bi % ui);
479 public static BigInteger Modulus (BigInteger bi1, BigInteger bi2)
481 return (bi1 % bi2);
484 public static BigInteger Divid (BigInteger bi, int i)
486 return (bi / i);
489 public static BigInteger Divid (BigInteger bi1, BigInteger bi2)
491 return (bi1 / bi2);
494 public static BigInteger Multiply (BigInteger bi1, BigInteger bi2)
496 return (bi1 * bi2);
499 public static BigInteger Multiply (BigInteger bi, int i)
501 return (bi * i);
504 #endregion
506 #region Random
507 private static RandomNumberGenerator rng;
508 private static RandomNumberGenerator Rng {
509 get {
510 if (rng == null)
511 rng = RandomNumberGenerator.Create ();
512 return rng;
516 /// <summary>
517 /// Generates a new, random BigInteger of the specified length.
518 /// </summary>
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;
527 if (remBits != 0)
528 dwords++;
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);
536 if (remBits != 0) {
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;
543 else
544 ret.data [dwords-1] |= 0x80000000;
546 ret.Normalize ();
547 return ret;
550 /// <summary>
551 /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
552 /// </summary>
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);
560 /// <summary>
561 /// Randomizes the bits in "this" from the specified RNG.
562 /// </summary>
563 /// <param name="rng">A RNG.</param>
564 public void Randomize (RandomNumberGenerator rng)
566 if (this == 0)
567 return;
569 int bits = this.BitCount ();
570 int dwords = bits >> 5;
571 int remBits = bits & 0x1F;
573 if (remBits != 0)
574 dwords++;
576 byte [] random = new byte [dwords << 2];
578 rng.GetBytes (random);
579 Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
581 if (remBits != 0) {
582 uint mask = (uint)(0x01 << (remBits-1));
583 data [dwords-1] |= mask;
585 mask = (uint)(0xFFFFFFFF >> (32 - remBits));
586 data [dwords-1] &= mask;
589 else
590 data [dwords-1] |= 0x80000000;
592 Normalize ();
595 /// <summary>
596 /// Randomizes the bits in "this" from the default RNG.
597 /// </summary>
598 public void Randomize ()
600 Randomize (Rng);
603 #endregion
605 #region Bitwise
607 public int BitCount ()
609 this.Normalize ();
611 uint value = data [length - 1];
612 uint mask = 0x80000000;
613 uint bits = 32;
615 while (bits > 0 && (value & mask) == 0) {
616 bits--;
617 mask >>= 1;
619 bits += ((length - 1) << 5);
621 return (int)bits;
624 /// <summary>
625 /// Tests if the specified bit is 1.
626 /// </summary>
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>
629 #if !INSIDE_CORLIB
630 [CLSCompliant (false)]
631 #endif
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]);
652 #if !INSIDE_CORLIB
653 [CLSCompliant (false)]
654 #endif
655 public void SetBit (uint bitNum)
657 SetBit (bitNum, true);
660 #if !INSIDE_CORLIB
661 [CLSCompliant (false)]
662 #endif
663 public void ClearBit (uint bitNum)
665 SetBit (bitNum, false);
668 #if !INSIDE_CORLIB
669 [CLSCompliant (false)]
670 #endif
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);
677 if (value)
678 this.data [bytePos] |= mask;
679 else
680 this.data [bytePos] &= ~mask;
684 public int LowestSetBit ()
686 if (this == 0) return -1;
687 int i = 0;
688 while (!TestBit (i)) i++;
689 return 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)
699 numBytes++;
701 byte [] result = new byte [numBytes];
703 int numBytesInWord = numBytes & 0x3;
704 if (numBytesInWord == 0) numBytesInWord = 4;
706 int pos = 0;
707 for (int i = (int)length - 1; i >= 0; i--) {
708 uint val = data [i];
709 for (int j = numBytesInWord - 1; j >= 0; j--) {
710 result [pos+j] = (byte)(val & 0xFF);
711 val >>= 8;
713 pos += numBytesInWord;
714 numBytesInWord = 4;
716 return result;
719 #endregion
721 #region Compare
723 #if !INSIDE_CORLIB
724 [CLSCompliant (false)]
725 #endif
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;
732 #if !INSIDE_CORLIB
733 [CLSCompliant (false)]
734 #endif
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))
745 return true;
746 if (null == bi1 || null == bi2)
747 return false;
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))
755 return false;
756 if (null == bi1 || null == bi2)
757 return true;
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);
786 #endregion
788 #region Formatting
790 #if !INSIDE_CORLIB
791 [CLSCompliant (false)]
792 #endif
793 public string ToString (uint radix)
795 return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
798 #if !INSIDE_CORLIB
799 [CLSCompliant (false)]
800 #endif
801 public string ToString (uint radix, string characterSet)
803 if (characterSet.Length < radix)
804 throw new ArgumentException ("charSet length less than radix", "characterSet");
805 if (radix == 1)
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";
811 string result = "";
813 BigInteger a = new BigInteger (this);
815 while (a != 0) {
816 uint rem = Kernel.SingleByteDivideInPlace (a, radix);
817 result = characterSet [(int) rem] + result;
820 return result;
823 #endregion
825 #region Misc
827 /// <summary>
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.
831 /// </summary>
832 private void Normalize ()
834 // Normalize length
835 while (length > 0 && data [length-1] == 0) length--;
837 // Check for zero
838 if (length == 0)
839 length++;
842 public void Clear ()
844 for (int i=0; i < length; i++)
845 data [i] = 0x00;
848 #endregion
850 #region Object Impl
852 public override int GetHashCode ()
854 uint val = 0;
856 for (uint i = 0; i < this.length; i++)
857 val ^= this.data [i];
859 return (int)val;
862 public override string ToString ()
864 return ToString (10);
867 public override bool Equals (object o)
869 if (o == null)
870 return false;
871 if (o is int)
872 return (int)o >= 0 && this == (uint)o;
874 BigInteger bi = o as BigInteger;
875 if (bi == null)
876 return false;
878 return Kernel.Compare (this, bi) == 0;
881 #endregion
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);
901 #endregion
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])
911 return true;
913 // the list is complete, so it's not a prime
914 return false;
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)
920 return false;
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);
926 #endregion
928 #region Prime Number Generation
930 /// <summary>
931 /// Generates the smallest prime >= bi
932 /// </summary>
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);
947 /// <summary>
948 /// Increments this by two
949 /// </summary>
950 public void Incr2 ()
952 int i = 0;
954 data [0] += 2;
956 // If there was no carry, nothing to do
957 if (data [0] < 2) {
959 // Account for the first carry
960 data [++i]++;
962 // Keep adding until no carry
963 while (data [i++] == 0x0)
964 data [i]++;
966 // See if we increased the data length
967 if (length == (uint)i)
968 length++;
972 #endregion
974 #if INSIDE_CORLIB
975 internal
976 #else
977 public
978 #endif
979 sealed class ModulusRing {
981 BigInteger mod, constant;
983 public ModulusRing (BigInteger modulus)
985 this.mod = 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)
998 BigInteger n = mod;
999 uint k = n.length,
1000 kPlusOne = k+1,
1001 kMinusOne = k-1;
1003 // x < mod, so nothing to do.
1004 if (x.length < k) return;
1006 BigInteger q3;
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;
1027 x.Normalize ();
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);
1035 r2.Normalize ();
1037 if (r2 <= x) {
1038 Kernel.MinusEq (x, r2);
1039 } else {
1040 BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
1041 val.data [kPlusOne] = 0x00000001;
1043 Kernel.MinusEq (val, r2);
1044 Kernel.PlusEq (x, val);
1047 while (x >= n)
1048 Kernel.MinusEq (x, n);
1051 public BigInteger Multiply (BigInteger a, BigInteger b)
1053 if (a == 0 || b == 0) return 0;
1055 if (a > mod)
1056 a %= mod;
1058 if (b > mod)
1059 b %= mod;
1061 BigInteger ret = a * b;
1062 BarrettReduction (ret);
1064 return ret;
1067 public BigInteger Difference (BigInteger a, BigInteger b)
1069 Sign cmp = Kernel.Compare (a, b);
1070 BigInteger diff;
1072 switch (cmp) {
1073 case Sign.Zero:
1074 return 0;
1075 case Sign.Positive:
1076 diff = a - b; break;
1077 case Sign.Negative:
1078 diff = b - a; break;
1079 default:
1080 throw new Exception ();
1083 if (diff >= mod) {
1084 if (diff.length >= mod.length << 1)
1085 diff %= mod;
1086 else
1087 BarrettReduction (diff);
1089 if (cmp == Sign.Negative)
1090 diff = mod - diff;
1091 return diff;
1093 #if true
1094 public BigInteger Pow (BigInteger a, BigInteger k)
1096 BigInteger b = new BigInteger (1);
1097 if (k == 0)
1098 return b;
1100 BigInteger A = a;
1101 if (k.TestBit (0))
1102 b = a;
1104 for (int i = 1; i < k.BitCount (); i++) {
1105 A = Multiply (A, A);
1106 if (k.TestBit (i))
1107 b = Multiply (A, b);
1109 return b;
1111 #else
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;
1136 resultNum.data = t;
1138 BarrettReduction (resultNum);
1141 Kernel.SquarePositive (tempNum, ref wkspace);
1142 BarrettReduction (tempNum);
1144 if (tempNum == 1) {
1145 return resultNum;
1149 return resultNum;
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;
1170 resultNum.data = t;
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);
1183 return resultNum;
1185 #endif
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
1190 #if !INSIDE_CORLIB
1191 [CLSCompliant (false)]
1192 #endif
1193 #if true
1194 public BigInteger Pow (uint b, BigInteger exp)
1196 return Pow (new BigInteger (b), exp);
1198 #else
1199 public BigInteger Pow (uint b, BigInteger exp)
1201 // if (b != 2) {
1202 if ((mod.data [0] & 1) == 1)
1203 return OddPow (b, exp);
1204 else
1205 return EvenPow (b, exp);
1206 /* buggy in some cases (like the well tested primes)
1207 } else {
1208 if ((mod.data [0] & 1) == 1)
1209 return OddModTwoPow (exp);
1210 else
1211 return EvenModTwoPow (exp);
1215 private unsafe BigInteger OddPow (uint b, BigInteger exp)
1217 exp.Normalize ();
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
1232 do {
1234 // r = r ^ 2 % m
1236 Kernel.SquarePositive (resultNum, ref wkspace);
1237 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1239 if (exp.TestBit (pos)) {
1242 // r = r * b % m
1245 // TODO: Is Unsafe really speeding things up?
1246 fixed (uint* u = resultNum.data) {
1248 uint i = 0;
1249 ulong mc = 0;
1251 do {
1252 mc += (ulong)u [i] * (ulong)b;
1253 u [i] = (uint)mc;
1254 mc >>= 32;
1255 } while (++i < resultNum.length);
1257 if (resultNum.length < mod.length) {
1258 if (mc != 0) {
1259 u [i] = (uint)mc;
1260 resultNum.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.
1272 uint cc = (uint)mc;
1274 // We would rather have this estimate overshoot,
1275 // so we add one to the divisor
1276 uint divEstimate;
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));
1281 else {
1282 // guess but don't divide by 0
1283 divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
1284 (mod.data [mod.length-1]));
1287 uint t;
1289 i = 0;
1290 mc = 0;
1291 do {
1292 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1293 t = u [i];
1294 u [i] -= (uint)mc;
1295 mc >>= 32;
1296 if (u [i] > t) mc++;
1297 i++;
1298 } while (i < resultNum.length);
1299 cc -= (uint)mc;
1301 if (cc != 0) {
1303 uint sc = 0, j = 0;
1304 uint [] s = mod.data;
1305 do {
1306 uint a = s [j];
1307 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1308 else sc = 0;
1309 j++;
1310 } while (j < resultNum.length);
1311 cc -= sc;
1313 while (resultNum >= mod)
1314 Kernel.MinusEq (resultNum, mod);
1315 } else {
1316 while (resultNum >= mod)
1317 Kernel.MinusEq (resultNum, mod);
1321 } while (pos-- > 0);
1323 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1324 return resultNum;
1328 private unsafe BigInteger EvenPow (uint b, BigInteger exp)
1330 exp.Normalize ();
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
1340 do {
1342 // r = r ^ 2 % m
1344 Kernel.SquarePositive (resultNum, ref wkspace);
1345 if (!(resultNum.length < mod.length))
1346 BarrettReduction (resultNum);
1348 if (exp.TestBit (pos)) {
1351 // r = r * b % m
1354 // TODO: Is Unsafe really speeding things up?
1355 fixed (uint* u = resultNum.data) {
1357 uint i = 0;
1358 ulong mc = 0;
1360 do {
1361 mc += (ulong)u [i] * (ulong)b;
1362 u [i] = (uint)mc;
1363 mc >>= 32;
1364 } while (++i < resultNum.length);
1366 if (resultNum.length < mod.length) {
1367 if (mc != 0) {
1368 u [i] = (uint)mc;
1369 resultNum.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.
1381 uint cc = (uint)mc;
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));
1388 uint t;
1390 i = 0;
1391 mc = 0;
1392 do {
1393 mc += (ulong)mod.data [i] * (ulong)divEstimate;
1394 t = u [i];
1395 u [i] -= (uint)mc;
1396 mc >>= 32;
1397 if (u [i] > t) mc++;
1398 i++;
1399 } while (i < resultNum.length);
1400 cc -= (uint)mc;
1402 if (cc != 0) {
1404 uint sc = 0, j = 0;
1405 uint [] s = mod.data;
1406 do {
1407 uint a = s [j];
1408 if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
1409 else sc = 0;
1410 j++;
1411 } while (j < resultNum.length);
1412 cc -= sc;
1414 while (resultNum >= mod)
1415 Kernel.MinusEq (resultNum, mod);
1416 } else {
1417 while (resultNum >= mod)
1418 Kernel.MinusEq (resultNum, mod);
1422 } while (pos-- > 0);
1424 return resultNum;
1426 #endif
1427 /* known to be buggy in some cases */
1428 #if false
1429 private unsafe BigInteger EvenModTwoPow (BigInteger exp)
1431 exp.Normalize ();
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)
1441 mask >>= 1;
1444 // We know that the first itr will make the val 2,
1445 // so eat one bit of the exponent
1447 mask >>= 1;
1449 uint wPos = exp.length - 1;
1451 do {
1452 value = exp.data [wPos];
1453 do {
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) {
1465 // Double
1467 uint* uu = u;
1468 uint* uuE = u + resultNum.length;
1469 uint x, carry = 0;
1470 while (uu < uuE) {
1471 x = *uu;
1472 *uu = (x << 1) | carry;
1473 carry = x >> (32 - 1);
1474 uu++;
1477 // subtraction inlined because we know it is square
1478 if (carry != 0 || resultNum >= mod) {
1479 uu = u;
1480 uint c = 0;
1481 uint [] s = mod.data;
1482 uint i = 0;
1483 do {
1484 uint a = s [i];
1485 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1486 c = 1;
1487 else
1488 c = 0;
1489 i++;
1490 } while (uu < uuE);
1494 } while ((mask >>= 1) > 0);
1495 mask = 0x80000000;
1496 } while (wPos-- > 0);
1498 return resultNum;
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;
1516 do {
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) {
1527 // Double
1529 uint* uu = u;
1530 uint* uuE = u + resultNum.length;
1531 uint x, carry = 0;
1532 while (uu < uuE) {
1533 x = *uu;
1534 *uu = (x << 1) | carry;
1535 carry = x >> (32 - 1);
1536 uu++;
1539 // subtraction inlined because we know it is square
1540 if (carry != 0 || resultNum >= mod) {
1541 fixed (uint* s = mod.data) {
1542 uu = u;
1543 uint c = 0;
1544 uint* ss = s;
1545 do {
1546 uint a = *ss++;
1547 if (((a += c) < c) | ((* (uu++) -= a) > ~a))
1548 c = 1;
1549 else
1550 c = 0;
1551 } while (uu < uuE);
1556 } while (pos-- > 0);
1558 resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
1559 return resultNum;
1561 #endif
1562 #endregion
1565 /// <summary>
1566 /// Low level functions for the BigInteger
1567 /// </summary>
1568 private sealed class Kernel {
1570 #region Addition/Subtraction
1572 /// <summary>
1573 /// Adds two numbers with the same sign.
1574 /// </summary>
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)
1580 uint [] x, y;
1581 uint yMax, xMax, i = 0;
1583 // x should be bigger
1584 if (bi1.length < bi2.length) {
1585 x = bi2.data;
1586 xMax = bi2.length;
1587 y = bi1.data;
1588 yMax = bi1.length;
1589 } else {
1590 x = bi1.data;
1591 xMax = bi1.length;
1592 y = bi2.data;
1593 yMax = bi2.length;
1596 BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
1598 uint [] r = result.data;
1600 ulong sum = 0;
1602 // Add common parts of both numbers
1603 do {
1604 sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
1605 r [i] = (uint)sum;
1606 sum >>= 32;
1607 } while (++i < yMax);
1609 // Copy remainder of longer number while carry propagation is required
1610 bool carry = (sum != 0);
1612 if (carry) {
1614 if (i < xMax) {
1616 carry = ((r [i] = x [i] + 1) == 0);
1617 while (++i < xMax && carry);
1620 if (carry) {
1621 r [i] = 1;
1622 result.length = ++i;
1623 return result;
1627 // Copy the rest
1628 if (i < xMax) {
1630 r [i] = x [i];
1631 while (++i < xMax);
1634 result.Normalize ();
1635 return result;
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;
1643 uint i = 0, c = 0;
1645 do {
1647 uint x = s [i];
1648 if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
1649 c = 1;
1650 else
1651 c = 0;
1653 } while (++i < small.length);
1655 if (i == big.length) goto fixup;
1657 if (c == 1) {
1659 r [i] = b [i] - 1;
1660 while (b [i++] == 0 && i < big.length);
1662 if (i == big.length) goto fixup;
1666 r [i] = b [i];
1667 while (++i < big.length);
1669 fixup:
1671 result.Normalize ();
1672 return result;
1675 public static void MinusEq (BigInteger big, BigInteger small)
1677 uint [] b = big.data, s = small.data;
1678 uint i = 0, c = 0;
1680 do {
1681 uint x = s [i];
1682 if (((x += c) < c) | ((b [i] -= x) > ~x))
1683 c = 1;
1684 else
1685 c = 0;
1686 } while (++i < small.length);
1688 if (i == big.length) goto fixup;
1690 if (c == 1) {
1692 b [i]--;
1693 while (b [i++] == 0 && i < big.length);
1696 fixup:
1698 // Normalize length
1699 while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
1701 // Check for zero
1702 if (big.length == 0)
1703 big.length++;
1707 public static void PlusEq (BigInteger bi1, BigInteger bi2)
1709 uint [] x, y;
1710 uint yMax, xMax, i = 0;
1711 bool flag = false;
1713 // x should be bigger
1714 if (bi1.length < bi2.length){
1715 flag = true;
1716 x = bi2.data;
1717 xMax = bi2.length;
1718 y = bi1.data;
1719 yMax = bi1.length;
1720 } else {
1721 x = bi1.data;
1722 xMax = bi1.length;
1723 y = bi2.data;
1724 yMax = bi2.length;
1727 uint [] r = bi1.data;
1729 ulong sum = 0;
1731 // Add common parts of both numbers
1732 do {
1733 sum += ((ulong)x [i]) + ((ulong)y [i]);
1734 r [i] = (uint)sum;
1735 sum >>= 32;
1736 } while (++i < yMax);
1738 // Copy remainder of longer number while carry propagation is required
1739 bool carry = (sum != 0);
1741 if (carry){
1743 if (i < xMax) {
1745 carry = ((r [i] = x [i] + 1) == 0);
1746 while (++i < xMax && carry);
1749 if (carry) {
1750 r [i] = 1;
1751 bi1.length = ++i;
1752 return;
1756 // Copy the rest
1757 if (flag && i < xMax - 1) {
1759 r [i] = x [i];
1760 while (++i < xMax);
1763 bi1.length = xMax + 1;
1764 bi1.Normalize ();
1767 #endregion
1769 #region Compare
1771 /// <summary>
1772 /// Compares two BigInteger
1773 /// </summary>
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
1798 uint pos = l1 - 1;
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;
1806 else
1807 return Sign.Zero;
1810 #endregion
1812 #region Division
1814 #region Dword
1816 /// <summary>
1817 /// Performs n / d and n % d in one operation.
1818 /// </summary>
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)
1824 ulong r = 0;
1825 uint i = n.length;
1827 while (i-- > 0) {
1828 r <<= 32;
1829 r |= n.data [i];
1830 n.data [i] = (uint)(r / d);
1831 r %= d;
1833 n.Normalize ();
1835 return (uint)r;
1838 public static uint DwordMod (BigInteger n, uint d)
1840 ulong r = 0;
1841 uint i = n.length;
1843 while (i-- > 0) {
1844 r <<= 32;
1845 r |= n.data [i];
1846 r %= d;
1849 return (uint)r;
1852 public static BigInteger DwordDiv (BigInteger n, uint d)
1854 BigInteger ret = new BigInteger (Sign.Positive, n.length);
1856 ulong r = 0;
1857 uint i = n.length;
1859 while (i-- > 0) {
1860 r <<= 32;
1861 r |= n.data [i];
1862 ret.data [i] = (uint)(r / d);
1863 r %= d;
1865 ret.Normalize ();
1867 return ret;
1870 public static BigInteger [] DwordDivMod (BigInteger n, uint d)
1872 BigInteger ret = new BigInteger (Sign.Positive , n.length);
1874 ulong r = 0;
1875 uint i = n.length;
1877 while (i-- > 0) {
1878 r <<= 32;
1879 r |= n.data [i];
1880 ret.data [i] = (uint)(r / d);
1881 r %= d;
1883 ret.Normalize ();
1885 BigInteger rem = (uint)r;
1887 return new BigInteger [] {ret, rem};
1890 #endregion
1892 #region BigNum
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];
1909 int shift = 0;
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;
1921 bi2 = bi2 << shift;
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];
1929 while (j > 0) {
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;
1935 do {
1937 if (q_hat == 0x100000000 ||
1938 (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
1939 q_hat--;
1940 r_hat += (ulong)firstDivisorByte;
1942 if (r_hat < 0x100000000)
1943 continue;
1945 break;
1946 } while (true);
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.
1955 uint t;
1956 uint dPos = 0;
1957 int nPos = pos - divisorLen + 1;
1958 ulong mc = 0;
1959 uint uint_q_hat = (uint)q_hat;
1960 do {
1961 mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
1962 t = remainder [nPos];
1963 remainder [nPos] -= (uint)mc;
1964 mc >>= 32;
1965 if (remainder [nPos] > t) mc++;
1966 dPos++; nPos++;
1967 } while (dPos < divisorLen);
1969 nPos = pos - divisorLen + 1;
1970 dPos = 0;
1972 // Overestimate
1973 if (mc != 0) {
1974 uint_q_hat--;
1975 ulong sum = 0;
1977 do {
1978 sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
1979 remainder [nPos] = (uint)sum;
1980 sum >>= 32;
1981 dPos++; nPos++;
1982 } while (dPos < divisorLen);
1986 quot.data [resultPos--] = (uint)uint_q_hat;
1988 pos--;
1989 j--;
1992 quot.Normalize ();
1993 rem.Normalize ();
1994 BigInteger [] ret = new BigInteger [2] { quot, rem };
1996 if (shift != 0)
1997 ret [1] >>= shift;
1999 return ret;
2002 #endregion
2004 #endregion
2006 #region Shift
2007 public static BigInteger LeftShift (BigInteger bi, int n)
2009 if (n == 0) return new BigInteger (bi, bi.length + 1);
2011 int w = n >> 5;
2012 n &= ((1 << 5) - 1);
2014 BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
2016 uint i = 0, l = bi.length;
2017 if (n != 0) {
2018 uint x, carry = 0;
2019 while (i < l) {
2020 x = bi.data [i];
2021 ret.data [i + w] = (x << n) | carry;
2022 carry = x >> (32 - n);
2023 i++;
2025 ret.data [i + w] = carry;
2026 } else {
2027 while (i < l) {
2028 ret.data [i + w] = bi.data [i];
2029 i++;
2033 ret.Normalize ();
2034 return ret;
2037 public static BigInteger RightShift (BigInteger bi, int n)
2039 if (n == 0) return new BigInteger (bi);
2041 int w = n >> 5;
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;
2047 if (s != 0) {
2049 uint x, carry = 0;
2051 while (l-- > 0) {
2052 x = bi.data [l + w];
2053 ret.data [l] = (x >> n) | carry;
2054 carry = x << (32 - n);
2056 } else {
2057 while (l-- > 0)
2058 ret.data [l] = bi.data [l + w];
2061 ret.Normalize ();
2062 return ret;
2065 #endregion
2067 #region Multiply
2069 public static BigInteger MultiplyByDword (BigInteger n, uint f)
2071 BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
2073 uint i = 0;
2074 ulong c = 0;
2076 do {
2077 c += (ulong)n.data [i] * (ulong)f;
2078 ret.data [i] = (uint)c;
2079 c >>= 32;
2080 } while (++i < n.length);
2081 ret.data [i] = (uint)c;
2082 ret.Normalize ();
2083 return ret;
2087 /// <summary>
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].
2091 /// </summary>
2092 /// <remarks>
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].
2096 /// </remarks>
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,
2101 xE = xP + xLen,
2102 yB = yy + yOffset,
2103 yE = yB + yLen,
2104 dB = dd + dOffset;
2106 for (; xP < xE; xP++, dB++) {
2108 if (*xP == 0) continue;
2110 ulong mcarry = 0;
2112 uint* dP = dB;
2113 for (uint* yP = yB; yP < yE; yP++, dP++) {
2114 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2116 *dP = (uint)mcarry;
2117 mcarry >>= 32;
2120 if (mcarry != 0)
2121 *dP = (uint)mcarry;
2126 /// <summary>
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].
2130 /// </summary>
2131 /// <remarks>
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].
2135 /// </remarks>
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,
2140 xE = xP + xLen,
2141 yB = yy + yOffest,
2142 yE = yB + yLen,
2143 dB = dd + dOffset,
2144 dE = dB + mod;
2146 for (; xP < xE; xP++, dB++) {
2148 if (*xP == 0) continue;
2150 ulong mcarry = 0;
2151 uint* dP = dB;
2152 for (uint* yP = yB; yP < yE && dP < dE; yP++, dP++) {
2153 mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
2155 *dP = (uint)mcarry;
2156 mcarry >>= 32;
2159 if (mcarry != 0 && dP < dE)
2160 *dP = (uint)mcarry;
2165 public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
2167 uint [] t = wkSpace;
2168 wkSpace = bi.data;
2169 uint [] d = bi.data;
2170 uint dl = bi.length;
2171 bi.data = t;
2173 fixed (uint* dd = d, tt = t) {
2175 uint* ttE = tt + t.Length;
2176 // Clear the dest
2177 for (uint* ttt = tt; ttt < ttE; ttt++)
2178 *ttt = 0;
2180 uint* dP = dd, tP = tt;
2182 for (uint i = 0; i < dl; i++, dP++) {
2183 if (*dP == 0)
2184 continue;
2186 ulong mcarry = 0;
2187 uint bi1val = *dP;
2189 uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
2191 for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
2192 // k = i + j
2193 mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
2195 *tP2 = (uint)mcarry;
2196 mcarry >>= 32;
2199 if (mcarry != 0)
2200 *tP2 = (uint)mcarry;
2203 // Double t. Inlined for speed.
2205 tP = tt;
2207 uint x, carry = 0;
2208 while (tP < ttE) {
2209 x = *tP;
2210 *tP = (x << 1) | carry;
2211 carry = x >> (32 - 1);
2212 tP++;
2214 if (carry != 0) *tP = carry;
2216 // Add in the diagnals
2218 dP = dd;
2219 tP = tt;
2220 for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
2221 ulong val = (ulong)*dP * (ulong)*dP + *tP;
2222 *tP = (uint)val;
2223 val >>= 32;
2224 *(++tP) += (uint)val;
2225 if (*tP < (uint)val) {
2226 uint* tP3 = tP;
2227 // Account for the first carry
2228 (*++tP3)++;
2230 // Keep adding until no carry
2231 while ((*tP3++) == 0)
2232 (*tP3)++;
2237 bi.length <<= 1;
2239 // Normalize length
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)
2249 uint x, carry = 0;
2250 uint i = 0;
2251 while (i < l) {
2252 x = u [i];
2253 u [i] = (x << 1) | carry;
2254 carry = x >> (32 - 1);
2255 i++;
2257 if (carry != 0) u [l] = carry;
2258 return carry != 0;
2261 #endregion
2263 #region Number Theory
2265 public static BigInteger gcd (BigInteger a, BigInteger b)
2267 BigInteger x = a;
2268 BigInteger y = b;
2270 BigInteger g = y;
2272 while (x.length > 1) {
2273 g = x;
2274 x = y % x;
2275 y = g;
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];
2288 uint xx = y % yy;
2290 int t = 0;
2292 while (((xx | yy) & 1) == 0) {
2293 xx >>= 1; yy >>= 1; t++;
2295 while (xx != 0) {
2296 while ((xx & 1) == 0) xx >>= 1;
2297 while ((yy & 1) == 0) yy >>= 1;
2298 if (xx >= yy)
2299 xx = (xx - yy) >> 1;
2300 else
2301 yy = (yy - xx) >> 1;
2304 return yy << t;
2307 public static uint modInverse (BigInteger bi, uint modulus)
2309 uint a = modulus, b = bi % modulus;
2310 uint p0 = 0, p1 = 1;
2312 while (b != 0) {
2313 if (b == 1)
2314 return p1;
2315 p0 += (a / b) * p1;
2316 a %= b;
2318 if (a == 0)
2319 break;
2320 if (a == 1)
2321 return modulus-p0;
2323 p1 += (b / a) * p0;
2324 b %= a;
2327 return 0;
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
2338 int step = 0;
2340 BigInteger a = modulus;
2341 BigInteger b = bi;
2343 ModulusRing mr = new ModulusRing (modulus);
2345 while (b != 0) {
2347 if (step > 1) {
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];
2357 a = b;
2358 b = divret [1];
2360 step++;
2363 if (r [0] != 1)
2364 throw (new ArithmeticException ("No inverse!"));
2366 return mr.Difference (p [0], p [1] * q [0]);
2369 #endregion