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 public bool IsPowerOfTwo {
349 bool foundBit = false;
352 //This function is pop count == 1 for positive numbers
353 for (int i = 0; i < data.Length; ++i) {
354 int p = PopulationCount (data [i]);
356 if (p > 1 || foundBit)
366 get { return sign == 0; }
373 public static BigInteger MinusOne {
374 get { return new BigInteger (-1, ONE); }
377 public static BigInteger One {
378 get { return new BigInteger (1, ONE); }
381 public static BigInteger Zero {
382 get { return new BigInteger (0, ZERO); }
385 public static explicit operator int (BigInteger value)
389 if (value.data.Length > 1)
390 throw new OverflowException ();
391 uint data = value.data [0];
393 if (value.sign == 1) {
394 if (data > (uint)int.MaxValue)
395 throw new OverflowException ();
397 } else if (value.sign == -1) {
398 if (data > 0x80000000u)
399 throw new OverflowException ();
406 [CLSCompliantAttribute (false)]
407 public static explicit operator uint (BigInteger value)
411 if (value.data.Length > 1 || value.sign == -1)
412 throw new OverflowException ();
413 return value.data [0];
416 public static explicit operator short (BigInteger value)
418 int val = (int)value;
419 if (val < short.MinValue || val > short.MaxValue)
420 throw new OverflowException ();
424 [CLSCompliantAttribute (false)]
425 public static explicit operator ushort (BigInteger value)
427 uint val = (uint)value;
428 if (val > ushort.MaxValue)
429 throw new OverflowException ();
433 public static explicit operator byte (BigInteger value)
435 uint val = (uint)value;
436 if (val > byte.MaxValue)
437 throw new OverflowException ();
441 [CLSCompliantAttribute (false)]
442 public static explicit operator sbyte (BigInteger value)
444 int val = (int)value;
445 if (val < sbyte.MinValue || val > sbyte.MaxValue)
446 throw new OverflowException ();
451 public static explicit operator long (BigInteger value)
456 if (value.data.Length > 2)
457 throw new OverflowException ();
459 uint low = value.data [0];
461 if (value.data.Length == 1) {
464 long res = (long)low;
468 uint high = value.data [1];
470 if (value.sign == 1) {
471 if (high >= 0x80000000u)
472 throw new OverflowException ();
473 return (((long)high) << 32) | low;
477 We cannot represent negative numbers smaller than long.MinValue.
478 Those values are encoded into what look negative numbers, so negating
479 them produces a positive value, that's why it's safe to check for that
482 long.MinValue works fine since it's bigint encoding looks like a negative
483 number, but since long.MinValue == -long.MinValue, we're good.
486 long result = - ((((long)high) << 32) | (long)low);
488 throw new OverflowException ();
492 [CLSCompliantAttribute (false)]
493 public static explicit operator ulong (BigInteger value)
497 if (value.data.Length > 2 || value.sign == -1)
498 throw new OverflowException ();
500 uint low = value.data [0];
501 if (value.data.Length == 1)
504 uint high = value.data [1];
505 return (((ulong)high) << 32) | low;
508 public static explicit operator double (BigInteger value)
512 return double.Parse (value.ToString (),
513 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
514 } catch (OverflowException) {
515 return value.sign == -1 ? double.NegativeInfinity : double.PositiveInfinity;
519 public static explicit operator float (BigInteger value)
523 return float.Parse (value.ToString (),
524 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
525 } catch (OverflowException) {
526 return value.sign == -1 ? float.NegativeInfinity : float.PositiveInfinity;
530 public static explicit operator decimal (BigInteger value)
535 uint[] data = value.data;
537 throw new OverflowException ();
539 int lo = 0, mi = 0, hi = 0;
541 hi = (Int32)data [2];
543 mi = (Int32)data [1];
545 lo = (Int32)data [0];
547 return new Decimal(lo, mi, hi, value.sign < 0, 0);
550 public static implicit operator BigInteger (int value)
552 return new BigInteger (value);
555 [CLSCompliantAttribute (false)]
556 public static implicit operator BigInteger (uint value)
558 return new BigInteger (value);
561 public static implicit operator BigInteger (short value)
563 return new BigInteger (value);
566 [CLSCompliantAttribute (false)]
567 public static implicit operator BigInteger (ushort value)
569 return new BigInteger (value);
572 public static implicit operator BigInteger (byte value)
574 return new BigInteger (value);
577 [CLSCompliantAttribute (false)]
578 public static implicit operator BigInteger (sbyte value)
580 return new BigInteger (value);
583 public static implicit operator BigInteger (long value)
585 return new BigInteger (value);
588 [CLSCompliantAttribute (false)]
589 public static implicit operator BigInteger (ulong value)
591 return new BigInteger (value);
594 public static explicit operator BigInteger (double value)
596 return new BigInteger (value);
599 public static explicit operator BigInteger (float value)
601 return new BigInteger (value);
604 public static explicit operator BigInteger (decimal value)
606 return new BigInteger (value);
609 public static BigInteger operator+ (BigInteger left, BigInteger right)
616 if (left.sign == right.sign)
617 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
619 int r = CoreCompare (left.data, right.data);
622 return new BigInteger (0, ZERO);
624 if (r > 0) //left > right
625 return new BigInteger (left.sign, CoreSub (left.data, right.data));
627 return new BigInteger (right.sign, CoreSub (right.data, left.data));
630 public static BigInteger operator- (BigInteger left, BigInteger right)
635 return new BigInteger ((short)-right.sign, right.data);
637 if (left.sign == right.sign) {
638 int r = CoreCompare (left.data, right.data);
641 return new BigInteger (0, ZERO);
643 if (r > 0) //left > right
644 return new BigInteger (left.sign, CoreSub (left.data, right.data));
646 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
649 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
652 public static BigInteger operator* (BigInteger left, BigInteger right)
654 if (left.sign == 0 || right.sign == 0)
655 return new BigInteger (0, ZERO);
657 if (left.data [0] == 1 && left.data.Length == 1) {
660 return new BigInteger ((short)-right.sign, right.data);
663 if (right.data [0] == 1 && right.data.Length == 1) {
666 return new BigInteger ((short)-left.sign, left.data);
669 uint[] a = left.data;
670 uint[] b = right.data;
672 uint[] res = new uint [a.Length + b.Length];
674 for (int i = 0; i < a.Length; ++i) {
679 for (int j = 0; j < b.Length; ++j) {
680 carry = carry + ((ulong)ai) * b [j] + res [k];
681 res[k++] = (uint)carry;
687 res[k++] = (uint)carry;
693 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
694 if (m < res.Length - 1)
695 res = Resize (res, m + 1);
697 return new BigInteger ((short)(left.sign * right.sign), res);
700 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
702 if (divisor.sign == 0)
703 throw new DivideByZeroException ();
705 if (dividend.sign == 0)
709 uint[] remainder_value;
711 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
714 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
716 return new BigInteger (0, ZERO);
717 if (i < quotient.Length - 1)
718 quotient = Resize (quotient, i + 1);
720 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
723 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
725 if (divisor.sign == 0)
726 throw new DivideByZeroException ();
728 if (dividend.sign == 0)
732 uint[] remainder_value;
734 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
737 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
739 return new BigInteger (0, ZERO);
741 if (i < remainder_value.Length - 1)
742 remainder_value = Resize (remainder_value, i + 1);
743 return new BigInteger (dividend.sign, remainder_value);
746 public static BigInteger operator- (BigInteger value)
750 return new BigInteger ((short)-value.sign, value.data);
753 public static BigInteger operator+ (BigInteger value)
758 public static BigInteger operator++ (BigInteger value)
763 short sign = value.sign;
764 uint[] data = value.data;
765 if (data.Length == 1) {
766 if (sign == -1 && data [0] == 1)
767 return new BigInteger (0, ZERO);
769 return new BigInteger (1, ONE);
773 data = CoreSub (data, 1);
775 data = CoreAdd (data, 1);
777 return new BigInteger (sign, data);
780 public static BigInteger operator-- (BigInteger value)
785 short sign = value.sign;
786 uint[] data = value.data;
787 if (data.Length == 1) {
788 if (sign == 1 && data [0] == 1)
789 return new BigInteger (0, ZERO);
791 return new BigInteger (-1, ONE);
795 data = CoreAdd (data, 1);
797 data = CoreSub (data, 1);
799 return new BigInteger (sign, data);
802 public static BigInteger operator& (BigInteger left, BigInteger right)
810 uint[] a = left.data;
811 uint[] b = right.data;
815 bool neg_res = (ls == rs) && (ls == -1);
817 uint[] result = new uint [Math.Max (a.Length, b.Length)];
819 ulong ac = 1, bc = 1, borrow = 1;
822 for (i = 0; i < result.Length; ++i) {
829 ac = (uint)(ac >> 32);
838 bc = (uint)(bc >> 32);
844 borrow = word - borrow;
845 word = ~(uint)borrow;
846 borrow = (uint)(borrow >> 32) & 0x1u;
852 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
854 return new BigInteger (0, ZERO);
856 if (i < result.Length - 1)
857 result = Resize (result, i + 1);
859 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
862 public static BigInteger operator| (BigInteger left, BigInteger right)
870 uint[] a = left.data;
871 uint[] b = right.data;
875 bool neg_res = (ls == -1) || (rs == -1);
877 uint[] result = new uint [Math.Max (a.Length, b.Length)];
879 ulong ac = 1, bc = 1, borrow = 1;
882 for (i = 0; i < result.Length; ++i) {
889 ac = (uint)(ac >> 32);
898 bc = (uint)(bc >> 32);
904 borrow = word - borrow;
905 word = ~(uint)borrow;
906 borrow = (uint)(borrow >> 32) & 0x1u;
912 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
914 return new BigInteger (0, ZERO);
916 if (i < result.Length - 1)
917 result = Resize (result, i + 1);
919 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
922 public static BigInteger operator^ (BigInteger left, BigInteger right)
930 uint[] a = left.data;
931 uint[] b = right.data;
935 bool neg_res = (ls == -1) ^ (rs == -1);
937 uint[] result = new uint [Math.Max (a.Length, b.Length)];
939 ulong ac = 1, bc = 1, borrow = 1;
942 for (i = 0; i < result.Length; ++i) {
949 ac = (uint)(ac >> 32);
958 bc = (uint)(bc >> 32);
964 borrow = word - borrow;
965 word = ~(uint)borrow;
966 borrow = (uint)(borrow >> 32) & 0x1u;
972 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
974 return new BigInteger (0, ZERO);
976 if (i < result.Length - 1)
977 result = Resize (result, i + 1);
979 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
982 public static BigInteger operator~ (BigInteger value)
985 return new BigInteger (-1, ONE);
987 uint[] data = value.data;
988 int sign = value.sign;
990 bool neg_res = sign == 1;
992 uint[] result = new uint [data.Length];
994 ulong carry = 1, borrow = 1;
997 for (i = 0; i < result.Length; ++i) {
998 uint word = data [i];
1000 carry = ~word + carry;
1002 carry = (uint)(carry >> 32);
1008 borrow = word - borrow;
1009 word = ~(uint)borrow;
1010 borrow = (uint)(borrow >> 32) & 0x1u;
1016 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1018 return new BigInteger (0, ZERO);
1020 if (i < result.Length - 1)
1021 result = Resize (result, i + 1);
1023 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1026 //returns the 0-based index of the most significant set bit
1027 //returns 0 if no bit is set, so extra care when using it
1028 static int BitScanBackward (uint word)
1030 for (int i = 31; i >= 0; --i) {
1031 uint mask = 1u << i;
1032 if ((word & mask) == mask)
1038 public static BigInteger operator<< (BigInteger value, int shift)
1040 if (shift == 0 || value.sign == 0)
1043 return value >> -shift;
1045 uint[] data = value.data;
1046 int sign = value.sign;
1048 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1049 int bits = shift - (31 - topMostIdx);
1050 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
1052 uint[] res = new uint [data.Length + extra_words];
1054 int idx_shift = shift >> 5;
1055 int bit_shift = shift & 0x1F;
1056 int carry_shift = 32 - bit_shift;
1058 if (carry_shift == 32) {
1059 for (int i = 0; i < data.Length; ++i) {
1060 uint word = data [i];
1061 res [i + idx_shift] |= word << bit_shift;
1064 for (int i = 0; i < data.Length; ++i) {
1065 uint word = data [i];
1066 res [i + idx_shift] |= word << bit_shift;
1067 if (i + idx_shift + 1 < res.Length)
1068 res [i + idx_shift + 1] = word >> carry_shift;
1072 return new BigInteger ((short)sign, res);
1075 public static BigInteger operator>> (BigInteger value, int shift)
1077 if (shift == 0 || value.sign == 0)
1080 return value << -shift;
1082 uint[] data = value.data;
1083 int sign = value.sign;
1085 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1086 int idx_shift = shift >> 5;
1087 int bit_shift = shift & 0x1F;
1089 int extra_words = idx_shift;
1090 if (bit_shift > topMostIdx)
1092 int size = data.Length - extra_words;
1096 return new BigInteger (0, ZERO);
1097 return new BigInteger (-1, ONE);
1100 uint[] res = new uint [size];
1101 int carry_shift = 32 - bit_shift;
1103 if (carry_shift == 32) {
1104 for (int i = data.Length - 1; i >= idx_shift; --i) {
1105 uint word = data [i];
1107 if (i - idx_shift < res.Length)
1108 res [i - idx_shift] |= word >> bit_shift;
1111 for (int i = data.Length - 1; i >= idx_shift; --i) {
1112 uint word = data [i];
1114 if (i - idx_shift < res.Length)
1115 res [i - idx_shift] |= word >> bit_shift;
1116 if (i - idx_shift - 1 >= 0)
1117 res [i - idx_shift - 1] = word << carry_shift;
1122 //Round down instead of toward zero
1124 for (int i = 0; i < idx_shift; i++) {
1125 if (data [i] != 0u) {
1126 var tmp = new BigInteger ((short)sign, res);
1131 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
1132 var tmp = new BigInteger ((short)sign, res);
1137 return new BigInteger ((short)sign, res);
1140 public static bool operator< (BigInteger left, BigInteger right)
1142 return Compare (left, right) < 0;
1145 public static bool operator< (BigInteger left, long right)
1147 return left.CompareTo (right) < 0;
1151 public static bool operator< (long left, BigInteger right)
1153 return right.CompareTo (left) > 0;
1157 [CLSCompliantAttribute (false)]
1158 public static bool operator< (BigInteger left, ulong right)
1160 return left.CompareTo (right) < 0;
1163 [CLSCompliantAttribute (false)]
1164 public static bool operator< (ulong left, BigInteger right)
1166 return right.CompareTo (left) > 0;
1169 public static bool operator<= (BigInteger left, BigInteger right)
1171 return Compare (left, right) <= 0;
1174 public static bool operator<= (BigInteger left, long right)
1176 return left.CompareTo (right) <= 0;
1179 public static bool operator<= (long left, BigInteger right)
1181 return right.CompareTo (left) >= 0;
1184 [CLSCompliantAttribute (false)]
1185 public static bool operator<= (BigInteger left, ulong right)
1187 return left.CompareTo (right) <= 0;
1190 [CLSCompliantAttribute (false)]
1191 public static bool operator<= (ulong left, BigInteger right)
1193 return right.CompareTo (left) >= 0;
1196 public static bool operator> (BigInteger left, BigInteger right)
1198 return Compare (left, right) > 0;
1201 public static bool operator> (BigInteger left, long right)
1203 return left.CompareTo (right) > 0;
1206 public static bool operator> (long left, BigInteger right)
1208 return right.CompareTo (left) < 0;
1211 [CLSCompliantAttribute (false)]
1212 public static bool operator> (BigInteger left, ulong right)
1214 return left.CompareTo (right) > 0;
1217 [CLSCompliantAttribute (false)]
1218 public static bool operator> (ulong left, BigInteger right)
1220 return right.CompareTo (left) < 0;
1223 public static bool operator>= (BigInteger left, BigInteger right)
1225 return Compare (left, right) >= 0;
1228 public static bool operator>= (BigInteger left, long right)
1230 return left.CompareTo (right) >= 0;
1233 public static bool operator>= (long left, BigInteger right)
1235 return right.CompareTo (left) <= 0;
1238 [CLSCompliantAttribute (false)]
1239 public static bool operator>= (BigInteger left, ulong right)
1241 return left.CompareTo (right) >= 0;
1244 [CLSCompliantAttribute (false)]
1245 public static bool operator>= (ulong left, BigInteger right)
1247 return right.CompareTo (left) <= 0;
1250 public static bool operator== (BigInteger left, BigInteger right)
1252 return Compare (left, right) == 0;
1255 public static bool operator== (BigInteger left, long right)
1257 return left.CompareTo (right) == 0;
1260 public static bool operator== (long left, BigInteger right)
1262 return right.CompareTo (left) == 0;
1265 [CLSCompliantAttribute (false)]
1266 public static bool operator== (BigInteger left, ulong right)
1268 return left.CompareTo (right) == 0;
1271 [CLSCompliantAttribute (false)]
1272 public static bool operator== (ulong left, BigInteger right)
1274 return right.CompareTo (left) == 0;
1277 public static bool operator!= (BigInteger left, BigInteger right)
1279 return Compare (left, right) != 0;
1282 public static bool operator!= (BigInteger left, long right)
1284 return left.CompareTo (right) != 0;
1287 public static bool operator!= (long left, BigInteger right)
1289 return right.CompareTo (left) != 0;
1292 [CLSCompliantAttribute (false)]
1293 public static bool operator!= (BigInteger left, ulong right)
1295 return left.CompareTo (right) != 0;
1298 [CLSCompliantAttribute (false)]
1299 public static bool operator!= (ulong left, BigInteger right)
1301 return right.CompareTo (left) != 0;
1304 public override bool Equals (object obj)
1306 if (!(obj is BigInteger))
1308 return Equals ((BigInteger)obj);
1311 public bool Equals (BigInteger other)
1313 if (sign != other.sign)
1316 int alen = data != null ? data.Length : 0;
1317 int blen = other.data != null ? other.data.Length : 0;
1321 for (int i = 0; i < alen; ++i) {
1322 if (data [i] != other.data [i])
1328 public bool Equals (long other)
1330 return CompareTo (other) == 0;
1333 public override string ToString ()
1335 return ToString (10, null);
1338 string ToStringWithPadding (string format, uint radix, IFormatProvider provider)
1340 if (format.Length > 1) {
1341 int precision = Convert.ToInt32(format.Substring (1), CultureInfo.InvariantCulture.NumberFormat);
1342 string baseStr = ToString (radix, provider);
1343 if (baseStr.Length < precision) {
1344 string additional = new String ('0', precision - baseStr.Length);
1345 if (baseStr[0] != '-') {
1346 return additional + baseStr;
1348 return "-" + additional + baseStr.Substring (1);
1353 return ToString (radix, provider);
1356 public string ToString (string format)
1358 return ToString (format, null);
1361 public string ToString (IFormatProvider provider)
1363 return ToString (null, provider);
1367 public string ToString (string format, IFormatProvider provider)
1369 if (format == null || format == "")
1370 return ToString (10, provider);
1372 switch (format[0]) {
1379 return ToStringWithPadding (format, 10, provider);
1382 return ToStringWithPadding (format, 16, null);
1384 throw new FormatException (string.Format ("format '{0}' not implemented", format));
1388 static uint[] MakeTwoComplement (uint[] v)
1390 uint[] res = new uint [v.Length];
1393 for (int i = 0; i < v.Length; ++i) {
1395 carry = (ulong)~word + carry;
1397 carry = (uint)(carry >> 32);
1401 uint last = res [res.Length - 1];
1402 int idx = FirstNonFFByte (last);
1404 for (int i = 1; i < idx; ++i)
1405 mask = (mask << 8) | 0xFF;
1407 res [res.Length - 1] = last & mask;
1411 string ToString (uint radix, IFormatProvider provider)
1413 const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1415 if (characterSet.Length < radix)
1416 throw new ArgumentException ("charSet length less than radix", "characterSet");
1418 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
1422 if (data.Length == 1 && data [0] == 1)
1423 return sign == 1 ? "1" : "-1";
1425 List<char> digits = new List<char> (1 + data.Length * 3 / 10);
1433 dt = MakeTwoComplement (dt);
1434 a = new BigInteger (1, dt);
1439 a = DivRem (a, radix, out rem);
1440 digits.Add (characterSet [(int) rem]);
1443 if (sign == -1 && radix == 10) {
1444 NumberFormatInfo info = null;
1445 if (provider != null)
1446 info = provider.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo;
1448 string str = info.NegativeSign;
1449 for (int i = str.Length - 1; i >= 0; --i)
1450 digits.Add (str [i]);
1456 char last = digits [digits.Count - 1];
1457 if (sign == 1 && radix > 10 && (last < '0' || last > '9'))
1462 return new String (digits.ToArray ());
1465 public static BigInteger Parse (string value)
1470 if (!Parse (value, false, out result, out ex))
1475 public static bool TryParse (string value, out BigInteger result)
1478 return Parse (value, true, out result, out ex);
1481 public static BigInteger Parse (string value, NumberStyles style)
1483 return Parse (value, style, null);
1486 public static BigInteger Parse (string value, IFormatProvider provider)
1488 return Parse (value, NumberStyles.Integer, provider);
1491 public static BigInteger Parse (
1492 string value, NumberStyles style, IFormatProvider provider)
1497 if (!Parse (value, style, provider, false, out res, out exc))
1503 public static bool TryParse (
1504 string value, NumberStyles style, IFormatProvider provider,
1505 out BigInteger result)
1508 if (!Parse (value, style, provider, true, out result, out exc)) {
1516 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
1523 exc = new ArgumentNullException ("s");
1527 if (s.Length == 0) {
1529 exc = GetFormatException ();
1533 NumberFormatInfo nfi = null;
1535 Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
1536 nfi = (NumberFormatInfo)fp.GetFormat (typeNFI);
1539 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
1541 if (!CheckStyle (style, tryParse, ref exc))
1544 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
1545 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
1546 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
1547 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
1548 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
1549 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
1550 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
1551 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
1552 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
1553 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
1557 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1560 bool foundOpenParentheses = false;
1561 bool negative = false;
1562 bool foundSign = false;
1563 bool foundCurrency = false;
1566 if (AllowParentheses && s [pos] == '(') {
1567 foundOpenParentheses = true;
1569 negative = true; // MS always make the number negative when there parentheses
1570 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
1572 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1575 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
1577 exc = GetFormatException ();
1581 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
1583 exc = GetFormatException ();
1588 if (AllowLeadingSign && !foundSign) {
1590 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1592 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1594 if (AllowCurrencySymbol) {
1595 FindCurrency (ref pos, s, nfi,
1597 if (foundCurrency && AllowLeadingWhite &&
1598 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1604 if (AllowCurrencySymbol && !foundCurrency) {
1606 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1607 if (foundCurrency) {
1608 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1610 if (foundCurrency) {
1611 if (!foundSign && AllowLeadingSign) {
1612 FindSign (ref pos, s, nfi, ref foundSign,
1614 if (foundSign && AllowLeadingWhite &&
1615 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1622 BigInteger number = Zero;
1624 int decimalPointPos = -1;
1627 bool firstHexDigit = true;
1630 while (pos < s.Length) {
1632 if (!ValidDigit (s [pos], AllowHexSpecifier)) {
1633 if (AllowThousands &&
1634 (FindOther (ref pos, s, nfi.NumberGroupSeparator)
1635 || FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
1638 if (AllowDecimalPoint && decimalPointPos < 0 &&
1639 (FindOther (ref pos, s, nfi.NumberDecimalSeparator)
1640 || FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
1641 decimalPointPos = nDigits;
1650 if (AllowHexSpecifier) {
1651 hexDigit = s [pos++];
1652 if (Char.IsDigit (hexDigit))
1653 digitValue = (byte)(hexDigit - '0');
1654 else if (Char.IsLower (hexDigit))
1655 digitValue = (byte)(hexDigit - 'a' + 10);
1657 digitValue = (byte)(hexDigit - 'A' + 10);
1659 if (firstHexDigit && (byte)digitValue >= 8)
1662 number = number * 16 + digitValue;
1663 firstHexDigit = false;
1667 number = number * 10 + (byte)(s [pos++] - '0');
1670 // Post number stuff
1673 exc = GetFormatException ();
1678 if (AllowHexSpecifier && negative) {
1680 BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
1681 number = (number ^ mask) + 1;
1686 if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
1689 if (AllowTrailingSign && !foundSign) {
1691 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1692 if (foundSign && pos < s.Length) {
1693 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1698 if (AllowCurrencySymbol && !foundCurrency) {
1699 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1703 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1704 if (foundCurrency && pos < s.Length) {
1705 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1707 if (!foundSign && AllowTrailingSign)
1708 FindSign (ref pos, s, nfi, ref foundSign,
1713 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1716 if (foundOpenParentheses) {
1717 if (pos >= s.Length || s [pos++] != ')') {
1719 exc = GetFormatException ();
1722 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1726 if (pos < s.Length && s [pos] != '\u0000') {
1728 exc = GetFormatException ();
1732 if (decimalPointPos >= 0)
1733 exponent = exponent - nDigits + decimalPointPos;
1737 // Any non-zero values after decimal point are not allowed
1739 BigInteger remainder;
1740 number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
1742 if (!remainder.IsZero) {
1744 exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
1747 } else if (exponent > 0) {
1748 number = BigInteger.Pow(10, exponent) * number;
1751 if (number.sign == 0)
1754 result = new BigInteger (-1, number.data);
1756 result = new BigInteger (1, number.data);
1761 internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
1763 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
1764 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
1765 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
1766 ne ^= NumberStyles.AllowLeadingWhite;
1767 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
1768 ne ^= NumberStyles.AllowTrailingWhite;
1771 exc = new ArgumentException (
1772 "With AllowHexSpecifier only " +
1773 "AllowLeadingWhite and AllowTrailingWhite " +
1777 } else if ((uint) style > (uint) NumberStyles.Any){
1779 exc = new ArgumentException ("Not a valid number style");
1786 internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
1788 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
1791 if (reportError && pos >= s.Length) {
1793 exc = GetFormatException ();
1800 internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
1801 ref bool foundSign, ref bool negative)
1803 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
1804 string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
1807 pos += nfi.NegativeSign.Length;
1808 } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
1809 string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
1811 pos += nfi.PositiveSign.Length;
1816 internal static void FindCurrency (ref int pos,
1818 NumberFormatInfo nfi,
1819 ref bool foundCurrency)
1821 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
1822 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
1823 foundCurrency = true;
1824 pos += nfi.CurrencySymbol.Length;
1828 internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
1832 if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
1838 if (i == s.Length) {
1839 exc = tryParse ? null : GetFormatException ();
1843 bool negative = false;
1846 if(++i == s.Length){
1847 exc = tryParse ? null : GetFormatException ();
1852 if (s [i] == '+' && ++i == s.Length) {
1853 exc = tryParse ? null : GetFormatException ();
1857 long exp = 0; // temp long value
1858 for (; i < s.Length; i++) {
1859 if (!Char.IsDigit (s [i])) {
1860 exc = tryParse ? null : GetFormatException ();
1864 // Reduce the risk of throwing an overflow exc
1865 exp = checked (exp * 10 - (int) (s [i] - '0'));
1866 if (exp < Int32.MinValue || exp > Int32.MaxValue) {
1867 exc = tryParse ? null : new OverflowException ("Value too large or too small.");
1872 // exp value saved as negative
1877 exponent = (int)exp;
1882 internal static bool FindOther (ref int pos, string s, string other)
1884 if ((pos + other.Length) <= s.Length &&
1885 s.Substring (pos, other.Length) == other) {
1886 pos += other.Length;
1893 internal static bool ValidDigit (char e, bool allowHex)
1896 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
1898 return Char.IsDigit (e);
1901 static Exception GetFormatException ()
1903 return new FormatException ("Input string was not in the correct format");
1906 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1910 for (int i = position; i < len; i++){
1913 if (c != 0 && !Char.IsWhiteSpace (c)){
1915 exc = GetFormatException ();
1922 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
1926 bool digits_seen = false;
1933 exc = new ArgumentNullException ("value");
1940 for (i = 0; i < len; i++){
1942 if (!Char.IsWhiteSpace (c))
1948 exc = GetFormatException ();
1952 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
1954 string negative = info.NegativeSign;
1955 string positive = info.PositiveSign;
1957 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
1958 i += positive.Length;
1959 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
1961 i += negative.Length;
1964 BigInteger val = Zero;
1965 for (; i < len; i++){
1973 if (c >= '0' && c <= '9'){
1974 byte d = (byte) (c - '0');
1979 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
1985 exc = GetFormatException ();
1991 else if (sign == -1)
1992 result = new BigInteger (-1, val.data);
1994 result = new BigInteger (1, val.data);
1999 public static BigInteger Min (BigInteger left, BigInteger right)
2002 int rs = right.sign;
2009 int r = CoreCompare (left.data, right.data);
2019 public static BigInteger Max (BigInteger left, BigInteger right)
2022 int rs = right.sign;
2029 int r = CoreCompare (left.data, right.data);
2038 public static BigInteger Abs (BigInteger value)
2040 return new BigInteger ((short)Math.Abs (value.sign), value.data);
2044 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
2046 if (divisor.sign == 0)
2047 throw new DivideByZeroException ();
2049 if (dividend.sign == 0) {
2050 remainder = dividend;
2055 uint[] remainder_value;
2057 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
2060 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
2062 remainder = new BigInteger (0, ZERO);
2064 if (i < remainder_value.Length - 1)
2065 remainder_value = Resize (remainder_value, i + 1);
2066 remainder = new BigInteger (dividend.sign, remainder_value);
2069 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
2071 return new BigInteger (0, ZERO);
2072 if (i < quotient.Length - 1)
2073 quotient = Resize (quotient, i + 1);
2075 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
2078 public static BigInteger Pow (BigInteger value, int exponent)
2081 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
2087 BigInteger result = One;
2088 while (exponent != 0) {
2089 if ((exponent & 1) != 0)
2090 result = result * value;
2094 value = value * value;
2100 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
2101 if (exponent.sign == -1)
2102 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
2103 if (modulus.sign == 0)
2104 throw new DivideByZeroException ();
2106 BigInteger result = One % modulus;
2107 while (exponent.sign != 0) {
2108 if (!exponent.IsEven) {
2109 result = result * value;
2110 result = result % modulus;
2114 value = value * value;
2115 value = value % modulus;
2121 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
2123 if (left.sign != 0 && left.data.Length == 1 && left.data [0] == 1)
2124 return new BigInteger (1, ONE);
2125 if (right.sign != 0 && right.data.Length == 1 && right.data [0] == 1)
2126 return new BigInteger (1, ONE);
2132 BigInteger x = new BigInteger (1, left.data);
2133 BigInteger y = new BigInteger (1, right.data);
2137 while (x.data.Length > 1) {
2143 if (x.IsZero) return g;
2145 // TODO: should we have something here if we can convert to long?
2148 // Now we can just do it with single precision. I am using the binary gcd method,
2149 // as it should be faster.
2152 uint yy = x.data [0];
2153 uint xx = (uint)(y % yy);
2157 while (((xx | yy) & 1) == 0) {
2158 xx >>= 1; yy >>= 1; t++;
2161 while ((xx & 1) == 0) xx >>= 1;
2162 while ((yy & 1) == 0) yy >>= 1;
2164 xx = (xx - yy) >> 1;
2166 yy = (yy - xx) >> 1;
2172 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
2173 We are equilavent to MS with about 2 ULP
2175 public static double Log (BigInteger value, Double baseValue)
2177 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
2178 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
2181 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
2182 return value.IsOne ? 0 : double.NaN;
2184 if (value.sign == 0)
2185 return double.NegativeInfinity;
2187 int length = value.data.Length - 1;
2189 for (int curBit = 31; curBit >= 0; curBit--) {
2190 if ((value.data [length] & (1 << curBit)) != 0) {
2191 bitCount = curBit + length * 32;
2196 long bitlen = bitCount;
2197 Double c = 0, d = 1;
2199 BigInteger testBit = One;
2200 long tempBitlen = bitlen;
2201 while (tempBitlen > Int32.MaxValue) {
2202 testBit = testBit << Int32.MaxValue;
2203 tempBitlen -= Int32.MaxValue;
2205 testBit = testBit << (int)tempBitlen;
2207 for (long curbit = bitlen; curbit >= 0; --curbit) {
2208 if ((value & testBit).sign != 0)
2211 testBit = testBit >> 1;
2213 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
2217 public static double Log (BigInteger value)
2219 return Log (value, Math.E);
2223 public static double Log10 (BigInteger value)
2225 return Log (value, 10);
2228 [CLSCompliantAttribute (false)]
2229 public bool Equals (ulong other)
2231 return CompareTo (other) == 0;
2234 public override int GetHashCode ()
2236 uint hash = (uint)(sign * 0x01010101u);
2237 int len = data != null ? data.Length : 0;
2239 for (int i = 0; i < len; ++i)
2244 public static BigInteger Add (BigInteger left, BigInteger right)
2246 return left + right;
2249 public static BigInteger Subtract (BigInteger left, BigInteger right)
2251 return left - right;
2254 public static BigInteger Multiply (BigInteger left, BigInteger right)
2256 return left * right;
2259 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
2261 return dividend / divisor;
2264 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
2266 return dividend % divisor;
2269 public static BigInteger Negate (BigInteger value)
2274 public int CompareTo (object obj)
2279 if (!(obj is BigInteger))
2282 return Compare (this, (BigInteger)obj);
2285 public int CompareTo (BigInteger other)
2287 return Compare (this, other);
2290 [CLSCompliantAttribute (false)]
2291 public int CompareTo (ulong other)
2296 return other == 0 ? 0 : -1;
2298 if (data.Length > 2)
2301 uint high = (uint)(other >> 32);
2302 uint low = (uint)other;
2304 return LongCompare (low, high);
2307 int LongCompare (uint low, uint high)
2310 if (data.Length > 1)
2328 public int CompareTo (long other)
2331 int rs = Math.Sign (other);
2334 return ls > rs ? 1 : -1;
2339 if (data.Length > 2)
2344 uint low = (uint)other;
2345 uint high = (uint)((ulong)other >> 32);
2347 int r = LongCompare (low, high);
2354 public static int Compare (BigInteger left, BigInteger right)
2357 int rs = right.sign;
2360 return ls > rs ? 1 : -1;
2362 int r = CoreCompare (left.data, right.data);
2369 static int TopByte (uint x)
2371 if ((x & 0xFFFF0000u) != 0) {
2372 if ((x & 0xFF000000u) != 0)
2376 if ((x & 0xFF00u) != 0)
2381 static int FirstNonFFByte (uint word)
2383 if ((word & 0xFF000000u) != 0xFF000000u)
2385 else if ((word & 0xFF0000u) != 0xFF0000u)
2387 else if ((word & 0xFF00u) != 0xFF00u)
2392 public byte[] ToByteArray ()
2395 return new byte [1];
2397 //number of bytes not counting upper word
2398 int bytes = (data.Length - 1) * 4;
2399 bool needExtraZero = false;
2401 uint topWord = data [data.Length - 1];
2404 //if the topmost bit is set we need an extra
2406 extra = TopByte (topWord);
2407 uint mask = 0x80u << ((extra - 1) * 8);
2408 if ((topWord & mask) != 0) {
2409 needExtraZero = true;
2412 extra = TopByte (topWord);
2415 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
2418 int end = data.Length - 1;
2419 for (int i = 0; i < end; ++i) {
2420 uint word = data [i];
2422 res [j++] = (byte)word;
2423 res [j++] = (byte)(word >> 8);
2424 res [j++] = (byte)(word >> 16);
2425 res [j++] = (byte)(word >> 24);
2427 while (extra-- > 0) {
2428 res [j++] = (byte)topWord;
2433 int end = data.Length - 1;
2435 uint carry = 1, word;
2437 for (int i = 0; i < end; ++i) {
2439 add = (ulong)~word + carry;
2441 carry = (uint)(add >> 32);
2443 res [j++] = (byte)word;
2444 res [j++] = (byte)(word >> 8);
2445 res [j++] = (byte)(word >> 16);
2446 res [j++] = (byte)(word >> 24);
2449 add = (ulong)~topWord + (carry);
2451 carry = (uint)(add >> 32);
2453 int ex = FirstNonFFByte (word);
2454 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2455 int to = ex + (needExtra ? 1 : 0);
2458 res = Resize (res, bytes + to);
2461 res [j++] = (byte)word;
2467 res = Resize (res, bytes + 5);
2468 res [j++] = (byte)word;
2469 res [j++] = (byte)(word >> 8);
2470 res [j++] = (byte)(word >> 16);
2471 res [j++] = (byte)(word >> 24);
2479 static byte[] Resize (byte[] v, int len)
2481 byte[] res = new byte [len];
2482 Array.Copy (v, res, Math.Min (v.Length, len));
2486 static uint[] Resize (uint[] v, int len)
2488 uint[] res = new uint [len];
2489 Array.Copy (v, res, Math.Min (v.Length, len));
2493 static uint[] CoreAdd (uint[] a, uint[] b)
2495 if (a.Length < b.Length) {
2504 uint[] res = new uint [bl];
2509 for (; i < sl; i++) {
2510 sum = sum + a [i] + b [i];
2511 res [i] = (uint)sum;
2515 for (; i < bl; i++) {
2517 res [i] = (uint)sum;
2522 res = Resize (res, bl + 1);
2523 res [i] = (uint)sum;
2530 static uint[] CoreSub (uint[] a, uint[] b)
2535 uint[] res = new uint [bl];
2539 for (i = 0; i < sl; ++i) {
2540 borrow = (ulong)a [i] - b [i] - borrow;
2542 res [i] = (uint)borrow;
2543 borrow = (borrow >> 32) & 0x1;
2546 for (; i < bl; i++) {
2547 borrow = (ulong)a [i] - borrow;
2548 res [i] = (uint)borrow;
2549 borrow = (borrow >> 32) & 0x1;
2552 //remove extra zeroes
2553 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2555 res = Resize (res, i + 1);
2561 static uint[] CoreAdd (uint[] a, uint b)
2564 uint[] res = new uint [len];
2568 for (i = 0; i < len; i++) {
2570 res [i] = (uint)sum;
2575 res = Resize (res, len + 1);
2576 res [i] = (uint)sum;
2582 static uint[] CoreSub (uint[] a, uint b)
2585 uint[] res = new uint [len];
2589 for (i = 0; i < len; i++) {
2590 borrow = (ulong)a [i] - borrow;
2591 res [i] = (uint)borrow;
2592 borrow = (borrow >> 32) & 0x1;
2595 //remove extra zeroes
2596 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2598 res = Resize (res, i + 1);
2603 static int CoreCompare (uint[] a, uint[] b)
2605 int al = a != null ? a.Length : 0;
2606 int bl = b != null ? b.Length : 0;
2613 for (int i = al - 1; i >= 0; --i) {
2624 static int GetNormalizeShift(uint value) {
2627 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2628 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2629 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2630 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2631 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2636 static void Normalize (uint[] u, int l, uint[] un, int shift)
2641 int rshift = 32 - shift;
2642 for (i = 0; i < l; i++) {
2644 un [i] = (ui << shift) | carry;
2645 carry = ui >> rshift;
2648 for (i = 0; i < l; i++) {
2653 while (i < un.Length) {
2662 static void Unnormalize (uint[] un, out uint[] r, int shift)
2664 int length = un.Length;
2665 r = new uint [length];
2668 int lshift = 32 - shift;
2670 for (int i = length - 1; i >= 0; i--) {
2672 r [i] = (uni >> shift) | carry;
2673 carry = (uni << lshift);
2676 for (int i = 0; i < length; i++) {
2682 const ulong Base = 0x100000000;
2683 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2689 // Divide by single digit
2696 for (int j = m - 1; j >= 0; j--) {
2700 ulong div = rem / v0;
2705 } else if (m >= n) {
2706 int shift = GetNormalizeShift (v [n - 1]);
2708 uint[] un = new uint [m + 1];
2709 uint[] vn = new uint [n];
2711 Normalize (u, m, un, shift);
2712 Normalize (v, n, vn, shift);
2714 q = new uint [m - n + 1];
2717 // Main division loop
2719 for (int j = m - n; j >= 0; j--) {
2723 rr = Base * un [j + n] + un [j + n - 1];
2724 qq = rr / vn [n - 1];
2725 rr -= qq * vn [n - 1];
2728 // Estimate too big ?
2730 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2732 rr += (ulong)vn [n - 1];
2740 // Multiply and subtract
2744 for (i = 0; i < n; i++) {
2745 ulong p = vn [i] * qq;
2746 t = (long)un [i + j] - (long)(uint)p - b;
2747 un [i + j] = (uint)t;
2752 t = (long)un [j + n] - b;
2753 un [j + n] = (uint)t;
2755 // Store the calculated value
2759 // Add back vn[0..n] to un[j..j+n]
2764 for (i = 0; i < n; i++) {
2765 c = (ulong)vn [i] + un [j + i] + c;
2766 un [j + i] = (uint)c;
2769 c += (ulong)un [j + n];
2770 un [j + n] = (uint)c;
2774 Unnormalize (un, out r, shift);
2776 q = new uint [] { 0 };