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;
476 if (high > 0x80000000u)
477 throw new OverflowException ();
479 return - ((((long)high) << 32) | (long)low);
482 [CLSCompliantAttribute (false)]
483 public static explicit operator ulong (BigInteger value)
487 if (value.data.Length > 2 || value.sign == -1)
488 throw new OverflowException ();
490 uint low = value.data [0];
491 if (value.data.Length == 1)
494 uint high = value.data [1];
495 return (((ulong)high) << 32) | low;
498 public static explicit operator double (BigInteger value)
502 return double.Parse (value.ToString (),
503 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
504 } catch (OverflowException) {
505 return value.sign == -1 ? double.NegativeInfinity : double.PositiveInfinity;
509 public static explicit operator float (BigInteger value)
513 return float.Parse (value.ToString (),
514 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
515 } catch (OverflowException) {
516 return value.sign == -1 ? float.NegativeInfinity : float.PositiveInfinity;
520 public static explicit operator decimal (BigInteger value)
525 uint[] data = value.data;
527 throw new OverflowException ();
529 int lo = 0, mi = 0, hi = 0;
531 hi = (Int32)data [2];
533 mi = (Int32)data [1];
535 lo = (Int32)data [0];
537 return new Decimal(lo, mi, hi, value.sign < 0, 0);
540 public static implicit operator BigInteger (int value)
542 return new BigInteger (value);
545 [CLSCompliantAttribute (false)]
546 public static implicit operator BigInteger (uint value)
548 return new BigInteger (value);
551 public static implicit operator BigInteger (short value)
553 return new BigInteger (value);
556 [CLSCompliantAttribute (false)]
557 public static implicit operator BigInteger (ushort value)
559 return new BigInteger (value);
562 public static implicit operator BigInteger (byte value)
564 return new BigInteger (value);
567 [CLSCompliantAttribute (false)]
568 public static implicit operator BigInteger (sbyte value)
570 return new BigInteger (value);
573 public static implicit operator BigInteger (long value)
575 return new BigInteger (value);
578 [CLSCompliantAttribute (false)]
579 public static implicit operator BigInteger (ulong value)
581 return new BigInteger (value);
584 public static explicit operator BigInteger (double value)
586 return new BigInteger (value);
589 public static explicit operator BigInteger (float value)
591 return new BigInteger (value);
594 public static explicit operator BigInteger (decimal value)
596 return new BigInteger (value);
599 public static BigInteger operator+ (BigInteger left, BigInteger right)
606 if (left.sign == right.sign)
607 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
609 int r = CoreCompare (left.data, right.data);
612 return new BigInteger (0, ZERO);
614 if (r > 0) //left > right
615 return new BigInteger (left.sign, CoreSub (left.data, right.data));
617 return new BigInteger (right.sign, CoreSub (right.data, left.data));
620 public static BigInteger operator- (BigInteger left, BigInteger right)
625 return new BigInteger ((short)-right.sign, right.data);
627 if (left.sign == right.sign) {
628 int r = CoreCompare (left.data, right.data);
631 return new BigInteger (0, ZERO);
633 if (r > 0) //left > right
634 return new BigInteger (left.sign, CoreSub (left.data, right.data));
636 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
639 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
642 public static BigInteger operator* (BigInteger left, BigInteger right)
644 if (left.sign == 0 || right.sign == 0)
645 return new BigInteger (0, ZERO);
647 if (left.data [0] == 1 && left.data.Length == 1) {
650 return new BigInteger ((short)-right.sign, right.data);
653 if (right.data [0] == 1 && right.data.Length == 1) {
656 return new BigInteger ((short)-left.sign, left.data);
659 uint[] a = left.data;
660 uint[] b = right.data;
662 uint[] res = new uint [a.Length + b.Length];
664 for (int i = 0; i < a.Length; ++i) {
669 for (int j = 0; j < b.Length; ++j) {
670 carry = carry + ((ulong)ai) * b [j] + res [k];
671 res[k++] = (uint)carry;
677 res[k++] = (uint)carry;
683 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
684 if (m < res.Length - 1)
685 res = Resize (res, m + 1);
687 return new BigInteger ((short)(left.sign * right.sign), res);
690 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
692 if (divisor.sign == 0)
693 throw new DivideByZeroException ();
695 if (dividend.sign == 0)
699 uint[] remainder_value;
701 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
704 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
706 return new BigInteger (0, ZERO);
707 if (i < quotient.Length - 1)
708 quotient = Resize (quotient, i + 1);
710 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
713 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
715 if (divisor.sign == 0)
716 throw new DivideByZeroException ();
718 if (dividend.sign == 0)
722 uint[] remainder_value;
724 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
727 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
729 return new BigInteger (0, ZERO);
731 if (i < remainder_value.Length - 1)
732 remainder_value = Resize (remainder_value, i + 1);
733 return new BigInteger (dividend.sign, remainder_value);
736 public static BigInteger operator- (BigInteger value)
740 return new BigInteger ((short)-value.sign, value.data);
743 public static BigInteger operator+ (BigInteger value)
748 public static BigInteger operator++ (BigInteger value)
753 short sign = value.sign;
754 uint[] data = value.data;
755 if (data.Length == 1) {
756 if (sign == -1 && data [0] == 1)
757 return new BigInteger (0, ZERO);
759 return new BigInteger (1, ONE);
763 data = CoreSub (data, 1);
765 data = CoreAdd (data, 1);
767 return new BigInteger (sign, data);
770 public static BigInteger operator-- (BigInteger value)
775 short sign = value.sign;
776 uint[] data = value.data;
777 if (data.Length == 1) {
778 if (sign == 1 && data [0] == 1)
779 return new BigInteger (0, ZERO);
781 return new BigInteger (-1, ONE);
785 data = CoreAdd (data, 1);
787 data = CoreSub (data, 1);
789 return new BigInteger (sign, data);
792 public static BigInteger operator& (BigInteger left, BigInteger right)
800 uint[] a = left.data;
801 uint[] b = right.data;
805 bool neg_res = (ls == rs) && (ls == -1);
807 uint[] result = new uint [Math.Max (a.Length, b.Length)];
809 ulong ac = 1, bc = 1, borrow = 1;
812 for (i = 0; i < result.Length; ++i) {
819 ac = (uint)(ac >> 32);
828 bc = (uint)(bc >> 32);
834 borrow = word - borrow;
835 word = ~(uint)borrow;
836 borrow = (uint)(borrow >> 32) & 0x1u;
842 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
844 return new BigInteger (0, ZERO);
846 if (i < result.Length - 1)
847 result = Resize (result, i + 1);
849 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
852 public static BigInteger operator| (BigInteger left, BigInteger right)
860 uint[] a = left.data;
861 uint[] b = right.data;
865 bool neg_res = (ls == -1) || (rs == -1);
867 uint[] result = new uint [Math.Max (a.Length, b.Length)];
869 ulong ac = 1, bc = 1, borrow = 1;
872 for (i = 0; i < result.Length; ++i) {
879 ac = (uint)(ac >> 32);
888 bc = (uint)(bc >> 32);
894 borrow = word - borrow;
895 word = ~(uint)borrow;
896 borrow = (uint)(borrow >> 32) & 0x1u;
902 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
904 return new BigInteger (0, ZERO);
906 if (i < result.Length - 1)
907 result = Resize (result, i + 1);
909 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
912 public static BigInteger operator^ (BigInteger left, BigInteger right)
920 uint[] a = left.data;
921 uint[] b = right.data;
925 bool neg_res = (ls == -1) ^ (rs == -1);
927 uint[] result = new uint [Math.Max (a.Length, b.Length)];
929 ulong ac = 1, bc = 1, borrow = 1;
932 for (i = 0; i < result.Length; ++i) {
939 ac = (uint)(ac >> 32);
948 bc = (uint)(bc >> 32);
954 borrow = word - borrow;
955 word = ~(uint)borrow;
956 borrow = (uint)(borrow >> 32) & 0x1u;
962 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
964 return new BigInteger (0, ZERO);
966 if (i < result.Length - 1)
967 result = Resize (result, i + 1);
969 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
972 public static BigInteger operator~ (BigInteger value)
975 return new BigInteger (-1, ONE);
977 uint[] data = value.data;
978 int sign = value.sign;
980 bool neg_res = sign == 1;
982 uint[] result = new uint [data.Length];
984 ulong carry = 1, borrow = 1;
987 for (i = 0; i < result.Length; ++i) {
988 uint word = data [i];
990 carry = ~word + carry;
992 carry = (uint)(carry >> 32);
998 borrow = word - borrow;
999 word = ~(uint)borrow;
1000 borrow = (uint)(borrow >> 32) & 0x1u;
1006 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1008 return new BigInteger (0, ZERO);
1010 if (i < result.Length - 1)
1011 result = Resize (result, i + 1);
1013 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1016 //returns the 0-based index of the most significant set bit
1017 //returns 0 if no bit is set, so extra care when using it
1018 static int BitScanBackward (uint word)
1020 for (int i = 31; i >= 0; --i) {
1021 uint mask = 1u << i;
1022 if ((word & mask) == mask)
1028 public static BigInteger operator<< (BigInteger value, int shift)
1030 if (shift == 0 || value.sign == 0)
1033 return value >> -shift;
1035 uint[] data = value.data;
1036 int sign = value.sign;
1038 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1039 int bits = shift - (31 - topMostIdx);
1040 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
1042 uint[] res = new uint [data.Length + extra_words];
1044 int idx_shift = shift >> 5;
1045 int bit_shift = shift & 0x1F;
1046 int carry_shift = 32 - bit_shift;
1048 if (carry_shift == 32) {
1049 for (int i = 0; i < data.Length; ++i) {
1050 uint word = data [i];
1051 res [i + idx_shift] |= word << bit_shift;
1054 for (int i = 0; i < data.Length; ++i) {
1055 uint word = data [i];
1056 res [i + idx_shift] |= word << bit_shift;
1057 if (i + idx_shift + 1 < res.Length)
1058 res [i + idx_shift + 1] = word >> carry_shift;
1062 return new BigInteger ((short)sign, res);
1065 public static BigInteger operator>> (BigInteger value, int shift)
1067 if (shift == 0 || value.sign == 0)
1070 return value << -shift;
1072 uint[] data = value.data;
1073 int sign = value.sign;
1075 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1076 int idx_shift = shift >> 5;
1077 int bit_shift = shift & 0x1F;
1079 int extra_words = idx_shift;
1080 if (bit_shift > topMostIdx)
1082 int size = data.Length - extra_words;
1086 return new BigInteger (0, ZERO);
1087 return new BigInteger (-1, ONE);
1090 uint[] res = new uint [size];
1091 int carry_shift = 32 - bit_shift;
1093 if (carry_shift == 32) {
1094 for (int i = data.Length - 1; i >= idx_shift; --i) {
1095 uint word = data [i];
1097 if (i - idx_shift < res.Length)
1098 res [i - idx_shift] |= word >> bit_shift;
1101 for (int i = data.Length - 1; i >= idx_shift; --i) {
1102 uint word = data [i];
1104 if (i - idx_shift < res.Length)
1105 res [i - idx_shift] |= word >> bit_shift;
1106 if (i - idx_shift - 1 >= 0)
1107 res [i - idx_shift - 1] = word << carry_shift;
1112 //Round down instead of toward zero
1114 for (int i = 0; i < idx_shift; i++) {
1115 if (data [i] != 0u) {
1116 var tmp = new BigInteger ((short)sign, res);
1121 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
1122 var tmp = new BigInteger ((short)sign, res);
1127 return new BigInteger ((short)sign, res);
1130 public static bool operator< (BigInteger left, BigInteger right)
1132 return Compare (left, right) < 0;
1135 public static bool operator< (BigInteger left, long right)
1137 return left.CompareTo (right) < 0;
1141 public static bool operator< (long left, BigInteger right)
1143 return right.CompareTo (left) > 0;
1147 [CLSCompliantAttribute (false)]
1148 public static bool operator< (BigInteger left, ulong right)
1150 return left.CompareTo (right) < 0;
1153 [CLSCompliantAttribute (false)]
1154 public static bool operator< (ulong left, BigInteger right)
1156 return right.CompareTo (left) > 0;
1159 public static bool operator<= (BigInteger left, BigInteger right)
1161 return Compare (left, right) <= 0;
1164 public static bool operator<= (BigInteger left, long right)
1166 return left.CompareTo (right) <= 0;
1169 public static bool operator<= (long left, BigInteger right)
1171 return right.CompareTo (left) >= 0;
1174 [CLSCompliantAttribute (false)]
1175 public static bool operator<= (BigInteger left, ulong right)
1177 return left.CompareTo (right) <= 0;
1180 [CLSCompliantAttribute (false)]
1181 public static bool operator<= (ulong left, BigInteger right)
1183 return right.CompareTo (left) >= 0;
1186 public static bool operator> (BigInteger left, BigInteger right)
1188 return Compare (left, right) > 0;
1191 public static bool operator> (BigInteger left, long right)
1193 return left.CompareTo (right) > 0;
1196 public static bool operator> (long left, BigInteger right)
1198 return right.CompareTo (left) < 0;
1201 [CLSCompliantAttribute (false)]
1202 public static bool operator> (BigInteger left, ulong right)
1204 return left.CompareTo (right) > 0;
1207 [CLSCompliantAttribute (false)]
1208 public static bool operator> (ulong left, BigInteger right)
1210 return right.CompareTo (left) < 0;
1213 public static bool operator>= (BigInteger left, BigInteger right)
1215 return Compare (left, right) >= 0;
1218 public static bool operator>= (BigInteger left, long right)
1220 return left.CompareTo (right) >= 0;
1223 public static bool operator>= (long left, BigInteger right)
1225 return right.CompareTo (left) <= 0;
1228 [CLSCompliantAttribute (false)]
1229 public static bool operator>= (BigInteger left, ulong right)
1231 return left.CompareTo (right) >= 0;
1234 [CLSCompliantAttribute (false)]
1235 public static bool operator>= (ulong left, BigInteger right)
1237 return right.CompareTo (left) <= 0;
1240 public static bool operator== (BigInteger left, BigInteger right)
1242 return Compare (left, right) == 0;
1245 public static bool operator== (BigInteger left, long right)
1247 return left.CompareTo (right) == 0;
1250 public static bool operator== (long left, BigInteger right)
1252 return right.CompareTo (left) == 0;
1255 [CLSCompliantAttribute (false)]
1256 public static bool operator== (BigInteger left, ulong right)
1258 return left.CompareTo (right) == 0;
1261 [CLSCompliantAttribute (false)]
1262 public static bool operator== (ulong left, BigInteger right)
1264 return right.CompareTo (left) == 0;
1267 public static bool operator!= (BigInteger left, BigInteger right)
1269 return Compare (left, right) != 0;
1272 public static bool operator!= (BigInteger left, long right)
1274 return left.CompareTo (right) != 0;
1277 public static bool operator!= (long left, BigInteger right)
1279 return right.CompareTo (left) != 0;
1282 [CLSCompliantAttribute (false)]
1283 public static bool operator!= (BigInteger left, ulong right)
1285 return left.CompareTo (right) != 0;
1288 [CLSCompliantAttribute (false)]
1289 public static bool operator!= (ulong left, BigInteger right)
1291 return right.CompareTo (left) != 0;
1294 public override bool Equals (object obj)
1296 if (!(obj is BigInteger))
1298 return Equals ((BigInteger)obj);
1301 public bool Equals (BigInteger other)
1303 if (sign != other.sign)
1306 int alen = data != null ? data.Length : 0;
1307 int blen = other.data != null ? other.data.Length : 0;
1311 for (int i = 0; i < alen; ++i) {
1312 if (data [i] != other.data [i])
1318 public bool Equals (long other)
1320 return CompareTo (other) == 0;
1323 public override string ToString ()
1325 return ToString (10, null);
1328 string ToStringWithPadding (string format, uint radix, IFormatProvider provider)
1330 if (format.Length > 1) {
1331 int precision = Convert.ToInt32(format.Substring (1), CultureInfo.InvariantCulture.NumberFormat);
1332 string baseStr = ToString (radix, provider);
1333 if (baseStr.Length < precision) {
1334 string additional = new String ('0', precision - baseStr.Length);
1335 if (baseStr[0] != '-') {
1336 return additional + baseStr;
1338 return "-" + additional + baseStr.Substring (1);
1343 return ToString (radix, provider);
1346 public string ToString (string format)
1348 return ToString (format, null);
1351 public string ToString (IFormatProvider provider)
1353 return ToString (null, provider);
1357 public string ToString (string format, IFormatProvider provider)
1359 if (format == null || format == "")
1360 return ToString (10, provider);
1362 switch (format[0]) {
1369 return ToStringWithPadding (format, 10, provider);
1372 return ToStringWithPadding (format, 16, null);
1374 throw new FormatException (string.Format ("format '{0}' not implemented", format));
1378 static uint[] MakeTwoComplement (uint[] v)
1380 uint[] res = new uint [v.Length];
1383 for (int i = 0; i < v.Length; ++i) {
1385 carry = (ulong)~word + carry;
1387 carry = (uint)(carry >> 32);
1391 uint last = res [res.Length - 1];
1392 int idx = FirstNonFFByte (last);
1394 for (int i = 1; i < idx; ++i)
1395 mask = (mask << 8) | 0xFF;
1397 res [res.Length - 1] = last & mask;
1401 string ToString (uint radix, IFormatProvider provider)
1403 const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1405 if (characterSet.Length < radix)
1406 throw new ArgumentException ("charSet length less than radix", "characterSet");
1408 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
1412 if (data.Length == 1 && data [0] == 1)
1413 return sign == 1 ? "1" : "-1";
1415 List<char> digits = new List<char> (1 + data.Length * 3 / 10);
1423 dt = MakeTwoComplement (dt);
1424 a = new BigInteger (1, dt);
1429 a = DivRem (a, radix, out rem);
1430 digits.Add (characterSet [(int) rem]);
1433 if (sign == -1 && radix == 10) {
1434 NumberFormatInfo info = null;
1435 if (provider != null)
1436 info = provider.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo;
1438 string str = info.NegativeSign;
1439 for (int i = str.Length - 1; i >= 0; --i)
1440 digits.Add (str [i]);
1446 char last = digits [digits.Count - 1];
1447 if (sign == 1 && radix > 10 && (last < '0' || last > '9'))
1452 return new String (digits.ToArray ());
1455 public static BigInteger Parse (string value)
1460 if (!Parse (value, false, out result, out ex))
1465 public static bool TryParse (string value, out BigInteger result)
1468 return Parse (value, true, out result, out ex);
1471 public static BigInteger Parse (string value, NumberStyles style)
1473 return Parse (value, style, null);
1476 public static BigInteger Parse (string value, IFormatProvider provider)
1478 return Parse (value, NumberStyles.Integer, provider);
1481 public static BigInteger Parse (
1482 string value, NumberStyles style, IFormatProvider provider)
1487 if (!Parse (value, style, provider, false, out res, out exc))
1493 public static bool TryParse (
1494 string value, NumberStyles style, IFormatProvider provider,
1495 out BigInteger result)
1498 if (!Parse (value, style, provider, true, out result, out exc)) {
1506 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
1513 exc = new ArgumentNullException ("s");
1517 if (s.Length == 0) {
1519 exc = GetFormatException ();
1523 NumberFormatInfo nfi = null;
1525 Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
1526 nfi = (NumberFormatInfo)fp.GetFormat (typeNFI);
1529 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
1531 if (!CheckStyle (style, tryParse, ref exc))
1534 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
1535 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
1536 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
1537 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
1538 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
1539 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
1540 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
1541 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
1542 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
1543 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
1547 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1550 bool foundOpenParentheses = false;
1551 bool negative = false;
1552 bool foundSign = false;
1553 bool foundCurrency = false;
1556 if (AllowParentheses && s [pos] == '(') {
1557 foundOpenParentheses = true;
1559 negative = true; // MS always make the number negative when there parentheses
1560 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
1562 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1565 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
1567 exc = GetFormatException ();
1571 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
1573 exc = GetFormatException ();
1578 if (AllowLeadingSign && !foundSign) {
1580 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1582 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1584 if (AllowCurrencySymbol) {
1585 FindCurrency (ref pos, s, nfi,
1587 if (foundCurrency && AllowLeadingWhite &&
1588 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1594 if (AllowCurrencySymbol && !foundCurrency) {
1596 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1597 if (foundCurrency) {
1598 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1600 if (foundCurrency) {
1601 if (!foundSign && AllowLeadingSign) {
1602 FindSign (ref pos, s, nfi, ref foundSign,
1604 if (foundSign && AllowLeadingWhite &&
1605 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1612 BigInteger number = Zero;
1614 int decimalPointPos = -1;
1617 bool firstHexDigit = true;
1620 while (pos < s.Length) {
1622 if (!ValidDigit (s [pos], AllowHexSpecifier)) {
1623 if (AllowThousands &&
1624 (FindOther (ref pos, s, nfi.NumberGroupSeparator)
1625 || FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
1628 if (AllowDecimalPoint && decimalPointPos < 0 &&
1629 (FindOther (ref pos, s, nfi.NumberDecimalSeparator)
1630 || FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
1631 decimalPointPos = nDigits;
1640 if (AllowHexSpecifier) {
1641 hexDigit = s [pos++];
1642 if (Char.IsDigit (hexDigit))
1643 digitValue = (byte)(hexDigit - '0');
1644 else if (Char.IsLower (hexDigit))
1645 digitValue = (byte)(hexDigit - 'a' + 10);
1647 digitValue = (byte)(hexDigit - 'A' + 10);
1649 if (firstHexDigit && (byte)digitValue >= 8)
1652 number = number * 16 + digitValue;
1653 firstHexDigit = false;
1657 number = number * 10 + (byte)(s [pos++] - '0');
1660 // Post number stuff
1663 exc = GetFormatException ();
1668 if (AllowHexSpecifier && negative) {
1670 BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
1671 number = (number ^ mask) + 1;
1676 if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
1679 if (AllowTrailingSign && !foundSign) {
1681 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1682 if (foundSign && pos < s.Length) {
1683 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1688 if (AllowCurrencySymbol && !foundCurrency) {
1689 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1693 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1694 if (foundCurrency && pos < s.Length) {
1695 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1697 if (!foundSign && AllowTrailingSign)
1698 FindSign (ref pos, s, nfi, ref foundSign,
1703 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1706 if (foundOpenParentheses) {
1707 if (pos >= s.Length || s [pos++] != ')') {
1709 exc = GetFormatException ();
1712 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1716 if (pos < s.Length && s [pos] != '\u0000') {
1718 exc = GetFormatException ();
1722 if (decimalPointPos >= 0)
1723 exponent = exponent - nDigits + decimalPointPos;
1727 // Any non-zero values after decimal point are not allowed
1729 BigInteger remainder;
1730 number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
1732 if (!remainder.IsZero) {
1734 exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
1737 } else if (exponent > 0) {
1738 number = BigInteger.Pow(10, exponent) * number;
1741 if (number.sign == 0)
1744 result = new BigInteger (-1, number.data);
1746 result = new BigInteger (1, number.data);
1751 internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
1753 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
1754 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
1755 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
1756 ne ^= NumberStyles.AllowLeadingWhite;
1757 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
1758 ne ^= NumberStyles.AllowTrailingWhite;
1761 exc = new ArgumentException (
1762 "With AllowHexSpecifier only " +
1763 "AllowLeadingWhite and AllowTrailingWhite " +
1767 } else if ((uint) style > (uint) NumberStyles.Any){
1769 exc = new ArgumentException ("Not a valid number style");
1776 internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
1778 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
1781 if (reportError && pos >= s.Length) {
1783 exc = GetFormatException ();
1790 internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
1791 ref bool foundSign, ref bool negative)
1793 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
1794 string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
1797 pos += nfi.NegativeSign.Length;
1798 } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
1799 string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
1801 pos += nfi.PositiveSign.Length;
1806 internal static void FindCurrency (ref int pos,
1808 NumberFormatInfo nfi,
1809 ref bool foundCurrency)
1811 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
1812 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
1813 foundCurrency = true;
1814 pos += nfi.CurrencySymbol.Length;
1818 internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
1822 if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
1828 if (i == s.Length) {
1829 exc = tryParse ? null : GetFormatException ();
1833 bool negative = false;
1836 if(++i == s.Length){
1837 exc = tryParse ? null : GetFormatException ();
1842 if (s [i] == '+' && ++i == s.Length) {
1843 exc = tryParse ? null : GetFormatException ();
1847 long exp = 0; // temp long value
1848 for (; i < s.Length; i++) {
1849 if (!Char.IsDigit (s [i])) {
1850 exc = tryParse ? null : GetFormatException ();
1854 // Reduce the risk of throwing an overflow exc
1855 exp = checked (exp * 10 - (int) (s [i] - '0'));
1856 if (exp < Int32.MinValue || exp > Int32.MaxValue) {
1857 exc = tryParse ? null : new OverflowException ("Value too large or too small.");
1862 // exp value saved as negative
1867 exponent = (int)exp;
1872 internal static bool FindOther (ref int pos, string s, string other)
1874 if ((pos + other.Length) <= s.Length &&
1875 s.Substring (pos, other.Length) == other) {
1876 pos += other.Length;
1883 internal static bool ValidDigit (char e, bool allowHex)
1886 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
1888 return Char.IsDigit (e);
1891 static Exception GetFormatException ()
1893 return new FormatException ("Input string was not in the correct format");
1896 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1900 for (int i = position; i < len; i++){
1903 if (c != 0 && !Char.IsWhiteSpace (c)){
1905 exc = GetFormatException ();
1912 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
1916 bool digits_seen = false;
1923 exc = new ArgumentNullException ("value");
1930 for (i = 0; i < len; i++){
1932 if (!Char.IsWhiteSpace (c))
1938 exc = GetFormatException ();
1942 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
1944 string negative = info.NegativeSign;
1945 string positive = info.PositiveSign;
1947 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
1948 i += positive.Length;
1949 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
1951 i += negative.Length;
1954 BigInteger val = Zero;
1955 for (; i < len; i++){
1963 if (c >= '0' && c <= '9'){
1964 byte d = (byte) (c - '0');
1969 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
1975 exc = GetFormatException ();
1981 else if (sign == -1)
1982 result = new BigInteger (-1, val.data);
1984 result = new BigInteger (1, val.data);
1989 public static BigInteger Min (BigInteger left, BigInteger right)
1992 int rs = right.sign;
1999 int r = CoreCompare (left.data, right.data);
2009 public static BigInteger Max (BigInteger left, BigInteger right)
2012 int rs = right.sign;
2019 int r = CoreCompare (left.data, right.data);
2028 public static BigInteger Abs (BigInteger value)
2030 return new BigInteger ((short)Math.Abs (value.sign), value.data);
2034 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
2036 if (divisor.sign == 0)
2037 throw new DivideByZeroException ();
2039 if (dividend.sign == 0) {
2040 remainder = dividend;
2045 uint[] remainder_value;
2047 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
2050 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
2052 remainder = new BigInteger (0, ZERO);
2054 if (i < remainder_value.Length - 1)
2055 remainder_value = Resize (remainder_value, i + 1);
2056 remainder = new BigInteger (dividend.sign, remainder_value);
2059 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
2061 return new BigInteger (0, ZERO);
2062 if (i < quotient.Length - 1)
2063 quotient = Resize (quotient, i + 1);
2065 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
2068 public static BigInteger Pow (BigInteger value, int exponent)
2071 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
2077 BigInteger result = One;
2078 while (exponent != 0) {
2079 if ((exponent & 1) != 0)
2080 result = result * value;
2084 value = value * value;
2090 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
2091 if (exponent.sign == -1)
2092 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
2093 if (modulus.sign == 0)
2094 throw new DivideByZeroException ();
2096 BigInteger result = One % modulus;
2097 while (exponent.sign != 0) {
2098 if (!exponent.IsEven) {
2099 result = result * value;
2100 result = result % modulus;
2104 value = value * value;
2105 value = value % modulus;
2111 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
2113 if (left.sign != 0 && left.data.Length == 1 && left.data [0] == 1)
2114 return new BigInteger (1, ONE);
2115 if (right.sign != 0 && right.data.Length == 1 && right.data [0] == 1)
2116 return new BigInteger (1, ONE);
2122 BigInteger x = new BigInteger (1, left.data);
2123 BigInteger y = new BigInteger (1, right.data);
2127 while (x.data.Length > 1) {
2133 if (x.IsZero) return g;
2135 // TODO: should we have something here if we can convert to long?
2138 // Now we can just do it with single precision. I am using the binary gcd method,
2139 // as it should be faster.
2142 uint yy = x.data [0];
2143 uint xx = (uint)(y % yy);
2147 while (((xx | yy) & 1) == 0) {
2148 xx >>= 1; yy >>= 1; t++;
2151 while ((xx & 1) == 0) xx >>= 1;
2152 while ((yy & 1) == 0) yy >>= 1;
2154 xx = (xx - yy) >> 1;
2156 yy = (yy - xx) >> 1;
2162 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
2163 We are equilavent to MS with about 2 ULP
2165 public static double Log (BigInteger value, Double baseValue)
2167 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
2168 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
2171 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
2172 return value.IsOne ? 0 : double.NaN;
2174 if (value.sign == 0)
2175 return double.NegativeInfinity;
2177 int length = value.data.Length - 1;
2179 for (int curBit = 31; curBit >= 0; curBit--) {
2180 if ((value.data [length] & (1 << curBit)) != 0) {
2181 bitCount = curBit + length * 32;
2186 long bitlen = bitCount;
2187 Double c = 0, d = 1;
2189 BigInteger testBit = One;
2190 long tempBitlen = bitlen;
2191 while (tempBitlen > Int32.MaxValue) {
2192 testBit = testBit << Int32.MaxValue;
2193 tempBitlen -= Int32.MaxValue;
2195 testBit = testBit << (int)tempBitlen;
2197 for (long curbit = bitlen; curbit >= 0; --curbit) {
2198 if ((value & testBit).sign != 0)
2201 testBit = testBit >> 1;
2203 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
2207 public static double Log (BigInteger value)
2209 return Log (value, Math.E);
2213 public static double Log10 (BigInteger value)
2215 return Log (value, 10);
2218 [CLSCompliantAttribute (false)]
2219 public bool Equals (ulong other)
2221 return CompareTo (other) == 0;
2224 public override int GetHashCode ()
2226 uint hash = (uint)(sign * 0x01010101u);
2227 int len = data != null ? data.Length : 0;
2229 for (int i = 0; i < len; ++i)
2234 public static BigInteger Add (BigInteger left, BigInteger right)
2236 return left + right;
2239 public static BigInteger Subtract (BigInteger left, BigInteger right)
2241 return left - right;
2244 public static BigInteger Multiply (BigInteger left, BigInteger right)
2246 return left * right;
2249 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
2251 return dividend / divisor;
2254 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
2256 return dividend % divisor;
2259 public static BigInteger Negate (BigInteger value)
2264 public int CompareTo (object obj)
2269 if (!(obj is BigInteger))
2272 return Compare (this, (BigInteger)obj);
2275 public int CompareTo (BigInteger other)
2277 return Compare (this, other);
2280 [CLSCompliantAttribute (false)]
2281 public int CompareTo (ulong other)
2286 return other == 0 ? 0 : -1;
2288 if (data.Length > 2)
2291 uint high = (uint)(other >> 32);
2292 uint low = (uint)other;
2294 return LongCompare (low, high);
2297 int LongCompare (uint low, uint high)
2300 if (data.Length > 1)
2318 public int CompareTo (long other)
2321 int rs = Math.Sign (other);
2324 return ls > rs ? 1 : -1;
2329 if (data.Length > 2)
2334 uint low = (uint)other;
2335 uint high = (uint)((ulong)other >> 32);
2337 int r = LongCompare (low, high);
2344 public static int Compare (BigInteger left, BigInteger right)
2347 int rs = right.sign;
2350 return ls > rs ? 1 : -1;
2352 int r = CoreCompare (left.data, right.data);
2359 static int TopByte (uint x)
2361 if ((x & 0xFFFF0000u) != 0) {
2362 if ((x & 0xFF000000u) != 0)
2366 if ((x & 0xFF00u) != 0)
2371 static int FirstNonFFByte (uint word)
2373 if ((word & 0xFF000000u) != 0xFF000000u)
2375 else if ((word & 0xFF0000u) != 0xFF0000u)
2377 else if ((word & 0xFF00u) != 0xFF00u)
2382 public byte[] ToByteArray ()
2385 return new byte [1];
2387 //number of bytes not counting upper word
2388 int bytes = (data.Length - 1) * 4;
2389 bool needExtraZero = false;
2391 uint topWord = data [data.Length - 1];
2394 //if the topmost bit is set we need an extra
2396 extra = TopByte (topWord);
2397 uint mask = 0x80u << ((extra - 1) * 8);
2398 if ((topWord & mask) != 0) {
2399 needExtraZero = true;
2402 extra = TopByte (topWord);
2405 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
2408 int end = data.Length - 1;
2409 for (int i = 0; i < end; ++i) {
2410 uint word = data [i];
2412 res [j++] = (byte)word;
2413 res [j++] = (byte)(word >> 8);
2414 res [j++] = (byte)(word >> 16);
2415 res [j++] = (byte)(word >> 24);
2417 while (extra-- > 0) {
2418 res [j++] = (byte)topWord;
2423 int end = data.Length - 1;
2425 uint carry = 1, word;
2427 for (int i = 0; i < end; ++i) {
2429 add = (ulong)~word + carry;
2431 carry = (uint)(add >> 32);
2433 res [j++] = (byte)word;
2434 res [j++] = (byte)(word >> 8);
2435 res [j++] = (byte)(word >> 16);
2436 res [j++] = (byte)(word >> 24);
2439 add = (ulong)~topWord + (carry);
2441 carry = (uint)(add >> 32);
2443 int ex = FirstNonFFByte (word);
2444 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2445 int to = ex + (needExtra ? 1 : 0);
2448 res = Resize (res, bytes + to);
2451 res [j++] = (byte)word;
2457 res = Resize (res, bytes + 5);
2458 res [j++] = (byte)word;
2459 res [j++] = (byte)(word >> 8);
2460 res [j++] = (byte)(word >> 16);
2461 res [j++] = (byte)(word >> 24);
2469 static byte[] Resize (byte[] v, int len)
2471 byte[] res = new byte [len];
2472 Array.Copy (v, res, Math.Min (v.Length, len));
2476 static uint[] Resize (uint[] v, int len)
2478 uint[] res = new uint [len];
2479 Array.Copy (v, res, Math.Min (v.Length, len));
2483 static uint[] CoreAdd (uint[] a, uint[] b)
2485 if (a.Length < b.Length) {
2494 uint[] res = new uint [bl];
2499 for (; i < sl; i++) {
2500 sum = sum + a [i] + b [i];
2501 res [i] = (uint)sum;
2505 for (; i < bl; i++) {
2507 res [i] = (uint)sum;
2512 res = Resize (res, bl + 1);
2513 res [i] = (uint)sum;
2520 static uint[] CoreSub (uint[] a, uint[] b)
2525 uint[] res = new uint [bl];
2529 for (i = 0; i < sl; ++i) {
2530 borrow = (ulong)a [i] - b [i] - borrow;
2532 res [i] = (uint)borrow;
2533 borrow = (borrow >> 32) & 0x1;
2536 for (; i < bl; i++) {
2537 borrow = (ulong)a [i] - borrow;
2538 res [i] = (uint)borrow;
2539 borrow = (borrow >> 32) & 0x1;
2542 //remove extra zeroes
2543 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2545 res = Resize (res, i + 1);
2551 static uint[] CoreAdd (uint[] a, uint b)
2554 uint[] res = new uint [len];
2558 for (i = 0; i < len; i++) {
2560 res [i] = (uint)sum;
2565 res = Resize (res, len + 1);
2566 res [i] = (uint)sum;
2572 static uint[] CoreSub (uint[] a, uint b)
2575 uint[] res = new uint [len];
2579 for (i = 0; i < len; i++) {
2580 borrow = (ulong)a [i] - borrow;
2581 res [i] = (uint)borrow;
2582 borrow = (borrow >> 32) & 0x1;
2585 //remove extra zeroes
2586 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2588 res = Resize (res, i + 1);
2593 static int CoreCompare (uint[] a, uint[] b)
2595 int al = a != null ? a.Length : 0;
2596 int bl = b != null ? b.Length : 0;
2603 for (int i = al - 1; i >= 0; --i) {
2614 static int GetNormalizeShift(uint value) {
2617 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2618 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2619 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2620 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2621 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2626 static void Normalize (uint[] u, int l, uint[] un, int shift)
2631 int rshift = 32 - shift;
2632 for (i = 0; i < l; i++) {
2634 un [i] = (ui << shift) | carry;
2635 carry = ui >> rshift;
2638 for (i = 0; i < l; i++) {
2643 while (i < un.Length) {
2652 static void Unnormalize (uint[] un, out uint[] r, int shift)
2654 int length = un.Length;
2655 r = new uint [length];
2658 int lshift = 32 - shift;
2660 for (int i = length - 1; i >= 0; i--) {
2662 r [i] = (uni >> shift) | carry;
2663 carry = (uni << lshift);
2666 for (int i = 0; i < length; i++) {
2672 const ulong Base = 0x100000000;
2673 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2679 // Divide by single digit
2686 for (int j = m - 1; j >= 0; j--) {
2690 ulong div = rem / v0;
2695 } else if (m >= n) {
2696 int shift = GetNormalizeShift (v [n - 1]);
2698 uint[] un = new uint [m + 1];
2699 uint[] vn = new uint [n];
2701 Normalize (u, m, un, shift);
2702 Normalize (v, n, vn, shift);
2704 q = new uint [m - n + 1];
2707 // Main division loop
2709 for (int j = m - n; j >= 0; j--) {
2713 rr = Base * un [j + n] + un [j + n - 1];
2714 qq = rr / vn [n - 1];
2715 rr -= qq * vn [n - 1];
2718 // Estimate too big ?
2720 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2722 rr += (ulong)vn [n - 1];
2730 // Multiply and subtract
2734 for (i = 0; i < n; i++) {
2735 ulong p = vn [i] * qq;
2736 t = (long)un [i + j] - (long)(uint)p - b;
2737 un [i + j] = (uint)t;
2742 t = (long)un [j + n] - b;
2743 un [j + n] = (uint)t;
2745 // Store the calculated value
2749 // Add back vn[0..n] to un[j..j+n]
2754 for (i = 0; i < n; i++) {
2755 c = (ulong)vn [i] + un [j + i] + c;
2756 un [j + i] = (uint)c;
2759 c += (ulong)un [j + n];
2760 un [j + n] = (uint)c;
2764 Unnormalize (un, out r, shift);
2766 q = new uint [] { 0 };