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);
539 public static BigInteger operator/ (BigInteger dividend, BigInteger divisor)
541 if (divisor.sign == 0)
542 throw new DivideByZeroException ();
544 if (dividend.sign == 0)
548 uint[] remainder_value;
550 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
553 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
555 return new BigInteger (0, ZERO);
556 if (i < quotient.Length - 1)
557 quotient = Resize (quotient, i + 1);
559 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
562 public static BigInteger operator% (BigInteger dividend, BigInteger divisor)
564 if (divisor.sign == 0)
565 throw new DivideByZeroException ();
567 if (dividend.sign == 0)
571 uint[] remainder_value;
573 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
576 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
578 return new BigInteger (0, ZERO);
580 if (i < remainder_value.Length - 1)
581 remainder_value = Resize (remainder_value, i + 1);
582 return new BigInteger (dividend.sign, remainder_value);
585 public static BigInteger operator- (BigInteger value)
589 return new BigInteger ((short)-value.sign, value.data);
592 public static BigInteger operator+ (BigInteger value)
597 public static BigInteger operator++ (BigInteger value)
599 short sign = value.sign;
600 uint[] data = value.data;
601 if (data.Length == 1) {
602 if (sign == -1 && data [0] == 1)
603 return new BigInteger (0, ZERO);
605 return new BigInteger (1, ONE);
609 data = CoreSub (data, 1);
611 data = CoreAdd (data, 1);
613 return new BigInteger (sign, data);
616 public static BigInteger operator-- (BigInteger value)
618 short sign = value.sign;
619 uint[] data = value.data;
620 if (data.Length == 1) {
621 if (sign == 1 && data [0] == 1)
622 return new BigInteger (0, ZERO);
624 return new BigInteger (-1, ONE);
628 data = CoreAdd (data, 1);
630 data = CoreSub (data, 1);
632 return new BigInteger (sign, data);
635 public static BigInteger operator& (BigInteger left, BigInteger right)
643 uint[] a = left.data;
644 uint[] b = right.data;
648 bool neg_res = (ls == rs) && (ls == -1);
650 uint[] result = new uint [Math.Max (a.Length, b.Length)];
652 ulong ac = 1, bc = 1, borrow = 1;
655 for (i = 0; i < result.Length; ++i) {
662 ac = (uint)(ac >> 32);
671 bc = (uint)(bc >> 32);
677 borrow = word - borrow;
678 word = ~(uint)borrow;
679 borrow = (uint)(borrow >> 32) & 0x1u;
685 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
687 return new BigInteger (0, ZERO);
689 if (i < result.Length - 1)
690 result = Resize (result, i + 1);
692 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
695 public static BigInteger operator| (BigInteger left, BigInteger right)
703 uint[] a = left.data;
704 uint[] b = right.data;
708 bool neg_res = (ls == -1) || (rs == -1);
710 uint[] result = new uint [Math.Max (a.Length, b.Length)];
712 ulong ac = 1, bc = 1, borrow = 1;
715 for (i = 0; i < result.Length; ++i) {
722 ac = (uint)(ac >> 32);
731 bc = (uint)(bc >> 32);
737 borrow = word - borrow;
738 word = ~(uint)borrow;
739 borrow = (uint)(borrow >> 32) & 0x1u;
745 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
747 return new BigInteger (0, ZERO);
749 if (i < result.Length - 1)
750 result = Resize (result, i + 1);
752 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
755 public static BigInteger operator^ (BigInteger left, BigInteger right)
763 uint[] a = left.data;
764 uint[] b = right.data;
768 bool neg_res = (ls == -1) ^ (rs == -1);
770 uint[] result = new uint [Math.Max (a.Length, b.Length)];
772 ulong ac = 1, bc = 1, borrow = 1;
775 for (i = 0; i < result.Length; ++i) {
782 ac = (uint)(ac >> 32);
791 bc = (uint)(bc >> 32);
797 borrow = word - borrow;
798 word = ~(uint)borrow;
799 borrow = (uint)(borrow >> 32) & 0x1u;
805 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
807 return new BigInteger (0, ZERO);
809 if (i < result.Length - 1)
810 result = Resize (result, i + 1);
812 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
815 public static BigInteger operator~ (BigInteger value)
818 return new BigInteger (-1, ONE);
820 uint[] data = value.data;
821 int sign = value.sign;
823 bool neg_res = sign == 1;
825 uint[] result = new uint [data.Length];
827 ulong carry = 1, borrow = 1;
830 for (i = 0; i < result.Length; ++i) {
831 uint word = data [i];
833 carry = ~word + carry;
835 carry = (uint)(carry >> 32);
841 borrow = word - borrow;
842 word = ~(uint)borrow;
843 borrow = (uint)(borrow >> 32) & 0x1u;
849 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
851 return new BigInteger (0, ZERO);
853 if (i < result.Length - 1)
854 result = Resize (result, i + 1);
856 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
859 //returns the 0-based index of the most significant set bit
860 //returns 0 if no bit is set, so extra care when using it
861 static int BitScanBackward (uint word)
863 for (int i = 31; i >= 0; --i) {
865 if ((word & mask) == mask)
871 public static BigInteger operator<< (BigInteger value, int shift)
873 if (shift == 0 || value.sign == 0)
876 return value >> -shift;
878 uint[] data = value.data;
879 int sign = value.sign;
881 int topMostIdx = BitScanBackward (data [data.Length - 1]);
882 int bits = shift - (31 - topMostIdx);
883 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
885 uint[] res = new uint [data.Length + extra_words];
887 int idx_shift = shift >> 5;
888 int bit_shift = shift & 0x1F;
889 int carry_shift = 32 - bit_shift;
891 for (int i = 0; i < data.Length; ++i) {
892 uint word = data [i];
893 res [i + idx_shift] |= word << bit_shift;
894 if (i + idx_shift + 1 < res.Length)
895 res [i + idx_shift + 1] = word >> carry_shift;
898 return new BigInteger ((short)sign, res);
901 public static BigInteger operator>> (BigInteger value, int shift)
903 if (shift == 0 || value.sign == 0)
906 return value << -shift;
908 uint[] data = value.data;
909 int sign = value.sign;
911 int topMostIdx = BitScanBackward (data [data.Length - 1]);
912 int idx_shift = shift >> 5;
913 int bit_shift = shift & 0x1F;
915 int extra_words = idx_shift;
916 if (bit_shift > topMostIdx)
918 int size = data.Length - extra_words;
922 return new BigInteger (0, ZERO);
923 return new BigInteger (-1, ONE);
926 uint[] res = new uint [size];
927 int carry_shift = 32 - bit_shift;
929 for (int i = data.Length - 1; i >= idx_shift; --i) {
930 uint word = data [i];
932 if (i - idx_shift < res.Length)
933 res [i - idx_shift] |= word >> bit_shift;
934 if (i - idx_shift - 1 >= 0)
935 res [i - idx_shift - 1] = word << carry_shift;
938 //Round down instead of toward zero
940 for (int i = 0; i < idx_shift; i++) {
941 if (data [i] != 0u) {
942 var tmp = new BigInteger ((short)sign, res);
947 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
948 var tmp = new BigInteger ((short)sign, res);
953 return new BigInteger ((short)sign, res);
956 public static bool operator< (BigInteger left, BigInteger right)
958 return Compare (left, right) < 0;
961 public static bool operator< (BigInteger left, long right)
963 return left.CompareTo (right) < 0;
967 public static bool operator< (long left, BigInteger right)
969 return right.CompareTo (left) > 0;
973 [CLSCompliantAttribute (false)]
974 public static bool operator< (BigInteger left, ulong right)
976 return left.CompareTo (right) < 0;
979 [CLSCompliantAttribute (false)]
980 public static bool operator< (ulong left, BigInteger right)
982 return right.CompareTo (left) > 0;
985 public static bool operator<= (BigInteger left, BigInteger right)
987 return Compare (left, right) <= 0;
990 public static bool operator<= (BigInteger left, long right)
992 return left.CompareTo (right) <= 0;
995 public static bool operator<= (long left, BigInteger right)
997 return right.CompareTo (left) >= 0;
1000 [CLSCompliantAttribute (false)]
1001 public static bool operator<= (BigInteger left, ulong right)
1003 return left.CompareTo (right) <= 0;
1006 [CLSCompliantAttribute (false)]
1007 public static bool operator<= (ulong left, BigInteger right)
1009 return right.CompareTo (left) >= 0;
1012 public static bool operator> (BigInteger left, BigInteger right)
1014 return Compare (left, right) > 0;
1017 public static bool operator> (BigInteger left, long right)
1019 return left.CompareTo (right) > 0;
1022 public static bool operator> (long left, BigInteger right)
1024 return right.CompareTo (left) < 0;
1027 [CLSCompliantAttribute (false)]
1028 public static bool operator> (BigInteger left, ulong right)
1030 return left.CompareTo (right) > 0;
1033 [CLSCompliantAttribute (false)]
1034 public static bool operator> (ulong left, BigInteger right)
1036 return right.CompareTo (left) < 0;
1039 public static bool operator>= (BigInteger left, BigInteger right)
1041 return Compare (left, right) >= 0;
1044 public static bool operator>= (BigInteger left, long right)
1046 return left.CompareTo (right) >= 0;
1049 public static bool operator>= (long left, BigInteger right)
1051 return right.CompareTo (left) <= 0;
1054 [CLSCompliantAttribute (false)]
1055 public static bool operator>= (BigInteger left, ulong right)
1057 return left.CompareTo (right) >= 0;
1060 [CLSCompliantAttribute (false)]
1061 public static bool operator>= (ulong left, BigInteger right)
1063 return right.CompareTo (left) <= 0;
1066 public static bool operator== (BigInteger left, BigInteger right)
1068 return Compare (left, right) == 0;
1071 public static bool operator== (BigInteger left, long right)
1073 return left.CompareTo (right) == 0;
1076 public static bool operator== (long left, BigInteger right)
1078 return right.CompareTo (left) == 0;
1081 [CLSCompliantAttribute (false)]
1082 public static bool operator== (BigInteger left, ulong right)
1084 return left.CompareTo (right) == 0;
1087 [CLSCompliantAttribute (false)]
1088 public static bool operator== (ulong left, BigInteger right)
1090 return right.CompareTo (left) == 0;
1093 public static bool operator!= (BigInteger left, BigInteger right)
1095 return Compare (left, right) != 0;
1098 public static bool operator!= (BigInteger left, long right)
1100 return left.CompareTo (right) != 0;
1103 public static bool operator!= (long left, BigInteger right)
1105 return right.CompareTo (left) != 0;
1108 [CLSCompliantAttribute (false)]
1109 public static bool operator!= (BigInteger left, ulong right)
1111 return left.CompareTo (right) != 0;
1114 [CLSCompliantAttribute (false)]
1115 public static bool operator!= (ulong left, BigInteger right)
1117 return right.CompareTo (left) != 0;
1120 public override bool Equals (object obj)
1122 if (!(obj is BigInteger))
1124 return Equals ((BigInteger)obj);
1127 public bool Equals (BigInteger other)
1129 if (sign != other.sign)
1131 if (data.Length != other.data.Length)
1133 for (int i = 0; i < data.Length; ++i) {
1134 if (data [i] != other.data [i])
1140 public bool Equals (long other)
1142 return CompareTo (other) == 0;
1145 public static BigInteger Min (BigInteger left, BigInteger right)
1148 int rs = right.sign;
1155 int r = CoreCompare (left.data, right.data);
1165 public static BigInteger Max (BigInteger left, BigInteger right)
1168 int rs = right.sign;
1175 int r = CoreCompare (left.data, right.data);
1184 public static BigInteger Abs (BigInteger value)
1186 return new BigInteger ((short)Math.Abs (value.sign), value.data);
1190 public static BigInteger DivRem (BigInteger dividend, BigInteger divisor, out BigInteger remainder)
1192 if (divisor.sign == 0)
1193 throw new DivideByZeroException ();
1195 if (dividend.sign == 0) {
1196 remainder = dividend;
1201 uint[] remainder_value;
1203 DivModUnsigned (dividend.data, divisor.data, out quotient, out remainder_value);
1206 for (i = remainder_value.Length - 1; i >= 0 && remainder_value [i] == 0; --i) ;
1208 remainder = new BigInteger (0, ZERO);
1210 if (i < remainder_value.Length - 1)
1211 remainder_value = Resize (remainder_value, i + 1);
1212 remainder = new BigInteger (dividend.sign, remainder_value);
1215 for (i = quotient.Length - 1; i >= 0 && quotient [i] == 0; --i) ;
1217 return new BigInteger (0, ZERO);
1218 if (i < quotient.Length - 1)
1219 quotient = Resize (quotient, i + 1);
1221 return new BigInteger ((short)(dividend.sign * divisor.sign), quotient);
1224 public static BigInteger Pow (BigInteger value, int exponent)
1227 throw new ArgumentOutOfRangeException("exp", "exp must be >= 0");
1233 BigInteger result = One;
1234 while (exponent != 0) {
1235 if ((exponent & 1) != 0)
1236 result = result * value;
1240 value = value * value;
1247 [CLSCompliantAttribute (false)]
1248 public bool Equals (ulong other)
1250 return CompareTo (other) == 0;
1253 public override int GetHashCode ()
1255 uint hash = (uint)(sign * 0x01010101u);
1257 for (int i = 0; i < data.Length; ++i)
1262 public static BigInteger Add (BigInteger left, BigInteger right)
1264 return left + right;
1267 public static BigInteger Subtract (BigInteger left, BigInteger right)
1269 return left - right;
1272 public static BigInteger Multiply (BigInteger left, BigInteger right)
1274 return left * right;
1277 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
1279 return dividend / divisor;
1282 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
1284 return dividend % divisor;
1287 public static BigInteger Negate (BigInteger value)
1292 public int CompareTo (object obj)
1297 if (!(obj is BigInteger))
1300 return Compare (this, (BigInteger)obj);
1303 public int CompareTo (BigInteger other)
1305 return Compare (this, other);
1308 [CLSCompliantAttribute (false)]
1309 public int CompareTo (ulong other)
1314 return other == 0 ? 0 : -1;
1316 if (data.Length > 2)
1319 uint high = (uint)(other >> 32);
1320 uint low = (uint)other;
1322 return LongCompare (low, high);
1325 int LongCompare (uint low, uint high)
1328 if (data.Length > 1)
1346 public int CompareTo (long other)
1349 int rs = Math.Sign (other);
1352 return ls > rs ? 1 : -1;
1357 if (data.Length > 2)
1362 uint low = (uint)other;
1363 uint high = (uint)((ulong)other >> 32);
1365 int r = LongCompare (low, high);
1372 public static int Compare (BigInteger left, BigInteger right)
1375 int rs = right.sign;
1378 return ls > rs ? 1 : -1;
1380 int r = CoreCompare (left.data, right.data);
1387 static int TopByte (uint x)
1389 if ((x & 0xFFFF0000u) != 0) {
1390 if ((x & 0xFF000000u) != 0)
1394 if ((x & 0xFF00u) != 0)
1399 static int FirstNonFFByte (uint word)
1401 if ((word & 0xFF000000u) != 0xFF000000u)
1403 else if ((word & 0xFF0000u) != 0xFF0000u)
1405 else if ((word & 0xFF00u) != 0xFF00u)
1410 public byte[] ToByteArray ()
1413 return new byte [1];
1415 //number of bytes not counting upper word
1416 int bytes = (data.Length - 1) * 4;
1417 bool needExtraZero = false;
1419 uint topWord = data [data.Length - 1];
1422 //if the topmost bit is set we need an extra
1424 extra = TopByte (topWord);
1425 uint mask = 0x80u << ((extra - 1) * 8);
1426 if ((topWord & mask) != 0) {
1427 needExtraZero = true;
1430 extra = TopByte (topWord);
1433 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1436 int end = data.Length - 1;
1437 for (int i = 0; i < end; ++i) {
1438 uint word = data [i];
1440 res [j++] = (byte)word;
1441 res [j++] = (byte)(word >> 8);
1442 res [j++] = (byte)(word >> 16);
1443 res [j++] = (byte)(word >> 24);
1445 while (extra-- > 0) {
1446 res [j++] = (byte)topWord;
1451 int end = data.Length - 1;
1453 uint carry = 1, word;
1455 for (int i = 0; i < end; ++i) {
1457 add = (ulong)~word + carry;
1459 carry = (uint)(add >> 32);
1461 res [j++] = (byte)word;
1462 res [j++] = (byte)(word >> 8);
1463 res [j++] = (byte)(word >> 16);
1464 res [j++] = (byte)(word >> 24);
1467 add = (ulong)~topWord + (carry);
1469 carry = (uint)(add >> 32);
1471 int ex = FirstNonFFByte (word);
1472 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
1473 int to = ex + (needExtra ? 1 : 0);
1476 res = Resize (res, bytes + to);
1479 res [j++] = (byte)word;
1485 res = Resize (res, bytes + 5);
1486 res [j++] = (byte)word;
1487 res [j++] = (byte)(word >> 8);
1488 res [j++] = (byte)(word >> 16);
1489 res [j++] = (byte)(word >> 24);
1497 static byte[] Resize (byte[] v, int len)
1499 byte[] res = new byte [len];
\r
1500 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1504 static uint[] Resize (uint[] v, int len)
1506 uint[] res = new uint [len];
\r
1507 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1511 static uint[] CoreAdd (uint[] a, uint[] b)
1513 if (a.Length < b.Length) {
1522 uint[] res = new uint [bl];
1527 for (; i < sl; i++) {
1528 sum = sum + a [i] + b [i];
1529 res [i] = (uint)sum;
1533 for (; i < bl; i++) {
1535 res [i] = (uint)sum;
1540 res = Resize (res, bl + 1);
1541 res [i] = (uint)sum;
1548 static uint[] CoreSub (uint[] a, uint[] b)
1553 uint[] res = new uint [bl];
1557 for (i = 0; i < sl; ++i) {
1558 borrow = (ulong)a [i] - b [i] - borrow;
1560 res [i] = (uint)borrow;
1561 borrow = (borrow >> 32) & 0x1;
1564 for (; i < bl; i++) {
1565 borrow = (ulong)a [i] - borrow;
1566 res [i] = (uint)borrow;
1567 borrow = (borrow >> 32) & 0x1;
1570 //remove extra zeroes
1571 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
1573 res = Resize (res, i + 1);
1579 static uint[] CoreAdd (uint[] a, uint b)
1582 uint[] res = new uint [len];
1586 for (i = 0; i < len; i++) {
1588 res [i] = (uint)sum;
1593 res = Resize (res, len + 1);
1594 res [i] = (uint)sum;
1600 static uint[] CoreSub (uint[] a, uint b)
1603 uint[] res = new uint [len];
1607 for (i = 0; i < len; i++) {
1608 borrow = (ulong)a [i] - borrow;
1609 res [i] = (uint)borrow;
1610 borrow = (borrow >> 32) & 0x1;
1613 //remove extra zeroes
1614 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
1616 res = Resize (res, i + 1);
1621 static int CoreCompare (uint[] a, uint[] b)
1631 for (int i = al - 1; i >= 0; --i) {
1642 static int GetNormalizeShift(uint value) {
1645 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
1646 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
1647 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
1648 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
1649 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
1654 static void Normalize (uint[] u, int l, uint[] un, int shift)
1659 int rshift = 32 - shift;
1660 for (i = 0; i < l; i++) {
1662 un [i] = (ui << shift) | carry;
1663 carry = ui >> rshift;
1666 for (i = 0; i < l; i++) {
1671 while (i < un.Length) {
1680 static void Unnormalize (uint[] un, out uint[] r, int shift)
1682 int length = un.Length;
1683 r = new uint [length];
1686 int lshift = 32 - shift;
1688 for (int i = length - 1; i >= 0; i--) {
1690 r [i] = (uni >> shift) | carry;
1691 carry = (uni << lshift);
1694 for (int i = 0; i < length; i++) {
1700 const ulong Base = 0x100000000;
1701 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
1707 // Divide by single digit
1714 for (int j = m - 1; j >= 0; j--) {
1718 ulong div = rem / v0;
1723 } else if (m >= n) {
1724 int shift = GetNormalizeShift (v [n - 1]);
1726 uint[] un = new uint [m + 1];
1727 uint[] vn = new uint [n];
1729 Normalize (u, m, un, shift);
1730 Normalize (v, n, vn, shift);
1732 q = new uint [m - n + 1];
1735 // Main division loop
1737 for (int j = m - n; j >= 0; j--) {
1741 rr = Base * un [j + n] + un [j + n - 1];
1742 qq = rr / vn [n - 1];
1743 rr -= qq * vn [n - 1];
1746 // Estimate too big ?
1748 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
1750 rr += (ulong)vn [n - 1];
1758 // Multiply and subtract
1762 for (i = 0; i < n; i++) {
1763 ulong p = vn [i] * qq;
1764 t = (long)un [i + j] - (long)(uint)p - b;
1765 un [i + j] = (uint)t;
1770 t = (long)un [j + n] - b;
1771 un [j + n] = (uint)t;
1773 // Store the calculated value
1777 // Add back vn[0..n] to un[j..j+n]
1782 for (i = 0; i < n; i++) {
1783 c = (ulong)vn [i] + un [j + i] + c;
1784 un [j + i] = (uint)c;
1787 c += (ulong)un [j + n];
1788 un [j + n] = (uint)c;
1792 Unnormalize (un, out r, shift);
1794 q = new uint [] { 0 };