2 // System.Numerics.BigInteger
4 // Rodrigo Kumpera (rkumpera@novell.com)
7 // Copyright (C) 2010 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 // A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com),
29 // which has the following License:
31 /* ****************************************************************************
33 * Copyright (c) Microsoft Corporation.
35 * This source code is subject to terms and conditions of the Microsoft Public License. A
36 * copy of the license can be found in the License.html file at the root of this distribution. If
37 * you cannot locate the Microsoft Public License, please send an email to
38 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
39 * by the terms of the Microsoft Public License.
41 * You must not remove this notice, or any other, from this software.
44 * ***************************************************************************/
47 using System.Collections.Generic;
48 using System.Diagnostics;
49 using System.Diagnostics.CodeAnalysis;
50 using System.Globalization;
52 using System.Threading;
56 Have proper popcount function for IsPowerOfTwo
57 Use unsafe ops to avoid bounds check
58 CoreAdd could avoid some resizes by checking for equal sized array that top overflow
59 For bitwise operators, hoist the conditionals out of their main loop
60 Optimize BitScanBackward
61 Use a carry variable to make shift opts do half the number of array ops.
62 Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
64 namespace System.Numerics {
65 public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
71 static readonly uint[] ZERO = new uint [1];
72 static readonly uint[] ONE = new uint [1] { 1 };
74 BigInteger (short sign, uint[] data)
80 public BigInteger (int value)
85 } else if (value > 0) {
87 data = new uint[] { (uint) value };
90 data = new uint[1] { (uint)-value };
94 [CLSCompliantAttribute (false)]
95 public BigInteger (uint value)
102 data = new uint [1] { value };
106 public BigInteger (long value)
111 } else if (value > 0) {
113 uint low = (uint)value;
114 uint high = (uint)(value >> 32);
116 data = new uint [high != 0 ? 2 : 1];
123 uint low = (uint)value;
124 uint high = (uint)((ulong)value >> 32);
126 data = new uint [high != 0 ? 2 : 1];
133 [CLSCompliantAttribute (false)]
134 public BigInteger (ulong value)
141 uint low = (uint)value;
142 uint high = (uint)(value >> 32);
144 data = new uint [high != 0 ? 2 : 1];
152 static bool Negative (byte[] v)
154 return ((v[7] & 0x80) != 0);
157 static ushort Exponent (byte[] v)
159 return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
162 static ulong Mantissa(byte[] v)
164 uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
165 uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
167 return (ulong)((ulong)i1 | ((ulong)i2 << 32));
170 const int bias = 1075;
171 public BigInteger (double value)
173 if (double.IsNaN (value) || Double.IsInfinity (value))
174 throw new OverflowException ();
176 byte[] bytes = BitConverter.GetBytes (value);
177 ulong mantissa = Mantissa (bytes);
179 // 1.0 * 2**exp, we have a power of 2
180 int exponent = Exponent (bytes);
187 BigInteger res = Negative (bytes) ? MinusOne : One;
188 res = res << (exponent - 0x3ff);
189 this.sign = res.sign;
190 this.data = res.data;
192 // 1.mantissa * 2**exp
193 int exponent = Exponent(bytes);
194 mantissa |= 0x10000000000000ul;
195 BigInteger res = mantissa;
196 res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent);
198 this.sign = (short) (Negative (bytes) ? -1 : 1);
199 this.data = res.data;
203 public BigInteger (float value) : this ((double)value)
207 const Int32 DecimalScaleFactorMask = 0x00FF0000;
208 const Int32 DecimalSignMask = unchecked((Int32)0x80000000);
210 public BigInteger (decimal value)
212 // First truncate to get scale to 0 and extract bits
213 int[] bits = Decimal.GetBits(Decimal.Truncate(value));
216 while (size > 0 && bits[size - 1] == 0) size--;
224 sign = (short) ((bits [3] & DecimalSignMask) != 0 ? -1 : 1);
226 data = new uint [size];
227 data [0] = (uint)bits [0];
229 data [1] = (uint)bits [1];
231 data [2] = (uint)bits [2];
234 [CLSCompliantAttribute (false)]
235 public BigInteger (byte[] value)
238 throw new ArgumentNullException ("value");
240 int len = value.Length;
242 if (len == 0 || (len == 1 && value [0] == 0)) {
248 if ((value [len - 1] & 0x80) != 0)
254 while (value [len - 1] == 0) {
262 int full_words, size;
263 full_words = size = len / 4;
264 if ((len & 0x3) != 0)
267 data = new uint [size];
269 for (int i = 0; i < full_words; ++i) {
270 data [i] = (uint)value [j++] |
271 (uint)(value [j++] << 8) |
272 (uint)(value [j++] << 16) |
273 (uint)(value [j++] << 24);
277 int idx = data.Length - 1;
278 for (int i = 0; i < size; ++i)
279 data [idx] |= (uint)(value [j++] << (i * 8));
282 int full_words, size;
283 full_words = size = len / 4;
284 if ((len & 0x3) != 0)
287 data = new uint [size];
289 uint word, borrow = 1;
293 for (int i = 0; i < full_words; ++i) {
294 word = (uint)value [j++] |
295 (uint)(value [j++] << 8) |
296 (uint)(value [j++] << 16) |
297 (uint)(value [j++] << 24);
299 sub = (ulong)word - borrow;
301 borrow = (uint)(sub >> 32) & 0x1u;
309 for (int i = 0; i < size; ++i) {
310 word |= (uint)(value [j++] << (i * 8));
311 store_mask = (store_mask << 8) | 0xFF;
316 borrow = (uint)(sub >> 32) & 0x1u;
318 data [data.Length - 1] = ~word & store_mask;
320 if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
321 throw new Exception ("non zero final carry");
327 get { return sign == 0 || (data [0] & 0x1) == 0; }
331 get { return sign == 1 && data.Length == 1 && data [0] == 1; }
335 //Gem from Hacker's Delight
336 //Returns the number of bits set in @x
337 static int PopulationCount (uint x)
339 x = x - ((x >> 1) & 0x55555555);
340 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
341 x = (x + (x >> 4)) & 0x0F0F0F0F;
344 return (int)(x & 0x0000003F);
347 static int LeadingZeroCount(uint value)
353 value |= value >> 16;
354 return 32 - PopulationCount (value); // 32 = bits in uint
357 public bool IsPowerOfTwo {
359 bool foundBit = false;
362 //This function is pop count == 1 for positive numbers
363 for (int i = 0; i < data.Length; ++i) {
364 int p = PopulationCount (data [i]);
366 if (p > 1 || foundBit)
376 get { return sign == 0; }
383 public static BigInteger MinusOne {
384 get { return new BigInteger (-1, ONE); }
387 public static BigInteger One {
388 get { return new BigInteger (1, ONE); }
391 public static BigInteger Zero {
392 get { return new BigInteger (0, ZERO); }
395 public static explicit operator int (BigInteger value)
399 if (value.data.Length > 1)
400 throw new OverflowException ();
401 uint data = value.data [0];
403 if (value.sign == 1) {
404 if (data > (uint)int.MaxValue)
405 throw new OverflowException ();
407 } else if (value.sign == -1) {
408 if (data > 0x80000000u)
409 throw new OverflowException ();
416 [CLSCompliantAttribute (false)]
417 public static explicit operator uint (BigInteger value)
421 if (value.data.Length > 1 || value.sign == -1)
422 throw new OverflowException ();
423 return value.data [0];
426 public static explicit operator short (BigInteger value)
428 int val = (int)value;
429 if (val < short.MinValue || val > short.MaxValue)
430 throw new OverflowException ();
434 [CLSCompliantAttribute (false)]
435 public static explicit operator ushort (BigInteger value)
437 uint val = (uint)value;
438 if (val > ushort.MaxValue)
439 throw new OverflowException ();
443 public static explicit operator byte (BigInteger value)
445 uint val = (uint)value;
446 if (val > byte.MaxValue)
447 throw new OverflowException ();
451 [CLSCompliantAttribute (false)]
452 public static explicit operator sbyte (BigInteger value)
454 int val = (int)value;
455 if (val < sbyte.MinValue || val > sbyte.MaxValue)
456 throw new OverflowException ();
461 public static explicit operator long (BigInteger value)
466 if (value.data.Length > 2)
467 throw new OverflowException ();
469 uint low = value.data [0];
471 if (value.data.Length == 1) {
474 long res = (long)low;
478 uint high = value.data [1];
480 if (value.sign == 1) {
481 if (high >= 0x80000000u)
482 throw new OverflowException ();
483 return (((long)high) << 32) | low;
487 We cannot represent negative numbers smaller than long.MinValue.
488 Those values are encoded into what look negative numbers, so negating
489 them produces a positive value, that's why it's safe to check for that
492 long.MinValue works fine since it's bigint encoding looks like a negative
493 number, but since long.MinValue == -long.MinValue, we're good.
496 long result = - ((((long)high) << 32) | (long)low);
498 throw new OverflowException ();
502 [CLSCompliantAttribute (false)]
503 public static explicit operator ulong (BigInteger value)
507 if (value.data.Length > 2 || value.sign == -1)
508 throw new OverflowException ();
510 uint low = value.data [0];
511 if (value.data.Length == 1)
514 uint high = value.data [1];
515 return (((ulong)high) << 32) | low;
518 public static explicit operator double (BigInteger value)
520 switch (value.data.Length) {
524 return (value.sign > 0 ? 1 : - 1) * (double)value.data [0];
526 return (value.sign > 0 ? 1 : - 1) * (double)((ulong)value.data [1] << 32 | (ulong)value.data [0]);
528 var index = value.data.Length - 1;
529 var word = value.data [index];
530 var mantissa = ((ulong)word << 32) | value.data [index - 1];
531 int missing = LeadingZeroCount (word) - 11; // 11 = bits in exponent
533 // add the missing bits from the next word
534 mantissa = (mantissa << missing) | (value.data [index - 2] >> (32 - missing));
536 mantissa >>= -missing;
538 return (value.sign > 0 ? 1 : - 1) * (double)mantissa * Math.Pow (2, ((value.data.Length - 2) * 32) - missing);
542 public static explicit operator float (BigInteger value)
544 switch (value.data.Length) {
548 return (value.sign > 0 ? 1 : - 1) * (float)value.data [0];
550 var index = value.data.Length - 1;
551 var mantissa = value.data [index];
552 int missing = LeadingZeroCount (mantissa) - 8; // 8 = bits in exponent
554 // add the missing bits from the next word
555 mantissa = (mantissa << missing) | (value.data [index - 1] >> (32 - missing));
557 mantissa >>= -missing;
559 return (value.sign > 0 ? 1 : - 1) * (float)(mantissa * Math.Pow (2, ((value.data.Length - 1) * 32) - missing));
563 public static explicit operator decimal (BigInteger value)
568 uint[] data = value.data;
570 throw new OverflowException ();
572 int lo = 0, mi = 0, hi = 0;
574 hi = (Int32)data [2];
576 mi = (Int32)data [1];
578 lo = (Int32)data [0];
580 return new Decimal(lo, mi, hi, value.sign < 0, 0);
583 public static implicit operator BigInteger (int value)
585 return new BigInteger (value);
588 [CLSCompliantAttribute (false)]
589 public static implicit operator BigInteger (uint value)
591 return new BigInteger (value);
594 public static implicit operator BigInteger (short value)
596 return new BigInteger (value);
599 [CLSCompliantAttribute (false)]
600 public static implicit operator BigInteger (ushort value)
602 return new BigInteger (value);
605 public static implicit operator BigInteger (byte value)
607 return new BigInteger (value);
610 [CLSCompliantAttribute (false)]
611 public static implicit operator BigInteger (sbyte value)
613 return new BigInteger (value);
616 public static implicit operator BigInteger (long value)
618 return new BigInteger (value);
621 [CLSCompliantAttribute (false)]
622 public static implicit operator BigInteger (ulong value)
624 return new BigInteger (value);
627 public static explicit operator BigInteger (double value)
629 return new BigInteger (value);
632 public static explicit operator BigInteger (float value)
634 return new BigInteger (value);
637 public static explicit operator BigInteger (decimal value)
639 return new BigInteger (value);
642 public static BigInteger operator+ (BigInteger left, BigInteger right)
649 if (left.sign == right.sign)
650 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
652 int r = CoreCompare (left.data, right.data);
655 return new BigInteger (0, ZERO);
657 if (r > 0) //left > right
658 return new BigInteger (left.sign, CoreSub (left.data, right.data));
660 return new BigInteger (right.sign, CoreSub (right.data, left.data));
663 public static BigInteger operator- (BigInteger left, BigInteger right)
668 return new BigInteger ((short)-right.sign, right.data);
670 if (left.sign == right.sign) {
671 int r = CoreCompare (left.data, right.data);
674 return new BigInteger (0, ZERO);
676 if (r > 0) //left > right
677 return new BigInteger (left.sign, CoreSub (left.data, right.data));
679 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
682 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
685 public static BigInteger operator* (BigInteger left, BigInteger right)
687 if (left.sign == 0 || right.sign == 0)
688 return new BigInteger (0, ZERO);
690 if (left.data [0] == 1 && left.data.Length == 1) {
693 return new BigInteger ((short)-right.sign, right.data);
696 if (right.data [0] == 1 && right.data.Length == 1) {
699 return new BigInteger ((short)-left.sign, left.data);
702 uint[] a = left.data;
703 uint[] b = right.data;
705 uint[] res = new uint [a.Length + b.Length];
707 for (int i = 0; i < a.Length; ++i) {
712 for (int j = 0; j < b.Length; ++j) {
713 carry = carry + ((ulong)ai) * b [j] + res [k];
714 res[k++] = (uint)carry;
720 res[k++] = (uint)carry;
726 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
727 if (m < res.Length - 1)
728 res = Resize (res, m + 1);
730 return new BigInteger ((short)(left.sign * right.sign), res);
733 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
735 if (divisor.sign == 0)
736 throw new DivideByZeroException ();
738 if (dividend.sign == 0)
742 uint[] remainder_value;
744 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
747 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
749 return new BigInteger (0, ZERO);
750 if (i < quotient.Length - 1)
751 quotient = Resize (quotient, i + 1);
753 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
756 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
758 if (divisor.sign == 0)
759 throw new DivideByZeroException ();
761 if (dividend.sign == 0)
765 uint[] remainder_value;
767 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
770 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
772 return new BigInteger (0, ZERO);
774 if (i < remainder_value.Length - 1)
775 remainder_value = Resize (remainder_value, i + 1);
776 return new BigInteger (dividend.sign, remainder_value);
779 public static BigInteger operator- (BigInteger value)
783 return new BigInteger ((short)-value.sign, value.data);
786 public static BigInteger operator+ (BigInteger value)
791 public static BigInteger operator++ (BigInteger value)
796 short sign = value.sign;
797 uint[] data = value.data;
798 if (data.Length == 1) {
799 if (sign == -1 && data [0] == 1)
800 return new BigInteger (0, ZERO);
802 return new BigInteger (1, ONE);
806 data = CoreSub (data, 1);
808 data = CoreAdd (data, 1);
810 return new BigInteger (sign, data);
813 public static BigInteger operator-- (BigInteger value)
818 short sign = value.sign;
819 uint[] data = value.data;
820 if (data.Length == 1) {
821 if (sign == 1 && data [0] == 1)
822 return new BigInteger (0, ZERO);
824 return new BigInteger (-1, ONE);
828 data = CoreAdd (data, 1);
830 data = CoreSub (data, 1);
832 return new BigInteger (sign, data);
835 public static BigInteger operator& (BigInteger left, BigInteger right)
843 uint[] a = left.data;
844 uint[] b = right.data;
848 bool neg_res = (ls == rs) && (ls == -1);
850 uint[] result = new uint [Math.Max (a.Length, b.Length)];
852 ulong ac = 1, bc = 1, borrow = 1;
855 for (i = 0; i < result.Length; ++i) {
862 ac = (uint)(ac >> 32);
871 bc = (uint)(bc >> 32);
877 borrow = word - borrow;
878 word = ~(uint)borrow;
879 borrow = (uint)(borrow >> 32) & 0x1u;
885 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
887 return new BigInteger (0, ZERO);
889 if (i < result.Length - 1)
890 result = Resize (result, i + 1);
892 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
895 public static BigInteger operator| (BigInteger left, BigInteger right)
903 uint[] a = left.data;
904 uint[] b = right.data;
908 bool neg_res = (ls == -1) || (rs == -1);
910 uint[] result = new uint [Math.Max (a.Length, b.Length)];
912 ulong ac = 1, bc = 1, borrow = 1;
915 for (i = 0; i < result.Length; ++i) {
922 ac = (uint)(ac >> 32);
931 bc = (uint)(bc >> 32);
937 borrow = word - borrow;
938 word = ~(uint)borrow;
939 borrow = (uint)(borrow >> 32) & 0x1u;
945 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
947 return new BigInteger (0, ZERO);
949 if (i < result.Length - 1)
950 result = Resize (result, i + 1);
952 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
955 public static BigInteger operator^ (BigInteger left, BigInteger right)
963 uint[] a = left.data;
964 uint[] b = right.data;
968 bool neg_res = (ls == -1) ^ (rs == -1);
970 uint[] result = new uint [Math.Max (a.Length, b.Length)];
972 ulong ac = 1, bc = 1, borrow = 1;
975 for (i = 0; i < result.Length; ++i) {
982 ac = (uint)(ac >> 32);
991 bc = (uint)(bc >> 32);
997 borrow = word - borrow;
998 word = ~(uint)borrow;
999 borrow = (uint)(borrow >> 32) & 0x1u;
1005 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1007 return new BigInteger (0, ZERO);
1009 if (i < result.Length - 1)
1010 result = Resize (result, i + 1);
1012 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1015 public static BigInteger operator~ (BigInteger value)
1017 if (value.sign == 0)
1018 return new BigInteger (-1, ONE);
1020 uint[] data = value.data;
1021 int sign = value.sign;
1023 bool neg_res = sign == 1;
1025 uint[] result = new uint [data.Length];
1027 ulong carry = 1, borrow = 1;
1030 for (i = 0; i < result.Length; ++i) {
1031 uint word = data [i];
1033 carry = ~word + carry;
1035 carry = (uint)(carry >> 32);
1041 borrow = word - borrow;
1042 word = ~(uint)borrow;
1043 borrow = (uint)(borrow >> 32) & 0x1u;
1049 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1051 return new BigInteger (0, ZERO);
1053 if (i < result.Length - 1)
1054 result = Resize (result, i + 1);
1056 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1059 //returns the 0-based index of the most significant set bit
1060 //returns 0 if no bit is set, so extra care when using it
1061 static int BitScanBackward (uint word)
1063 for (int i = 31; i >= 0; --i) {
1064 uint mask = 1u << i;
1065 if ((word & mask) == mask)
1071 public static BigInteger operator<< (BigInteger value, int shift)
1073 if (shift == 0 || value.sign == 0)
1076 return value >> -shift;
1078 uint[] data = value.data;
1079 int sign = value.sign;
1081 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1082 int bits = shift - (31 - topMostIdx);
1083 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
1085 uint[] res = new uint [data.Length + extra_words];
1087 int idx_shift = shift >> 5;
1088 int bit_shift = shift & 0x1F;
1089 int carry_shift = 32 - bit_shift;
1091 if (carry_shift == 32) {
1092 for (int i = 0; i < data.Length; ++i) {
1093 uint word = data [i];
1094 res [i + idx_shift] |= word << bit_shift;
1097 for (int i = 0; i < data.Length; ++i) {
1098 uint word = data [i];
1099 res [i + idx_shift] |= word << bit_shift;
1100 if (i + idx_shift + 1 < res.Length)
1101 res [i + idx_shift + 1] = word >> carry_shift;
1105 return new BigInteger ((short)sign, res);
1108 public static BigInteger operator>> (BigInteger value, int shift)
1110 if (shift == 0 || value.sign == 0)
1113 return value << -shift;
1115 uint[] data = value.data;
1116 int sign = value.sign;
1118 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1119 int idx_shift = shift >> 5;
1120 int bit_shift = shift & 0x1F;
1122 int extra_words = idx_shift;
1123 if (bit_shift > topMostIdx)
1125 int size = data.Length - extra_words;
1129 return new BigInteger (0, ZERO);
1130 return new BigInteger (-1, ONE);
1133 uint[] res = new uint [size];
1134 int carry_shift = 32 - bit_shift;
1136 if (carry_shift == 32) {
1137 for (int i = data.Length - 1; i >= idx_shift; --i) {
1138 uint word = data [i];
1140 if (i - idx_shift < res.Length)
1141 res [i - idx_shift] |= word >> bit_shift;
1144 for (int i = data.Length - 1; i >= idx_shift; --i) {
1145 uint word = data [i];
1147 if (i - idx_shift < res.Length)
1148 res [i - idx_shift] |= word >> bit_shift;
1149 if (i - idx_shift - 1 >= 0)
1150 res [i - idx_shift - 1] = word << carry_shift;
1155 //Round down instead of toward zero
1157 for (int i = 0; i < idx_shift; i++) {
1158 if (data [i] != 0u) {
1159 var tmp = new BigInteger ((short)sign, res);
1164 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
1165 var tmp = new BigInteger ((short)sign, res);
1170 return new BigInteger ((short)sign, res);
1173 public static bool operator< (BigInteger left, BigInteger right)
1175 return Compare (left, right) < 0;
1178 public static bool operator< (BigInteger left, long right)
1180 return left.CompareTo (right) < 0;
1184 public static bool operator< (long left, BigInteger right)
1186 return right.CompareTo (left) > 0;
1190 [CLSCompliantAttribute (false)]
1191 public static bool operator< (BigInteger left, ulong right)
1193 return left.CompareTo (right) < 0;
1196 [CLSCompliantAttribute (false)]
1197 public static bool operator< (ulong left, BigInteger right)
1199 return right.CompareTo (left) > 0;
1202 public static bool operator<= (BigInteger left, BigInteger right)
1204 return Compare (left, right) <= 0;
1207 public static bool operator<= (BigInteger left, long right)
1209 return left.CompareTo (right) <= 0;
1212 public static bool operator<= (long left, BigInteger right)
1214 return right.CompareTo (left) >= 0;
1217 [CLSCompliantAttribute (false)]
1218 public static bool operator<= (BigInteger left, ulong right)
1220 return left.CompareTo (right) <= 0;
1223 [CLSCompliantAttribute (false)]
1224 public static bool operator<= (ulong left, BigInteger right)
1226 return right.CompareTo (left) >= 0;
1229 public static bool operator> (BigInteger left, BigInteger right)
1231 return Compare (left, right) > 0;
1234 public static bool operator> (BigInteger left, long right)
1236 return left.CompareTo (right) > 0;
1239 public static bool operator> (long left, BigInteger right)
1241 return right.CompareTo (left) < 0;
1244 [CLSCompliantAttribute (false)]
1245 public static bool operator> (BigInteger left, ulong right)
1247 return left.CompareTo (right) > 0;
1250 [CLSCompliantAttribute (false)]
1251 public static bool operator> (ulong left, BigInteger right)
1253 return right.CompareTo (left) < 0;
1256 public static bool operator>= (BigInteger left, BigInteger right)
1258 return Compare (left, right) >= 0;
1261 public static bool operator>= (BigInteger left, long right)
1263 return left.CompareTo (right) >= 0;
1266 public static bool operator>= (long left, BigInteger right)
1268 return right.CompareTo (left) <= 0;
1271 [CLSCompliantAttribute (false)]
1272 public static bool operator>= (BigInteger left, ulong right)
1274 return left.CompareTo (right) >= 0;
1277 [CLSCompliantAttribute (false)]
1278 public static bool operator>= (ulong left, BigInteger right)
1280 return right.CompareTo (left) <= 0;
1283 public static bool operator== (BigInteger left, BigInteger right)
1285 return Compare (left, right) == 0;
1288 public static bool operator== (BigInteger left, long right)
1290 return left.CompareTo (right) == 0;
1293 public static bool operator== (long left, BigInteger right)
1295 return right.CompareTo (left) == 0;
1298 [CLSCompliantAttribute (false)]
1299 public static bool operator== (BigInteger left, ulong right)
1301 return left.CompareTo (right) == 0;
1304 [CLSCompliantAttribute (false)]
1305 public static bool operator== (ulong left, BigInteger right)
1307 return right.CompareTo (left) == 0;
1310 public static bool operator!= (BigInteger left, BigInteger right)
1312 return Compare (left, right) != 0;
1315 public static bool operator!= (BigInteger left, long right)
1317 return left.CompareTo (right) != 0;
1320 public static bool operator!= (long left, BigInteger right)
1322 return right.CompareTo (left) != 0;
1325 [CLSCompliantAttribute (false)]
1326 public static bool operator!= (BigInteger left, ulong right)
1328 return left.CompareTo (right) != 0;
1331 [CLSCompliantAttribute (false)]
1332 public static bool operator!= (ulong left, BigInteger right)
1334 return right.CompareTo (left) != 0;
1337 public override bool Equals (object obj)
1339 if (!(obj is BigInteger))
1341 return Equals ((BigInteger)obj);
1344 public bool Equals (BigInteger other)
1346 if (sign != other.sign)
1349 int alen = data != null ? data.Length : 0;
1350 int blen = other.data != null ? other.data.Length : 0;
1354 for (int i = 0; i < alen; ++i) {
1355 if (data [i] != other.data [i])
1361 public bool Equals (long other)
1363 return CompareTo (other) == 0;
1366 public override string ToString ()
1368 return ToString (10, null);
1371 string ToStringWithPadding (string format, uint radix, IFormatProvider provider)
1373 if (format.Length > 1) {
1374 int precision = Convert.ToInt32(format.Substring (1), CultureInfo.InvariantCulture.NumberFormat);
1375 string baseStr = ToString (radix, provider);
1376 if (baseStr.Length < precision) {
1377 string additional = new String ('0', precision - baseStr.Length);
1378 if (baseStr[0] != '-') {
1379 return additional + baseStr;
1381 return "-" + additional + baseStr.Substring (1);
1386 return ToString (radix, provider);
1389 public string ToString (string format)
1391 return ToString (format, null);
1394 public string ToString (IFormatProvider provider)
1396 return ToString (null, provider);
1400 public string ToString (string format, IFormatProvider provider)
1402 if (format == null || format == "")
1403 return ToString (10, provider);
1405 switch (format[0]) {
1412 return ToStringWithPadding (format, 10, provider);
1415 return ToStringWithPadding (format, 16, null);
1417 throw new FormatException (string.Format ("format '{0}' not implemented", format));
1421 static uint[] MakeTwoComplement (uint[] v)
1423 uint[] res = new uint [v.Length];
1426 for (int i = 0; i < v.Length; ++i) {
1428 carry = (ulong)~word + carry;
1430 carry = (uint)(carry >> 32);
1434 uint last = res [res.Length - 1];
1435 int idx = FirstNonFFByte (last);
1437 for (int i = 1; i < idx; ++i)
1438 mask = (mask << 8) | 0xFF;
1440 res [res.Length - 1] = last & mask;
1444 string ToString (uint radix, IFormatProvider provider)
1446 const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1448 if (characterSet.Length < radix)
1449 throw new ArgumentException ("charSet length less than radix", "characterSet");
1451 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
1455 if (data.Length == 1 && data [0] == 1)
1456 return sign == 1 ? "1" : "-1";
1458 List<char> digits = new List<char> (1 + data.Length * 3 / 10);
1466 dt = MakeTwoComplement (dt);
1467 a = new BigInteger (1, dt);
1472 a = DivRem (a, radix, out rem);
1473 digits.Add (characterSet [(int) rem]);
1476 if (sign == -1 && radix == 10) {
1477 NumberFormatInfo info = null;
1478 if (provider != null)
1479 info = provider.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo;
1481 string str = info.NegativeSign;
1482 for (int i = str.Length - 1; i >= 0; --i)
1483 digits.Add (str [i]);
1489 char last = digits [digits.Count - 1];
1490 if (sign == 1 && radix > 10 && (last < '0' || last > '9'))
1495 return new String (digits.ToArray ());
1498 public static BigInteger Parse (string value)
1503 if (!Parse (value, false, out result, out ex))
1508 public static bool TryParse (string value, out BigInteger result)
1511 return Parse (value, true, out result, out ex);
1514 public static BigInteger Parse (string value, NumberStyles style)
1516 return Parse (value, style, null);
1519 public static BigInteger Parse (string value, IFormatProvider provider)
1521 return Parse (value, NumberStyles.Integer, provider);
1524 public static BigInteger Parse (
1525 string value, NumberStyles style, IFormatProvider provider)
1530 if (!Parse (value, style, provider, false, out res, out exc))
1536 public static bool TryParse (
1537 string value, NumberStyles style, IFormatProvider provider,
1538 out BigInteger result)
1541 if (!Parse (value, style, provider, true, out result, out exc)) {
1549 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
1556 exc = new ArgumentNullException ("s");
1560 if (s.Length == 0) {
1562 exc = GetFormatException ();
1566 NumberFormatInfo nfi = null;
1568 Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
1569 nfi = (NumberFormatInfo)fp.GetFormat (typeNFI);
1572 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
1574 if (!CheckStyle (style, tryParse, ref exc))
1577 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
1578 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
1579 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
1580 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
1581 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
1582 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
1583 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
1584 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
1585 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
1586 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
1590 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1593 bool foundOpenParentheses = false;
1594 bool negative = false;
1595 bool foundSign = false;
1596 bool foundCurrency = false;
1599 if (AllowParentheses && s [pos] == '(') {
1600 foundOpenParentheses = true;
1602 negative = true; // MS always make the number negative when there parentheses
1603 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
1605 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1608 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
1610 exc = GetFormatException ();
1614 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
1616 exc = GetFormatException ();
1621 if (AllowLeadingSign && !foundSign) {
1623 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1625 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1627 if (AllowCurrencySymbol) {
1628 FindCurrency (ref pos, s, nfi,
1630 if (foundCurrency && AllowLeadingWhite &&
1631 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1637 if (AllowCurrencySymbol && !foundCurrency) {
1639 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1640 if (foundCurrency) {
1641 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1643 if (foundCurrency) {
1644 if (!foundSign && AllowLeadingSign) {
1645 FindSign (ref pos, s, nfi, ref foundSign,
1647 if (foundSign && AllowLeadingWhite &&
1648 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1655 BigInteger number = Zero;
1657 int decimalPointPos = -1;
1660 bool firstHexDigit = true;
1663 while (pos < s.Length) {
1665 if (!ValidDigit (s [pos], AllowHexSpecifier)) {
1666 if (AllowThousands &&
1667 (FindOther (ref pos, s, nfi.NumberGroupSeparator)
1668 || FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
1671 if (AllowDecimalPoint && decimalPointPos < 0 &&
1672 (FindOther (ref pos, s, nfi.NumberDecimalSeparator)
1673 || FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
1674 decimalPointPos = nDigits;
1683 if (AllowHexSpecifier) {
1684 hexDigit = s [pos++];
1685 if (Char.IsDigit (hexDigit))
1686 digitValue = (byte)(hexDigit - '0');
1687 else if (Char.IsLower (hexDigit))
1688 digitValue = (byte)(hexDigit - 'a' + 10);
1690 digitValue = (byte)(hexDigit - 'A' + 10);
1692 if (firstHexDigit && (byte)digitValue >= 8)
1695 number = number * 16 + digitValue;
1696 firstHexDigit = false;
1700 number = number * 10 + (byte)(s [pos++] - '0');
1703 // Post number stuff
1706 exc = GetFormatException ();
1710 //Signed hex value (Two's Complement)
1711 if (AllowHexSpecifier && negative) {
1712 BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
1713 number = (number ^ mask) + 1;
1718 if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
1721 if (AllowTrailingSign && !foundSign) {
1723 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1724 if (foundSign && pos < s.Length) {
1725 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1730 if (AllowCurrencySymbol && !foundCurrency) {
1731 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1735 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1736 if (foundCurrency && pos < s.Length) {
1737 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1739 if (!foundSign && AllowTrailingSign)
1740 FindSign (ref pos, s, nfi, ref foundSign,
1745 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1748 if (foundOpenParentheses) {
1749 if (pos >= s.Length || s [pos++] != ')') {
1751 exc = GetFormatException ();
1754 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1758 if (pos < s.Length && s [pos] != '\u0000') {
1760 exc = GetFormatException ();
1764 if (decimalPointPos >= 0)
1765 exponent = exponent - nDigits + decimalPointPos;
1769 // Any non-zero values after decimal point are not allowed
1771 BigInteger remainder;
1772 number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
1774 if (!remainder.IsZero) {
1776 exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
1779 } else if (exponent > 0) {
1780 number = BigInteger.Pow(10, exponent) * number;
1783 if (number.sign == 0)
1786 result = new BigInteger (-1, number.data);
1788 result = new BigInteger (1, number.data);
1793 internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
1795 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
1796 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
1797 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
1798 ne ^= NumberStyles.AllowLeadingWhite;
1799 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
1800 ne ^= NumberStyles.AllowTrailingWhite;
1803 exc = new ArgumentException (
1804 "With AllowHexSpecifier only " +
1805 "AllowLeadingWhite and AllowTrailingWhite " +
1809 } else if ((uint) style > (uint) NumberStyles.Any){
1811 exc = new ArgumentException ("Not a valid number style");
1818 internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
1820 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
1823 if (reportError && pos >= s.Length) {
1825 exc = GetFormatException ();
1832 internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
1833 ref bool foundSign, ref bool negative)
1835 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
1836 string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
1839 pos += nfi.NegativeSign.Length;
1840 } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
1841 string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
1843 pos += nfi.PositiveSign.Length;
1848 internal static void FindCurrency (ref int pos,
1850 NumberFormatInfo nfi,
1851 ref bool foundCurrency)
1853 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
1854 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
1855 foundCurrency = true;
1856 pos += nfi.CurrencySymbol.Length;
1860 internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
1864 if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
1870 if (i == s.Length) {
1871 exc = tryParse ? null : GetFormatException ();
1875 bool negative = false;
1878 if(++i == s.Length){
1879 exc = tryParse ? null : GetFormatException ();
1884 if (s [i] == '+' && ++i == s.Length) {
1885 exc = tryParse ? null : GetFormatException ();
1889 long exp = 0; // temp long value
1890 for (; i < s.Length; i++) {
1891 if (!Char.IsDigit (s [i])) {
1892 exc = tryParse ? null : GetFormatException ();
1896 // Reduce the risk of throwing an overflow exc
1897 exp = checked (exp * 10 - (int) (s [i] - '0'));
1898 if (exp < Int32.MinValue || exp > Int32.MaxValue) {
1899 exc = tryParse ? null : new OverflowException ("Value too large or too small.");
1904 // exp value saved as negative
1909 exponent = (int)exp;
1914 internal static bool FindOther (ref int pos, string s, string other)
1916 if ((pos + other.Length) <= s.Length &&
1917 s.Substring (pos, other.Length) == other) {
1918 pos += other.Length;
1925 internal static bool ValidDigit (char e, bool allowHex)
1928 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
1930 return Char.IsDigit (e);
1933 static Exception GetFormatException ()
1935 return new FormatException ("Input string was not in the correct format");
1938 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1942 for (int i = position; i < len; i++){
1945 if (c != 0 && !Char.IsWhiteSpace (c)){
1947 exc = GetFormatException ();
1954 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
1958 bool digits_seen = false;
1965 exc = new ArgumentNullException ("value");
1972 for (i = 0; i < len; i++){
1974 if (!Char.IsWhiteSpace (c))
1980 exc = GetFormatException ();
1984 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
1986 string negative = info.NegativeSign;
1987 string positive = info.PositiveSign;
1989 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
1990 i += positive.Length;
1991 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
1993 i += negative.Length;
1996 BigInteger val = Zero;
1997 for (; i < len; i++){
2005 if (c >= '0' && c <= '9'){
2006 byte d = (byte) (c - '0');
2011 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
2017 exc = GetFormatException ();
2023 else if (sign == -1)
2024 result = new BigInteger (-1, val.data);
2026 result = new BigInteger (1, val.data);
2031 public static BigInteger Min (BigInteger left, BigInteger right)
2034 int rs = right.sign;
2041 int r = CoreCompare (left.data, right.data);
2051 public static BigInteger Max (BigInteger left, BigInteger right)
2054 int rs = right.sign;
2061 int r = CoreCompare (left.data, right.data);
2070 public static BigInteger Abs (BigInteger value)
2072 return new BigInteger ((short)Math.Abs (value.sign), value.data);
2076 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
2078 if (divisor.sign == 0)
2079 throw new DivideByZeroException ();
2081 if (dividend.sign == 0) {
2082 remainder = dividend;
2087 uint[] remainder_value;
2089 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
2092 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
2094 remainder = new BigInteger (0, ZERO);
2096 if (i < remainder_value.Length - 1)
2097 remainder_value = Resize (remainder_value, i + 1);
2098 remainder = new BigInteger (dividend.sign, remainder_value);
2101 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
2103 return new BigInteger (0, ZERO);
2104 if (i < quotient.Length - 1)
2105 quotient = Resize (quotient, i + 1);
2107 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
2110 public static BigInteger Pow (BigInteger value, int exponent)
2113 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
2119 BigInteger result = One;
2120 while (exponent != 0) {
2121 if ((exponent & 1) != 0)
2122 result = result * value;
2126 value = value * value;
2132 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
2133 if (exponent.sign == -1)
2134 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
2135 if (modulus.sign == 0)
2136 throw new DivideByZeroException ();
2138 BigInteger result = One % modulus;
2139 while (exponent.sign != 0) {
2140 if (!exponent.IsEven) {
2141 result = result * value;
2142 result = result % modulus;
2146 value = value * value;
2147 value = value % modulus;
2153 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
2155 if (left.sign != 0 && left.data.Length == 1 && left.data [0] == 1)
2156 return new BigInteger (1, ONE);
2157 if (right.sign != 0 && right.data.Length == 1 && right.data [0] == 1)
2158 return new BigInteger (1, ONE);
2164 BigInteger x = new BigInteger (1, left.data);
2165 BigInteger y = new BigInteger (1, right.data);
2169 while (x.data.Length > 1) {
2175 if (x.IsZero) return g;
2177 // TODO: should we have something here if we can convert to long?
2180 // Now we can just do it with single precision. I am using the binary gcd method,
2181 // as it should be faster.
2184 uint yy = x.data [0];
2185 uint xx = (uint)(y % yy);
2189 while (((xx | yy) & 1) == 0) {
2190 xx >>= 1; yy >>= 1; t++;
2193 while ((xx & 1) == 0) xx >>= 1;
2194 while ((yy & 1) == 0) yy >>= 1;
2196 xx = (xx - yy) >> 1;
2198 yy = (yy - xx) >> 1;
2204 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
2205 We are equilavent to MS with about 2 ULP
2207 public static double Log (BigInteger value, Double baseValue)
2209 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
2210 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
2213 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
2214 return value.IsOne ? 0 : double.NaN;
2216 if (value.sign == 0)
2217 return double.NegativeInfinity;
2219 int length = value.data.Length - 1;
2221 for (int curBit = 31; curBit >= 0; curBit--) {
2222 if ((value.data [length] & (1 << curBit)) != 0) {
2223 bitCount = curBit + length * 32;
2228 long bitlen = bitCount;
2229 Double c = 0, d = 1;
2231 BigInteger testBit = One;
2232 long tempBitlen = bitlen;
2233 while (tempBitlen > Int32.MaxValue) {
2234 testBit = testBit << Int32.MaxValue;
2235 tempBitlen -= Int32.MaxValue;
2237 testBit = testBit << (int)tempBitlen;
2239 for (long curbit = bitlen; curbit >= 0; --curbit) {
2240 if ((value & testBit).sign != 0)
2243 testBit = testBit >> 1;
2245 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
2249 public static double Log (BigInteger value)
2251 return Log (value, Math.E);
2255 public static double Log10 (BigInteger value)
2257 return Log (value, 10);
2260 [CLSCompliantAttribute (false)]
2261 public bool Equals (ulong other)
2263 return CompareTo (other) == 0;
2266 public override int GetHashCode ()
2268 uint hash = (uint)(sign * 0x01010101u);
2269 int len = data != null ? data.Length : 0;
2271 for (int i = 0; i < len; ++i)
2276 public static BigInteger Add (BigInteger left, BigInteger right)
2278 return left + right;
2281 public static BigInteger Subtract (BigInteger left, BigInteger right)
2283 return left - right;
2286 public static BigInteger Multiply (BigInteger left, BigInteger right)
2288 return left * right;
2291 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
2293 return dividend / divisor;
2296 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
2298 return dividend % divisor;
2301 public static BigInteger Negate (BigInteger value)
2306 public int CompareTo (object obj)
2311 if (!(obj is BigInteger))
2314 return Compare (this, (BigInteger)obj);
2317 public int CompareTo (BigInteger other)
2319 return Compare (this, other);
2322 [CLSCompliantAttribute (false)]
2323 public int CompareTo (ulong other)
2328 return other == 0 ? 0 : -1;
2330 if (data.Length > 2)
2333 uint high = (uint)(other >> 32);
2334 uint low = (uint)other;
2336 return LongCompare (low, high);
2339 int LongCompare (uint low, uint high)
2342 if (data.Length > 1)
2360 public int CompareTo (long other)
2363 int rs = Math.Sign (other);
2366 return ls > rs ? 1 : -1;
2371 if (data.Length > 2)
2376 uint low = (uint)other;
2377 uint high = (uint)((ulong)other >> 32);
2379 int r = LongCompare (low, high);
2386 public static int Compare (BigInteger left, BigInteger right)
2389 int rs = right.sign;
2392 return ls > rs ? 1 : -1;
2394 int r = CoreCompare (left.data, right.data);
2401 static int TopByte (uint x)
2403 if ((x & 0xFFFF0000u) != 0) {
2404 if ((x & 0xFF000000u) != 0)
2408 if ((x & 0xFF00u) != 0)
2413 static int FirstNonFFByte (uint word)
2415 if ((word & 0xFF000000u) != 0xFF000000u)
2417 else if ((word & 0xFF0000u) != 0xFF0000u)
2419 else if ((word & 0xFF00u) != 0xFF00u)
2424 public byte[] ToByteArray ()
2427 return new byte [1];
2429 //number of bytes not counting upper word
2430 int bytes = (data.Length - 1) * 4;
2431 bool needExtraZero = false;
2433 uint topWord = data [data.Length - 1];
2436 //if the topmost bit is set we need an extra
2438 extra = TopByte (topWord);
2439 uint mask = 0x80u << ((extra - 1) * 8);
2440 if ((topWord & mask) != 0) {
2441 needExtraZero = true;
2444 extra = TopByte (topWord);
2447 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
2450 int end = data.Length - 1;
2451 for (int i = 0; i < end; ++i) {
2452 uint word = data [i];
2454 res [j++] = (byte)word;
2455 res [j++] = (byte)(word >> 8);
2456 res [j++] = (byte)(word >> 16);
2457 res [j++] = (byte)(word >> 24);
2459 while (extra-- > 0) {
2460 res [j++] = (byte)topWord;
2465 int end = data.Length - 1;
2467 uint carry = 1, word;
2469 for (int i = 0; i < end; ++i) {
2471 add = (ulong)~word + carry;
2473 carry = (uint)(add >> 32);
2475 res [j++] = (byte)word;
2476 res [j++] = (byte)(word >> 8);
2477 res [j++] = (byte)(word >> 16);
2478 res [j++] = (byte)(word >> 24);
2481 add = (ulong)~topWord + (carry);
2483 carry = (uint)(add >> 32);
2485 int ex = FirstNonFFByte (word);
2486 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2487 int to = ex + (needExtra ? 1 : 0);
2490 res = Resize (res, bytes + to);
2493 res [j++] = (byte)word;
2499 res = Resize (res, bytes + 5);
2500 res [j++] = (byte)word;
2501 res [j++] = (byte)(word >> 8);
2502 res [j++] = (byte)(word >> 16);
2503 res [j++] = (byte)(word >> 24);
2511 static byte[] Resize (byte[] v, int len)
2513 byte[] res = new byte [len];
2514 Array.Copy (v, res, Math.Min (v.Length, len));
2518 static uint[] Resize (uint[] v, int len)
2520 uint[] res = new uint [len];
2521 Array.Copy (v, res, Math.Min (v.Length, len));
2525 static uint[] CoreAdd (uint[] a, uint[] b)
2527 if (a.Length < b.Length) {
2536 uint[] res = new uint [bl];
2541 for (; i < sl; i++) {
2542 sum = sum + a [i] + b [i];
2543 res [i] = (uint)sum;
2547 for (; i < bl; i++) {
2549 res [i] = (uint)sum;
2554 res = Resize (res, bl + 1);
2555 res [i] = (uint)sum;
2562 static uint[] CoreSub (uint[] a, uint[] b)
2567 uint[] res = new uint [bl];
2571 for (i = 0; i < sl; ++i) {
2572 borrow = (ulong)a [i] - b [i] - borrow;
2574 res [i] = (uint)borrow;
2575 borrow = (borrow >> 32) & 0x1;
2578 for (; i < bl; i++) {
2579 borrow = (ulong)a [i] - borrow;
2580 res [i] = (uint)borrow;
2581 borrow = (borrow >> 32) & 0x1;
2584 //remove extra zeroes
2585 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2587 res = Resize (res, i + 1);
2593 static uint[] CoreAdd (uint[] a, uint b)
2596 uint[] res = new uint [len];
2600 for (i = 0; i < len; i++) {
2602 res [i] = (uint)sum;
2607 res = Resize (res, len + 1);
2608 res [i] = (uint)sum;
2614 static uint[] CoreSub (uint[] a, uint b)
2617 uint[] res = new uint [len];
2621 for (i = 0; i < len; i++) {
2622 borrow = (ulong)a [i] - borrow;
2623 res [i] = (uint)borrow;
2624 borrow = (borrow >> 32) & 0x1;
2627 //remove extra zeroes
2628 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2630 res = Resize (res, i + 1);
2635 static int CoreCompare (uint[] a, uint[] b)
2637 int al = a != null ? a.Length : 0;
2638 int bl = b != null ? b.Length : 0;
2645 for (int i = al - 1; i >= 0; --i) {
2656 static int GetNormalizeShift(uint value) {
2659 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2660 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2661 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2662 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2663 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2668 static void Normalize (uint[] u, int l, uint[] un, int shift)
2673 int rshift = 32 - shift;
2674 for (i = 0; i < l; i++) {
2676 un [i] = (ui << shift) | carry;
2677 carry = ui >> rshift;
2680 for (i = 0; i < l; i++) {
2685 while (i < un.Length) {
2694 static void Unnormalize (uint[] un, out uint[] r, int shift)
2696 int length = un.Length;
2697 r = new uint [length];
2700 int lshift = 32 - shift;
2702 for (int i = length - 1; i >= 0; i--) {
2704 r [i] = (uni >> shift) | carry;
2705 carry = (uni << lshift);
2708 for (int i = 0; i < length; i++) {
2714 const ulong Base = 0x100000000;
2715 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2721 // Divide by single digit
2728 for (int j = m - 1; j >= 0; j--) {
2732 ulong div = rem / v0;
2737 } else if (m >= n) {
2738 int shift = GetNormalizeShift (v [n - 1]);
2740 uint[] un = new uint [m + 1];
2741 uint[] vn = new uint [n];
2743 Normalize (u, m, un, shift);
2744 Normalize (v, n, vn, shift);
2746 q = new uint [m - n + 1];
2749 // Main division loop
2751 for (int j = m - n; j >= 0; j--) {
2755 rr = Base * un [j + n] + un [j + n - 1];
2756 qq = rr / vn [n - 1];
2757 rr -= qq * vn [n - 1];
2760 // Estimate too big ?
2762 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2764 rr += (ulong)vn [n - 1];
2772 // Multiply and subtract
2776 for (i = 0; i < n; i++) {
2777 ulong p = vn [i] * qq;
2778 t = (long)un [i + j] - (long)(uint)p - b;
2779 un [i + j] = (uint)t;
2784 t = (long)un [j + n] - b;
2785 un [j + n] = (uint)t;
2787 // Store the calculated value
2791 // Add back vn[0..n] to un[j..j+n]
2796 for (i = 0; i < n; i++) {
2797 c = (ulong)vn [i] + un [j + i] + c;
2798 un [j + i] = (uint)c;
2801 c += (ulong)un [j + n];
2802 un [j + n] = (uint)c;
2806 Unnormalize (un, out r, shift);
2808 q = new uint [] { 0 };