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 // The Multiply and Div 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;
\r
48 using System.Diagnostics;
\r
49 using System.Diagnostics.CodeAnalysis;
\r
50 using System.Globalization;
\r
55 Have proper popcount function for IsPowerOfTwo
56 Use unsafe ops to avoid bounds check
57 CoreAdd could avoid some resizes by checking for equal sized array that top overflow
58 For bitwise operators, hoist the conditionals out of their main loop
59 Optimize BitScanBackward
60 Use a carry variable to make shift opts do half the number of array ops.
61 Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
63 namespace System.Numerics {
\r
64 public struct BigInteger : IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
70 static readonly uint[] ZERO = new uint [1];
71 static readonly uint[] ONE = new uint [1] { 1 };
73 BigInteger (short sign, uint[] data)
79 public BigInteger (int value)
84 } else if (value > 0) {
86 data = new uint[] { (uint) value };
89 data = new uint[1] { (uint)-value };
93 [CLSCompliantAttribute (false)]
94 public BigInteger (uint value)
101 data = new uint [1] { value };
105 public BigInteger (long value)
110 } else if (value > 0) {
112 uint low = (uint)value;
113 uint high = (uint)(value >> 32);
115 data = new uint [high != 0 ? 2 : 1];
122 uint low = (uint)value;
123 uint high = (uint)((ulong)value >> 32);
125 data = new uint [high != 0 ? 2 : 1];
132 [CLSCompliantAttribute (false)]
133 public BigInteger (ulong value)
140 uint low = (uint)value;
141 uint high = (uint)(value >> 32);
143 data = new uint [high != 0 ? 2 : 1];
150 [CLSCompliantAttribute (false)]
151 public BigInteger (byte[] value)
154 throw new ArgumentNullException ("value");
156 int len = value.Length;
158 if (len == 0 || (len == 1 && value [0] == 0)) {
164 if ((value [len - 1] & 0x80) != 0)
170 while (value [len - 1] == 0)
173 int full_words, size;
174 full_words = size = len / 4;
175 if ((len & 0x3) != 0)
178 data = new uint [size];
180 for (int i = 0; i < full_words; ++i) {
181 data [i] = (uint)value [j++] |
182 (uint)(value [j++] << 8) |
183 (uint)(value [j++] << 16) |
184 (uint)(value [j++] << 24);
188 int idx = data.Length - 1;
189 for (int i = 0; i < size; ++i)
190 data [idx] |= (uint)(value [j++] << (i * 8));
193 int full_words, size;
194 full_words = size = len / 4;
195 if ((len & 0x3) != 0)
198 data = new uint [size];
200 uint word, borrow = 1;
204 for (int i = 0; i < full_words; ++i) {
205 word = (uint)value [j++] |
206 (uint)(value [j++] << 8) |
207 (uint)(value [j++] << 16) |
208 (uint)(value [j++] << 24);
210 sub = (ulong)word - borrow;
212 borrow = (uint)(sub >> 32) & 0x1u;
220 for (int i = 0; i < size; ++i) {
221 word |= (uint)(value [j++] << (i * 8));
222 store_mask = (store_mask << 8) | 0xFF;
227 borrow = (uint)(sub >> 32) & 0x1u;
229 data [data.Length - 1] = ~word & store_mask;
231 if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
232 throw new Exception ("non zero final carry");
238 get { return (data [0] & 0x1) == 0; }
242 get { return sign == 1 && data.Length == 1 && data [0] == 1; }
246 //Gem from Hacker's Delight
247 //Returns the number of bits set in @x
248 static int PopulationCount (uint x)
250 x = x - ((x >> 1) & 0x55555555);
251 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
252 x = (x + (x >> 4)) & 0x0F0F0F0F;
255 return (int)(x & 0x0000003F);
258 public bool IsPowerOfTwo {
260 bool foundBit = false;
263 //This function is pop count == 1 for positive numbers
264 for (int i = 0; i < data.Length; ++i) {
265 int p = PopulationCount (data [i]);
267 if (p > 1 || foundBit)
277 get { return sign == 0; }
284 public static BigInteger MinusOne {
285 get { return new BigInteger (-1, ONE); }
288 public static BigInteger One {
289 get { return new BigInteger (1, ONE); }
292 public static BigInteger Zero {
293 get { return new BigInteger (0, ZERO); }
296 public static explicit operator int (BigInteger value)
298 if (value.data.Length > 1)
299 throw new OverflowException ();
300 uint data = value.data [0];
302 if (value.sign == 1) {
303 if (data > (uint)int.MaxValue)
304 throw new OverflowException ();
306 } else if (value.sign == -1) {
307 if (data > 0x80000000u)
308 throw new OverflowException ();
315 [CLSCompliantAttribute (false)]
316 public static explicit operator uint (BigInteger value)
318 if (value.data.Length > 1 || value.sign == -1)
319 throw new OverflowException ();
320 return value.data [0];
323 public static explicit operator short (BigInteger value)
325 int val = (int)value;
326 if (val < short.MinValue || val > short.MaxValue)
327 throw new OverflowException ();
331 [CLSCompliantAttribute (false)]
332 public static explicit operator ushort (BigInteger value)
334 uint val = (uint)value;
335 if (val > ushort.MaxValue)
336 throw new OverflowException ();
340 public static explicit operator byte (BigInteger value)
342 uint val = (uint)value;
343 if (val > byte.MaxValue)
344 throw new OverflowException ();
348 [CLSCompliantAttribute (false)]
349 public static explicit operator sbyte (BigInteger value)
351 int val = (int)value;
352 if (val < sbyte.MinValue || val > sbyte.MaxValue)
353 throw new OverflowException ();
358 public static explicit operator long (BigInteger value)
363 if (value.data.Length > 2)
364 throw new OverflowException ();
366 uint low = value.data [0];
368 if (value.data.Length == 1) {
371 long res = (long)low;
375 uint high = value.data [1];
377 if (value.sign == 1) {
378 if (high >= 0x80000000u)
379 throw new OverflowException ();
380 return (((long)high) << 32) | low;
383 if (high > 0x80000000u)
384 throw new OverflowException ();
386 return - ((((long)high) << 32) | (long)low);
389 [CLSCompliantAttribute (false)]
390 public static explicit operator ulong (BigInteger value)
392 if (value.data.Length > 2 || value.sign == -1)
393 throw new OverflowException ();
395 uint low = value.data [0];
396 if (value.data.Length == 1)
399 uint high = value.data [1];
400 return (((ulong)high) << 32) | low;
404 public static implicit operator BigInteger (int value)
406 return new BigInteger (value);
409 [CLSCompliantAttribute (false)]
410 public static implicit operator BigInteger (uint value)
412 return new BigInteger (value);
415 public static implicit operator BigInteger (short value)
417 return new BigInteger (value);
420 [CLSCompliantAttribute (false)]
421 public static implicit operator BigInteger (ushort value)
423 return new BigInteger (value);
426 public static implicit operator BigInteger (byte value)
428 return new BigInteger (value);
431 [CLSCompliantAttribute (false)]
432 public static implicit operator BigInteger (sbyte value)
434 return new BigInteger (value);
437 public static implicit operator BigInteger (long value)
439 return new BigInteger (value);
442 [CLSCompliantAttribute (false)]
443 public static implicit operator BigInteger (ulong value)
445 return new BigInteger (value);
448 public static BigInteger operator+ (BigInteger left, BigInteger right)
455 if (left.sign == right.sign)
456 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
458 int r = CoreCompare (left.data, right.data);
461 return new BigInteger (0, ZERO);
463 if (r > 0) //left > right
464 return new BigInteger (left.sign, CoreSub (left.data, right.data));
466 return new BigInteger (right.sign, CoreSub (right.data, left.data));
469 public static BigInteger operator- (BigInteger left, BigInteger right)
474 return new BigInteger ((short)-right.sign, right.data);
476 if (left.sign == right.sign) {
477 int r = CoreCompare (left.data, right.data);
480 return new BigInteger (0, ZERO);
482 if (r > 0) //left > right
483 return new BigInteger (left.sign, CoreSub (left.data, right.data));
485 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
488 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
491 public static BigInteger operator* (BigInteger left, BigInteger right)
493 if (left.sign == 0 || right.sign == 0)
494 return new BigInteger (0, ZERO);
496 if (left.data [0] == 1 && left.data.Length == 1) {
499 return new BigInteger ((short)-right.sign, right.data);
502 if (right.data [0] == 1 && right.data.Length == 1) {
505 return new BigInteger ((short)-left.sign, left.data);
508 uint[] a = left.data;
509 uint[] b = right.data;
511 uint[] res = new uint [a.Length + b.Length];
513 for (int i = 0; i < a.Length; ++i) {
518 for (int j = 0; j < b.Length; ++j) {
519 carry = carry + ((ulong)ai) * b [j] + res [k];
520 res[k++] = (uint)carry;
526 res[k++] = (uint)carry;
532 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
533 if (m < res.Length - 1)
534 res = Resize (res, m + 1);
536 return new BigInteger ((short)(left.sign * right.sign), res);
540 public static BigInteger operator- (BigInteger value)
544 return new BigInteger ((short)-value.sign, value.data);
547 public static BigInteger operator+ (BigInteger value)
552 public static BigInteger operator++ (BigInteger value)
554 short sign = value.sign;
555 uint[] data = value.data;
556 if (data.Length == 1) {
557 if (sign == -1 && data [0] == 1)
558 return new BigInteger (0, ZERO);
560 return new BigInteger (1, ONE);
564 data = CoreSub (data, 1);
566 data = CoreAdd (data, 1);
568 return new BigInteger (sign, data);
571 public static BigInteger operator-- (BigInteger value)
573 short sign = value.sign;
574 uint[] data = value.data;
575 if (data.Length == 1) {
576 if (sign == 1 && data [0] == 1)
577 return new BigInteger (0, ZERO);
579 return new BigInteger (-1, ONE);
583 data = CoreAdd (data, 1);
585 data = CoreSub (data, 1);
587 return new BigInteger (sign, data);
590 public static BigInteger operator& (BigInteger left, BigInteger right)
598 uint[] a = left.data;
599 uint[] b = right.data;
603 bool neg_res = (ls == rs) && (ls == -1);
605 uint[] result = new uint [Math.Max (a.Length, b.Length)];
607 ulong ac = 1, bc = 1, borrow = 1;
610 for (i = 0; i < result.Length; ++i) {
617 ac = (uint)(ac >> 32);
626 bc = (uint)(bc >> 32);
632 borrow = word - borrow;
633 word = ~(uint)borrow;
634 borrow = (uint)(borrow >> 32) & 0x1u;
640 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
642 return new BigInteger (0, ZERO);
644 if (i < result.Length - 1)
645 result = Resize (result, i + 1);
647 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
650 public static BigInteger operator| (BigInteger left, BigInteger right)
658 uint[] a = left.data;
659 uint[] b = right.data;
663 bool neg_res = (ls == -1) || (rs == -1);
665 uint[] result = new uint [Math.Max (a.Length, b.Length)];
667 ulong ac = 1, bc = 1, borrow = 1;
670 for (i = 0; i < result.Length; ++i) {
677 ac = (uint)(ac >> 32);
686 bc = (uint)(bc >> 32);
692 borrow = word - borrow;
693 word = ~(uint)borrow;
694 borrow = (uint)(borrow >> 32) & 0x1u;
700 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
702 return new BigInteger (0, ZERO);
704 if (i < result.Length - 1)
705 result = Resize (result, i + 1);
707 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
710 public static BigInteger operator^ (BigInteger left, BigInteger right)
718 uint[] a = left.data;
719 uint[] b = right.data;
723 bool neg_res = (ls == -1) ^ (rs == -1);
725 uint[] result = new uint [Math.Max (a.Length, b.Length)];
727 ulong ac = 1, bc = 1, borrow = 1;
730 for (i = 0; i < result.Length; ++i) {
737 ac = (uint)(ac >> 32);
746 bc = (uint)(bc >> 32);
752 borrow = word - borrow;
753 word = ~(uint)borrow;
754 borrow = (uint)(borrow >> 32) & 0x1u;
760 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
762 return new BigInteger (0, ZERO);
764 if (i < result.Length - 1)
765 result = Resize (result, i + 1);
767 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
770 public static BigInteger operator~ (BigInteger value)
773 return new BigInteger (-1, ONE);
775 uint[] data = value.data;
776 int sign = value.sign;
778 bool neg_res = sign == 1;
780 uint[] result = new uint [data.Length];
782 ulong carry = 1, borrow = 1;
785 for (i = 0; i < result.Length; ++i) {
786 uint word = data [i];
788 carry = ~word + carry;
790 carry = (uint)(carry >> 32);
796 borrow = word - borrow;
797 word = ~(uint)borrow;
798 borrow = (uint)(borrow >> 32) & 0x1u;
804 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
806 return new BigInteger (0, ZERO);
808 if (i < result.Length - 1)
809 result = Resize (result, i + 1);
811 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
814 //returns the 0-based index of the most significant set bit
815 //returns 0 if no bit is set, so extra care when using it
816 static int BitScanBackward (uint word)
818 for (int i = 31; i >= 0; --i) {
820 if ((word & mask) == mask)
826 public static BigInteger operator<< (BigInteger value, int shift)
828 if (shift == 0 || value.sign == 0)
831 return value >> -shift;
833 uint[] data = value.data;
834 int sign = value.sign;
836 int topMostIdx = BitScanBackward (data [data.Length - 1]);
837 int bits = shift - (31 - topMostIdx);
838 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
840 uint[] res = new uint [data.Length + extra_words];
842 int idx_shift = shift >> 5;
843 int bit_shift = shift & 0x1F;
844 int carry_shift = 32 - bit_shift;
846 for (int i = 0; i < data.Length; ++i) {
847 uint word = data [i];
848 res [i + idx_shift] |= word << bit_shift;
849 if (i + idx_shift + 1 < res.Length)
850 res [i + idx_shift + 1] = word >> carry_shift;
853 return new BigInteger ((short)sign, res);
856 public static BigInteger operator>> (BigInteger value, int shift)
858 if (shift == 0 || value.sign == 0)
861 return value << -shift;
863 uint[] data = value.data;
864 int sign = value.sign;
866 int topMostIdx = BitScanBackward (data [data.Length - 1]);
867 int idx_shift = shift >> 5;
868 int bit_shift = shift & 0x1F;
870 int extra_words = idx_shift;
871 if (bit_shift > topMostIdx)
873 int size = data.Length - extra_words;
877 return new BigInteger (0, ZERO);
878 return new BigInteger (-1, ONE);
881 uint[] res = new uint [size];
882 int carry_shift = 32 - bit_shift;
884 for (int i = data.Length - 1; i >= idx_shift; --i) {
885 uint word = data [i];
887 if (i - idx_shift < res.Length)
888 res [i - idx_shift] |= word >> bit_shift;
889 if (i - idx_shift - 1 >= 0)
890 res [i - idx_shift - 1] = word << carry_shift;
893 //Round down instead of toward zero
895 for (int i = 0; i < idx_shift; i++) {
896 if (data [i] != 0u) {
897 var tmp = new BigInteger ((short)sign, res);
902 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
903 var tmp = new BigInteger ((short)sign, res);
908 return new BigInteger ((short)sign, res);
911 public static bool operator< (BigInteger left, BigInteger right)
913 return Compare (left, right) < 0;
916 public static bool operator< (BigInteger left, long right)
918 return left.CompareTo (right) < 0;
922 public static bool operator< (long left, BigInteger right)
924 return right.CompareTo (left) > 0;
928 [CLSCompliantAttribute (false)]
929 public static bool operator< (BigInteger left, ulong right)
931 return left.CompareTo (right) < 0;
934 [CLSCompliantAttribute (false)]
935 public static bool operator< (ulong left, BigInteger right)
937 return right.CompareTo (left) > 0;
940 public static bool operator<= (BigInteger left, BigInteger right)
942 return Compare (left, right) <= 0;
945 public static bool operator<= (BigInteger left, long right)
947 return left.CompareTo (right) <= 0;
950 public static bool operator<= (long left, BigInteger right)
952 return right.CompareTo (left) >= 0;
955 [CLSCompliantAttribute (false)]
956 public static bool operator<= (BigInteger left, ulong right)
958 return left.CompareTo (right) <= 0;
961 [CLSCompliantAttribute (false)]
962 public static bool operator<= (ulong left, BigInteger right)
964 return right.CompareTo (left) >= 0;
967 public static bool operator> (BigInteger left, BigInteger right)
969 return Compare (left, right) > 0;
972 public static bool operator> (BigInteger left, long right)
974 return left.CompareTo (right) > 0;
977 public static bool operator> (long left, BigInteger right)
979 return right.CompareTo (left) < 0;
982 [CLSCompliantAttribute (false)]
983 public static bool operator> (BigInteger left, ulong right)
985 return left.CompareTo (right) > 0;
988 [CLSCompliantAttribute (false)]
989 public static bool operator> (ulong left, BigInteger right)
991 return right.CompareTo (left) < 0;
994 public static bool operator>= (BigInteger left, BigInteger right)
996 return Compare (left, right) >= 0;
999 public static bool operator>= (BigInteger left, long right)
1001 return left.CompareTo (right) >= 0;
1004 public static bool operator>= (long left, BigInteger right)
1006 return right.CompareTo (left) <= 0;
1009 [CLSCompliantAttribute (false)]
1010 public static bool operator>= (BigInteger left, ulong right)
1012 return left.CompareTo (right) >= 0;
1015 [CLSCompliantAttribute (false)]
1016 public static bool operator>= (ulong left, BigInteger right)
1018 return right.CompareTo (left) <= 0;
1021 public static bool operator== (BigInteger left, BigInteger right)
1023 return Compare (left, right) == 0;
1026 public static bool operator== (BigInteger left, long right)
1028 return left.CompareTo (right) == 0;
1031 public static bool operator== (long left, BigInteger right)
1033 return right.CompareTo (left) == 0;
1036 [CLSCompliantAttribute (false)]
1037 public static bool operator== (BigInteger left, ulong right)
1039 return left.CompareTo (right) == 0;
1042 [CLSCompliantAttribute (false)]
1043 public static bool operator== (ulong left, BigInteger right)
1045 return right.CompareTo (left) == 0;
1048 public static bool operator!= (BigInteger left, BigInteger right)
1050 return Compare (left, right) != 0;
1053 public static bool operator!= (BigInteger left, long right)
1055 return left.CompareTo (right) != 0;
1058 public static bool operator!= (long left, BigInteger right)
1060 return right.CompareTo (left) != 0;
1063 [CLSCompliantAttribute (false)]
1064 public static bool operator!= (BigInteger left, ulong right)
1066 return left.CompareTo (right) != 0;
1069 [CLSCompliantAttribute (false)]
1070 public static bool operator!= (ulong left, BigInteger right)
1072 return right.CompareTo (left) != 0;
1075 public override bool Equals (object obj)
1077 if (!(obj is BigInteger))
1079 return Equals ((BigInteger)obj);
1082 public bool Equals (BigInteger other)
1084 if (sign != other.sign)
1086 if (data.Length != other.data.Length)
1088 for (int i = 0; i < data.Length; ++i) {
1089 if (data [i] != other.data [i])
1095 public bool Equals (long other)
1097 return CompareTo (other) == 0;
1100 public static BigInteger Min (BigInteger left, BigInteger right)
1103 int rs = right.sign;
1110 int r = CoreCompare (left.data, right.data);
1120 public static BigInteger Max (BigInteger left, BigInteger right)
1123 int rs = right.sign;
1130 int r = CoreCompare (left.data, right.data);
1139 public static BigInteger Abs (BigInteger value)
1141 return new BigInteger ((short)Math.Abs (value.sign), value.data);
1145 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
1147 if (divisor.sign == 0)
1148 throw new DivideByZeroException ();
1150 if (dividend.sign == 0) {
1151 remainder = dividend;
1156 uint[] remainder_value;
1158 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
1161 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
1163 remainder = new BigInteger (0, ZERO);
1165 if (i < remainder_value.Length - 1)
1166 remainder_value = Resize (remainder_value, i + 1);
1167 remainder = new BigInteger (dividend.sign, remainder_value);
1170 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
1172 return new BigInteger (0, ZERO);
1173 if (i < quotient.Length - 1)
1174 quotient = Resize (quotient, i + 1);
1176 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
1179 [CLSCompliantAttribute (false)]
1180 public bool Equals (ulong other)
1182 return CompareTo (other) == 0;
1185 public override int GetHashCode ()
1187 uint hash = (uint)(sign * 0x01010101u);
1189 for (int i = 0; i < data.Length; ++i)
1194 public static BigInteger Add (BigInteger left, BigInteger right)
1196 return left + right;
1199 public static BigInteger Subtract (BigInteger left, BigInteger right)
1201 return left - right;
1204 public static BigInteger Multiply (BigInteger left, BigInteger right)
1206 return left * right;
1209 public static BigInteger Negate (BigInteger value)
1214 public int CompareTo (object obj)
1219 if (!(obj is BigInteger))
1222 return Compare (this, (BigInteger)obj);
1225 public int CompareTo (BigInteger other)
1227 return Compare (this, other);
1230 [CLSCompliantAttribute (false)]
1231 public int CompareTo (ulong other)
1236 return other == 0 ? 0 : -1;
1238 if (data.Length > 2)
1241 uint high = (uint)(other >> 32);
1242 uint low = (uint)other;
1244 return LongCompare (low, high);
1247 int LongCompare (uint low, uint high)
1250 if (data.Length > 1)
1268 public int CompareTo (long other)
1271 int rs = Math.Sign (other);
1274 return ls > rs ? 1 : -1;
1279 if (data.Length > 2)
1284 uint low = (uint)other;
1285 uint high = (uint)((ulong)other >> 32);
1287 int r = LongCompare (low, high);
1294 public static int Compare (BigInteger left, BigInteger right)
1297 int rs = right.sign;
1300 return ls > rs ? 1 : -1;
1302 int r = CoreCompare (left.data, right.data);
1309 static int TopByte (uint x)
1311 if ((x & 0xFFFF0000u) != 0) {
1312 if ((x & 0xFF000000u) != 0)
1316 if ((x & 0xFF00u) != 0)
1321 static int FirstNonFFByte (uint word)
1323 if ((word & 0xFF000000u) != 0xFF000000u)
1325 else if ((word & 0xFF0000u) != 0xFF0000u)
1327 else if ((word & 0xFF00u) != 0xFF00u)
1332 public byte[] ToByteArray ()
1335 return new byte [1];
1337 //number of bytes not counting upper word
1338 int bytes = (data.Length - 1) * 4;
1339 bool needExtraZero = false;
1341 uint topWord = data [data.Length - 1];
1344 //if the topmost bit is set we need an extra
1346 extra = TopByte (topWord);
1347 uint mask = 0x80u << ((extra - 1) * 8);
1348 if ((topWord & mask) != 0) {
1349 needExtraZero = true;
1352 extra = TopByte (topWord);
1355 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1358 int end = data.Length - 1;
1359 for (int i = 0; i < end; ++i) {
1360 uint word = data [i];
1362 res [j++] = (byte)word;
1363 res [j++] = (byte)(word >> 8);
1364 res [j++] = (byte)(word >> 16);
1365 res [j++] = (byte)(word >> 24);
1367 while (extra-- > 0) {
1368 res [j++] = (byte)topWord;
1373 int end = data.Length - 1;
1375 uint carry = 1, word;
1377 for (int i = 0; i < end; ++i) {
1379 add = (ulong)~word + carry;
1381 carry = (uint)(add >> 32);
1383 res [j++] = (byte)word;
1384 res [j++] = (byte)(word >> 8);
1385 res [j++] = (byte)(word >> 16);
1386 res [j++] = (byte)(word >> 24);
1389 add = (ulong)~topWord + (carry);
1391 carry = (uint)(add >> 32);
1393 int ex = FirstNonFFByte (word);
1394 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
1395 int to = ex + (needExtra ? 1 : 0);
1398 res = Resize (res, bytes + to);
1401 res [j++] = (byte)word;
1407 res = Resize (res, bytes + 5);
1408 res [j++] = (byte)word;
1409 res [j++] = (byte)(word >> 8);
1410 res [j++] = (byte)(word >> 16);
1411 res [j++] = (byte)(word >> 24);
1419 static byte[] Resize (byte[] v, int len)
1421 byte[] res = new byte [len];
\r
1422 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1426 static uint[] Resize (uint[] v, int len)
1428 uint[] res = new uint [len];
\r
1429 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1433 static uint[] CoreAdd (uint[] a, uint[] b)
1435 if (a.Length < b.Length) {
1444 uint[] res = new uint [bl];
1449 for (; i < sl; i++) {
1450 sum = sum + a [i] + b [i];
1451 res [i] = (uint)sum;
1455 for (; i < bl; i++) {
1457 res [i] = (uint)sum;
1462 res = Resize (res, bl + 1);
1463 res [i] = (uint)sum;
1470 static uint[] CoreSub (uint[] a, uint[] b)
1475 uint[] res = new uint [bl];
1479 for (i = 0; i < sl; ++i) {
1480 borrow = (ulong)a [i] - b [i] - borrow;
1482 res [i] = (uint)borrow;
1483 borrow = (borrow >> 32) & 0x1;
1486 for (; i < bl; i++) {
1487 borrow = (ulong)a [i] - borrow;
1488 res [i] = (uint)borrow;
1489 borrow = (borrow >> 32) & 0x1;
1492 //remove extra zeroes
1493 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
1495 res = Resize (res, i + 1);
1501 static uint[] CoreAdd (uint[] a, uint b)
1504 uint[] res = new uint [len];
1508 for (i = 0; i < len; i++) {
1510 res [i] = (uint)sum;
1515 res = Resize (res, len + 1);
1516 res [i] = (uint)sum;
1522 static uint[] CoreSub (uint[] a, uint b)
1525 uint[] res = new uint [len];
1529 for (i = 0; i < len; i++) {
1530 borrow = (ulong)a [i] - borrow;
1531 res [i] = (uint)borrow;
1532 borrow = (borrow >> 32) & 0x1;
1535 //remove extra zeroes
1536 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
1538 res = Resize (res, i + 1);
1543 static int CoreCompare (uint[] a, uint[] b)
1553 for (int i = al - 1; i >= 0; --i) {
1564 static int GetNormalizeShift(uint value) {
1567 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
1568 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
1569 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
1570 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
1571 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
1576 static void Normalize (uint[] u, int l, uint[] un, int shift)
1581 int rshift = 32 - shift;
1582 for (i = 0; i < l; i++) {
1584 un [i] = (ui << shift) | carry;
1585 carry = ui >> rshift;
1588 for (i = 0; i < l; i++) {
1593 while (i < un.Length) {
1602 static void Unnormalize (uint[] un, out uint[] r, int shift)
1604 int length = un.Length;
1605 r = new uint [length];
1608 int lshift = 32 - shift;
1610 for (int i = length - 1; i >= 0; i--) {
1612 r [i] = (uni >> shift) | carry;
1613 carry = (uni << lshift);
1616 for (int i = 0; i < length; i++) {
1622 const ulong Base = 0x100000000;
1623 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
1629 // Divide by single digit
1636 for (int j = m - 1; j >= 0; j--) {
1640 ulong div = rem / v0;
1645 } else if (m >= n) {
1646 int shift = GetNormalizeShift (v [n - 1]);
1648 uint[] un = new uint [m + 1];
1649 uint[] vn = new uint [n];
1651 Normalize (u, m, un, shift);
1652 Normalize (v, n, vn, shift);
1654 q = new uint [m - n + 1];
1657 // Main division loop
1659 for (int j = m - n; j >= 0; j--) {
1663 rr = Base * un [j + n] + un [j + n - 1];
1664 qq = rr / vn [n - 1];
1665 rr -= qq * vn [n - 1];
1668 // Estimate too big ?
1670 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
1672 rr += (ulong)vn [n - 1];
1680 // Multiply and subtract
1684 for (i = 0; i < n; i++) {
1685 ulong p = vn [i] * qq;
1686 t = (long)un [i + j] - (long)(uint)p - b;
1687 un [i + j] = (uint)t;
1692 t = (long)un [j + n] - b;
1693 un [j + n] = (uint)t;
1695 // Store the calculated value
1699 // Add back vn[0..n] to un[j..j+n]
1704 for (i = 0; i < n; i++) {
1705 c = (ulong)vn [i] + un [j + i] + c;
1706 un [j + i] = (uint)c;
1709 c += (ulong)un [j + n];
1710 un [j + n] = (uint)c;
1714 Unnormalize (un, out r, shift);
1716 q = new uint [] { 0 };