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("exponent", "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;
1246 public static BigInteger ModPow (BigInteger value, BigInteger exponent, BigInteger modulus) {
1247 if (exponent.sign == -1)
1248 throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
1249 if (modulus.sign == 0)
1250 throw new DivideByZeroException ();
1252 BigInteger result = One % modulus;
1253 while (exponent.sign != 0) {
1254 if (!exponent.IsEven) {
1255 result = result * value;
1256 result = result % modulus;
1260 value = value * value;
1261 value = value % modulus;
1267 public static BigInteger GreatestCommonDivisor (BigInteger left, BigInteger right)
1269 if (left.data.Length == 1 && left.data [0] == 1)
1270 return new BigInteger (1, ONE);
1271 if (right.data.Length == 1 && right.data [0] == 1)
1272 return new BigInteger (1, ONE);
1278 BigInteger x = new BigInteger (1, left.data);
1279 BigInteger y = new BigInteger (1, right.data);
1283 while (x.data.Length > 1) {
1289 if (x.IsZero) return g;
1291 // TODO: should we have something here if we can convert to long?
1294 // Now we can just do it with single precision. I am using the binary gcd method,
1295 // as it should be faster.
1298 uint yy = x.data [0];
1299 uint xx = (uint)(y % yy);
1303 while (((xx | yy) & 1) == 0) {
1304 xx >>= 1; yy >>= 1; t++;
1307 while ((xx & 1) == 0) xx >>= 1;
1308 while ((yy & 1) == 0) yy >>= 1;
1310 xx = (xx - yy) >> 1;
1312 yy = (yy - xx) >> 1;
1318 [CLSCompliantAttribute (false)]
1319 public bool Equals (ulong other)
1321 return CompareTo (other) == 0;
1324 public override int GetHashCode ()
1326 uint hash = (uint)(sign * 0x01010101u);
1328 for (int i = 0; i < data.Length; ++i)
1333 public static BigInteger Add (BigInteger left, BigInteger right)
1335 return left + right;
1338 public static BigInteger Subtract (BigInteger left, BigInteger right)
1340 return left - right;
1343 public static BigInteger Multiply (BigInteger left, BigInteger right)
1345 return left * right;
1348 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
1350 return dividend / divisor;
1353 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
1355 return dividend % divisor;
1358 public static BigInteger Negate (BigInteger value)
1363 public int CompareTo (object obj)
1368 if (!(obj is BigInteger))
1371 return Compare (this, (BigInteger)obj);
1374 public int CompareTo (BigInteger other)
1376 return Compare (this, other);
1379 [CLSCompliantAttribute (false)]
1380 public int CompareTo (ulong other)
1385 return other == 0 ? 0 : -1;
1387 if (data.Length > 2)
1390 uint high = (uint)(other >> 32);
1391 uint low = (uint)other;
1393 return LongCompare (low, high);
1396 int LongCompare (uint low, uint high)
1399 if (data.Length > 1)
1417 public int CompareTo (long other)
1420 int rs = Math.Sign (other);
1423 return ls > rs ? 1 : -1;
1428 if (data.Length > 2)
1433 uint low = (uint)other;
1434 uint high = (uint)((ulong)other >> 32);
1436 int r = LongCompare (low, high);
1443 public static int Compare (BigInteger left, BigInteger right)
1446 int rs = right.sign;
1449 return ls > rs ? 1 : -1;
1451 int r = CoreCompare (left.data, right.data);
1458 static int TopByte (uint x)
1460 if ((x & 0xFFFF0000u) != 0) {
1461 if ((x & 0xFF000000u) != 0)
1465 if ((x & 0xFF00u) != 0)
1470 static int FirstNonFFByte (uint word)
1472 if ((word & 0xFF000000u) != 0xFF000000u)
1474 else if ((word & 0xFF0000u) != 0xFF0000u)
1476 else if ((word & 0xFF00u) != 0xFF00u)
1481 public byte[] ToByteArray ()
1484 return new byte [1];
1486 //number of bytes not counting upper word
1487 int bytes = (data.Length - 1) * 4;
1488 bool needExtraZero = false;
1490 uint topWord = data [data.Length - 1];
1493 //if the topmost bit is set we need an extra
1495 extra = TopByte (topWord);
1496 uint mask = 0x80u << ((extra - 1) * 8);
1497 if ((topWord & mask) != 0) {
1498 needExtraZero = true;
1501 extra = TopByte (topWord);
1504 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1507 int end = data.Length - 1;
1508 for (int i = 0; i < end; ++i) {
1509 uint word = data [i];
1511 res [j++] = (byte)word;
1512 res [j++] = (byte)(word >> 8);
1513 res [j++] = (byte)(word >> 16);
1514 res [j++] = (byte)(word >> 24);
1516 while (extra-- > 0) {
1517 res [j++] = (byte)topWord;
1522 int end = data.Length - 1;
1524 uint carry = 1, word;
1526 for (int i = 0; i < end; ++i) {
1528 add = (ulong)~word + carry;
1530 carry = (uint)(add >> 32);
1532 res [j++] = (byte)word;
1533 res [j++] = (byte)(word >> 8);
1534 res [j++] = (byte)(word >> 16);
1535 res [j++] = (byte)(word >> 24);
1538 add = (ulong)~topWord + (carry);
1540 carry = (uint)(add >> 32);
1542 int ex = FirstNonFFByte (word);
1543 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
1544 int to = ex + (needExtra ? 1 : 0);
1547 res = Resize (res, bytes + to);
1550 res [j++] = (byte)word;
1556 res = Resize (res, bytes + 5);
1557 res [j++] = (byte)word;
1558 res [j++] = (byte)(word >> 8);
1559 res [j++] = (byte)(word >> 16);
1560 res [j++] = (byte)(word >> 24);
1568 static byte[] Resize (byte[] v, int len)
1570 byte[] res = new byte [len];
\r
1571 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1575 static uint[] Resize (uint[] v, int len)
1577 uint[] res = new uint [len];
\r
1578 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1582 static uint[] CoreAdd (uint[] a, uint[] b)
1584 if (a.Length < b.Length) {
1593 uint[] res = new uint [bl];
1598 for (; i < sl; i++) {
1599 sum = sum + a [i] + b [i];
1600 res [i] = (uint)sum;
1604 for (; i < bl; i++) {
1606 res [i] = (uint)sum;
1611 res = Resize (res, bl + 1);
1612 res [i] = (uint)sum;
1619 static uint[] CoreSub (uint[] a, uint[] b)
1624 uint[] res = new uint [bl];
1628 for (i = 0; i < sl; ++i) {
1629 borrow = (ulong)a [i] - b [i] - borrow;
1631 res [i] = (uint)borrow;
1632 borrow = (borrow >> 32) & 0x1;
1635 for (; i < bl; i++) {
1636 borrow = (ulong)a [i] - borrow;
1637 res [i] = (uint)borrow;
1638 borrow = (borrow >> 32) & 0x1;
1641 //remove extra zeroes
1642 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
1644 res = Resize (res, i + 1);
1650 static uint[] CoreAdd (uint[] a, uint b)
1653 uint[] res = new uint [len];
1657 for (i = 0; i < len; i++) {
1659 res [i] = (uint)sum;
1664 res = Resize (res, len + 1);
1665 res [i] = (uint)sum;
1671 static uint[] CoreSub (uint[] a, uint b)
1674 uint[] res = new uint [len];
1678 for (i = 0; i < len; i++) {
1679 borrow = (ulong)a [i] - borrow;
1680 res [i] = (uint)borrow;
1681 borrow = (borrow >> 32) & 0x1;
1684 //remove extra zeroes
1685 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
1687 res = Resize (res, i + 1);
1692 static int CoreCompare (uint[] a, uint[] b)
1702 for (int i = al - 1; i >= 0; --i) {
1713 static int GetNormalizeShift(uint value) {
1716 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
1717 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
1718 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
1719 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
1720 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
1725 static void Normalize (uint[] u, int l, uint[] un, int shift)
1730 int rshift = 32 - shift;
1731 for (i = 0; i < l; i++) {
1733 un [i] = (ui << shift) | carry;
1734 carry = ui >> rshift;
1737 for (i = 0; i < l; i++) {
1742 while (i < un.Length) {
1751 static void Unnormalize (uint[] un, out uint[] r, int shift)
1753 int length = un.Length;
1754 r = new uint [length];
1757 int lshift = 32 - shift;
1759 for (int i = length - 1; i >= 0; i--) {
1761 r [i] = (uni >> shift) | carry;
1762 carry = (uni << lshift);
1765 for (int i = 0; i < length; i++) {
1771 const ulong Base = 0x100000000;
1772 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
1778 // Divide by single digit
1785 for (int j = m - 1; j >= 0; j--) {
1789 ulong div = rem / v0;
1794 } else if (m >= n) {
1795 int shift = GetNormalizeShift (v [n - 1]);
1797 uint[] un = new uint [m + 1];
1798 uint[] vn = new uint [n];
1800 Normalize (u, m, un, shift);
1801 Normalize (v, n, vn, shift);
1803 q = new uint [m - n + 1];
1806 // Main division loop
1808 for (int j = m - n; j >= 0; j--) {
1812 rr = Base * un [j + n] + un [j + n - 1];
1813 qq = rr / vn [n - 1];
1814 rr -= qq * vn [n - 1];
1817 // Estimate too big ?
1819 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
1821 rr += (ulong)vn [n - 1];
1829 // Multiply and subtract
1833 for (i = 0; i < n; i++) {
1834 ulong p = vn [i] * qq;
1835 t = (long)un [i + j] - (long)(uint)p - b;
1836 un [i + j] = (uint)t;
1841 t = (long)un [j + n] - b;
1842 un [j + n] = (uint)t;
1844 // Store the calculated value
1848 // Add back vn[0..n] to un[j..j+n]
1853 for (i = 0; i < n; i++) {
1854 c = (ulong)vn [i] + un [j + i] + c;
1855 un [j + i] = (uint)c;
1858 c += (ulong)un [j + n];
1859 un [j + n] = (uint)c;
1863 Unnormalize (un, out r, shift);
1865 q = new uint [] { 0 };