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.
29 using System.Collections.Generic;
\r
30 using System.Diagnostics;
\r
31 using System.Diagnostics.CodeAnalysis;
\r
32 using System.Globalization;
\r
37 Have proper popcount function for IsPowerOfTwo
38 Use unsafe ops to avoid bounds check
39 CoreAdd could avoid some resizes by checking for equal sized array that top overflow
40 For bitwise operators, hoist the conditionals out of their main loop
41 Optimize BitScanBackward
42 Use a carry variable to make shift opts do half the number of array ops.
43 Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers
45 namespace System.Numerics {
\r
46 public struct BigInteger : IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
52 static readonly uint[] ZERO = new uint [1];
53 static readonly uint[] ONE = new uint [1] { 1 };
55 BigInteger (short sign, uint[] data)
61 public BigInteger (int value)
66 } else if (value > 0) {
68 data = new uint[] { (uint) value };
71 data = new uint[1] { (uint)-value };
75 [CLSCompliantAttribute (false)]
76 public BigInteger (uint value)
83 data = new uint [1] { value };
87 public BigInteger (long value)
92 } else if (value > 0) {
94 uint low = (uint)value;
95 uint high = (uint)(value >> 32);
97 data = new uint [high != 0 ? 2 : 1];
104 uint low = (uint)value;
105 uint high = (uint)((ulong)value >> 32);
107 data = new uint [high != 0 ? 2 : 1];
114 [CLSCompliantAttribute (false)]
115 public BigInteger (ulong value)
122 uint low = (uint)value;
123 uint high = (uint)(value >> 32);
125 data = new uint [high != 0 ? 2 : 1];
132 [CLSCompliantAttribute (false)]
133 public BigInteger (byte[] value)
136 throw new ArgumentNullException ("value");
138 int len = value.Length;
140 if (len == 0 || (len == 1 && value [0] == 0)) {
146 if ((value [len - 1] & 0x80) != 0)
152 while (value [len - 1] == 0)
155 int full_words, size;
156 full_words = size = len / 4;
157 if ((len & 0x3) != 0)
160 data = new uint [size];
162 for (int i = 0; i < full_words; ++i) {
163 data [i] = (uint)value [j++] |
164 (uint)(value [j++] << 8) |
165 (uint)(value [j++] << 16) |
166 (uint)(value [j++] << 24);
170 int idx = data.Length - 1;
171 for (int i = 0; i < size; ++i)
172 data [idx] |= (uint)(value [j++] << (i * 8));
175 int full_words, size;
176 full_words = size = len / 4;
177 if ((len & 0x3) != 0)
180 data = new uint [size];
182 uint word, borrow = 1;
186 for (int i = 0; i < full_words; ++i) {
187 word = (uint)value [j++] |
188 (uint)(value [j++] << 8) |
189 (uint)(value [j++] << 16) |
190 (uint)(value [j++] << 24);
192 sub = (ulong)word - borrow;
194 borrow = (uint)(sub >> 32) & 0x1u;
202 for (int i = 0; i < size; ++i) {
203 word |= (uint)(value [j++] << (i * 8));
204 store_mask = (store_mask << 8) | 0xFF;
209 borrow = (uint)(sub >> 32) & 0x1u;
211 data [data.Length - 1] = ~word & store_mask;
213 if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it?
214 throw new Exception ("non zero final carry");
220 get { return (data [0] & 0x1) == 0; }
224 get { return sign == 1 && data.Length == 1 && data [0] == 1; }
228 //Gem from Hacker's Delight
229 //Returns the number of bits set in @x
230 static int PopulationCount (uint x)
232 x = x - ((x >> 1) & 0x55555555);
233 x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
234 x = (x + (x >> 4)) & 0x0F0F0F0F;
237 return (int)(x & 0x0000003F);
240 public bool IsPowerOfTwo {
242 bool foundBit = false;
245 //This function is pop count == 1 for positive numbers
246 for (int i = 0; i < data.Length; ++i) {
247 int p = PopulationCount (data [i]);
249 if (p > 1 || foundBit)
259 get { return sign == 0; }
266 public static BigInteger MinusOne {
267 get { return new BigInteger (-1, ONE); }
270 public static BigInteger One {
271 get { return new BigInteger (1, ONE); }
274 public static BigInteger Zero {
275 get { return new BigInteger (0, ZERO); }
278 public static explicit operator int (BigInteger value)
280 if (value.data.Length > 1)
281 throw new OverflowException ();
282 uint data = value.data [0];
284 if (value.sign == 1) {
285 if (data > (uint)int.MaxValue)
286 throw new OverflowException ();
288 } else if (value.sign == -1) {
289 if (data > 0x80000000u)
290 throw new OverflowException ();
297 [CLSCompliantAttribute (false)]
298 public static explicit operator uint (BigInteger value)
300 if (value.data.Length > 1 || value.sign == -1)
301 throw new OverflowException ();
302 return value.data [0];
305 public static explicit operator short (BigInteger value)
307 int val = (int)value;
308 if (val < short.MinValue || val > short.MaxValue)
309 throw new OverflowException ();
313 [CLSCompliantAttribute (false)]
314 public static explicit operator ushort (BigInteger value)
316 uint val = (uint)value;
317 if (val > ushort.MaxValue)
318 throw new OverflowException ();
322 public static explicit operator byte (BigInteger value)
324 uint val = (uint)value;
325 if (val > byte.MaxValue)
326 throw new OverflowException ();
330 [CLSCompliantAttribute (false)]
331 public static explicit operator sbyte (BigInteger value)
333 int val = (int)value;
334 if (val < sbyte.MinValue || val > sbyte.MaxValue)
335 throw new OverflowException ();
340 public static explicit operator long (BigInteger value)
345 if (value.data.Length > 2)
346 throw new OverflowException ();
348 uint low = value.data [0];
350 if (value.data.Length == 1) {
353 long res = (long)low;
357 uint high = value.data [1];
359 if (value.sign == 1) {
360 if (high >= 0x80000000u)
361 throw new OverflowException ();
362 return (((long)high) << 32) | low;
365 if (high > 0x80000000u)
366 throw new OverflowException ();
368 return - ((((long)high) << 32) | (long)low);
371 [CLSCompliantAttribute (false)]
372 public static explicit operator ulong (BigInteger value)
374 if (value.data.Length > 2 || value.sign == -1)
375 throw new OverflowException ();
377 uint low = value.data [0];
378 if (value.data.Length == 1)
381 uint high = value.data [1];
382 return (((ulong)high) << 32) | low;
386 public static implicit operator BigInteger (int value)
388 return new BigInteger (value);
391 [CLSCompliantAttribute (false)]
392 public static implicit operator BigInteger (uint value)
394 return new BigInteger (value);
397 public static implicit operator BigInteger (short value)
399 return new BigInteger (value);
402 [CLSCompliantAttribute (false)]
403 public static implicit operator BigInteger (ushort value)
405 return new BigInteger (value);
408 public static implicit operator BigInteger (byte value)
410 return new BigInteger (value);
413 [CLSCompliantAttribute (false)]
414 public static implicit operator BigInteger (sbyte value)
416 return new BigInteger (value);
419 public static implicit operator BigInteger (long value)
421 return new BigInteger (value);
424 [CLSCompliantAttribute (false)]
425 public static implicit operator BigInteger (ulong value)
427 return new BigInteger (value);
430 public static BigInteger operator+ (BigInteger left, BigInteger right)
437 if (left.sign == right.sign)
438 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
440 int r = CoreCompare (left.data, right.data);
443 return new BigInteger (0, ZERO);
445 if (r > 0) //left > right
446 return new BigInteger (left.sign, CoreSub (left.data, right.data));
448 return new BigInteger (right.sign, CoreSub (right.data, left.data));
451 public static BigInteger operator- (BigInteger left, BigInteger right)
456 return new BigInteger ((short)-right.sign, right.data);
458 if (left.sign == right.sign) {
459 int r = CoreCompare (left.data, right.data);
462 return new BigInteger (0, ZERO);
464 if (r > 0) //left > right
465 return new BigInteger (left.sign, CoreSub (left.data, right.data));
467 return new BigInteger ((short)-right.sign, CoreSub (right.data, left.data));
470 return new BigInteger (left.sign, CoreAdd (left.data, right.data));
473 public static BigInteger operator* (BigInteger left, BigInteger right)
475 if (left.sign == 0 || right.sign == 0)
476 return new BigInteger (0, ZERO);
478 if (left.data [0] == 1 && left.data.Length == 1) {
481 return new BigInteger ((short)-right.sign, right.data);
484 if (right.data [0] == 1 && right.data.Length == 1) {
487 return new BigInteger ((short)-left.sign, left.data);
490 uint[] a = left.data;
491 uint[] b = right.data;
493 uint[] res = new uint [a.Length + b.Length];
495 for (int i = 0; i < a.Length; ++i) {
500 for (int j = 0; j < b.Length; ++j) {
501 carry = carry + ((ulong)ai) * b [j] + res [k];
502 res[k++] = (uint)carry;
508 res[k++] = (uint)carry;
514 for (m = res.Length - 1; m >= 0 && res [m] == 0; --m) ;
515 if (m < res.Length - 1)
516 res = Resize (res, m + 1);
519 if (left.sign != right.sign)
522 return new BigInteger (sign, res);
526 public static BigInteger operator- (BigInteger value)
530 return new BigInteger ((short)-value.sign, value.data);
533 public static BigInteger operator+ (BigInteger value)
538 public static BigInteger operator++ (BigInteger value)
540 short sign = value.sign;
541 uint[] data = value.data;
542 if (data.Length == 1) {
543 if (sign == -1 && data [0] == 1)
544 return new BigInteger (0, ZERO);
546 return new BigInteger (1, ONE);
550 data = CoreSub (data, 1);
552 data = CoreAdd (data, 1);
554 return new BigInteger (sign, data);
557 public static BigInteger operator-- (BigInteger value)
559 short sign = value.sign;
560 uint[] data = value.data;
561 if (data.Length == 1) {
562 if (sign == 1 && data [0] == 1)
563 return new BigInteger (0, ZERO);
565 return new BigInteger (-1, ONE);
569 data = CoreAdd (data, 1);
571 data = CoreSub (data, 1);
573 return new BigInteger (sign, data);
576 public static BigInteger operator& (BigInteger left, BigInteger right)
584 uint[] a = left.data;
585 uint[] b = right.data;
589 bool neg_res = (ls == rs) && (ls == -1);
591 uint[] result = new uint [Math.Max (a.Length, b.Length)];
593 ulong ac = 1, bc = 1, borrow = 1;
596 for (i = 0; i < result.Length; ++i) {
603 ac = (uint)(ac >> 32);
612 bc = (uint)(bc >> 32);
618 borrow = word - borrow;
619 word = ~(uint)borrow;
620 borrow = (uint)(borrow >> 32) & 0x1u;
626 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
628 return new BigInteger (0, ZERO);
630 if (i < result.Length - 1)
631 result = Resize (result, i + 1);
633 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
636 public static BigInteger operator| (BigInteger left, BigInteger right)
644 uint[] a = left.data;
645 uint[] b = right.data;
649 bool neg_res = (ls == -1) || (rs == -1);
651 uint[] result = new uint [Math.Max (a.Length, b.Length)];
653 ulong ac = 1, bc = 1, borrow = 1;
656 for (i = 0; i < result.Length; ++i) {
663 ac = (uint)(ac >> 32);
672 bc = (uint)(bc >> 32);
678 borrow = word - borrow;
679 word = ~(uint)borrow;
680 borrow = (uint)(borrow >> 32) & 0x1u;
686 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
688 return new BigInteger (0, ZERO);
690 if (i < result.Length - 1)
691 result = Resize (result, i + 1);
693 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
696 public static BigInteger operator^ (BigInteger left, BigInteger right)
704 uint[] a = left.data;
705 uint[] b = right.data;
709 bool neg_res = (ls == -1) ^ (rs == -1);
711 uint[] result = new uint [Math.Max (a.Length, b.Length)];
713 ulong ac = 1, bc = 1, borrow = 1;
716 for (i = 0; i < result.Length; ++i) {
723 ac = (uint)(ac >> 32);
732 bc = (uint)(bc >> 32);
738 borrow = word - borrow;
739 word = ~(uint)borrow;
740 borrow = (uint)(borrow >> 32) & 0x1u;
746 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
748 return new BigInteger (0, ZERO);
750 if (i < result.Length - 1)
751 result = Resize (result, i + 1);
753 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
756 public static BigInteger operator~ (BigInteger value)
759 return new BigInteger (-1, ONE);
761 uint[] data = value.data;
762 int sign = value.sign;
764 bool neg_res = sign == 1;
766 uint[] result = new uint [data.Length];
768 ulong carry = 1, borrow = 1;
771 for (i = 0; i < result.Length; ++i) {
772 uint word = data [i];
774 carry = ~word + carry;
776 carry = (uint)(carry >> 32);
782 borrow = word - borrow;
783 word = ~(uint)borrow;
784 borrow = (uint)(borrow >> 32) & 0x1u;
790 for (i = result.Length - 1; i >= 0 && result [i] == 0; --i) ;
792 return new BigInteger (0, ZERO);
794 if (i < result.Length - 1)
795 result = Resize (result, i + 1);
797 return new BigInteger (neg_res ? (short)-1 : (short)1, result);
800 //returns the 0-based index of the most significant set bit
801 //returns 0 if no bit is set, so extra care when using it
802 static int BitScanBackward (uint word)
804 for (int i = 31; i >= 0; --i) {
806 if ((word & mask) == mask)
812 public static BigInteger operator<< (BigInteger value, int shift)
814 if (shift == 0 || value.sign == 0)
817 return value >> -shift;
819 uint[] data = value.data;
820 int sign = value.sign;
822 int topMostIdx = BitScanBackward (data [data.Length - 1]);
823 int bits = shift - (31 - topMostIdx);
824 int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0);
826 uint[] res = new uint [data.Length + extra_words];
828 int idx_shift = shift >> 5;
829 int bit_shift = shift & 0x1F;
830 int carry_shift = 32 - bit_shift;
832 for (int i = 0; i < data.Length; ++i) {
833 uint word = data [i];
834 res [i + idx_shift] |= word << bit_shift;
835 if (i + idx_shift + 1 < res.Length)
836 res [i + idx_shift + 1] = word >> carry_shift;
839 return new BigInteger ((short)sign, res);
842 public static BigInteger operator>> (BigInteger value, int shift)
844 if (shift == 0 || value.sign == 0)
847 return value << -shift;
849 uint[] data = value.data;
850 int sign = value.sign;
852 int topMostIdx = BitScanBackward (data [data.Length - 1]);
853 int idx_shift = shift >> 5;
854 int bit_shift = shift & 0x1F;
856 int extra_words = idx_shift;
857 if (bit_shift > topMostIdx)
859 int size = data.Length - extra_words;
863 return new BigInteger (0, ZERO);
864 return new BigInteger (-1, ONE);
867 uint[] res = new uint [size];
868 int carry_shift = 32 - bit_shift;
870 for (int i = data.Length - 1; i >= idx_shift; --i) {
871 uint word = data [i];
873 if (i - idx_shift < res.Length)
874 res [i - idx_shift] |= word >> bit_shift;
875 if (i - idx_shift - 1 >= 0)
876 res [i - idx_shift - 1] = word << carry_shift;
879 //Round down instead of toward zero
881 for (int i = 0; i < idx_shift; i++) {
882 if (data [i] != 0u) {
883 var tmp = new BigInteger ((short)sign, res);
888 if (bit_shift > 0 && (data [idx_shift] << carry_shift) != 0u) {
889 var tmp = new BigInteger ((short)sign, res);
894 return new BigInteger ((short)sign, res);
897 public static bool operator< (BigInteger left, BigInteger right)
899 return Compare (left, right) < 0;
902 public static bool operator< (BigInteger left, long right)
904 return left.CompareTo (right) < 0;
908 public static bool operator< (long left, BigInteger right)
910 return right.CompareTo (left) > 0;
914 [CLSCompliantAttribute (false)]
915 public static bool operator< (BigInteger left, ulong right)
917 return left.CompareTo (right) < 0;
920 [CLSCompliantAttribute (false)]
921 public static bool operator< (ulong left, BigInteger right)
923 return right.CompareTo (left) > 0;
926 public static bool operator<= (BigInteger left, BigInteger right)
928 return Compare (left, right) <= 0;
931 public static bool operator<= (BigInteger left, long right)
933 return left.CompareTo (right) <= 0;
936 public static bool operator<= (long left, BigInteger right)
938 return right.CompareTo (left) >= 0;
941 [CLSCompliantAttribute (false)]
942 public static bool operator<= (BigInteger left, ulong right)
944 return left.CompareTo (right) <= 0;
947 [CLSCompliantAttribute (false)]
948 public static bool operator<= (ulong left, BigInteger right)
950 return right.CompareTo (left) >= 0;
953 public static bool operator> (BigInteger left, BigInteger right)
955 return Compare (left, right) > 0;
958 public static bool operator> (BigInteger left, long right)
960 return left.CompareTo (right) > 0;
963 public static bool operator> (long left, BigInteger right)
965 return right.CompareTo (left) < 0;
968 [CLSCompliantAttribute (false)]
969 public static bool operator> (BigInteger left, ulong right)
971 return left.CompareTo (right) > 0;
974 [CLSCompliantAttribute (false)]
975 public static bool operator> (ulong left, BigInteger right)
977 return right.CompareTo (left) < 0;
980 public static bool operator>= (BigInteger left, BigInteger right)
982 return Compare (left, right) >= 0;
985 public static bool operator>= (BigInteger left, long right)
987 return left.CompareTo (right) >= 0;
990 public static bool operator>= (long left, BigInteger right)
992 return right.CompareTo (left) <= 0;
995 [CLSCompliantAttribute (false)]
996 public static bool operator>= (BigInteger left, ulong right)
998 return left.CompareTo (right) >= 0;
1001 [CLSCompliantAttribute (false)]
1002 public static bool operator>= (ulong left, BigInteger right)
1004 return right.CompareTo (left) <= 0;
1007 public static bool operator== (BigInteger left, BigInteger right)
1009 return Compare (left, right) == 0;
1012 public static bool operator== (BigInteger left, long right)
1014 return left.CompareTo (right) == 0;
1017 public static bool operator== (long left, BigInteger right)
1019 return right.CompareTo (left) == 0;
1022 [CLSCompliantAttribute (false)]
1023 public static bool operator== (BigInteger left, ulong right)
1025 return left.CompareTo (right) == 0;
1028 [CLSCompliantAttribute (false)]
1029 public static bool operator== (ulong left, BigInteger right)
1031 return right.CompareTo (left) == 0;
1034 public static bool operator!= (BigInteger left, BigInteger right)
1036 return Compare (left, right) != 0;
1039 public static bool operator!= (BigInteger left, long right)
1041 return left.CompareTo (right) != 0;
1044 public static bool operator!= (long left, BigInteger right)
1046 return right.CompareTo (left) != 0;
1049 [CLSCompliantAttribute (false)]
1050 public static bool operator!= (BigInteger left, ulong right)
1052 return left.CompareTo (right) != 0;
1055 [CLSCompliantAttribute (false)]
1056 public static bool operator!= (ulong left, BigInteger right)
1058 return right.CompareTo (left) != 0;
1061 public override bool Equals (object obj)
1063 if (!(obj is BigInteger))
1065 return Equals ((BigInteger)obj);
1068 public bool Equals (BigInteger other)
1070 if (sign != other.sign)
1072 if (data.Length != other.data.Length)
1074 for (int i = 0; i < data.Length; ++i) {
1075 if (data [i] != other.data [i])
1081 public bool Equals (long other)
1083 return CompareTo (other) == 0;
1086 public static BigInteger Min (BigInteger left, BigInteger right)
1089 int rs = right.sign;
1096 int r = CoreCompare (left.data, right.data);
1106 public static BigInteger Max (BigInteger left, BigInteger right)
1109 int rs = right.sign;
1116 int r = CoreCompare (left.data, right.data);
1125 public static BigInteger Abs (BigInteger value)
1127 return new BigInteger ((short)Math.Abs (value.sign), value.data);
1130 [CLSCompliantAttribute (false)]
1131 public bool Equals (ulong other)
1133 return CompareTo (other) == 0;
1136 public override int GetHashCode ()
1138 uint hash = (uint)(sign * 0x01010101u);
1140 for (int i = 0; i < data.Length; ++i)
1145 public static BigInteger Add (BigInteger left, BigInteger right)
1147 return left + right;
1150 public static BigInteger Subtract (BigInteger left, BigInteger right)
1152 return left - right;
1155 public static BigInteger Multiply (BigInteger left, BigInteger right)
1157 return left * right;
1160 public static BigInteger Negate (BigInteger value)
1165 public int CompareTo (object obj)
1170 if (!(obj is BigInteger))
1173 return Compare (this, (BigInteger)obj);
1176 public int CompareTo (BigInteger other)
1178 return Compare (this, other);
1181 [CLSCompliantAttribute (false)]
1182 public int CompareTo (ulong other)
1187 return other == 0 ? 0 : -1;
1189 if (data.Length > 2)
1192 uint high = (uint)(other >> 32);
1193 uint low = (uint)other;
1195 return LongCompare (low, high);
1198 int LongCompare (uint low, uint high)
1201 if (data.Length > 1)
1219 public int CompareTo (long other)
1222 int rs = Math.Sign (other);
1225 return ls > rs ? 1 : -1;
1230 if (data.Length > 2)
1235 uint low = (uint)other;
1236 uint high = (uint)((ulong)other >> 32);
1238 int r = LongCompare (low, high);
1245 public static int Compare (BigInteger left, BigInteger right)
1248 int rs = right.sign;
1251 return ls > rs ? 1 : -1;
1253 int r = CoreCompare (left.data, right.data);
1260 static int TopByte (uint x)
1262 if ((x & 0xFFFF0000u) != 0) {
1263 if ((x & 0xFF000000u) != 0)
1267 if ((x & 0xFF00u) != 0)
1272 static int FirstNonFFByte (uint word)
1274 if ((word & 0xFF000000u) != 0xFF000000u)
1276 else if ((word & 0xFF0000u) != 0xFF0000u)
1278 else if ((word & 0xFF00u) != 0xFF00u)
1283 public byte[] ToByteArray ()
1286 return new byte [1];
1288 //number of bytes not counting upper word
1289 int bytes = (data.Length - 1) * 4;
1290 bool needExtraZero = false;
1292 uint topWord = data [data.Length - 1];
1295 //if the topmost bit is set we need an extra
1297 extra = TopByte (topWord);
1298 uint mask = 0x80u << ((extra - 1) * 8);
1299 if ((topWord & mask) != 0) {
1300 needExtraZero = true;
1303 extra = TopByte (topWord);
1306 byte[] res = new byte [bytes + extra + (needExtraZero ? 1 : 0) ];
1309 int end = data.Length - 1;
1310 for (int i = 0; i < end; ++i) {
1311 uint word = data [i];
1313 res [j++] = (byte)word;
1314 res [j++] = (byte)(word >> 8);
1315 res [j++] = (byte)(word >> 16);
1316 res [j++] = (byte)(word >> 24);
1318 while (extra-- > 0) {
1319 res [j++] = (byte)topWord;
1324 int end = data.Length - 1;
1326 uint carry = 1, word;
1328 for (int i = 0; i < end; ++i) {
1330 add = (ulong)~word + carry;
1332 carry = (uint)(add >> 32);
1334 res [j++] = (byte)word;
1335 res [j++] = (byte)(word >> 8);
1336 res [j++] = (byte)(word >> 16);
1337 res [j++] = (byte)(word >> 24);
1340 add = (ulong)~topWord + (carry);
1342 carry = (uint)(add >> 32);
1344 int ex = FirstNonFFByte (word);
1345 bool needExtra = (word & (1 << (ex * 8 - 1))) == 0;
1346 int to = ex + (needExtra ? 1 : 0);
1349 res = Resize (res, bytes + to);
1352 res [j++] = (byte)word;
1358 res = Resize (res, bytes + 5);
1359 res [j++] = (byte)word;
1360 res [j++] = (byte)(word >> 8);
1361 res [j++] = (byte)(word >> 16);
1362 res [j++] = (byte)(word >> 24);
1370 static byte[] Resize (byte[] v, int len)
1372 byte[] res = new byte [len];
\r
1373 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1377 static uint[] Resize (uint[] v, int len)
1379 uint[] res = new uint [len];
\r
1380 Array.Copy (v, res, Math.Min (v.Length, len));
\r
1384 static uint[] CoreAdd (uint[] a, uint[] b)
1386 if (a.Length < b.Length) {
1395 uint[] res = new uint [bl];
1400 for (; i < sl; i++) {
1401 sum = sum + a [i] + b [i];
1402 res [i] = (uint)sum;
1406 for (; i < bl; i++) {
1408 res [i] = (uint)sum;
1413 res = Resize (res, bl + 1);
1414 res [i] = (uint)sum;
1421 static uint[] CoreSub (uint[] a, uint[] b)
1426 uint[] res = new uint [bl];
1430 for (i = 0; i < sl; ++i) {
1431 borrow = (ulong)a [i] - b [i] - borrow;
1433 res [i] = (uint)borrow;
1434 borrow = (borrow >> 32) & 0x1;
1437 for (; i < bl; i++) {
1438 borrow = (ulong)a [i] - borrow;
1439 res [i] = (uint)borrow;
1440 borrow = (borrow >> 32) & 0x1;
1443 //remove extra zeroes
1444 for (i = bl - 1; i >= 0 && res [i] == 0; --i) ;
1446 res = Resize (res, i + 1);
1452 static uint[] CoreAdd (uint[] a, uint b)
1455 uint[] res = new uint [len];
1459 for (i = 0; i < len; i++) {
1461 res [i] = (uint)sum;
1466 res = Resize (res, len + 1);
1467 res [i] = (uint)sum;
1473 static uint[] CoreSub (uint[] a, uint b)
1476 uint[] res = new uint [len];
1480 for (i = 0; i < len; i++) {
1481 borrow = (ulong)a [i] - borrow;
1482 res [i] = (uint)borrow;
1483 borrow = (borrow >> 32) & 0x1;
1486 //remove extra zeroes
1487 for (i = len - 1; i >= 0 && res [i] == 0; --i) ;
1489 res = Resize (res, i + 1);
1494 static int CoreCompare (uint[] a, uint[] b)
1504 for (int i = al - 1; i >= 0; --i) {