2 // System.Numerics.BigInteger
5 // Rodrigo Kumpera (rkumpera@novell.com)
6 // Marek Safar <marek.safar@gmail.com>
8 // Copyright (C) 2010 Novell, Inc (http://www.novell.com)
9 // Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 // A big chuck of code comes the DLR (as hosted in http://ironpython.codeplex.com),
31 // which has the following License:
33 /* ****************************************************************************
35 * Copyright (c) Microsoft Corporation.
37 * This source code is subject to terms and conditions of the Microsoft Public License. A
38 * copy of the license can be found in the License.html file at the root of this distribution. If
39 * you cannot locate the Microsoft Public License, please send an email to
40 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
41 * by the terms of the Microsoft Public License.
43 * You must not remove this notice, or any other, from this software.
46 * ***************************************************************************/
49 using System.Collections.Generic;
50 using System.Diagnostics;
51 using System.Diagnostics.CodeAnalysis;
52 using System.Globalization;
54 using System.Threading;
58 Have proper popcount function for IsPowerOfTwo
59 Use unsafe ops to avoid bounds check
60 CoreAdd could avoid some resizes by checking for equal sized array that top overflow
61 For bitwise operators, hoist the conditionals out of their main loop
62 Optimize BitScanBackward
63 Use a carry variable to make shift opts do half the number of array ops.
64 Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
66 namespace System.Numerics {
67 public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
73 static readonly uint[] ONE = new uint [1] { 1 };
75 BigInteger (short sign, uint[] data)
81 public BigInteger (int value)
86 } else if (value > 0) {
88 data = new uint[] { (uint) value };
91 data = new uint[1] { (uint)-value };
95 [CLSCompliantAttribute (false)]
96 public BigInteger (uint value)
103 data = new uint [1] { value };
107 public BigInteger (long value)
112 } else if (value > 0) {
114 uint low = (uint)value;
115 uint high = (uint)(value >> 32);
117 data = new uint [high != 0 ? 2 : 1];
124 uint low = (uint)value;
125 uint high = (uint)((ulong)value >> 32);
127 data = new uint [high != 0 ? 2 : 1];
134 [CLSCompliantAttribute (false)]
135 public BigInteger (ulong value)
142 uint low = (uint)value;
143 uint high = (uint)(value >> 32);
145 data = new uint [high != 0 ? 2 : 1];
153 static bool Negative (byte[] v)
155 return ((v[7] & 0x80) != 0);
158 static ushort Exponent (byte[] v)
160 return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
163 static ulong Mantissa(byte[] v)
165 uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
166 uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
168 return (ulong)((ulong)i1 | ((ulong)i2 << 32));
171 const int bias = 1075;
172 public BigInteger (double value)
174 if (double.IsNaN (value) || Double.IsInfinity (value))
175 throw new OverflowException ();
177 byte[] bytes = BitConverter.GetBytes (value);
178 ulong mantissa = Mantissa (bytes);
180 // 1.0 * 2**exp, we have a power of 2
181 int exponent = Exponent (bytes);
188 BigInteger res = Negative (bytes) ? MinusOne : One;
189 res = res << (exponent - 0x3ff);
190 this.sign = res.sign;
191 this.data = res.data;
193 // 1.mantissa * 2**exp
194 int exponent = Exponent(bytes);
195 mantissa |= 0x10000000000000ul;
196 BigInteger res = mantissa;
197 res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent);
199 this.sign = (short) (Negative (bytes) ? -1 : 1);
200 this.data = res.data;
204 public BigInteger (float value) : this ((double)value)
208 const Int32 DecimalScaleFactorMask = 0x00FF0000;
209 const Int32 DecimalSignMask = unchecked((Int32)0x80000000);
211 public BigInteger (decimal value)
213 // First truncate to get scale to 0 and extract bits
214 int[] bits = Decimal.GetBits(Decimal.Truncate(value));
217 while (size > 0 && bits[size - 1] == 0) size--;
225 sign = (short) ((bits [3] & DecimalSignMask) != 0 ? -1 : 1);
227 data = new uint [size];
228 data [0] = (uint)bits [0];
230 data [1] = (uint)bits [1];
232 data [2] = (uint)bits [2];
235 [CLSCompliantAttribute (false)]
236 public BigInteger (byte[] value)
239 throw new ArgumentNullException ("value");
241 int len = value.Length;
243 if (len == 0 || (len == 1 && value [0] == 0)) {
249 if ((value [len - 1] & 0x80) != 0)
255 while (value [len - 1] == 0) {
263 int full_words, size;
264 full_words = size = len / 4;
265 if ((len & 0x3) != 0)
268 data = new uint [size];
270 for (int i = 0; i < full_words; ++i) {
271 data [i] = (uint)value [j++] |
272 (uint)(value [j++] << 8) |
273 (uint)(value [j++] << 16) |
274 (uint)(value [j++] << 24);
278 int idx = data.Length - 1;
279 for (int i = 0; i < size; ++i)
280 data [idx] |= (uint)(value [j++] << (i * 8));
283 int full_words, size;
284 full_words = size = len / 4;
285 if ((len & 0x3) != 0)
288 data = new uint [size];
290 uint word, borrow = 1;
294 for (int i = 0; i < full_words; ++i) {
295 word = (uint)value [j++] |
296 (uint)(value [j++] << 8) |
297 (uint)(value [j++] << 16) |
298 (uint)(value [j++] << 24);
300 sub = (ulong)word - borrow;
302 borrow = (uint)(sub >> 32) & 0x1u;
310 for (int i = 0; i < size; ++i) {
311 word |= (uint)(value [j++] << (i * 8));
312 store_mask = (store_mask << 8) | 0xFF;
317 borrow = (uint)(sub >> 32) & 0x1u;
319 if ((~word & store_mask) == 0)
320 data = Resize (data, data.Length - 1);
322 data [data.Length - 1] = ~word & store_mask;
324 if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
325 throw new Exception ("non zero final carry");
330 get { return sign == 0 || (data [0] & 0x1) == 0; }
334 get { return sign == 1 && data.Length == 1 && data [0] == 1; }
338 //Gem from Hacker's Delight
339 //Returns the number of bits set in @x
340 static int PopulationCount (uint x)
342 x = x - ((x >> 1) & 0x55555555);
343 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
344 x = (x + (x >> 4)) & 0x0F0F0F0F;
347 return (int)(x & 0x0000003F);
350 //Based on code by Zilong Tan on Ulib released under MIT license
351 //Returns the number of bits set in @x
352 static int PopulationCount(ulong x)
354 x -= (x >> 1) & 0x5555555555555555UL;
355 x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL);
356 x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fUL;
357 return (int)((x * 0x0101010101010101UL) >> 56);
360 static int LeadingZeroCount(uint value)
366 value |= value >> 16;
367 return 32 - PopulationCount (value); // 32 = bits in uint
370 static int LeadingZeroCount(ulong value)
376 value |= value >> 16;
377 value |= value >> 32;
378 return 64 - PopulationCount (value); // 64 = bits in ulong
381 static double BuildDouble(int sign, ulong mantissa, int exponent)
383 const int exponentBias = 1023;
384 const int mantissaLength = 52;
385 const int exponentLength = 11;
386 const int maxExponent = 2046;
387 const long mantissaMask = 0xfffffffffffffL;
388 const long exponentMask = 0x7ffL;
389 const ulong negativeMark = 0x8000000000000000uL;
391 if (sign == 0 || mantissa == 0) {
394 exponent += exponentBias + mantissaLength;
395 int offset = LeadingZeroCount(mantissa) - exponentLength;
396 if (exponent - offset > maxExponent) {
397 return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
400 mantissa >>= -offset;
402 } else if (offset >= exponent) {
403 mantissa <<= exponent - 1;
409 mantissa = mantissa & mantissaMask;
410 if ((exponent & exponentMask) == exponent) {
412 ulong bits = mantissa | ((ulong)exponent << mantissaLength);
414 bits |= negativeMark;
416 return BitConverter.Int64BitsToDouble((long)bits);
419 return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity;
425 public bool IsPowerOfTwo {
427 bool foundBit = false;
430 //This function is pop count == 1 for positive numbers
431 for (int i = 0; i < data.Length; ++i) {
432 int p = PopulationCount (data [i]);
434 if (p > 1 || foundBit)
444 get { return sign == 0; }
451 public static BigInteger MinusOne {
452 get { return new BigInteger (-1, ONE); }
455 public static BigInteger One {
456 get { return new BigInteger (1, ONE); }
459 public static BigInteger Zero {
460 get { return new BigInteger (0); }
463 public static explicit operator int (BigInteger value)
465 if (value.data == null)
467 if (value.data.Length > 1)
468 throw new OverflowException ();
469 uint data = value.data [0];
471 if (value.sign == 1) {
472 if (data > (uint)int.MaxValue)
473 throw new OverflowException ();
475 } else if (value.sign == -1) {
476 if (data > 0x80000000u)
477 throw new OverflowException ();
484 [CLSCompliantAttribute (false)]
485 public static explicit operator uint (BigInteger value)
487 if (value.data == null)
489 if (value.data.Length > 1 || value.sign == -1)
490 throw new OverflowException ();
491 return value.data [0];
494 public static explicit operator short (BigInteger value)
496 int val = (int)value;
497 if (val < short.MinValue || val > short.MaxValue)
498 throw new OverflowException ();
502 [CLSCompliantAttribute (false)]
503 public static explicit operator ushort (BigInteger value)
505 uint val = (uint)value;
506 if (val > ushort.MaxValue)
507 throw new OverflowException ();
511 public static explicit operator byte (BigInteger value)
513 uint val = (uint)value;
514 if (val > byte.MaxValue)
515 throw new OverflowException ();
519 [CLSCompliantAttribute (false)]
520 public static explicit operator sbyte (BigInteger value)
522 int val = (int)value;
523 if (val < sbyte.MinValue || val > sbyte.MaxValue)
524 throw new OverflowException ();
529 public static explicit operator long (BigInteger value)
531 if (value.data == null)
534 if (value.data.Length > 2)
535 throw new OverflowException ();
537 uint low = value.data [0];
539 if (value.data.Length == 1) {
542 long res = (long)low;
546 uint high = value.data [1];
548 if (value.sign == 1) {
549 if (high >= 0x80000000u)
550 throw new OverflowException ();
551 return (((long)high) << 32) | low;
555 We cannot represent negative numbers smaller than long.MinValue.
556 Those values are encoded into what look negative numbers, so negating
557 them produces a positive value, that's why it's safe to check for that
560 long.MinValue works fine since it's bigint encoding looks like a negative
561 number, but since long.MinValue == -long.MinValue, we're good.
564 long result = - ((((long)high) << 32) | (long)low);
566 throw new OverflowException ();
570 [CLSCompliantAttribute (false)]
571 public static explicit operator ulong (BigInteger value)
573 if (value.data == null)
575 if (value.data.Length > 2 || value.sign == -1)
576 throw new OverflowException ();
578 uint low = value.data [0];
579 if (value.data.Length == 1)
582 uint high = value.data [1];
583 return (((ulong)high) << 32) | low;
586 public static explicit operator double (BigInteger value)
588 if (value.data == null)
591 switch (value.data.Length) {
593 return BuildDouble (value.sign, value.data [0], 0);
595 return BuildDouble (value.sign, (ulong)value.data [1] << 32 | (ulong)value.data [0], 0);
597 var index = value.data.Length - 1;
598 var word = value.data [index];
599 var mantissa = ((ulong)word << 32) | value.data [index - 1];
600 int missing = LeadingZeroCount (word) - 11; // 11 = bits in exponent
602 // add the missing bits from the next word
603 mantissa = (mantissa << missing) | (value.data [index - 2] >> (32 - missing));
605 mantissa >>= -missing;
607 return BuildDouble (value.sign, mantissa, ((value.data.Length - 2) * 32) - missing);
611 public static explicit operator float (BigInteger value)
613 return (float)(double)value;
616 public static explicit operator decimal (BigInteger value)
618 if (value.data == null)
621 uint[] data = value.data;
623 throw new OverflowException ();
625 int lo = 0, mi = 0, hi = 0;
627 hi = (Int32)data [2];
629 mi = (Int32)data [1];
631 lo = (Int32)data [0];
633 return new Decimal(lo, mi, hi, value.sign < 0, 0);
636 public static implicit operator BigInteger (int value)
638 return new BigInteger (value);
641 [CLSCompliantAttribute (false)]
642 public static implicit operator BigInteger (uint value)
644 return new BigInteger (value);
647 public static implicit operator BigInteger (short value)
649 return new BigInteger (value);
652 [CLSCompliantAttribute (false)]
653 public static implicit operator BigInteger (ushort value)
655 return new BigInteger (value);
658 public static implicit operator BigInteger (byte value)
660 return new BigInteger (value);
663 [CLSCompliantAttribute (false)]
664 public static implicit operator BigInteger (sbyte value)
666 return new BigInteger (value);
669 public static implicit operator BigInteger (long value)
671 return new BigInteger (value);
674 [CLSCompliantAttribute (false)]
675 public static implicit operator BigInteger (ulong value)
677 return new BigInteger (value);
680 public static explicit operator BigInteger (double value)
682 return new BigInteger (value);
685 public static explicit operator BigInteger (float value)
687 return new BigInteger (value);
690 public static explicit operator BigInteger (decimal value)
692 return new BigInteger (value);
695 public static BigInteger operator+ (BigInteger left, BigInteger right)
702 if (left.sign == right.sign)
703 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
705 int r = CoreCompare (left.data, right.data);
710 if (r > 0) //left > right
711 return new BigInteger (left.sign, CoreSub (left.data, right.data));
713 return new BigInteger (right.sign, CoreSub (right.data, left.data));
716 public static BigInteger operator- (BigInteger left, BigInteger right)
721 return new BigInteger ((short)-right.sign, right.data);
723 if (left.sign == right.sign) {
724 int r = CoreCompare (left.data, right.data);
729 if (r > 0) //left > right
730 return new BigInteger (left.sign, CoreSub (left.data, right.data));
732 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
735 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
738 public static BigInteger operator* (BigInteger left, BigInteger right)
740 if (left.sign == 0 || right.sign == 0)
743 if (left.data [0] == 1 && left.data.Length == 1) {
746 return new BigInteger ((short)-right.sign, right.data);
749 if (right.data [0] == 1 && right.data.Length == 1) {
752 return new BigInteger ((short)-left.sign, left.data);
755 uint[] a = left.data;
756 uint[] b = right.data;
758 uint[] res = new uint [a.Length + b.Length];
760 for (int i = 0; i < a.Length; ++i) {
765 for (int j = 0; j < b.Length; ++j) {
766 carry = carry + ((ulong)ai) * b [j] + res [k];
767 res[k++] = (uint)carry;
773 res[k++] = (uint)carry;
779 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
780 if (m < res.Length - 1)
781 res = Resize (res, m + 1);
783 return new BigInteger ((short)(left.sign * right.sign), res);
786 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
788 if (divisor.sign == 0)
789 throw new DivideByZeroException ();
791 if (dividend.sign == 0)
795 uint[] remainder_value;
797 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
800 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
803 if (i < quotient.Length - 1)
804 quotient = Resize (quotient, i + 1);
806 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
809 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
811 if (divisor.sign == 0)
812 throw new DivideByZeroException ();
814 if (dividend.sign == 0)
818 uint[] remainder_value;
820 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
823 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
827 if (i < remainder_value.Length - 1)
828 remainder_value = Resize (remainder_value, i + 1);
829 return new BigInteger (dividend.sign, remainder_value);
832 public static BigInteger operator- (BigInteger value)
834 if (value.data == null)
836 return new BigInteger ((short)-value.sign, value.data);
839 public static BigInteger operator+ (BigInteger value)
844 public static BigInteger operator++ (BigInteger value)
846 if (value.data == null)
849 short sign = value.sign;
850 uint[] data = value.data;
851 if (data.Length == 1) {
852 if (sign == -1 && data [0] == 1)
855 return new BigInteger (1, ONE);
859 data = CoreSub (data, 1);
861 data = CoreAdd (data, 1);
863 return new BigInteger (sign, data);
866 public static BigInteger operator-- (BigInteger value)
868 if (value.data == null)
871 short sign = value.sign;
872 uint[] data = value.data;
873 if (data.Length == 1) {
874 if (sign == 1 && data [0] == 1)
877 return new BigInteger (-1, ONE);
881 data = CoreAdd (data, 1);
883 data = CoreSub (data, 1);
885 return new BigInteger (sign, data);
888 public static BigInteger operator& (BigInteger left, BigInteger right)
896 uint[] a = left.data;
897 uint[] b = right.data;
901 bool neg_res = (ls == rs) && (ls == -1);
903 uint[] result = new uint [Math.Max (a.Length, b.Length)];
905 ulong ac = 1, bc = 1, borrow = 1;
908 for (i = 0; i < result.Length; ++i) {
915 ac = (uint)(ac >> 32);
924 bc = (uint)(bc >> 32);
930 borrow = word - borrow;
931 word = ~(uint)borrow;
932 borrow = (uint)(borrow >> 32) & 0x1u;
938 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
942 if (i < result.Length - 1)
943 result = Resize (result, i + 1);
945 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
948 public static BigInteger operator| (BigInteger left, BigInteger right)
956 uint[] a = left.data;
957 uint[] b = right.data;
961 bool neg_res = (ls == -1) || (rs == -1);
963 uint[] result = new uint [Math.Max (a.Length, b.Length)];
965 ulong ac = 1, bc = 1, borrow = 1;
968 for (i = 0; i < result.Length; ++i) {
975 ac = (uint)(ac >> 32);
984 bc = (uint)(bc >> 32);
990 borrow = word - borrow;
991 word = ~(uint)borrow;
992 borrow = (uint)(borrow >> 32) & 0x1u;
998 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1002 if (i < result.Length - 1)
1003 result = Resize (result, i + 1);
1005 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1008 public static BigInteger operator^ (BigInteger left, BigInteger right)
1013 if (right.sign == 0)
1016 uint[] a = left.data;
1017 uint[] b = right.data;
1019 int rs = right.sign;
1021 bool neg_res = (ls == -1) ^ (rs == -1);
1023 uint[] result = new uint [Math.Max (a.Length, b.Length)];
1025 ulong ac = 1, bc = 1, borrow = 1;
1028 for (i = 0; i < result.Length; ++i) {
1035 ac = (uint)(ac >> 32);
1044 bc = (uint)(bc >> 32);
1047 uint word = va ^ vb;
1050 borrow = word - borrow;
1051 word = ~(uint)borrow;
1052 borrow = (uint)(borrow >> 32) & 0x1u;
1058 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1062 if (i < result.Length - 1)
1063 result = Resize (result, i + 1);
1065 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1068 public static BigInteger operator~ (BigInteger value)
1070 if (value.data == null)
1071 return new BigInteger (-1, ONE);
1073 uint[] data = value.data;
1074 int sign = value.sign;
1076 bool neg_res = sign == 1;
1078 uint[] result = new uint [data.Length];
1080 ulong carry = 1, borrow = 1;
1083 for (i = 0; i < result.Length; ++i) {
1084 uint word = data [i];
1086 carry = ~word + carry;
1088 carry = (uint)(carry >> 32);
1094 borrow = word - borrow;
1095 word = ~(uint)borrow;
1096 borrow = (uint)(borrow >> 32) & 0x1u;
1102 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
1106 if (i < result.Length - 1)
1107 result = Resize (result, i + 1);
1109 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
1112 //returns the 0-based index of the most significant set bit
1113 //returns 0 if no bit is set, so extra care when using it
1114 static int BitScanBackward (uint word)
1116 for (int i = 31; i >= 0; --i) {
1117 uint mask = 1u << i;
1118 if ((word & mask) == mask)
1124 public static BigInteger operator<< (BigInteger value, int shift)
1126 if (shift == 0 || value.data == null)
1129 return value >> -shift;
1131 uint[] data = value.data;
1132 int sign = value.sign;
1134 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1135 int bits = shift - (31 - topMostIdx);
1136 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
1138 uint[] res = new uint [data.Length + extra_words];
1140 int idx_shift = shift >> 5;
1141 int bit_shift = shift & 0x1F;
1142 int carry_shift = 32 - bit_shift;
1144 if (carry_shift == 32) {
1145 for (int i = 0; i < data.Length; ++i) {
1146 uint word = data [i];
1147 res [i + idx_shift] |= word << bit_shift;
1150 for (int i = 0; i < data.Length; ++i) {
1151 uint word = data [i];
1152 res [i + idx_shift] |= word << bit_shift;
1153 if (i + idx_shift + 1 < res.Length)
1154 res [i + idx_shift + 1] = word >> carry_shift;
1158 return new BigInteger ((short)sign, res);
1161 public static BigInteger operator>> (BigInteger value, int shift)
1163 if (shift == 0 || value.sign == 0)
1166 return value << -shift;
1168 uint[] data = value.data;
1169 int sign = value.sign;
1171 int topMostIdx = BitScanBackward (data [data.Length - 1]);
1172 int idx_shift = shift >> 5;
1173 int bit_shift = shift & 0x1F;
1175 int extra_words = idx_shift;
1176 if (bit_shift > topMostIdx)
1178 int size = data.Length - extra_words;
1183 return new BigInteger (-1, ONE);
1186 uint[] res = new uint [size];
1187 int carry_shift = 32 - bit_shift;
1189 if (carry_shift == 32) {
1190 for (int i = data.Length - 1; i >= idx_shift; --i) {
1191 uint word = data [i];
1193 if (i - idx_shift < res.Length)
1194 res [i - idx_shift] |= word >> bit_shift;
1197 for (int i = data.Length - 1; i >= idx_shift; --i) {
1198 uint word = data [i];
1200 if (i - idx_shift < res.Length)
1201 res [i - idx_shift] |= word >> bit_shift;
1202 if (i - idx_shift - 1 >= 0)
1203 res [i - idx_shift - 1] = word << carry_shift;
1208 //Round down instead of toward zero
1210 for (int i = 0; i < idx_shift; i++) {
1211 if (data [i] != 0u) {
1212 var tmp = new BigInteger ((short)sign, res);
1217 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
1218 var tmp = new BigInteger ((short)sign, res);
1223 return new BigInteger ((short)sign, res);
1226 public static bool operator< (BigInteger left, BigInteger right)
1228 return Compare (left, right) < 0;
1231 public static bool operator< (BigInteger left, long right)
1233 return left.CompareTo (right) < 0;
1237 public static bool operator< (long left, BigInteger right)
1239 return right.CompareTo (left) > 0;
1243 [CLSCompliantAttribute (false)]
1244 public static bool operator< (BigInteger left, ulong right)
1246 return left.CompareTo (right) < 0;
1249 [CLSCompliantAttribute (false)]
1250 public static bool operator< (ulong left, BigInteger right)
1252 return right.CompareTo (left) > 0;
1255 public static bool operator<= (BigInteger left, BigInteger right)
1257 return Compare (left, right) <= 0;
1260 public static bool operator<= (BigInteger left, long right)
1262 return left.CompareTo (right) <= 0;
1265 public static bool operator<= (long left, BigInteger right)
1267 return right.CompareTo (left) >= 0;
1270 [CLSCompliantAttribute (false)]
1271 public static bool operator<= (BigInteger left, ulong right)
1273 return left.CompareTo (right) <= 0;
1276 [CLSCompliantAttribute (false)]
1277 public static bool operator<= (ulong left, BigInteger right)
1279 return right.CompareTo (left) >= 0;
1282 public static bool operator> (BigInteger left, BigInteger right)
1284 return Compare (left, right) > 0;
1287 public static bool operator> (BigInteger left, long right)
1289 return left.CompareTo (right) > 0;
1292 public static bool operator> (long left, BigInteger right)
1294 return right.CompareTo (left) < 0;
1297 [CLSCompliantAttribute (false)]
1298 public static bool operator> (BigInteger left, ulong right)
1300 return left.CompareTo (right) > 0;
1303 [CLSCompliantAttribute (false)]
1304 public static bool operator> (ulong left, BigInteger right)
1306 return right.CompareTo (left) < 0;
1309 public static bool operator>= (BigInteger left, BigInteger right)
1311 return Compare (left, right) >= 0;
1314 public static bool operator>= (BigInteger left, long right)
1316 return left.CompareTo (right) >= 0;
1319 public static bool operator>= (long left, BigInteger right)
1321 return right.CompareTo (left) <= 0;
1324 [CLSCompliantAttribute (false)]
1325 public static bool operator>= (BigInteger left, ulong right)
1327 return left.CompareTo (right) >= 0;
1330 [CLSCompliantAttribute (false)]
1331 public static bool operator>= (ulong left, BigInteger right)
1333 return right.CompareTo (left) <= 0;
1336 public static bool operator== (BigInteger left, BigInteger right)
1338 return Compare (left, right) == 0;
1341 public static bool operator== (BigInteger left, long right)
1343 return left.CompareTo (right) == 0;
1346 public static bool operator== (long left, BigInteger right)
1348 return right.CompareTo (left) == 0;
1351 [CLSCompliantAttribute (false)]
1352 public static bool operator== (BigInteger left, ulong right)
1354 return left.CompareTo (right) == 0;
1357 [CLSCompliantAttribute (false)]
1358 public static bool operator== (ulong left, BigInteger right)
1360 return right.CompareTo (left) == 0;
1363 public static bool operator!= (BigInteger left, BigInteger right)
1365 return Compare (left, right) != 0;
1368 public static bool operator!= (BigInteger left, long right)
1370 return left.CompareTo (right) != 0;
1373 public static bool operator!= (long left, BigInteger right)
1375 return right.CompareTo (left) != 0;
1378 [CLSCompliantAttribute (false)]
1379 public static bool operator!= (BigInteger left, ulong right)
1381 return left.CompareTo (right) != 0;
1384 [CLSCompliantAttribute (false)]
1385 public static bool operator!= (ulong left, BigInteger right)
1387 return right.CompareTo (left) != 0;
1390 public override bool Equals (object obj)
1392 if (!(obj is BigInteger))
1394 return Equals ((BigInteger)obj);
1397 public bool Equals (BigInteger other)
1399 if (sign != other.sign)
1402 int alen = data != null ? data.Length : 0;
1403 int blen = other.data != null ? other.data.Length : 0;
1407 for (int i = 0; i < alen; ++i) {
1408 if (data [i] != other.data [i])
1414 public bool Equals (long other)
1416 return CompareTo (other) == 0;
1419 public override string ToString ()
1421 return ToString (10, null);
1424 string ToStringWithPadding (string format, uint radix, IFormatProvider provider)
1426 if (format.Length > 1) {
1427 int precision = Convert.ToInt32(format.Substring (1), CultureInfo.InvariantCulture.NumberFormat);
1428 string baseStr = ToString (radix, provider);
1429 if (baseStr.Length < precision) {
1430 string additional = new String ('0', precision - baseStr.Length);
1431 if (baseStr[0] != '-') {
1432 return additional + baseStr;
1434 return "-" + additional + baseStr.Substring (1);
1439 return ToString (radix, provider);
1442 public string ToString (string format)
1444 return ToString (format, null);
1447 public string ToString (IFormatProvider provider)
1449 return ToString (null, provider);
1453 public string ToString (string format, IFormatProvider provider)
1455 if (format == null || format == "")
1456 return ToString (10, provider);
1458 switch (format[0]) {
1465 return ToStringWithPadding (format, 10, provider);
1468 return ToStringWithPadding (format, 16, null);
1470 throw new FormatException (string.Format ("format '{0}' not implemented", format));
1474 static uint[] MakeTwoComplement (uint[] v)
1476 uint[] res = new uint [v.Length];
1479 for (int i = 0; i < v.Length; ++i) {
1481 carry = (ulong)~word + carry;
1483 carry = (uint)(carry >> 32);
1487 uint last = res [res.Length - 1];
1488 int idx = FirstNonFFByte (last);
1490 for (int i = 1; i < idx; ++i)
1491 mask = (mask << 8) | 0xFF;
1493 res [res.Length - 1] = last & mask;
1497 string ToString (uint radix, IFormatProvider provider)
1499 const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1501 if (characterSet.Length < radix)
1502 throw new ArgumentException ("charSet length less than radix", "characterSet");
1504 throw new ArgumentException ("There is no such thing as radix one notation", "radix");
1508 if (data.Length == 1 && data [0] == 1)
1509 return sign == 1 ? "1" : "-1";
1511 List<char> digits = new List<char> (1 + data.Length * 3 / 10);
1519 dt = MakeTwoComplement (dt);
1520 a = new BigInteger (1, dt);
1525 a = DivRem (a, radix, out rem);
1526 digits.Add (characterSet [(int) rem]);
1529 if (sign == -1 && radix == 10) {
1530 NumberFormatInfo info = null;
1531 if (provider != null)
1532 info = provider.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo;
1534 string str = info.NegativeSign;
1535 for (int i = str.Length - 1; i >= 0; --i)
1536 digits.Add (str [i]);
1542 char last = digits [digits.Count - 1];
1543 if (sign == 1 && radix > 10 && (last < '0' || last > '9'))
1548 return new String (digits.ToArray ());
1551 public static BigInteger Parse (string value)
1556 if (!Parse (value, false, out result, out ex))
1561 public static bool TryParse (string value, out BigInteger result)
1564 return Parse (value, true, out result, out ex);
1567 public static BigInteger Parse (string value, NumberStyles style)
1569 return Parse (value, style, null);
1572 public static BigInteger Parse (string value, IFormatProvider provider)
1574 return Parse (value, NumberStyles.Integer, provider);
1577 public static BigInteger Parse (
1578 string value, NumberStyles style, IFormatProvider provider)
1583 if (!Parse (value, style, provider, false, out res, out exc))
1589 public static bool TryParse (
1590 string value, NumberStyles style, IFormatProvider provider,
1591 out BigInteger result)
1594 if (!Parse (value, style, provider, true, out result, out exc)) {
1602 internal static bool Parse (string s, NumberStyles style, IFormatProvider fp, bool tryParse, out BigInteger result, out Exception exc)
1609 exc = new ArgumentNullException ("s");
1613 if (s.Length == 0) {
1615 exc = GetFormatException ();
1619 NumberFormatInfo nfi = null;
1621 Type typeNFI = typeof(System.Globalization.NumberFormatInfo);
1622 nfi = (NumberFormatInfo)fp.GetFormat (typeNFI);
1625 nfi = Thread.CurrentThread.CurrentCulture.NumberFormat;
1627 if (!CheckStyle (style, tryParse, ref exc))
1630 bool AllowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0;
1631 bool AllowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0;
1632 bool AllowThousands = (style & NumberStyles.AllowThousands) != 0;
1633 bool AllowDecimalPoint = (style & NumberStyles.AllowDecimalPoint) != 0;
1634 bool AllowParentheses = (style & NumberStyles.AllowParentheses) != 0;
1635 bool AllowTrailingSign = (style & NumberStyles.AllowTrailingSign) != 0;
1636 bool AllowLeadingSign = (style & NumberStyles.AllowLeadingSign) != 0;
1637 bool AllowTrailingWhite = (style & NumberStyles.AllowTrailingWhite) != 0;
1638 bool AllowLeadingWhite = (style & NumberStyles.AllowLeadingWhite) != 0;
1639 bool AllowExponent = (style & NumberStyles.AllowExponent) != 0;
1643 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1646 bool foundOpenParentheses = false;
1647 bool negative = false;
1648 bool foundSign = false;
1649 bool foundCurrency = false;
1652 if (AllowParentheses && s [pos] == '(') {
1653 foundOpenParentheses = true;
1655 negative = true; // MS always make the number negative when there parentheses
1656 // even when NumberFormatInfo.NumberNegativePattern != 0!!!
1658 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1661 if (s.Substring (pos, nfi.NegativeSign.Length) == nfi.NegativeSign) {
1663 exc = GetFormatException ();
1667 if (s.Substring (pos, nfi.PositiveSign.Length) == nfi.PositiveSign) {
1669 exc = GetFormatException ();
1674 if (AllowLeadingSign && !foundSign) {
1676 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1678 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1680 if (AllowCurrencySymbol) {
1681 FindCurrency (ref pos, s, nfi,
1683 if (foundCurrency && AllowLeadingWhite &&
1684 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1690 if (AllowCurrencySymbol && !foundCurrency) {
1692 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1693 if (foundCurrency) {
1694 if (AllowLeadingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1696 if (foundCurrency) {
1697 if (!foundSign && AllowLeadingSign) {
1698 FindSign (ref pos, s, nfi, ref foundSign,
1700 if (foundSign && AllowLeadingWhite &&
1701 !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1708 BigInteger number = Zero;
1710 int decimalPointPos = -1;
1713 bool firstHexDigit = true;
1716 while (pos < s.Length) {
1718 if (!ValidDigit (s [pos], AllowHexSpecifier)) {
1719 if (AllowThousands &&
1720 (FindOther (ref pos, s, nfi.NumberGroupSeparator)
1721 || FindOther (ref pos, s, nfi.CurrencyGroupSeparator)))
1724 if (AllowDecimalPoint && decimalPointPos < 0 &&
1725 (FindOther (ref pos, s, nfi.NumberDecimalSeparator)
1726 || FindOther (ref pos, s, nfi.CurrencyDecimalSeparator))) {
1727 decimalPointPos = nDigits;
1736 if (AllowHexSpecifier) {
1737 hexDigit = s [pos++];
1738 if (Char.IsDigit (hexDigit))
1739 digitValue = (byte)(hexDigit - '0');
1740 else if (Char.IsLower (hexDigit))
1741 digitValue = (byte)(hexDigit - 'a' + 10);
1743 digitValue = (byte)(hexDigit - 'A' + 10);
1745 if (firstHexDigit && (byte)digitValue >= 8)
1748 number = number * 16 + digitValue;
1749 firstHexDigit = false;
1753 number = number * 10 + (byte)(s [pos++] - '0');
1756 // Post number stuff
1759 exc = GetFormatException ();
1763 //Signed hex value (Two's Complement)
1764 if (AllowHexSpecifier && negative) {
1765 BigInteger mask = BigInteger.Pow(16, nDigits) - 1;
1766 number = (number ^ mask) + 1;
1771 if (FindExponent (ref pos, s, ref exponent, tryParse, ref exc) && exc != null)
1774 if (AllowTrailingSign && !foundSign) {
1776 FindSign (ref pos, s, nfi, ref foundSign, ref negative);
1777 if (foundSign && pos < s.Length) {
1778 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1783 if (AllowCurrencySymbol && !foundCurrency) {
1784 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1788 FindCurrency (ref pos, s, nfi, ref foundCurrency);
1789 if (foundCurrency && pos < s.Length) {
1790 if (AllowTrailingWhite && !JumpOverWhite (ref pos, s, true, tryParse, ref exc))
1792 if (!foundSign && AllowTrailingSign)
1793 FindSign (ref pos, s, nfi, ref foundSign,
1798 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1801 if (foundOpenParentheses) {
1802 if (pos >= s.Length || s [pos++] != ')') {
1804 exc = GetFormatException ();
1807 if (AllowTrailingWhite && pos < s.Length && !JumpOverWhite (ref pos, s, false, tryParse, ref exc))
1811 if (pos < s.Length && s [pos] != '\u0000') {
1813 exc = GetFormatException ();
1817 if (decimalPointPos >= 0)
1818 exponent = exponent - nDigits + decimalPointPos;
1822 // Any non-zero values after decimal point are not allowed
1824 BigInteger remainder;
1825 number = BigInteger.DivRem(number, BigInteger.Pow(10, -exponent), out remainder);
1827 if (!remainder.IsZero) {
1829 exc = new OverflowException ("Value too large or too small. exp="+exponent+" rem = " + remainder + " pow = " + BigInteger.Pow(10, -exponent));
1832 } else if (exponent > 0) {
1833 number = BigInteger.Pow(10, exponent) * number;
1836 if (number.sign == 0)
1839 result = new BigInteger (-1, number.data);
1841 result = new BigInteger (1, number.data);
1846 internal static bool CheckStyle (NumberStyles style, bool tryParse, ref Exception exc)
1848 if ((style & NumberStyles.AllowHexSpecifier) != 0) {
1849 NumberStyles ne = style ^ NumberStyles.AllowHexSpecifier;
1850 if ((ne & NumberStyles.AllowLeadingWhite) != 0)
1851 ne ^= NumberStyles.AllowLeadingWhite;
1852 if ((ne & NumberStyles.AllowTrailingWhite) != 0)
1853 ne ^= NumberStyles.AllowTrailingWhite;
1856 exc = new ArgumentException (
1857 "With AllowHexSpecifier only " +
1858 "AllowLeadingWhite and AllowTrailingWhite " +
1862 } else if ((uint) style > (uint) NumberStyles.Any){
1864 exc = new ArgumentException ("Not a valid number style");
1871 internal static bool JumpOverWhite (ref int pos, string s, bool reportError, bool tryParse, ref Exception exc)
1873 while (pos < s.Length && Char.IsWhiteSpace (s [pos]))
1876 if (reportError && pos >= s.Length) {
1878 exc = GetFormatException ();
1885 internal static void FindSign (ref int pos, string s, NumberFormatInfo nfi,
1886 ref bool foundSign, ref bool negative)
1888 if ((pos + nfi.NegativeSign.Length) <= s.Length &&
1889 string.CompareOrdinal(s, pos, nfi.NegativeSign, 0, nfi.NegativeSign.Length) == 0) {
1892 pos += nfi.NegativeSign.Length;
1893 } else if ((pos + nfi.PositiveSign.Length) <= s.Length &&
1894 string.CompareOrdinal(s, pos, nfi.PositiveSign, 0, nfi.PositiveSign.Length) == 0) {
1896 pos += nfi.PositiveSign.Length;
1901 internal static void FindCurrency (ref int pos,
1903 NumberFormatInfo nfi,
1904 ref bool foundCurrency)
1906 if ((pos + nfi.CurrencySymbol.Length) <= s.Length &&
1907 s.Substring (pos, nfi.CurrencySymbol.Length) == nfi.CurrencySymbol) {
1908 foundCurrency = true;
1909 pos += nfi.CurrencySymbol.Length;
1913 internal static bool FindExponent (ref int pos, string s, ref int exponent, bool tryParse, ref Exception exc)
1917 if (pos >= s.Length || (s [pos] != 'e' && s[pos] != 'E')) {
1923 if (i == s.Length) {
1924 exc = tryParse ? null : GetFormatException ();
1928 bool negative = false;
1931 if(++i == s.Length){
1932 exc = tryParse ? null : GetFormatException ();
1937 if (s [i] == '+' && ++i == s.Length) {
1938 exc = tryParse ? null : GetFormatException ();
1942 long exp = 0; // temp long value
1943 for (; i < s.Length; i++) {
1944 if (!Char.IsDigit (s [i])) {
1945 exc = tryParse ? null : GetFormatException ();
1949 // Reduce the risk of throwing an overflow exc
1950 exp = checked (exp * 10 - (int) (s [i] - '0'));
1951 if (exp < Int32.MinValue || exp > Int32.MaxValue) {
1952 exc = tryParse ? null : new OverflowException ("Value too large or too small.");
1957 // exp value saved as negative
1962 exponent = (int)exp;
1967 internal static bool FindOther (ref int pos, string s, string other)
1969 if ((pos + other.Length) <= s.Length &&
1970 s.Substring (pos, other.Length) == other) {
1971 pos += other.Length;
1978 internal static bool ValidDigit (char e, bool allowHex)
1981 return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
1983 return Char.IsDigit (e);
1986 static Exception GetFormatException ()
1988 return new FormatException ("Input string was not in the correct format");
1991 static bool ProcessTrailingWhitespace (bool tryParse, string s, int position, ref Exception exc)
1995 for (int i = position; i < len; i++){
1998 if (c != 0 && !Char.IsWhiteSpace (c)){
2000 exc = GetFormatException ();
2007 static bool Parse (string s, bool tryParse, out BigInteger result, out Exception exc)
2011 bool digits_seen = false;
2018 exc = new ArgumentNullException ("value");
2025 for (i = 0; i < len; i++){
2027 if (!Char.IsWhiteSpace (c))
2033 exc = GetFormatException ();
2037 var info = Thread.CurrentThread.CurrentCulture.NumberFormat;
2039 string negative = info.NegativeSign;
2040 string positive = info.PositiveSign;
2042 if (string.CompareOrdinal (s, i, positive, 0, positive.Length) == 0)
2043 i += positive.Length;
2044 else if (string.CompareOrdinal (s, i, negative, 0, negative.Length) == 0) {
2046 i += negative.Length;
2049 BigInteger val = Zero;
2050 for (; i < len; i++){
2058 if (c >= '0' && c <= '9'){
2059 byte d = (byte) (c - '0');
2064 } else if (!ProcessTrailingWhitespace (tryParse, s, i, ref exc))
2070 exc = GetFormatException ();
2076 else if (sign == -1)
2077 result = new BigInteger (-1, val.data);
2079 result = new BigInteger (1, val.data);
2084 public static BigInteger Min (BigInteger left, BigInteger right)
2087 int rs = right.sign;
2094 int r = CoreCompare (left.data, right.data);
2104 public static BigInteger Max (BigInteger left, BigInteger right)
2107 int rs = right.sign;
2114 int r = CoreCompare (left.data, right.data);
2123 public static BigInteger Abs (BigInteger value)
2125 return new BigInteger ((short)Math.Abs (value.sign), value.data);
2129 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
2131 if (divisor.sign == 0)
2132 throw new DivideByZeroException ();
2134 if (dividend.sign == 0) {
2135 remainder = dividend;
2140 uint[] remainder_value;
2142 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
2145 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
2149 if (i < remainder_value.Length - 1)
2150 remainder_value = Resize (remainder_value, i + 1);
2151 remainder = new BigInteger (dividend.sign, remainder_value);
2154 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
2157 if (i < quotient.Length - 1)
2158 quotient = Resize (quotient, i + 1);
2160 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
2163 public static BigInteger Pow (BigInteger value, int exponent)
2166 throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0");
2172 BigInteger result = One;
2173 while (exponent != 0) {
2174 if ((exponent & 1) != 0)
2175 result = result * value;
2179 value = value * value;
2185 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
2186 if (exponent.sign == -1)
2187 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
2188 if (modulus.sign == 0)
2189 throw new DivideByZeroException ();
2191 BigInteger result = One % modulus;
2192 while (exponent.sign != 0) {
2193 if (!exponent.IsEven) {
2194 result = result * value;
2195 result = result % modulus;
2199 value = value * value;
2200 value = value % modulus;
2206 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
2208 if (left.sign != 0 && left.data.Length == 1 && left.data [0] == 1)
2209 return new BigInteger (1, ONE);
2210 if (right.sign != 0 && right.data.Length == 1 && right.data [0] == 1)
2211 return new BigInteger (1, ONE);
2217 BigInteger x = new BigInteger (1, left.data);
2218 BigInteger y = new BigInteger (1, right.data);
2222 while (x.data.Length > 1) {
2228 if (x.IsZero) return g;
2230 // TODO: should we have something here if we can convert to long?
2233 // Now we can just do it with single precision. I am using the binary gcd method,
2234 // as it should be faster.
2237 uint yy = x.data [0];
2238 uint xx = (uint)(y % yy);
2242 while (((xx | yy) & 1) == 0) {
2243 xx >>= 1; yy >>= 1; t++;
2246 while ((xx & 1) == 0) xx >>= 1;
2247 while ((yy & 1) == 0) yy >>= 1;
2249 xx = (xx - yy) >> 1;
2251 yy = (yy - xx) >> 1;
2257 /*LAMESPEC Log doesn't specify to how many ulp is has to be precise
2258 We are equilavent to MS with about 2 ULP
2260 public static double Log (BigInteger value, Double baseValue)
2262 if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d ||
2263 baseValue == Double.NegativeInfinity || double.IsNaN (baseValue))
2266 if (baseValue == 0.0d || baseValue == Double.PositiveInfinity)
2267 return value.IsOne ? 0 : double.NaN;
2269 if (value.data == null)
2270 return double.NegativeInfinity;
2272 int length = value.data.Length - 1;
2274 for (int curBit = 31; curBit >= 0; curBit--) {
2275 if ((value.data [length] & (1 << curBit)) != 0) {
2276 bitCount = curBit + length * 32;
2281 long bitlen = bitCount;
2282 Double c = 0, d = 1;
2284 BigInteger testBit = One;
2285 long tempBitlen = bitlen;
2286 while (tempBitlen > Int32.MaxValue) {
2287 testBit = testBit << Int32.MaxValue;
2288 tempBitlen -= Int32.MaxValue;
2290 testBit = testBit << (int)tempBitlen;
2292 for (long curbit = bitlen; curbit >= 0; --curbit) {
2293 if ((value & testBit).sign != 0)
2296 testBit = testBit >> 1;
2298 return (System.Math.Log (c) + System.Math.Log (2) * bitlen) / System.Math.Log (baseValue);
2302 public static double Log (BigInteger value)
2304 return Log (value, Math.E);
2308 public static double Log10 (BigInteger value)
2310 return Log (value, 10);
2313 [CLSCompliantAttribute (false)]
2314 public bool Equals (ulong other)
2316 return CompareTo (other) == 0;
2319 public override int GetHashCode ()
2321 uint hash = (uint)(sign * 0x01010101u);
2322 int len = data != null ? data.Length : 0;
2324 for (int i = 0; i < len; ++i)
2329 public static BigInteger Add (BigInteger left, BigInteger right)
2331 return left + right;
2334 public static BigInteger Subtract (BigInteger left, BigInteger right)
2336 return left - right;
2339 public static BigInteger Multiply (BigInteger left, BigInteger right)
2341 return left * right;
2344 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
2346 return dividend / divisor;
2349 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
2351 return dividend % divisor;
2354 public static BigInteger Negate (BigInteger value)
2359 public int CompareTo (object obj)
2364 if (!(obj is BigInteger))
2367 return Compare (this, (BigInteger)obj);
2370 public int CompareTo (BigInteger other)
2372 return Compare (this, other);
2375 [CLSCompliantAttribute (false)]
2376 public int CompareTo (ulong other)
2381 return other == 0 ? 0 : -1;
2383 if (data.Length > 2)
2386 uint high = (uint)(other >> 32);
2387 uint low = (uint)other;
2389 return LongCompare (low, high);
2392 int LongCompare (uint low, uint high)
2395 if (data.Length > 1)
2413 public int CompareTo (long other)
2416 int rs = Math.Sign (other);
2419 return ls > rs ? 1 : -1;
2424 if (data.Length > 2)
2429 uint low = (uint)other;
2430 uint high = (uint)((ulong)other >> 32);
2432 int r = LongCompare (low, high);
2439 public static int Compare (BigInteger left, BigInteger right)
2442 int rs = right.sign;
2445 return ls > rs ? 1 : -1;
2447 int r = CoreCompare (left.data, right.data);
2454 static int TopByte (uint x)
2456 if ((x & 0xFFFF0000u) != 0) {
2457 if ((x & 0xFF000000u) != 0)
2461 if ((x & 0xFF00u) != 0)
2466 static int FirstNonFFByte (uint word)
2468 if ((word & 0xFF000000u) != 0xFF000000u)
2470 else if ((word & 0xFF0000u) != 0xFF0000u)
2472 else if ((word & 0xFF00u) != 0xFF00u)
2477 public byte[] ToByteArray ()
2480 return new byte [1];
2482 //number of bytes not counting upper word
2483 int bytes = (data.Length - 1) * 4;
2484 bool needExtraZero = false;
2486 uint topWord = data [data.Length - 1];
2489 //if the topmost bit is set we need an extra
2491 extra = TopByte (topWord);
2492 uint mask = 0x80u << ((extra - 1) * 8);
2493 if ((topWord & mask) != 0) {
2494 needExtraZero = true;
2497 extra = TopByte (topWord);
2500 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
2503 int end = data.Length - 1;
2504 for (int i = 0; i < end; ++i) {
2505 uint word = data [i];
2507 res [j++] = (byte)word;
2508 res [j++] = (byte)(word >> 8);
2509 res [j++] = (byte)(word >> 16);
2510 res [j++] = (byte)(word >> 24);
2512 while (extra-- > 0) {
2513 res [j++] = (byte)topWord;
2518 int end = data.Length - 1;
2520 uint carry = 1, word;
2522 for (int i = 0; i < end; ++i) {
2524 add = (ulong)~word + carry;
2526 carry = (uint)(add >> 32);
2528 res [j++] = (byte)word;
2529 res [j++] = (byte)(word >> 8);
2530 res [j++] = (byte)(word >> 16);
2531 res [j++] = (byte)(word >> 24);
2534 add = (ulong)~topWord + (carry);
2536 carry = (uint)(add >> 32);
2538 int ex = FirstNonFFByte (word);
2539 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
2540 int to = ex + (needExtra ? 1 : 0);
2543 res = Resize (res, bytes + to);
2546 res [j++] = (byte)word;
2552 res = Resize (res, bytes + 5);
2553 res [j++] = (byte)word;
2554 res [j++] = (byte)(word >> 8);
2555 res [j++] = (byte)(word >> 16);
2556 res [j++] = (byte)(word >> 24);
2564 static byte[] Resize (byte[] v, int len)
2566 byte[] res = new byte [len];
2567 Array.Copy (v, res, Math.Min (v.Length, len));
2571 static uint[] Resize (uint[] v, int len)
2573 uint[] res = new uint [len];
2574 Array.Copy (v, res, Math.Min (v.Length, len));
2578 static uint[] CoreAdd (uint[] a, uint[] b)
2580 if (a.Length < b.Length) {
2589 uint[] res = new uint [bl];
2594 for (; i < sl; i++) {
2595 sum = sum + a [i] + b [i];
2596 res [i] = (uint)sum;
2600 for (; i < bl; i++) {
2602 res [i] = (uint)sum;
2607 res = Resize (res, bl + 1);
2608 res [i] = (uint)sum;
2615 static uint[] CoreSub (uint[] a, uint[] b)
2620 uint[] res = new uint [bl];
2624 for (i = 0; i < sl; ++i) {
2625 borrow = (ulong)a [i] - b [i] - borrow;
2627 res [i] = (uint)borrow;
2628 borrow = (borrow >> 32) & 0x1;
2631 for (; i < bl; i++) {
2632 borrow = (ulong)a [i] - borrow;
2633 res [i] = (uint)borrow;
2634 borrow = (borrow >> 32) & 0x1;
2637 //remove extra zeroes
2638 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
2640 res = Resize (res, i + 1);
2646 static uint[] CoreAdd (uint[] a, uint b)
2649 uint[] res = new uint [len];
2653 for (i = 0; i < len; i++) {
2655 res [i] = (uint)sum;
2660 res = Resize (res, len + 1);
2661 res [i] = (uint)sum;
2667 static uint[] CoreSub (uint[] a, uint b)
2670 uint[] res = new uint [len];
2674 for (i = 0; i < len; i++) {
2675 borrow = (ulong)a [i] - borrow;
2676 res [i] = (uint)borrow;
2677 borrow = (borrow >> 32) & 0x1;
2680 //remove extra zeroes
2681 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
2683 res = Resize (res, i + 1);
2688 static int CoreCompare (uint[] a, uint[] b)
2690 int al = a != null ? a.Length : 0;
2691 int bl = b != null ? b.Length : 0;
2698 for (int i = al - 1; i >= 0; --i) {
2709 static int GetNormalizeShift(uint value) {
2712 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
2713 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
2714 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
2715 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
2716 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
2721 static void Normalize (uint[] u, int l, uint[] un, int shift)
2726 int rshift = 32 - shift;
2727 for (i = 0; i < l; i++) {
2729 un [i] = (ui << shift) | carry;
2730 carry = ui >> rshift;
2733 for (i = 0; i < l; i++) {
2738 while (i < un.Length) {
2747 static void Unnormalize (uint[] un, out uint[] r, int shift)
2749 int length = un.Length;
2750 r = new uint [length];
2753 int lshift = 32 - shift;
2755 for (int i = length - 1; i >= 0; i--) {
2757 r [i] = (uni >> shift) | carry;
2758 carry = (uni << lshift);
2761 for (int i = 0; i < length; i++) {
2767 const ulong Base = 0x100000000;
2768 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
2774 // Divide by single digit
2781 for (int j = m - 1; j >= 0; j--) {
2785 ulong div = rem / v0;
2790 } else if (m >= n) {
2791 int shift = GetNormalizeShift (v [n - 1]);
2793 uint[] un = new uint [m + 1];
2794 uint[] vn = new uint [n];
2796 Normalize (u, m, un, shift);
2797 Normalize (v, n, vn, shift);
2799 q = new uint [m - n + 1];
2802 // Main division loop
2804 for (int j = m - n; j >= 0; j--) {
2808 rr = Base * un [j + n] + un [j + n - 1];
2809 qq = rr / vn [n - 1];
2810 rr -= qq * vn [n - 1];
2813 // Estimate too big ?
2815 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
2817 rr += (ulong)vn [n - 1];
2825 // Multiply and subtract
2829 for (i = 0; i < n; i++) {
2830 ulong p = vn [i] * qq;
2831 t = (long)un [i + j] - (long)(uint)p - b;
2832 un [i + j] = (uint)t;
2837 t = (long)un [j + n] - b;
2838 un [j + n] = (uint)t;
2840 // Store the calculated value
2844 // Add back vn[0..n] to un[j..j+n]
2849 for (i = 0; i < n; i++) {
2850 c = (ulong)vn [i] + un [j + i] + c;
2851 un [j + i] = (uint)c;
2854 c += (ulong)un [j + n];
2855 un [j + n] = (uint)c;
2859 Unnormalize (un, out r, shift);
2861 q = new uint [] { 0 };