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 (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)
387 if (value.data.Length > 1)
388 throw new OverflowException ();
389 uint data = value.data [0];
391 if (value.sign == 1) {
392 if (data > (uint)int.MaxValue)
393 throw new OverflowException ();
395 } else if (value.sign == -1) {
396 if (data > 0x80000000u)
397 throw new OverflowException ();
404 [CLSCompliantAttribute (false)]
405 public static explicit operator uint (BigInteger value)
407 if (value.data.Length > 1 || value.sign == -1)
408 throw new OverflowException ();
409 return value.data [0];
412 public static explicit operator short (BigInteger value)
414 int val = (int)value;
415 if (val < short.MinValue || val > short.MaxValue)
416 throw new OverflowException ();
420 [CLSCompliantAttribute (false)]
421 public static explicit operator ushort (BigInteger value)
423 uint val = (uint)value;
424 if (val > ushort.MaxValue)
425 throw new OverflowException ();
429 public static explicit operator byte (BigInteger value)
431 uint val = (uint)value;
432 if (val > byte.MaxValue)
433 throw new OverflowException ();
437 [CLSCompliantAttribute (false)]
438 public static explicit operator sbyte (BigInteger value)
440 int val = (int)value;
441 if (val < sbyte.MinValue || val > sbyte.MaxValue)
442 throw new OverflowException ();
447 public static explicit operator long (BigInteger value)
452 if (value.data.Length > 2)
453 throw new OverflowException ();
455 uint low = value.data [0];
457 if (value.data.Length == 1) {
460 long res = (long)low;
464 uint high = value.data [1];
466 if (value.sign == 1) {
467 if (high >= 0x80000000u)
468 throw new OverflowException ();
469 return (((long)high) << 32) | low;
472 if (high > 0x80000000u)
473 throw new OverflowException ();
475 return - ((((long)high) << 32) | (long)low);
478 [CLSCompliantAttribute (false)]
479 public static explicit operator ulong (BigInteger value)
481 if (value.data.Length > 2 || value.sign == -1)
482 throw new OverflowException ();
484 uint low = value.data [0];
485 if (value.data.Length == 1)
488 uint high = value.data [1];
489 return (((ulong)high) << 32) | low;
492 public static explicit operator double (BigInteger value)
496 return double.Parse (value.ToString (),
497 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
498 } catch (OverflowException) {
499 return value.sign == -1 ? double.NegativeInfinity : double.PositiveInfinity;
503 public static explicit operator float (BigInteger value)
507 return float.Parse (value.ToString (),
508 System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
509 } catch (OverflowException) {
510 return value.sign == -1 ? float.NegativeInfinity : float.PositiveInfinity;
514 public static explicit operator decimal (BigInteger value)
519 uint[] data = value.data;
521 throw new OverflowException ();
523 int lo = 0, mi = 0, hi = 0;
525 hi = (Int32)data [2];
527 mi = (Int32)data [1];
529 lo = (Int32)data [0];
531 return new Decimal(lo, mi, hi, value.sign < 0, 0);
534 public static implicit operator BigInteger (int value)
536 return new BigInteger (value);
539 [CLSCompliantAttribute (false)]
540 public static implicit operator BigInteger (uint value)
542 return new BigInteger (value);
545 public static implicit operator BigInteger (short value)
547 return new BigInteger (value);
550 [CLSCompliantAttribute (false)]
551 public static implicit operator BigInteger (ushort value)
553 return new BigInteger (value);
556 public static implicit operator BigInteger (byte value)
558 return new BigInteger (value);
561 [CLSCompliantAttribute (false)]
562 public static implicit operator BigInteger (sbyte value)
564 return new BigInteger (value);
567 public static implicit operator BigInteger (long value)
569 return new BigInteger (value);
572 [CLSCompliantAttribute (false)]
573 public static implicit operator BigInteger (ulong value)
575 return new BigInteger (value);
578 public static explicit operator BigInteger (double value)
580 return new BigInteger (value);
583 public static explicit operator BigInteger (float value)
585 return new BigInteger (value);
588 public static explicit operator BigInteger (decimal value)
590 return new BigInteger (value);
593 public static BigInteger operator+ (BigInteger left, BigInteger right)
600 if (left.sign == right.sign)
601 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
603 int r = CoreCompare (left.data, right.data);
606 return new BigInteger (0, ZERO);
608 if (r > 0) //left > right
609 return new BigInteger (left.sign, CoreSub (left.data, right.data));
611 return new BigInteger (right.sign, CoreSub (right.data, left.data));
614 public static BigInteger operator- (BigInteger left, BigInteger right)
619 return new BigInteger ((short)-right.sign, right.data);
621 if (left.sign == right.sign) {
622 int r = CoreCompare (left.data, right.data);
625 return new BigInteger (0, ZERO);
627 if (r > 0) //left > right
628 return new BigInteger (left.sign, CoreSub (left.data, right.data));
630 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
633 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
636 public static BigInteger operator* (BigInteger left, BigInteger right)
638 if (left.sign == 0 || right.sign == 0)
639 return new BigInteger (0, ZERO);
641 if (left.data [0] == 1 && left.data.Length == 1) {
644 return new BigInteger ((short)-right.sign, right.data);
647 if (right.data [0] == 1 && right.data.Length == 1) {
650 return new BigInteger ((short)-left.sign, left.data);
653 uint[] a = left.data;
654 uint[] b = right.data;
656 uint[] res = new uint [a.Length + b.Length];
658 for (int i = 0; i < a.Length; ++i) {
663 for (int j = 0; j < b.Length; ++j) {
664 carry = carry + ((ulong)ai) * b [j] + res [k];
665 res[k++] = (uint)carry;
671 res[k++] = (uint)carry;
677 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
678 if (m < res.Length - 1)
679 res = Resize (res, m + 1);
681 return new BigInteger ((short)(left.sign * right.sign), res);
684 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
686 if (divisor.sign == 0)
687 throw new DivideByZeroException ();
689 if (dividend.sign == 0)
693 uint[] remainder_value;
695 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
698 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
700 return new BigInteger (0, ZERO);
701 if (i < quotient.Length - 1)
702 quotient = Resize (quotient, i + 1);
704 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
707 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
709 if (divisor.sign == 0)
710 throw new DivideByZeroException ();
712 if (dividend.sign == 0)
716 uint[] remainder_value;
718 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
721 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
723 return new BigInteger (0, ZERO);
725 if (i < remainder_value.Length - 1)
726 remainder_value = Resize (remainder_value, i + 1);
727 return new BigInteger (dividend.sign, remainder_value);
730 public static BigInteger operator- (BigInteger value)
734 return new BigInteger ((short)-value.sign, value.data);
737 public static BigInteger operator+ (BigInteger value)
742 public static BigInteger operator++ (BigInteger value)
744 short sign = value.sign;
745 uint[] data = value.data;
746 if (data.Length == 1) {
747 if (sign == -1 && data [0] == 1)
748 return new BigInteger (0, ZERO);
750 return new BigInteger (1, ONE);
754 data = CoreSub (data, 1);
756 data = CoreAdd (data, 1);
758 return new BigInteger (sign, data);
761 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 = CoreAdd (data, 1);
775 data = CoreSub (data, 1);
777 return new BigInteger (sign, data);
780 public static BigInteger operator& (BigInteger left, BigInteger right)
788 uint[] a = left.data;
789 uint[] b = right.data;
793 bool neg_res = (ls == rs) && (ls == -1);
795 uint[] result = new uint [Math.Max (a.Length, b.Length)];
797 ulong ac = 1, bc = 1, borrow = 1;
800 for (i = 0; i < result.Length; ++i) {
807 ac = (uint)(ac >> 32);
816 bc = (uint)(bc >> 32);
822 borrow = word - borrow;
823 word = ~(uint)borrow;
824 borrow = (uint)(borrow >> 32) & 0x1u;
830 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
832 return new BigInteger (0, ZERO);
834 if (i < result.Length - 1)
835 result = Resize (result, i + 1);
837 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
840 public static BigInteger operator| (BigInteger left, BigInteger right)
848 uint[] a = left.data;
849 uint[] b = right.data;
853 bool neg_res = (ls == -1) || (rs == -1);
855 uint[] result = new uint [Math.Max (a.Length, b.Length)];
857 ulong ac = 1, bc = 1, borrow = 1;
860 for (i = 0; i < result.Length; ++i) {
867 ac = (uint)(ac >> 32);
876 bc = (uint)(bc >> 32);
882 borrow = word - borrow;
883 word = ~(uint)borrow;
884 borrow = (uint)(borrow >> 32) & 0x1u;
890 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
892 return new BigInteger (0, ZERO);
894 if (i < result.Length - 1)
895 result = Resize (result, i + 1);
897 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
900 public static BigInteger operator^ (BigInteger left, BigInteger right)
908 uint[] a = left.data;
909 uint[] b = right.data;
913 bool neg_res = (ls == -1) ^ (rs == -1);
915 uint[] result = new uint [Math.Max (a.Length, b.Length)];
917 ulong ac = 1, bc = 1, borrow = 1;
920 for (i = 0; i < result.Length; ++i) {
927 ac = (uint)(ac >> 32);
936 bc = (uint)(bc >> 32);
942 borrow = word - borrow;
943 word = ~(uint)borrow;
944 borrow = (uint)(borrow >> 32) & 0x1u;
950 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
952 return new BigInteger (0, ZERO);
954 if (i < result.Length - 1)
955 result = Resize (result, i + 1);
957 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
960 public static BigInteger operator~ (BigInteger value)
963 return new BigInteger (-1, ONE);
965 uint[] data = value.data;
966 int sign = value.sign;
968 bool neg_res = sign == 1;
970 uint[] result = new uint [data.Length];
972 ulong carry = 1, borrow = 1;
975 for (i = 0; i < result.Length; ++i) {
976 uint word = data [i];
978 carry = ~word + carry;
980 carry = (uint)(carry >> 32);
986 borrow = word - borrow;
987 word = ~(uint)borrow;
988 borrow = (uint)(borrow >> 32) & 0x1u;
994 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
996 return new BigInteger (0, ZERO);
998 if (i < result.Length - 1)
999 result = Resize (result, i + 1);
1001 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1004 //returns the 0-based index of the most significant set bit
1005 //returns 0 if no bit is set, so extra care when using it
1006 static int BitScanBackward (uint word)
1008 for (int i = 31; i >= 0; --i) {
1009 uint mask = 1u << i;
1010 if ((word & mask) == mask)
1016 public static BigInteger operator<< (BigInteger value, int shift)
1018 if (shift == 0 || value.sign == 0)
1021 return value >> -shift;
1023 uint[] data = value.data;
1024 int sign = value.sign;
1026 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1027 int bits = shift - (31 - topMostIdx);
1028 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
1030 uint[] res = new uint [data.Length + extra_words];
1032 int idx_shift = shift >> 5;
1033 int bit_shift = shift & 0x1F;
1034 int carry_shift = 32 - bit_shift;
1036 for (int i = 0; i < data.Length; ++i) {
1037 uint word = data [i];
1038 res [i + idx_shift] |= word << bit_shift;
1039 if (i + idx_shift + 1 < res.Length)
1040 res [i + idx_shift + 1] = word >> carry_shift;
1043 return new BigInteger ((short)sign, res);
1046 public static BigInteger operator>> (BigInteger value, int shift)
1048 if (shift == 0 || value.sign == 0)
1051 return value << -shift;
1053 uint[] data = value.data;
1054 int sign = value.sign;
1056 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1057 int idx_shift = shift >> 5;
1058 int bit_shift = shift & 0x1F;
1060 int extra_words = idx_shift;
1061 if (bit_shift > topMostIdx)
1063 int size = data.Length - extra_words;
1067 return new BigInteger (0, ZERO);
1068 return new BigInteger (-1, ONE);
1071 uint[] res = new uint [size];
1072 int carry_shift = 32 - bit_shift;
1074 for (int i = data.Length - 1; i >= idx_shift; --i) {
1075 uint word = data [i];
1077 if (i - idx_shift < res.Length)
1078 res [i - idx_shift] |= word >> bit_shift;
1079 if (i - idx_shift - 1 >= 0)
1080 res [i - idx_shift - 1] = word << carry_shift;
1083 //Round down instead of toward zero
1085 for (int i = 0; i < idx_shift; i++) {
1086 if (data [i] != 0u) {
1087 var tmp = new BigInteger ((short)sign, res);
1092 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
1093 var tmp = new BigInteger ((short)sign, res);
1098 return new BigInteger ((short)sign, res);
1101 public static bool operator< (BigInteger left, BigInteger right)
1103 return Compare (left, right) < 0;
1106 public static bool operator< (BigInteger left, long right)
1108 return left.CompareTo (right) < 0;
1112 public static bool operator< (long left, BigInteger right)
1114 return right.CompareTo (left) > 0;
1118 [CLSCompliantAttribute (false)]
1119 public static bool operator< (BigInteger left, ulong right)
1121 return left.CompareTo (right) < 0;
1124 [CLSCompliantAttribute (false)]
1125 public static bool operator< (ulong left, BigInteger right)
1127 return right.CompareTo (left) > 0;
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;
1140 public static bool operator<= (long left, BigInteger right)
1142 return right.CompareTo (left) >= 0;
1145 [CLSCompliantAttribute (false)]
1146 public static bool operator<= (BigInteger left, ulong right)
1148 return left.CompareTo (right) <= 0;
1151 [CLSCompliantAttribute (false)]
1152 public static bool operator<= (ulong left, BigInteger right)
1154 return right.CompareTo (left) >= 0;
1157 public static bool operator> (BigInteger left, BigInteger right)
1159 return Compare (left, right) > 0;
1162 public static bool operator> (BigInteger left, long right)
1164 return left.CompareTo (right) > 0;
1167 public static bool operator> (long left, BigInteger right)
1169 return right.CompareTo (left) < 0;
1172 [CLSCompliantAttribute (false)]
1173 public static bool operator> (BigInteger left, ulong right)
1175 return left.CompareTo (right) > 0;
1178 [CLSCompliantAttribute (false)]
1179 public static bool operator> (ulong left, BigInteger right)
1181 return right.CompareTo (left) < 0;
1184 public static bool operator>= (BigInteger left, BigInteger right)
1186 return Compare (left, right) >= 0;
1189 public static bool operator>= (BigInteger left, long right)
1191 return left.CompareTo (right) >= 0;
1194 public static bool operator>= (long left, BigInteger right)
1196 return right.CompareTo (left) <= 0;
1199 [CLSCompliantAttribute (false)]
1200 public static bool operator>= (BigInteger left, ulong right)
1202 return left.CompareTo (right) >= 0;
1205 [CLSCompliantAttribute (false)]
1206 public static bool operator>= (ulong left, BigInteger right)
1208 return right.CompareTo (left) <= 0;
1211 public static bool operator== (BigInteger left, BigInteger right)
1213 return Compare (left, right) == 0;
1216 public static bool operator== (BigInteger left, long right)
1218 return left.CompareTo (right) == 0;
1221 public static bool operator== (long left, BigInteger right)
1223 return right.CompareTo (left) == 0;
1226 [CLSCompliantAttribute (false)]
1227 public static bool operator== (BigInteger left, ulong right)
1229 return left.CompareTo (right) == 0;
1232 [CLSCompliantAttribute (false)]
1233 public static bool operator== (ulong left, BigInteger right)
1235 return right.CompareTo (left) == 0;
1238 public static bool operator!= (BigInteger left, BigInteger right)
1240 return Compare (left, right) != 0;
1243 public static bool operator!= (BigInteger left, long right)
1245 return left.CompareTo (right) != 0;
1248 public static bool operator!= (long left, BigInteger right)
1250 return right.CompareTo (left) != 0;
1253 [CLSCompliantAttribute (false)]
1254 public static bool operator!= (BigInteger left, ulong right)
1256 return left.CompareTo (right) != 0;
1259 [CLSCompliantAttribute (false)]
1260 public static bool operator!= (ulong left, BigInteger right)
1262 return right.CompareTo (left) != 0;
1265 public override bool Equals (object obj)
1267 if (!(obj is BigInteger))
1269 return Equals ((BigInteger)obj);
1272 public bool Equals (BigInteger other)
1274 if (sign != other.sign)
1276 if (data.Length != other.data.Length)
1278 for (int i = 0; i < data.Length; ++i) {
1279 if (data [i] != other.data [i])
1285 public bool Equals (long other)
1287 return CompareTo (other) == 0;
1290 public override string ToString ()
1292 return ToString (10, null);
1295 string ToStringWithPadding (string format, uint radix, IFormatProvider provider)
1297 if (format.Length > 1) {
1298 int precision = Convert.ToInt32(format.Substring (1), CultureInfo.InvariantCulture.NumberFormat);
1299 string baseStr = ToString (radix, provider);
1300 if (baseStr.Length < precision) {
1301 string additional = new String ('0', precision - baseStr.Length);
1302 if (baseStr[0] != '-') {
1303 return additional + baseStr;
1305 return "-" + additional + baseStr.Substring (1);
1310 return ToString (radix, provider);
1313 public string ToString (string format)
1315 return ToString (format, null);
1318 public string ToString (IFormatProvider provider)
1320 return ToString (null, provider);
1324 public string ToString (string format, IFormatProvider provider)
1326 if (format == null || format == "")
1327 return ToString (10, provider);
1329 switch (format[0]) {
1336 return ToStringWithPadding (format, 10, provider);
1339 return ToStringWithPadding (format, 16, null);
1341 throw new FormatException (string.Format ("format '{0}' not implemented", format));
1345 static uint[] MakeTwoComplement (uint[] v)
1347 uint[] res = new uint [v.Length];
1350 for (int i = 0; i < v.Length; ++i) {
1352 carry = (ulong)~word + carry;
1354 carry = (uint)(carry >> 32);
1358 uint last = res [res.Length - 1];
1359 int idx = FirstNonFFByte (last);
1361 for (int i = 1; i < idx; ++i)
1362 mask = (mask << 8) | 0xFF;
1364 res [res.Length - 1] = last & mask;
1368 string ToString (uint radix, IFormatProvider provider)
1370 const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1372 if (characterSet.Length < radix)
1373 throw new ArgumentException ("charSet length less than radix", "characterSet");
1375 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
1379 if (data.Length == 1 && data [0] == 1)
1380 return sign == 1 ? "1" : "-1";
1382 List<char> digits = new List<char> (1 + data.Length * 3 / 10);
1390 dt = MakeTwoComplement (dt);
1391 a = new BigInteger (1, dt);
1396 a = DivRem (a, radix, out rem);
1397 digits.Add (characterSet [(int) rem]);
1400 if (sign == -1 && radix == 10) {
1401 NumberFormatInfo info = null;
1402 if (provider != null)
1403 info = provider.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo;
1405 string str = info.NegativeSign;
1406 for (int i = str.Length - 1; i >= 0; --i)
1407 digits.Add (str [i]);
1413 char last = digits [digits.Count - 1];
1414 if (sign == 1 && radix > 10 && (last < '0' || last > '9'))
1419 return new String (digits.ToArray ());
1422 public static BigInteger Parse (string value)
1427 if (!Parse (value, false, out result, out ex))
1432 public static bool TryParse (string value, out BigInteger result)
1435 return Parse (value, true, out result, out ex);
1440 public static BigInteger Parse (string value, NumberStyles style)
1442 throw new NotImplementedException ();
1446 public static BigInteger Parse (string value, IFormatProvider provider)
1448 throw new NotImplementedException ();
1452 public static BigInteger Parse (
1453 string value, NumberStyles style, IFormatProvider provider)
1455 throw new InvalidOperationException ();
1459 public static bool TryParse (
1460 string value, NumberStyles style, IFormatProvider provider,
1461 out BigInteger result)
1463 throw new NotImplementedException ();
1468 static Exception GetFormatException ()
1470 return new FormatException ("Input string was not in the correct format");
1473 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1477 for (int i = position; i < len; i++){
1480 if (c != 0 && !Char.IsWhiteSpace (c)){
1482 exc = GetFormatException ();
1489 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
1493 bool digits_seen = false;
1500 exc = new ArgumentNullException ("value");
1507 for (i = 0; i < len; i++){
1509 if (!Char.IsWhiteSpace (c))
1515 exc = GetFormatException ();
1519 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
1521 string negative = info.NegativeSign;
1522 string positive = info.PositiveSign;
1524 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
1525 i += positive.Length;
1526 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
1528 i += negative.Length;
1531 BigInteger val = Zero;
1532 for (; i < len; i++){
1540 if (c >= '0' && c <= '9'){
1541 byte d = (byte) (c - '0');
1546 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
1552 exc = GetFormatException ();
1558 else if (sign == -1)
1559 result = new BigInteger (-1, val.data);
1561 result = new BigInteger (1, val.data);
1566 public static BigInteger Min (BigInteger left, BigInteger right)
1569 int rs = right.sign;
1576 int r = CoreCompare (left.data, right.data);
1586 public static BigInteger Max (BigInteger left, BigInteger right)
1589 int rs = right.sign;
1596 int r = CoreCompare (left.data, right.data);
1605 public static BigInteger Abs (BigInteger value)
1607 return new BigInteger ((short)Math.Abs (value.sign), value.data);
1611 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
1613 if (divisor.sign == 0)
1614 throw new DivideByZeroException ();
1616 if (dividend.sign == 0) {
1617 remainder = dividend;
1622 uint[] remainder_value;
1624 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
1627 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
1629 remainder = new BigInteger (0, ZERO);
1631 if (i < remainder_value.Length - 1)
1632 remainder_value = Resize (remainder_value, i + 1);
1633 remainder = new BigInteger (dividend.sign, remainder_value);
1636 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
1638 return new BigInteger (0, ZERO);
1639 if (i < quotient.Length - 1)
1640 quotient = Resize (quotient, i + 1);
1642 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
1645 public static BigInteger Pow (BigInteger value, int exponent)
1648 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
1654 BigInteger result = One;
1655 while (exponent != 0) {
1656 if ((exponent & 1) != 0)
1657 result = result * value;
1661 value = value * value;
1667 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
1668 if (exponent.sign == -1)
1669 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
1670 if (modulus.sign == 0)
1671 throw new DivideByZeroException ();
1673 BigInteger result = One % modulus;
1674 while (exponent.sign != 0) {
1675 if (!exponent.IsEven) {
1676 result = result * value;
1677 result = result % modulus;
1681 value = value * value;
1682 value = value % modulus;
1688 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
1690 if (left.data.Length == 1 && left.data [0] == 1)
1691 return new BigInteger (1, ONE);
1692 if (right.data.Length == 1 && right.data [0] == 1)
1693 return new BigInteger (1, ONE);
1699 BigInteger x = new BigInteger (1, left.data);
1700 BigInteger y = new BigInteger (1, right.data);
1704 while (x.data.Length > 1) {
1710 if (x.IsZero) return g;
1712 // TODO: should we have something here if we can convert to long?
1715 // Now we can just do it with single precision. I am using the binary gcd method,
1716 // as it should be faster.
1719 uint yy = x.data [0];
1720 uint xx = (uint)(y % yy);
1724 while (((xx | yy) & 1) == 0) {
1725 xx >>= 1; yy >>= 1; t++;
1728 while ((xx & 1) == 0) xx >>= 1;
1729 while ((yy & 1) == 0) yy >>= 1;
1731 xx = (xx - yy) >> 1;
1733 yy = (yy - xx) >> 1;
1739 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
1740 We are equilavent to MS with about 2 ULP
1742 public static double Log (BigInteger value, Double baseValue)
1744 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
1745 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
1748 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
1749 return value.IsOne ? 0 : double.NaN;
1751 if (value.sign == 0)
1752 return double.NegativeInfinity;
1754 int length = value.data.Length - 1;
1756 for (int curBit = 31; curBit >= 0; curBit--) {
1757 if ((value.data [length] & (1 << curBit)) != 0) {
1758 bitCount = curBit + length * 32;
1763 long bitlen = bitCount;
1764 Double c = 0, d = 1;
1766 BigInteger testBit = One;
1767 long tempBitlen = bitlen;
1768 while (tempBitlen > Int32.MaxValue) {
1769 testBit = testBit << Int32.MaxValue;
1770 tempBitlen -= Int32.MaxValue;
1772 testBit = testBit << (int)tempBitlen;
1774 for (long curbit = bitlen; curbit >= 0; --curbit) {
1775 if ((value & testBit).sign != 0)
1778 testBit = testBit >> 1;
1780 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
1784 public static double Log (BigInteger value)
1786 return Log (value, Math.E);
1790 public static double Log10 (BigInteger value)
1792 return Log (value, 10);
1795 [CLSCompliantAttribute (false)]
1796 public bool Equals (ulong other)
1798 return CompareTo (other) == 0;
1801 public override int GetHashCode ()
1803 uint hash = (uint)(sign * 0x01010101u);
1805 for (int i = 0; i < data.Length; ++i)
1810 public static BigInteger Add (BigInteger left, BigInteger right)
1812 return left + right;
1815 public static BigInteger Subtract (BigInteger left, BigInteger right)
1817 return left - right;
1820 public static BigInteger Multiply (BigInteger left, BigInteger right)
1822 return left * right;
1825 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
1827 return dividend / divisor;
1830 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
1832 return dividend % divisor;
1835 public static BigInteger Negate (BigInteger value)
1840 public int CompareTo (object obj)
1845 if (!(obj is BigInteger))
1848 return Compare (this, (BigInteger)obj);
1851 public int CompareTo (BigInteger other)
1853 return Compare (this, other);
1856 [CLSCompliantAttribute (false)]
1857 public int CompareTo (ulong other)
1862 return other == 0 ? 0 : -1;
1864 if (data.Length > 2)
1867 uint high = (uint)(other >> 32);
1868 uint low = (uint)other;
1870 return LongCompare (low, high);
1873 int LongCompare (uint low, uint high)
1876 if (data.Length > 1)
1894 public int CompareTo (long other)
1897 int rs = Math.Sign (other);
1900 return ls > rs ? 1 : -1;
1905 if (data.Length > 2)
1910 uint low = (uint)other;
1911 uint high = (uint)((ulong)other >> 32);
1913 int r = LongCompare (low, high);
1920 public static int Compare (BigInteger left, BigInteger right)
1923 int rs = right.sign;
1926 return ls > rs ? 1 : -1;
1928 int r = CoreCompare (left.data, right.data);
1935 static int TopByte (uint x)
1937 if ((x & 0xFFFF0000u) != 0) {
1938 if ((x & 0xFF000000u) != 0)
1942 if ((x & 0xFF00u) != 0)
1947 static int FirstNonFFByte (uint word)
1949 if ((word & 0xFF000000u) != 0xFF000000u)
1951 else if ((word & 0xFF0000u) != 0xFF0000u)
1953 else if ((word & 0xFF00u) != 0xFF00u)
1958 public byte[] ToByteArray ()
1961 return new byte [1];
1963 //number of bytes not counting upper word
1964 int bytes = (data.Length - 1) * 4;
1965 bool needExtraZero = false;
1967 uint topWord = data [data.Length - 1];
1970 //if the topmost bit is set we need an extra
1972 extra = TopByte (topWord);
1973 uint mask = 0x80u << ((extra - 1) * 8);
1974 if ((topWord & mask) != 0) {
1975 needExtraZero = true;
1978 extra = TopByte (topWord);
1981 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1984 int end = data.Length - 1;
1985 for (int i = 0; i < end; ++i) {
1986 uint word = data [i];
1988 res [j++] = (byte)word;
1989 res [j++] = (byte)(word >> 8);
1990 res [j++] = (byte)(word >> 16);
1991 res [j++] = (byte)(word >> 24);
1993 while (extra-- > 0) {
1994 res [j++] = (byte)topWord;
1999 int end = data.Length - 1;
2001 uint carry = 1, word;
2003 for (int i = 0; i < end; ++i) {
2005 add = (ulong)~word + carry;
2007 carry = (uint)(add >> 32);
2009 res [j++] = (byte)word;
2010 res [j++] = (byte)(word >> 8);
2011 res [j++] = (byte)(word >> 16);
2012 res [j++] = (byte)(word >> 24);
2015 add = (ulong)~topWord + (carry);
2017 carry = (uint)(add >> 32);
2019 int ex = FirstNonFFByte (word);
2020 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2021 int to = ex + (needExtra ? 1 : 0);
2024 res = Resize (res, bytes + to);
2027 res [j++] = (byte)word;
2033 res = Resize (res, bytes + 5);
2034 res [j++] = (byte)word;
2035 res [j++] = (byte)(word >> 8);
2036 res [j++] = (byte)(word >> 16);
2037 res [j++] = (byte)(word >> 24);
2045 static byte[] Resize (byte[] v, int len)
2047 byte[] res = new byte [len];
2048 Array.Copy (v, res, Math.Min (v.Length, len));
2052 static uint[] Resize (uint[] v, int len)
2054 uint[] res = new uint [len];
2055 Array.Copy (v, res, Math.Min (v.Length, len));
2059 static uint[] CoreAdd (uint[] a, uint[] b)
2061 if (a.Length < b.Length) {
2070 uint[] res = new uint [bl];
2075 for (; i < sl; i++) {
2076 sum = sum + a [i] + b [i];
2077 res [i] = (uint)sum;
2081 for (; i < bl; i++) {
2083 res [i] = (uint)sum;
2088 res = Resize (res, bl + 1);
2089 res [i] = (uint)sum;
2096 static uint[] CoreSub (uint[] a, uint[] b)
2101 uint[] res = new uint [bl];
2105 for (i = 0; i < sl; ++i) {
2106 borrow = (ulong)a [i] - b [i] - borrow;
2108 res [i] = (uint)borrow;
2109 borrow = (borrow >> 32) & 0x1;
2112 for (; i < bl; i++) {
2113 borrow = (ulong)a [i] - borrow;
2114 res [i] = (uint)borrow;
2115 borrow = (borrow >> 32) & 0x1;
2118 //remove extra zeroes
2119 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2121 res = Resize (res, i + 1);
2127 static uint[] CoreAdd (uint[] a, uint b)
2130 uint[] res = new uint [len];
2134 for (i = 0; i < len; i++) {
2136 res [i] = (uint)sum;
2141 res = Resize (res, len + 1);
2142 res [i] = (uint)sum;
2148 static uint[] CoreSub (uint[] a, uint b)
2151 uint[] res = new uint [len];
2155 for (i = 0; i < len; i++) {
2156 borrow = (ulong)a [i] - borrow;
2157 res [i] = (uint)borrow;
2158 borrow = (borrow >> 32) & 0x1;
2161 //remove extra zeroes
2162 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2164 res = Resize (res, i + 1);
2169 static int CoreCompare (uint[] a, uint[] b)
2179 for (int i = al - 1; i >= 0; --i) {
2190 static int GetNormalizeShift(uint value) {
2193 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2194 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2195 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2196 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2197 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2202 static void Normalize (uint[] u, int l, uint[] un, int shift)
2207 int rshift = 32 - shift;
2208 for (i = 0; i < l; i++) {
2210 un [i] = (ui << shift) | carry;
2211 carry = ui >> rshift;
2214 for (i = 0; i < l; i++) {
2219 while (i < un.Length) {
2228 static void Unnormalize (uint[] un, out uint[] r, int shift)
2230 int length = un.Length;
2231 r = new uint [length];
2234 int lshift = 32 - shift;
2236 for (int i = length - 1; i >= 0; i--) {
2238 r [i] = (uni >> shift) | carry;
2239 carry = (uni << lshift);
2242 for (int i = 0; i < length; i++) {
2248 const ulong Base = 0x100000000;
2249 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2255 // Divide by single digit
2262 for (int j = m - 1; j >= 0; j--) {
2266 ulong div = rem / v0;
2271 } else if (m >= n) {
2272 int shift = GetNormalizeShift (v [n - 1]);
2274 uint[] un = new uint [m + 1];
2275 uint[] vn = new uint [n];
2277 Normalize (u, m, un, shift);
2278 Normalize (v, n, vn, shift);
2280 q = new uint [m - n + 1];
2283 // Main division loop
2285 for (int j = m - n; j >= 0; j--) {
2289 rr = Base * un [j + n] + un [j + n - 1];
2290 qq = rr / vn [n - 1];
2291 rr -= qq * vn [n - 1];
2294 // Estimate too big ?
2296 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2298 rr += (ulong)vn [n - 1];
2306 // Multiply and subtract
2310 for (i = 0; i < n; i++) {
2311 ulong p = vn [i] * qq;
2312 t = (long)un [i + j] - (long)(uint)p - b;
2313 un [i + j] = (uint)t;
2318 t = (long)un [j + n] - b;
2319 un [j + n] = (uint)t;
2321 // Store the calculated value
2325 // Add back vn[0..n] to un[j..j+n]
2330 for (i = 0; i < n; i++) {
2331 c = (ulong)vn [i] + un [j + i] + c;
2332 un [j + i] = (uint)c;
2335 c += (ulong)un [j + n];
2336 un [j + n] = (uint)c;
2340 Unnormalize (un, out r, shift);
2342 q = new uint [] { 0 };