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 [CLSCompliantAttribute (false)]
1268 public bool Equals (ulong other)
1270 return CompareTo (other) == 0;
1273 public override int GetHashCode ()
1275 uint hash = (uint)(sign * 0x01010101u);
1277 for (int i = 0; i < data.Length; ++i)
1282 public static BigInteger Add (BigInteger left, BigInteger right)
1284 return left + right;
1287 public static BigInteger Subtract (BigInteger left, BigInteger right)
1289 return left - right;
1292 public static BigInteger Multiply (BigInteger left, BigInteger right)
1294 return left * right;
1297 public static BigInteger Divide (BigInteger dividend, BigInteger divisor)
1299 return dividend / divisor;
1302 public static BigInteger Remainder (BigInteger dividend, BigInteger divisor)
1304 return dividend % divisor;
1307 public static BigInteger Negate (BigInteger value)
1312 public int CompareTo (object obj)
1317 if (!(obj is BigInteger))
1320 return Compare (this, (BigInteger)obj);
1323 public int CompareTo (BigInteger other)
1325 return Compare (this, other);
1328 [CLSCompliantAttribute (false)]
1329 public int CompareTo (ulong other)
1334 return other == 0 ? 0 : -1;
1336 if (data.Length > 2)
1339 uint high = (uint)(other >> 32);
1340 uint low = (uint)other;
1342 return LongCompare (low, high);
1345 int LongCompare (uint low, uint high)
1348 if (data.Length > 1)
1366 public int CompareTo (long other)
1369 int rs = Math.Sign (other);
1372 return ls > rs ? 1 : -1;
1377 if (data.Length > 2)
1382 uint low = (uint)other;
1383 uint high = (uint)((ulong)other >> 32);
1385 int r = LongCompare (low, high);
1392 public static int Compare (BigInteger left, BigInteger right)
1395 int rs = right.sign;
1398 return ls > rs ? 1 : -1;
1400 int r = CoreCompare (left.data, right.data);
1407 static int TopByte (uint x)
1409 if ((x & 0xFFFF0000u) != 0) {
1410 if ((x & 0xFF000000u) != 0)
1414 if ((x & 0xFF00u) != 0)
1419 static int FirstNonFFByte (uint word)
1421 if ((word & 0xFF000000u) != 0xFF000000u)
1423 else if ((word & 0xFF0000u) != 0xFF0000u)
1425 else if ((word & 0xFF00u) != 0xFF00u)
1430 public byte[] ToByteArray ()
1433 return new byte [1];
1435 //number of bytes not counting upper word
1436 int bytes = (data.Length - 1) * 4;
1437 bool needExtraZero = false;
1439 uint topWord = data [data.Length - 1];
1442 //if the topmost bit is set we need an extra
1444 extra = TopByte (topWord);
1445 uint mask = 0x80u << ((extra - 1) * 8);
1446 if ((topWord & mask) != 0) {
1447 needExtraZero = true;
1450 extra = TopByte (topWord);
1453 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1456 int end = data.Length - 1;
1457 for (int i = 0; i < end; ++i) {
1458 uint word = data [i];
1460 res [j++] = (byte)word;
1461 res [j++] = (byte)(word >> 8);
1462 res [j++] = (byte)(word >> 16);
1463 res [j++] = (byte)(word >> 24);
1465 while (extra-- > 0) {
1466 res [j++] = (byte)topWord;
1471 int end = data.Length - 1;
1473 uint carry = 1, word;
1475 for (int i = 0; i < end; ++i) {
1477 add = (ulong)~word + carry;
1479 carry = (uint)(add >> 32);
1481 res [j++] = (byte)word;
1482 res [j++] = (byte)(word >> 8);
1483 res [j++] = (byte)(word >> 16);
1484 res [j++] = (byte)(word >> 24);
1487 add = (ulong)~topWord + (carry);
1489 carry = (uint)(add >> 32);
1491 int ex = FirstNonFFByte (word);
1492 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
1493 int to = ex + (needExtra ? 1 : 0);
1496 res = Resize (res, bytes + to);
1499 res [j++] = (byte)word;
1505 res = Resize (res, bytes + 5);
1506 res [j++] = (byte)word;
1507 res [j++] = (byte)(word >> 8);
1508 res [j++] = (byte)(word >> 16);
1509 res [j++] = (byte)(word >> 24);
1517 static byte[] Resize (byte[] v, int len)
1519 byte[] res = new byte [len];
\r
1520 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1524 static uint[] Resize (uint[] v, int len)
1526 uint[] res = new uint [len];
\r
1527 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1531 static uint[] CoreAdd (uint[] a, uint[] b)
1533 if (a.Length < b.Length) {
1542 uint[] res = new uint [bl];
1547 for (; i < sl; i++) {
1548 sum = sum + a [i] + b [i];
1549 res [i] = (uint)sum;
1553 for (; i < bl; i++) {
1555 res [i] = (uint)sum;
1560 res = Resize (res, bl + 1);
1561 res [i] = (uint)sum;
1568 static uint[] CoreSub (uint[] a, uint[] b)
1573 uint[] res = new uint [bl];
1577 for (i = 0; i < sl; ++i) {
1578 borrow = (ulong)a [i] - b [i] - borrow;
1580 res [i] = (uint)borrow;
1581 borrow = (borrow >> 32) & 0x1;
1584 for (; i < bl; i++) {
1585 borrow = (ulong)a [i] - borrow;
1586 res [i] = (uint)borrow;
1587 borrow = (borrow >> 32) & 0x1;
1590 //remove extra zeroes
1591 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
1593 res = Resize (res, i + 1);
1599 static uint[] CoreAdd (uint[] a, uint b)
1602 uint[] res = new uint [len];
1606 for (i = 0; i < len; i++) {
1608 res [i] = (uint)sum;
1613 res = Resize (res, len + 1);
1614 res [i] = (uint)sum;
1620 static uint[] CoreSub (uint[] a, uint b)
1623 uint[] res = new uint [len];
1627 for (i = 0; i < len; i++) {
1628 borrow = (ulong)a [i] - borrow;
1629 res [i] = (uint)borrow;
1630 borrow = (borrow >> 32) & 0x1;
1633 //remove extra zeroes
1634 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
1636 res = Resize (res, i + 1);
1641 static int CoreCompare (uint[] a, uint[] b)
1651 for (int i = al - 1; i >= 0; --i) {
1662 static int GetNormalizeShift(uint value) {
1665 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
1666 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
1667 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
1668 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
1669 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
1674 static void Normalize (uint[] u, int l, uint[] un, int shift)
1679 int rshift = 32 - shift;
1680 for (i = 0; i < l; i++) {
1682 un [i] = (ui << shift) | carry;
1683 carry = ui >> rshift;
1686 for (i = 0; i < l; i++) {
1691 while (i < un.Length) {
1700 static void Unnormalize (uint[] un, out uint[] r, int shift)
1702 int length = un.Length;
1703 r = new uint [length];
1706 int lshift = 32 - shift;
1708 for (int i = length - 1; i >= 0; i--) {
1710 r [i] = (uni >> shift) | carry;
1711 carry = (uni << lshift);
1714 for (int i = 0; i < length; i++) {
1720 const ulong Base = 0x100000000;
1721 static void DivModUnsigned (uint[] u, uint[] v, out uint[] q, out uint[] r)
1727 // Divide by single digit
1734 for (int j = m - 1; j >= 0; j--) {
1738 ulong div = rem / v0;
1743 } else if (m >= n) {
1744 int shift = GetNormalizeShift (v [n - 1]);
1746 uint[] un = new uint [m + 1];
1747 uint[] vn = new uint [n];
1749 Normalize (u, m, un, shift);
1750 Normalize (v, n, vn, shift);
1752 q = new uint [m - n + 1];
1755 // Main division loop
1757 for (int j = m - n; j >= 0; j--) {
1761 rr = Base * un [j + n] + un [j + n - 1];
1762 qq = rr / vn [n - 1];
1763 rr -= qq * vn [n - 1];
1766 // Estimate too big ?
1768 if ((qq >= Base) || (qq * vn [n - 2] > (rr * Base + un [j + n - 2]))) {
1770 rr += (ulong)vn [n - 1];
1778 // Multiply and subtract
1782 for (i = 0; i < n; i++) {
1783 ulong p = vn [i] * qq;
1784 t = (long)un [i + j] - (long)(uint)p - b;
1785 un [i + j] = (uint)t;
1790 t = (long)un [j + n] - b;
1791 un [j + n] = (uint)t;
1793 // Store the calculated value
1797 // Add back vn[0..n] to un[j..j+n]
1802 for (i = 0; i < n; i++) {
1803 c = (ulong)vn [i] + un [j + i] + c;
1804 un [j + i] = (uint)c;
1807 c += (ulong)un [j + n];
1808 un [j + n] = (uint)c;
1812 Unnormalize (un, out r, shift);
1814 q = new uint [] { 0 };