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 ();
1677 //Signed hex value (Two's Complement)
1678 if (AllowHexSpecifier && negative) {
1679 BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
1680 number = (number ^ mask) + 1;
1685 if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
1688 if (AllowTrailingSign && !foundSign) {
1690 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1691 if (foundSign && pos < s.Length) {
1692 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1697 if (AllowCurrencySymbol && !foundCurrency) {
1698 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1702 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1703 if (foundCurrency && pos < s.Length) {
1704 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1706 if (!foundSign && AllowTrailingSign)
1707 FindSign (ref pos, s, nfi, ref foundSign,
1712 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1715 if (foundOpenParentheses) {
1716 if (pos >= s.Length || s [pos++] != ')') {
1718 exc = GetFormatException ();
1721 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1725 if (pos < s.Length && s [pos] != '\u0000') {
1727 exc = GetFormatException ();
1731 if (decimalPointPos >= 0)
1732 exponent = exponent - nDigits + decimalPointPos;
1736 // Any non-zero values after decimal point are not allowed
1738 BigInteger remainder;
1739 number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
1741 if (!remainder.IsZero) {
1743 exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
1746 } else if (exponent > 0) {
1747 number = BigInteger.Pow(10, exponent) * number;
1750 if (number.sign == 0)
1753 result = new BigInteger (-1, number.data);
1755 result = new BigInteger (1, number.data);
1760 internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
1762 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
1763 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
1764 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
1765 ne ^= NumberStyles.AllowLeadingWhite;
1766 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
1767 ne ^= NumberStyles.AllowTrailingWhite;
1770 exc = new ArgumentException (
1771 "With AllowHexSpecifier only " +
1772 "AllowLeadingWhite and AllowTrailingWhite " +
1776 } else if ((uint) style > (uint) NumberStyles.Any){
1778 exc = new ArgumentException ("Not a valid number style");
1785 internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
1787 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
1790 if (reportError && pos >= s.Length) {
1792 exc = GetFormatException ();
1799 internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
1800 ref bool foundSign, ref bool negative)
1802 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
1803 string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
1806 pos += nfi.NegativeSign.Length;
1807 } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
1808 string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
1810 pos += nfi.PositiveSign.Length;
1815 internal static void FindCurrency (ref int pos,
1817 NumberFormatInfo nfi,
1818 ref bool foundCurrency)
1820 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
1821 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
1822 foundCurrency = true;
1823 pos += nfi.CurrencySymbol.Length;
1827 internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
1831 if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
1837 if (i == s.Length) {
1838 exc = tryParse ? null : GetFormatException ();
1842 bool negative = false;
1845 if(++i == s.Length){
1846 exc = tryParse ? null : GetFormatException ();
1851 if (s [i] == '+' && ++i == s.Length) {
1852 exc = tryParse ? null : GetFormatException ();
1856 long exp = 0; // temp long value
1857 for (; i < s.Length; i++) {
1858 if (!Char.IsDigit (s [i])) {
1859 exc = tryParse ? null : GetFormatException ();
1863 // Reduce the risk of throwing an overflow exc
1864 exp = checked (exp * 10 - (int) (s [i] - '0'));
1865 if (exp < Int32.MinValue || exp > Int32.MaxValue) {
1866 exc = tryParse ? null : new OverflowException ("Value too large or too small.");
1871 // exp value saved as negative
1876 exponent = (int)exp;
1881 internal static bool FindOther (ref int pos, string s, string other)
1883 if ((pos + other.Length) <= s.Length &&
1884 s.Substring (pos, other.Length) == other) {
1885 pos += other.Length;
1892 internal static bool ValidDigit (char e, bool allowHex)
1895 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
1897 return Char.IsDigit (e);
1900 static Exception GetFormatException ()
1902 return new FormatException ("Input string was not in the correct format");
1905 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1909 for (int i = position; i < len; i++){
1912 if (c != 0 && !Char.IsWhiteSpace (c)){
1914 exc = GetFormatException ();
1921 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
1925 bool digits_seen = false;
1932 exc = new ArgumentNullException ("value");
1939 for (i = 0; i < len; i++){
1941 if (!Char.IsWhiteSpace (c))
1947 exc = GetFormatException ();
1951 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
1953 string negative = info.NegativeSign;
1954 string positive = info.PositiveSign;
1956 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
1957 i += positive.Length;
1958 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
1960 i += negative.Length;
1963 BigInteger val = Zero;
1964 for (; i < len; i++){
1972 if (c >= '0' && c <= '9'){
1973 byte d = (byte) (c - '0');
1978 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
1984 exc = GetFormatException ();
1990 else if (sign == -1)
1991 result = new BigInteger (-1, val.data);
1993 result = new BigInteger (1, val.data);
1998 public static BigInteger Min (BigInteger left, BigInteger right)
2001 int rs = right.sign;
2008 int r = CoreCompare (left.data, right.data);
2018 public static BigInteger Max (BigInteger left, BigInteger right)
2021 int rs = right.sign;
2028 int r = CoreCompare (left.data, right.data);
2037 public static BigInteger Abs (BigInteger value)
2039 return new BigInteger ((short)Math.Abs (value.sign), value.data);
2043 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
2045 if (divisor.sign == 0)
2046 throw new DivideByZeroException ();
2048 if (dividend.sign == 0) {
2049 remainder = dividend;
2054 uint[] remainder_value;
2056 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
2059 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
2061 remainder = new BigInteger (0, ZERO);
2063 if (i < remainder_value.Length - 1)
2064 remainder_value = Resize (remainder_value, i + 1);
2065 remainder = new BigInteger (dividend.sign, remainder_value);
2068 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
2070 return new BigInteger (0, ZERO);
2071 if (i < quotient.Length - 1)
2072 quotient = Resize (quotient, i + 1);
2074 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
2077 public static BigInteger Pow (BigInteger value, int exponent)
2080 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
2086 BigInteger result = One;
2087 while (exponent != 0) {
2088 if ((exponent & 1) != 0)
2089 result = result * value;
2093 value = value * value;
2099 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
2100 if (exponent.sign == -1)
2101 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
2102 if (modulus.sign == 0)
2103 throw new DivideByZeroException ();
2105 BigInteger result = One % modulus;
2106 while (exponent.sign != 0) {
2107 if (!exponent.IsEven) {
2108 result = result * value;
2109 result = result % modulus;
2113 value = value * value;
2114 value = value % modulus;
2120 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
2122 if (left.sign != 0 && left.data.Length == 1 && left.data [0] == 1)
2123 return new BigInteger (1, ONE);
2124 if (right.sign != 0 && right.data.Length == 1 && right.data [0] == 1)
2125 return new BigInteger (1, ONE);
2131 BigInteger x = new BigInteger (1, left.data);
2132 BigInteger y = new BigInteger (1, right.data);
2136 while (x.data.Length > 1) {
2142 if (x.IsZero) return g;
2144 // TODO: should we have something here if we can convert to long?
2147 // Now we can just do it with single precision. I am using the binary gcd method,
2148 // as it should be faster.
2151 uint yy = x.data [0];
2152 uint xx = (uint)(y % yy);
2156 while (((xx | yy) & 1) == 0) {
2157 xx >>= 1; yy >>= 1; t++;
2160 while ((xx & 1) == 0) xx >>= 1;
2161 while ((yy & 1) == 0) yy >>= 1;
2163 xx = (xx - yy) >> 1;
2165 yy = (yy - xx) >> 1;
2171 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
2172 We are equilavent to MS with about 2 ULP
2174 public static double Log (BigInteger value, Double baseValue)
2176 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
2177 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
2180 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
2181 return value.IsOne ? 0 : double.NaN;
2183 if (value.sign == 0)
2184 return double.NegativeInfinity;
2186 int length = value.data.Length - 1;
2188 for (int curBit = 31; curBit >= 0; curBit--) {
2189 if ((value.data [length] & (1 << curBit)) != 0) {
2190 bitCount = curBit + length * 32;
2195 long bitlen = bitCount;
2196 Double c = 0, d = 1;
2198 BigInteger testBit = One;
2199 long tempBitlen = bitlen;
2200 while (tempBitlen > Int32.MaxValue) {
2201 testBit = testBit << Int32.MaxValue;
2202 tempBitlen -= Int32.MaxValue;
2204 testBit = testBit << (int)tempBitlen;
2206 for (long curbit = bitlen; curbit >= 0; --curbit) {
2207 if ((value & testBit).sign != 0)
2210 testBit = testBit >> 1;
2212 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
2216 public static double Log (BigInteger value)
2218 return Log (value, Math.E);
2222 public static double Log10 (BigInteger value)
2224 return Log (value, 10);
2227 [CLSCompliantAttribute (false)]
2228 public bool Equals (ulong other)
2230 return CompareTo (other) == 0;
2233 public override int GetHashCode ()
2235 uint hash = (uint)(sign * 0x01010101u);
2236 int len = data != null ? data.Length : 0;
2238 for (int i = 0; i < len; ++i)
2243 public static BigInteger Add (BigInteger left, BigInteger right)
2245 return left + right;
2248 public static BigInteger Subtract (BigInteger left, BigInteger right)
2250 return left - right;
2253 public static BigInteger Multiply (BigInteger left, BigInteger right)
2255 return left * right;
2258 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
2260 return dividend / divisor;
2263 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
2265 return dividend % divisor;
2268 public static BigInteger Negate (BigInteger value)
2273 public int CompareTo (object obj)
2278 if (!(obj is BigInteger))
2281 return Compare (this, (BigInteger)obj);
2284 public int CompareTo (BigInteger other)
2286 return Compare (this, other);
2289 [CLSCompliantAttribute (false)]
2290 public int CompareTo (ulong other)
2295 return other == 0 ? 0 : -1;
2297 if (data.Length > 2)
2300 uint high = (uint)(other >> 32);
2301 uint low = (uint)other;
2303 return LongCompare (low, high);
2306 int LongCompare (uint low, uint high)
2309 if (data.Length > 1)
2327 public int CompareTo (long other)
2330 int rs = Math.Sign (other);
2333 return ls > rs ? 1 : -1;
2338 if (data.Length > 2)
2343 uint low = (uint)other;
2344 uint high = (uint)((ulong)other >> 32);
2346 int r = LongCompare (low, high);
2353 public static int Compare (BigInteger left, BigInteger right)
2356 int rs = right.sign;
2359 return ls > rs ? 1 : -1;
2361 int r = CoreCompare (left.data, right.data);
2368 static int TopByte (uint x)
2370 if ((x & 0xFFFF0000u) != 0) {
2371 if ((x & 0xFF000000u) != 0)
2375 if ((x & 0xFF00u) != 0)
2380 static int FirstNonFFByte (uint word)
2382 if ((word & 0xFF000000u) != 0xFF000000u)
2384 else if ((word & 0xFF0000u) != 0xFF0000u)
2386 else if ((word & 0xFF00u) != 0xFF00u)
2391 public byte[] ToByteArray ()
2394 return new byte [1];
2396 //number of bytes not counting upper word
2397 int bytes = (data.Length - 1) * 4;
2398 bool needExtraZero = false;
2400 uint topWord = data [data.Length - 1];
2403 //if the topmost bit is set we need an extra
2405 extra = TopByte (topWord);
2406 uint mask = 0x80u << ((extra - 1) * 8);
2407 if ((topWord & mask) != 0) {
2408 needExtraZero = true;
2411 extra = TopByte (topWord);
2414 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
2417 int end = data.Length - 1;
2418 for (int i = 0; i < end; ++i) {
2419 uint word = data [i];
2421 res [j++] = (byte)word;
2422 res [j++] = (byte)(word >> 8);
2423 res [j++] = (byte)(word >> 16);
2424 res [j++] = (byte)(word >> 24);
2426 while (extra-- > 0) {
2427 res [j++] = (byte)topWord;
2432 int end = data.Length - 1;
2434 uint carry = 1, word;
2436 for (int i = 0; i < end; ++i) {
2438 add = (ulong)~word + carry;
2440 carry = (uint)(add >> 32);
2442 res [j++] = (byte)word;
2443 res [j++] = (byte)(word >> 8);
2444 res [j++] = (byte)(word >> 16);
2445 res [j++] = (byte)(word >> 24);
2448 add = (ulong)~topWord + (carry);
2450 carry = (uint)(add >> 32);
2452 int ex = FirstNonFFByte (word);
2453 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2454 int to = ex + (needExtra ? 1 : 0);
2457 res = Resize (res, bytes + to);
2460 res [j++] = (byte)word;
2466 res = Resize (res, bytes + 5);
2467 res [j++] = (byte)word;
2468 res [j++] = (byte)(word >> 8);
2469 res [j++] = (byte)(word >> 16);
2470 res [j++] = (byte)(word >> 24);
2478 static byte[] Resize (byte[] v, int len)
2480 byte[] res = new byte [len];
2481 Array.Copy (v, res, Math.Min (v.Length, len));
2485 static uint[] Resize (uint[] v, int len)
2487 uint[] res = new uint [len];
2488 Array.Copy (v, res, Math.Min (v.Length, len));
2492 static uint[] CoreAdd (uint[] a, uint[] b)
2494 if (a.Length < b.Length) {
2503 uint[] res = new uint [bl];
2508 for (; i < sl; i++) {
2509 sum = sum + a [i] + b [i];
2510 res [i] = (uint)sum;
2514 for (; i < bl; i++) {
2516 res [i] = (uint)sum;
2521 res = Resize (res, bl + 1);
2522 res [i] = (uint)sum;
2529 static uint[] CoreSub (uint[] a, uint[] b)
2534 uint[] res = new uint [bl];
2538 for (i = 0; i < sl; ++i) {
2539 borrow = (ulong)a [i] - b [i] - borrow;
2541 res [i] = (uint)borrow;
2542 borrow = (borrow >> 32) & 0x1;
2545 for (; i < bl; i++) {
2546 borrow = (ulong)a [i] - borrow;
2547 res [i] = (uint)borrow;
2548 borrow = (borrow >> 32) & 0x1;
2551 //remove extra zeroes
2552 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2554 res = Resize (res, i + 1);
2560 static uint[] CoreAdd (uint[] a, uint b)
2563 uint[] res = new uint [len];
2567 for (i = 0; i < len; i++) {
2569 res [i] = (uint)sum;
2574 res = Resize (res, len + 1);
2575 res [i] = (uint)sum;
2581 static uint[] CoreSub (uint[] a, uint b)
2584 uint[] res = new uint [len];
2588 for (i = 0; i < len; i++) {
2589 borrow = (ulong)a [i] - borrow;
2590 res [i] = (uint)borrow;
2591 borrow = (borrow >> 32) & 0x1;
2594 //remove extra zeroes
2595 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2597 res = Resize (res, i + 1);
2602 static int CoreCompare (uint[] a, uint[] b)
2604 int al = a != null ? a.Length : 0;
2605 int bl = b != null ? b.Length : 0;
2612 for (int i = al - 1; i >= 0; --i) {
2623 static int GetNormalizeShift(uint value) {
2626 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2627 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2628 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2629 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2630 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2635 static void Normalize (uint[] u, int l, uint[] un, int shift)
2640 int rshift = 32 - shift;
2641 for (i = 0; i < l; i++) {
2643 un [i] = (ui << shift) | carry;
2644 carry = ui >> rshift;
2647 for (i = 0; i < l; i++) {
2652 while (i < un.Length) {
2661 static void Unnormalize (uint[] un, out uint[] r, int shift)
2663 int length = un.Length;
2664 r = new uint [length];
2667 int lshift = 32 - shift;
2669 for (int i = length - 1; i >= 0; i--) {
2671 r [i] = (uni >> shift) | carry;
2672 carry = (uni << lshift);
2675 for (int i = 0; i < length; i++) {
2681 const ulong Base = 0x100000000;
2682 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2688 // Divide by single digit
2695 for (int j = m - 1; j >= 0; j--) {
2699 ulong div = rem / v0;
2704 } else if (m >= n) {
2705 int shift = GetNormalizeShift (v [n - 1]);
2707 uint[] un = new uint [m + 1];
2708 uint[] vn = new uint [n];
2710 Normalize (u, m, un, shift);
2711 Normalize (v, n, vn, shift);
2713 q = new uint [m - n + 1];
2716 // Main division loop
2718 for (int j = m - n; j >= 0; j--) {
2722 rr = Base * un [j + n] + un [j + n - 1];
2723 qq = rr / vn [n - 1];
2724 rr -= qq * vn [n - 1];
2727 // Estimate too big ?
2729 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2731 rr += (ulong)vn [n - 1];
2739 // Multiply and subtract
2743 for (i = 0; i < n; i++) {
2744 ulong p = vn [i] * qq;
2745 t = (long)un [i + j] - (long)(uint)p - b;
2746 un [i + j] = (uint)t;
2751 t = (long)un [j + n] - b;
2752 un [j + n] = (uint)t;
2754 // Store the calculated value
2758 // Add back vn[0..n] to un[j..j+n]
2763 for (i = 0; i < n; i++) {
2764 c = (ulong)vn [i] + un [j + i] + c;
2765 un [j + i] = (uint)c;
2768 c += (ulong)un [j + n];
2769 un [j + n] = (uint)c;
2773 Unnormalize (un, out r, shift);
2775 q = new uint [] { 0 };