1
// Notes from Irony project coordinator (Roman Ivantsov)
2
// 1. The code in this file is a copy of the file with the same name from Microsoft.Scripting distribution,
3
// with a few minor changes made to be able to compile as part of Irony.
4
// Waiting for MS to provide big integers as part of .NET core distribution - long promised
5
// 2. I had to tweak a few static fields to make them readonly, to comply with security requirements
6
// for SQL Server-imported assemblies. To find the modified fields, search for "RI:" token
9
/* ****************************************************************************
11
* Copyright (c) Microsoft Corporation.
13
* This source code is subject to terms and conditions of the Microsoft Public License. A
14
* copy of the license can be found in the License.html file at the root of this distribution. If
15
* you cannot locate the Microsoft Public License, please send an email to
16
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
17
* by the terms of the Microsoft Public License.
19
* You must not remove this notice, or any other, from this software.
22
* ***************************************************************************/
26
using System.Collections;
27
using System.Collections.Generic;
28
using System.Globalization;
29
using System.Diagnostics;
30
using System.Diagnostics.CodeAnalysis;
31
//using Microsoft.Scripting.Utils;
33
namespace Microsoft.Scripting.Math {
35
/// arbitrary precision integers
37
[System.ComponentModel.TypeConverter(typeof(BigInteger.TypeConvertor))]
38
public class BigInteger : IFormattable, IComparable, IConvertible {
40
class TypeConvertor : System.ComponentModel.TypeConverter {
41
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType) {
42
if (sourceType == typeof(BigInteger)) {
45
switch (Type.GetTypeCode(sourceType)) {
46
case TypeCode.Boolean:
47
case TypeCode.DateTime:
57
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, CultureInfo culture, object value) {
59
Type vt = value.GetType();
60
if (vt == typeof(BigInteger)) {
63
switch (Type.GetTypeCode(vt)) {
65
return BigInteger.Create((byte)value);
67
return BigInteger.Create((char)value);
69
return BigInteger.Create((short)value);
71
return BigInteger.Create((int)value);
73
return BigInteger.Create((long)value);
75
return BigInteger.Create((sbyte)value);
77
return BigInteger.Create((ushort)value);
79
return BigInteger.Create((uint)value);
81
return BigInteger.Create((ulong)value);
82
case TypeCode.Decimal:
83
return BigInteger.Create((decimal)value);
85
return BigInteger.Create((float)value);
87
return BigInteger.Create((double)value);
90
return base.ConvertFrom(context, culture, value);
93
public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType) {
94
if (destinationType == typeof(BigInteger)) {
97
switch (Type.GetTypeCode(destinationType)) {
98
case TypeCode.Boolean:
99
case TypeCode.DateTime:
100
case TypeCode.DBNull:
102
case TypeCode.Object:
109
public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
111
BigInteger bi = (BigInteger)value;
112
Type vt = destinationType;
113
if (vt == typeof(BigInteger)) {
116
switch (Type.GetTypeCode(vt)) {
118
return bi.ToByte(null);
120
return bi.ToChar(null);
122
return bi.ToInt16(null);
124
return bi.ToInt32(null);
126
return bi.ToInt64(null);
128
return bi.ToSByte(null);
129
case TypeCode.UInt16:
130
return bi.ToUInt16(null);
131
case TypeCode.UInt32:
132
return bi.ToUInt32(null);
133
case TypeCode.UInt64:
134
return bi.ToUInt64(null);
135
case TypeCode.Decimal:
136
return bi.ToDecimal(null);
137
case TypeCode.Single:
138
return bi.ToSingle(null);
139
case TypeCode.Double:
140
return bi.ToDouble(null);
143
return base.ConvertTo(context, culture, value, destinationType);
147
private const int BitsPerDigit = 32;
148
private const ulong Base = 0x100000000;
150
private readonly short sign;
151
private readonly uint[] data;
153
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
154
public static readonly BigInteger Zero = new BigInteger(0, new uint[0]);
155
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
156
public static readonly BigInteger One = new BigInteger(+1, new uint[] { 1 });
158
[CLSCompliant(false)]
159
public static BigInteger Create(ulong v) {
160
return new BigInteger(+1, (uint)v, (uint)(v >> BitsPerDigit));
163
[CLSCompliant(false)]
164
public static BigInteger Create(uint v) {
165
if (v == 0) return Zero;
166
else if (v == 1) return One;
167
else return new BigInteger(+1, v);
170
public static BigInteger Create(long v) {
174
x = (ulong)-v; s = -1;
179
//Console.WriteLine("{0}, {1}, {2}, {3}", v, x, (uint)x, (uint)(x >> BitsPerDigit));
180
return new BigInteger(s, (uint)x, (uint)(x >> BitsPerDigit));
183
public static BigInteger Create(int v) {
184
if (v == 0) return Zero;
185
else if (v == 1) return One;
186
else if (v < 0) return new BigInteger(-1, (uint)-v);
187
else return new BigInteger(+1, (uint)v);
190
private const Int32 DecimalScaleFactorMask = 0x00FF0000;
191
private const Int32 DecimalSignMask = unchecked((Int32)0x80000000);
193
public static BigInteger Create(decimal v) {
194
// First truncate to get scale to 0 and extract bits
195
int[] bits = Decimal.GetBits(Decimal.Truncate(v));
197
Debug.Assert(bits.Length == 4 && (bits[3] & DecimalScaleFactorMask) == 0);
200
while (size > 0 && bits[size - 1] == 0) size--;
203
return BigInteger.Zero;
206
UInt32[] array = new UInt32[size];
207
array[0] = (UInt32)bits[0];
208
if (size > 1) array[1] = (UInt32)bits[1];
209
if (size > 2) array[2] = (UInt32)bits[2];
211
return new BigInteger(((bits[3] & DecimalSignMask) != 0) ? -1 : +1, array);
215
/// Create a BigInteger from a little-endian twos-complement byte array
216
/// (inverse of ToByteArray())
218
public static BigInteger Create(byte[] v) {
219
//Contract.RequiresNotNull(v, "v");
220
if (v.Length == 0) return Create(0);
222
int byteCount = v.Length;
223
int unalignedBytes = byteCount % 4;
224
int dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
225
uint[] data = new uint[dwordCount];
227
bool isNegative = (v[byteCount - 1] & 0x80) == 0x80;
231
// Copy all dwords, except but don't do the last one if it's not a full four bytes
232
int curDword, curByte, byteInDword;
234
for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++) {
236
while (byteInDword < 4) {
237
if (v[curByte] != 0x00) isZero = false;
238
data[curDword] <<= 8;
239
data[curDword] |= v[curByte];
246
// Copy the last dword specially if it's not aligned
247
if (unalignedBytes != 0) {
248
if (isNegative) data[dwordCount - 1] = 0xffffffff;
249
for (curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--) {
250
if (v[curByte] != 0x00) isZero = false;
251
data[curDword] <<= 8;
252
data[curDword] |= v[curByte];
256
if (isZero) return Zero;
259
makeTwosComplement(data);
260
return new BigInteger(-1, data);
262
return new BigInteger(1, data);
266
private static bool Negative(byte[] v) {
267
return ((v[7] & 0x80) != 0);
270
private static ushort Exponent(byte[] v) {
271
return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
274
private static ulong Mantissa(byte[] v) {
275
uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
276
uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
278
return (ulong)((ulong)i1 | ((ulong)i2 << 32));
281
private const int bias = 1075; //RI: changed from static field to const, to avoid security warning
282
public static BigInteger Create(double v) {
283
byte[] bytes = System.BitConverter.GetBytes(v);
284
ulong mantissa = Mantissa(bytes);
286
// 1.0 * 2**exp, we have a power of 2
287
int exponent = Exponent(bytes);
288
if (exponent == 0) return Zero;
290
BigInteger res = Negative(bytes) ? Negate(One) : One;
291
res = res << (exponent - 0x3ff);
294
// 1.mantissa * 2**exp
295
int exponent = Exponent(bytes);
296
mantissa |= 0x10000000000000ul;
297
BigInteger res = BigInteger.Create(mantissa);
298
res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent);
299
return Negative(bytes) ? res * (-1) : res;
303
public static implicit operator BigInteger(byte i) {
304
return Create((uint)i);
307
[CLSCompliant(false)]
308
public static implicit operator BigInteger(sbyte i) {
309
return Create((int)i);
312
public static implicit operator BigInteger(short i) {
313
return Create((int)i);
316
[CLSCompliant(false)]
317
public static implicit operator BigInteger(ushort i) {
318
return Create((uint)i);
321
[CLSCompliant(false)]
322
public static implicit operator BigInteger(uint i) {
326
public static implicit operator BigInteger(int i) {
330
[CLSCompliant(false)]
331
public static implicit operator BigInteger(ulong i) {
335
public static implicit operator BigInteger(long i) {
339
public static implicit operator BigInteger(decimal i) {
343
public static implicit operator double(BigInteger i) {
344
if (object.ReferenceEquals(i, null)) {
345
throw new ArgumentNullException("i");
347
return i.ToFloat64();
350
public static explicit operator byte(BigInteger self) {
352
if (self.AsInt32(out tmp)) {
353
return checked((byte)tmp);
355
throw new OverflowException();
358
[CLSCompliant(false)]
359
public static explicit operator sbyte(BigInteger self) {
361
if (self.AsInt32(out tmp)) {
362
return checked((sbyte)tmp);
364
throw new OverflowException();
367
[CLSCompliant(false)]
368
public static explicit operator UInt16(BigInteger self) {
370
if (self.AsInt32(out tmp)) {
371
return checked((UInt16)tmp);
373
throw new OverflowException();
376
public static explicit operator Int16(BigInteger self) {
378
if (self.AsInt32(out tmp)) {
379
return checked((Int16)tmp);
381
throw new OverflowException();
384
[CLSCompliant(false)]
385
public static explicit operator UInt32(BigInteger self) {
387
if (self.AsUInt32(out tmp)) {
390
throw new OverflowException();
393
public static explicit operator Int32(BigInteger self) {
395
if (self.AsInt32(out tmp)) {
398
throw new OverflowException();
401
public static explicit operator Int64(BigInteger self) {
403
if (self.AsInt64(out tmp)) {
406
throw new OverflowException();
409
[CLSCompliant(false)]
410
public static explicit operator UInt64(BigInteger self) {
412
if (self.AsUInt64(out tmp)) {
415
throw new OverflowException();
418
public static explicit operator float(BigInteger self) {
419
if (object.ReferenceEquals(self, null)) {
420
throw new ArgumentNullException("self");
422
return checked((float)self.ToFloat64());
425
public static explicit operator decimal(BigInteger self) {
427
if (self.AsDecimal(out res)) {
430
throw new OverflowException();
433
public BigInteger(BigInteger copy) {
434
if (object.ReferenceEquals(copy, null)) {
435
throw new ArgumentNullException("copy");
437
this.sign = copy.sign;
438
this.data = copy.data;
441
[CLSCompliant(false)]
442
public BigInteger(int sign, params uint[] data) {
443
//Contract.RequiresNotNull(data, "data");
444
if (sign != -1 && sign != 0 && sign != 1) throw new ArgumentException(MathResources.InvalidArgument, "sign");
445
if (GetLength(data) != 0) {
446
if (sign == 0) throw new ArgumentException(MathResources.InvalidArgument, "sign");
450
this.sign = (short)sign;
454
/// Return the magnitude of this BigInteger as an array of zero or more uints.
455
/// Element zero is the value of the least significant four bytes, element one is
456
/// the value of the four next most significant bytes, etc.
458
/// The returned data is the unsigned magnitude of the number. To determine the sign,
461
/// It is guaranteed that the highest element of the returned array is never zero.
462
/// This means that if the value of this BigInteger is zero, a zero-length array
465
[CLSCompliant(false)]
466
public uint[] GetBits() {
467
if (sign == 0) return new uint[0];
468
int mostSignificantNonZeroWord;
470
mostSignificantNonZeroWord = data.Length - 1;
471
mostSignificantNonZeroWord >= 0 && data[mostSignificantNonZeroWord] == 0;
472
mostSignificantNonZeroWord--
474
uint[] bits = new uint[mostSignificantNonZeroWord + 1];
475
Array.Copy(data, bits, mostSignificantNonZeroWord + 1);
480
/// Return the sign of this BigInteger: -1, 0, or 1.
488
public bool AsInt64(out long ret) {
490
if (sign == 0) return true;
491
if (Length > 2) return false;
492
if (data.Length == 1) {
493
ret = sign * (long)data[0];
496
ulong tmp = (((ulong)data[1]) << 32 | (ulong)data[0]);
497
if (tmp > 0x8000000000000000) return false;
498
if (tmp == 0x8000000000000000 && sign == 1) return false;
499
ret = ((long)tmp) * sign;
503
[CLSCompliant(false)]
504
public bool AsUInt32(out uint ret) {
506
if (sign == 0) return true;
507
if (sign < 0) return false;
508
if (Length > 1) return false;
513
[CLSCompliant(false)]
514
public bool AsUInt64(out ulong ret) {
516
if (sign == 0) return true;
517
if (sign < 0) return false;
518
if (Length > 2) return false;
519
ret = (ulong)data[0];
520
if (data.Length > 1) {
521
ret |= ((ulong)data[1]) << 32;
526
public bool AsInt32(out int ret) {
528
if (sign == 0) return true;
529
if (Length > 1) return false;
530
if (data[0] > 0x80000000) return false;
531
if (data[0] == 0x80000000 && sign == 1) return false;
537
public bool AsDecimal(out Decimal ret) {
543
BigInteger bi = this;
549
ret = default(decimal);
558
int lo = 0, mi = 0, hi = 0;
559
if (length > 2) hi = (Int32)bi.data[2];
560
if (length > 1) mi = (Int32)bi.data[1];
561
if (length > 0) lo = (Int32)bi.data[0];
563
ret = new Decimal(lo, mi, hi, sign < 0, (byte)scale);
568
[CLSCompliant(false)]
569
public uint ToUInt32() {
571
if (AsUInt32(out ret)) return ret;
572
throw new OverflowException(MathResources.BigIntWontFitUInt);
575
public int ToInt32() {
577
if (AsInt32(out ret)) return ret;
578
throw new OverflowException(MathResources.BigIntWontFitInt);
581
public decimal ToDecimal() {
583
if (AsDecimal(out ret)) return ret;
584
throw new OverflowException(MathResources.BigIntWontFitDecimal);
587
[CLSCompliant(false)]
588
public ulong ToUInt64() {
590
if (AsUInt64(out ret)) return ret;
591
throw new OverflowException(MathResources.BigIntWontFitULong);
594
public long ToInt64() {
596
if (AsInt64(out ret)) return ret;
597
throw new OverflowException(MathResources.BigIntWontFitLong);
600
public bool TryToFloat64(out double result) {
601
return double.TryParse(ToString(10),
602
System.Globalization.NumberStyles.Number,
603
System.Globalization.CultureInfo.InvariantCulture.NumberFormat,
607
public double ToFloat64() {
610
System.Globalization.CultureInfo.InvariantCulture.NumberFormat
616
return GetLength(data);
620
private static int GetLength(uint[] data) {
621
int ret = data.Length - 1;
622
while (ret >= 0 && data[ret] == 0) ret--;
627
private static uint[] copy(uint[] v) {
628
uint[] ret = new uint[v.Length];
629
Array.Copy(v, ret, v.Length);
633
private static uint[] resize(uint[] v, int len) {
634
if (v.Length == len) return v;
635
uint[] ret = new uint[len];
636
int n = System.Math.Min(v.Length, len);
637
for (int i = 0; i < n; i++) {
643
private static uint[] InternalAdd(uint[] x, int xl, uint[] y, int yl) {
644
Debug.Assert(xl >= yl);
645
uint[] z = new uint[xl];
649
for (i = 0; i < yl; i++) {
650
sum = sum + x[i] + y[i];
652
sum >>= BitsPerDigit;
655
for (; i < xl && sum != 0; i++) {
658
sum >>= BitsPerDigit;
661
z = resize(z, xl + 1);
664
for (; i < xl; i++) {
671
private static uint[] sub(uint[] x, int xl, uint[] y, int yl) {
672
Debug.Assert(xl >= yl);
673
uint[] z = new uint[xl];
677
for (i = 0; i < yl; i++) {
689
if (yi > xi) borrow = true;
694
for (; i < xl; i++) {
697
if (xi != 0) { i++; break; }
700
for (; i < xl; i++) {
703
return z; // may have leading zeros
706
private static uint[] add0(uint[] x, int xl, uint[] y, int yl) {
707
if (xl >= yl) return InternalAdd(x, xl, y, yl);
708
else return InternalAdd(y, yl, x, xl);
711
public static int Compare(BigInteger x, BigInteger y) {
712
if (object.ReferenceEquals(x, null)) {
713
throw new ArgumentNullException("x");
715
if (object.ReferenceEquals(y, null)) {
716
throw new ArgumentNullException("y");
718
if (x.sign == y.sign) {
722
for (int i = xl - 1; i >= 0; i--) {
723
if (x.data[i] == y.data[i]) continue;
724
return x.data[i] > y.data[i] ? x.sign : -x.sign;
728
return xl > yl ? +x.sign : -x.sign;
731
return x.sign > y.sign ? +1 : -1;
735
public static bool operator ==(BigInteger x, int y) {
736
return x == (BigInteger)y;
739
public static bool operator !=(BigInteger x, int y) {
743
public static bool operator ==(BigInteger x, double y) {
744
if (object.ReferenceEquals(x, null)) {
745
throw new ArgumentNullException("x");
748
// we can hold all double values, but not all double values
749
// can hold BigInteger values, and we may lose precision. Convert
750
// the double to a big int, then compare.
752
if ((y % 1) != 0) return false; // not a whole number, can't be equal
754
return x == BigInteger.Create(y);
757
public static bool operator ==(double x, BigInteger y) {
761
public static bool operator !=(BigInteger x, double y) {
765
public static bool operator !=(double x, BigInteger y) {
770
public static bool operator ==(BigInteger x, BigInteger y) {
771
return Compare(x, y) == 0;
774
public static bool operator !=(BigInteger x, BigInteger y) {
775
return Compare(x, y) != 0;
777
public static bool operator <(BigInteger x, BigInteger y) {
778
return Compare(x, y) < 0;
780
public static bool operator <=(BigInteger x, BigInteger y) {
781
return Compare(x, y) <= 0;
783
public static bool operator >(BigInteger x, BigInteger y) {
784
return Compare(x, y) > 0;
786
public static bool operator >=(BigInteger x, BigInteger y) {
787
return Compare(x, y) >= 0;
790
public static BigInteger Add(BigInteger x, BigInteger y) {
794
public static BigInteger operator +(BigInteger x, BigInteger y) {
795
if (object.ReferenceEquals(x, null)) {
796
throw new ArgumentNullException("x");
798
if (object.ReferenceEquals(y, null)) {
799
throw new ArgumentNullException("y");
802
if (x.sign == y.sign) {
803
return new BigInteger(x.sign, add0(x.data, x.Length, y.data, y.Length));
805
return x - new BigInteger(-y.sign, y.data); //??? performance issue
809
public static BigInteger Subtract(BigInteger x, BigInteger y) {
813
public static BigInteger operator -(BigInteger x, BigInteger y) {
814
int c = Compare(x, y);
815
if (c == 0) return Zero;
817
if (x.sign == y.sign) {
819
switch (c * x.sign) {
821
z = sub(x.data, x.Length, y.data, y.Length);
824
z = sub(y.data, y.Length, x.data, x.Length);
829
return new BigInteger(c, z);
831
uint[] z = add0(x.data, x.Length, y.data, y.Length);
832
return new BigInteger(c, z);
836
public static BigInteger Multiply(BigInteger x, BigInteger y) {
840
public static BigInteger operator *(BigInteger x, BigInteger y) {
841
if (object.ReferenceEquals(x, null)) {
842
throw new ArgumentNullException("x");
844
if (object.ReferenceEquals(y, null)) {
845
throw new ArgumentNullException("y");
850
uint[] xd = x.data, yd = y.data, zd = new uint[zl];
852
for (int xi = 0; xi < xl; xi++) {
856
for (int yi = 0; yi < yl; yi++) {
857
carry = carry + ((ulong)xv) * yd[yi] + zd[zi];
858
zd[zi++] = (uint)carry;
859
carry >>= BitsPerDigit;
863
zd[zi++] = (uint)carry;
864
carry >>= BitsPerDigit;
868
return new BigInteger(x.sign * y.sign, zd);
871
public static BigInteger Divide(BigInteger x, BigInteger y) {
875
public static BigInteger operator /(BigInteger x, BigInteger y) {
877
return DivRem(x, y, out dummy);
880
public static BigInteger Mod(BigInteger x, BigInteger y) {
884
public static BigInteger operator %(BigInteger x, BigInteger y) {
886
DivRem(x, y, out ret);
890
private static int GetNormalizeShift(uint value) {
893
if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
894
if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
895
if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
896
if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
897
if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
902
[Conditional("DEBUG")]
903
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
904
private static void TestNormalize(uint[] u, uint[] un, int shift) {
905
BigInteger i = new BigInteger(1, u);
906
BigInteger j = new BigInteger(1, un);
907
BigInteger k = j >> shift;
909
Debug.Assert(i == k);
912
[Conditional("DEBUG")]
913
private static void TestDivisionStep(uint[] un, uint[] vn, uint[] q, uint[] u, uint[] v) {
914
int n = GetLength(v);
915
int shift = GetNormalizeShift(v[n - 1]);
917
BigInteger uni = new BigInteger(1, un);
918
BigInteger vni = new BigInteger(1, vn);
919
BigInteger qi = new BigInteger(1, q);
920
BigInteger ui = new BigInteger(1, u);
922
BigInteger expected = vni * qi + uni;
923
BigInteger usi = ui << shift;
925
Debug.Assert(expected == usi);
928
[Conditional("DEBUG")]
929
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
930
private static void TestResult(uint[] u, uint[] v, uint[] q, uint[] r) {
931
BigInteger ui = new BigInteger(1, u);
932
BigInteger vi = new BigInteger(1, v);
933
BigInteger qi = new BigInteger(1, q);
934
BigInteger ri = new BigInteger(1, r);
936
BigInteger viqi = vi * qi;
937
BigInteger expected = viqi + ri;
938
Debug.Assert(ui == expected);
939
Debug.Assert(ri < vi);
942
private static void Normalize(uint[] u, int l, uint[] un, int shift) {
943
Debug.Assert(un.Length == l || un.Length == l + 1);
944
Debug.Assert(un.Length == l + 1 || ((u[l - 1] << shift) >> shift) == u[l - 1]);
945
Debug.Assert(0 <= shift && shift < 32);
950
int rshift = BitsPerDigit - shift;
951
for (i = 0; i < l; i++) {
953
un[i] = (ui << shift) | carry;
954
carry = ui >> rshift;
957
for (i = 0; i < l; i++) {
962
while (i < un.Length) {
967
Debug.Assert(l == un.Length - 1);
971
TestNormalize(u, un, shift);
974
private static void Unnormalize(uint[] un, out uint[] r, int shift) {
975
Debug.Assert(0 <= shift && shift < 32);
977
int length = GetLength(un);
978
r = new uint[length];
981
int lshift = 32 - shift;
983
for (int i = length - 1; i >= 0; i--) {
985
r[i] = (uni >> shift) | carry;
986
carry = (uni << lshift);
989
for (int i = 0; i < length; i++) {
994
TestNormalize(r, un, shift);
997
private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) {
998
int m = GetLength(u);
999
int n = GetLength(v);
1003
throw new DivideByZeroException();
1006
// Divide by single digit
1013
for (int j = m - 1; j >= 0; j--) {
1017
ulong div = rem / v0;
1022
} else if (m >= n) {
1023
int shift = GetNormalizeShift(v[n - 1]);
1025
uint[] un = new uint[m + 1];
1026
uint[] vn = new uint[n];
1028
Normalize(u, m, un, shift);
1029
Normalize(v, n, vn, shift);
1031
q = new uint[m - n + 1];
1034
TestDivisionStep(un, vn, q, u, v);
1036
// Main division loop
1038
for (int j = m - n; j >= 0; j--) {
1042
rr = Base * un[j + n] + un[j + n - 1];
1043
qq = rr / vn[n - 1];
1044
rr -= qq * vn[n - 1];
1046
Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
1049
// Estimate too big ?
1051
if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2]))) {
1053
rr += (ulong)vn[n - 1];
1054
if (rr < Base) continue;
1059
Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
1061
// Multiply and subtract
1065
for (i = 0; i < n; i++) {
1066
ulong p = vn[i] * qq;
1067
t = (long)un[i + j] - (long)(uint)p - b;
1068
un[i + j] = (uint)t;
1071
Debug.Assert(t == 0 || t == -1 || t == -2);
1074
t = (long)un[j + n] - b;
1075
un[j + n] = (uint)t;
1077
// Store the calculated value
1081
// Add back vn[0..n] to un[j..j+n]
1086
for (i = 0; i < n; i++) {
1087
c = (ulong)vn[i] + un[j + i] + c;
1088
un[j + i] = (uint)c;
1091
c += (ulong)un[j + n];
1092
un[j + n] = (uint)c;
1095
TestDivisionStep(un, vn, q, u, v);
1098
Unnormalize(un, out r, shift);
1100
// Test normalized value ... Call TestNormalize
1101
// only pass the values in different order.
1103
TestNormalize(r, un, shift);
1105
q = new uint[] { 0 };
1109
TestResult(u, v, q, r);
1112
public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
1113
if (object.ReferenceEquals(x, null)) {
1114
throw new ArgumentNullException("x");
1116
if (object.ReferenceEquals(y, null)) {
1117
throw new ArgumentNullException("y");
1123
DivModUnsigned(x.data, y.data, out q, out r);
1125
remainder = new BigInteger(x.sign, r);
1126
return new BigInteger(x.sign * y.sign, q);
1129
private static uint div(uint[] n, ref int nl, uint d) {
1132
bool seenNonZero = false;
1134
rem <<= BitsPerDigit;
1136
uint v = (uint)(rem / d);
1139
if (!seenNonZero) nl--;
1148
private static uint extend(uint v, ref bool seenNonZero) {
1161
private static uint getOne(bool isNeg, uint[] data, int i, ref bool seenNonZero) {
1162
if (i < data.Length) {
1164
return isNeg ? extend(ret, ref seenNonZero) : ret;
1166
return isNeg ? uint.MaxValue : 0;
1171
/// Do an in-place twos complement of d and also return the result.
1173
private static uint[] makeTwosComplement(uint[] d) {
1174
// first do complement and +1 as long as carry is needed
1177
for (; i < d.Length; i++) {
1180
if (v != 0) { i++; break; }
1184
// now ones complement is sufficient
1185
for (; i < d.Length; i++) {
1190
d = resize(d, d.Length + 1);
1191
d[d.Length - 1] = 1;
1196
public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
1200
public static BigInteger operator &(BigInteger x, BigInteger y) {
1201
if (object.ReferenceEquals(x, null)) {
1202
throw new ArgumentNullException("x");
1204
if (object.ReferenceEquals(y, null)) {
1205
throw new ArgumentNullException("y");
1207
int xl = x.Length, yl = y.Length;
1208
uint[] xd = x.data, yd = y.data;
1210
int zl = System.Math.Max(xl, yl);
1211
uint[] zd = new uint[zl];
1213
bool negx = x.sign == -1, negy = y.sign == -1;
1214
bool seenNonZeroX = false, seenNonZeroY = false;
1215
for (int i = 0; i < zl; i++) {
1216
uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1217
uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1223
return new BigInteger(-1, makeTwosComplement(zd));
1224
} else if (negx || negy) {
1225
return new BigInteger(+1, zd);
1227
return new BigInteger(+1, zd);
1231
public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
1235
public static BigInteger operator |(BigInteger x, BigInteger y) {
1236
if (object.ReferenceEquals(x, null)) {
1237
throw new ArgumentNullException("x");
1239
if (object.ReferenceEquals(y, null)) {
1240
throw new ArgumentNullException("y");
1242
int xl = x.Length, yl = y.Length;
1243
uint[] xd = x.data, yd = y.data;
1245
int zl = System.Math.Max(xl, yl);
1246
uint[] zd = new uint[zl];
1248
bool negx = x.sign == -1, negy = y.sign == -1;
1249
bool seenNonZeroX = false, seenNonZeroY = false;
1250
for (int i = 0; i < zl; i++) {
1251
uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1252
uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1257
return new BigInteger(-1, makeTwosComplement(zd));
1258
} else if (negx || negy) {
1259
return new BigInteger(-1, makeTwosComplement(zd));
1261
return new BigInteger(+1, zd);
1265
public static BigInteger Xor(BigInteger x, BigInteger y) {
1269
public static BigInteger operator ^(BigInteger x, BigInteger y) {
1270
if (object.ReferenceEquals(x, null)) {
1271
throw new ArgumentNullException("x");
1273
if (object.ReferenceEquals(y, null)) {
1274
throw new ArgumentNullException("y");
1276
int xl = x.Length, yl = y.Length;
1277
uint[] xd = x.data, yd = y.data;
1279
int zl = System.Math.Max(xl, yl);
1280
uint[] zd = new uint[zl];
1282
bool negx = x.sign == -1, negy = y.sign == -1;
1283
bool seenNonZeroX = false, seenNonZeroY = false;
1284
for (int i = 0; i < zl; i++) {
1285
uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1286
uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1291
return new BigInteger(+1, zd);
1292
} else if (negx || negy) {
1293
return new BigInteger(-1, makeTwosComplement(zd));
1295
return new BigInteger(+1, zd);
1299
public static BigInteger LeftShift(BigInteger x, int shift) {
1303
public static BigInteger operator <<(BigInteger x, int shift) {
1304
if (object.ReferenceEquals(x, null)) {
1305
throw new ArgumentNullException("x");
1307
if (shift == 0) return x;
1308
else if (shift < 0) return x >> -shift;
1310
int digitShift = shift / BitsPerDigit;
1311
int smallShift = shift - (digitShift * BitsPerDigit);
1315
int zl = xl + digitShift + 1;
1316
uint[] zd = new uint[zl];
1318
if (smallShift == 0) {
1319
for (int i = 0; i < xl; i++) {
1320
zd[i + digitShift] = xd[i];
1323
int carryShift = BitsPerDigit - smallShift;
1326
for (i = 0; i < xl; i++) {
1328
zd[i + digitShift] = rot << smallShift | carry;
1329
carry = rot >> carryShift;
1331
zd[i + digitShift] = carry;
1333
return new BigInteger(x.sign, zd);
1336
public static BigInteger RightShift(BigInteger x, int shift) {
1340
public static BigInteger operator >>(BigInteger x, int shift) {
1341
if (object.ReferenceEquals(x, null)) {
1342
throw new ArgumentNullException("x");
1344
if (shift == 0) return x;
1345
else if (shift < 0) return x << -shift;
1347
int digitShift = shift / BitsPerDigit;
1348
int smallShift = shift - (digitShift * BitsPerDigit);
1352
int zl = xl - digitShift;
1354
uint[] zd = new uint[zl];
1356
if (smallShift == 0) {
1357
for (int i = xl - 1; i >= digitShift; i--) {
1358
zd[i - digitShift] = xd[i];
1361
int carryShift = BitsPerDigit - smallShift;
1363
for (int i = xl - 1; i >= digitShift; i--) {
1365
zd[i - digitShift] = rot >> smallShift | carry;
1366
carry = rot << carryShift;
1369
return new BigInteger(x.sign, zd);
1372
public static BigInteger Negate(BigInteger x) {
1376
public static BigInteger operator -(BigInteger x) {
1377
if (object.ReferenceEquals(x, null)) {
1378
throw new ArgumentNullException("x");
1380
return new BigInteger(-x.sign, x.data);
1383
public BigInteger OnesComplement() {
1387
public static BigInteger operator ~(BigInteger x) {
1388
if (object.ReferenceEquals(x, null)) {
1389
throw new ArgumentNullException("x");
1394
public BigInteger Abs() {
1395
if (this.sign == -1) return -this;
1399
public BigInteger Power(int exp) {
1400
if (exp == 0) return One;
1402
throw new ArgumentOutOfRangeException(MathResources.NonNegativePower);
1404
BigInteger factor = this;
1405
BigInteger result = One;
1407
if ((exp & 1) != 0) result = result * factor;
1408
if (exp == 1) break; // avoid costly factor.square()
1409
factor = factor.Square();
1415
public BigInteger ModPow(int power, BigInteger mod) {
1416
if (object.ReferenceEquals(mod, null)) {
1417
throw new ArgumentNullException("mod");
1421
throw new ArgumentOutOfRangeException(MathResources.NonNegativePower);
1423
BigInteger factor = this;
1424
BigInteger result = One % mod; // Handle special case of power=0, mod=1
1425
while (power != 0) {
1426
if ((power & 1) != 0) {
1427
result = result * factor;
1428
result = result % mod;
1430
if (power == 1) break; // avoid costly factor.Square()
1431
factor = factor.Square();
1432
factor = factor % mod;
1438
public BigInteger ModPow(BigInteger power, BigInteger mod) {
1439
if (object.ReferenceEquals(power, null)) {
1440
throw new ArgumentNullException("power");
1442
if (object.ReferenceEquals(mod, null)) {
1443
throw new ArgumentNullException("mod");
1447
throw new ArgumentOutOfRangeException(MathResources.NonNegativePower);
1450
BigInteger factor = this;
1451
BigInteger result = One % mod;
1452
while (power != Zero) {
1453
if (power.IsOdd()) {
1454
result = result * factor;
1455
result = result % mod;
1457
if (power == One) break; // avoid costly factor.Square()
1458
factor = factor.Square();
1459
factor = factor % mod;
1465
public BigInteger Square() {
1469
public override string ToString() {
1470
return ToString(10);
1473
// generated by scripts/radix_generator.py
1474
//RI: made fields read-only to comply with security requirements for SQL Server-imported assemblies
1475
private static readonly uint[] maxCharsPerDigit = { 0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
1476
private static readonly uint[] groupRadixValues = { 0, 0, 2147483648, 3486784401, 1073741824, 1220703125, 2176782336, 1977326743, 1073741824, 3486784401, 1000000000, 2357947691, 429981696, 815730721, 1475789056, 2562890625, 268435456, 410338673, 612220032, 893871739, 1280000000, 1801088541, 2494357888, 3404825447, 191102976, 244140625, 308915776, 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, 1838265625, 2176782336 };
1479
[CLSCompliant(false)]
1480
public string ToString(uint radix) {
1482
throw new ArgumentOutOfRangeException("radix", radix, MathResources.RadixLessThan2);
1485
throw new ArgumentOutOfRangeException("radix", radix, MathResources.RadixGreaterThan36);
1489
if (len == 0) return "0";
1491
List<uint> digitGroups = new List<uint>();
1493
uint[] d = copy(data);
1496
uint groupRadix = groupRadixValues[radix];
1498
uint rem = div(d, ref dl, groupRadix);
1499
digitGroups.Add(rem);
1502
StringBuilder ret = new StringBuilder();
1503
if (sign == -1) ret.Append("-");
1504
int digitIndex = digitGroups.Count - 1;
1506
char[] tmpDigits = new char[maxCharsPerDigit[radix]];
1508
AppendRadix((uint)digitGroups[digitIndex--], radix, tmpDigits, ret, false);
1509
while (digitIndex >= 0) {
1510
AppendRadix((uint)digitGroups[digitIndex--], radix, tmpDigits, ret, true);
1512
return ret.ToString();
1515
private static void AppendRadix(uint rem, uint radix, char[] tmp, StringBuilder buf, bool leadingZeros) {
1516
const string symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1518
int digits = tmp.Length;
1520
while (i > 0 && (leadingZeros || rem != 0)) {
1521
uint digit = rem % radix;
1523
tmp[--i] = symbols[(int)digit];
1525
if (leadingZeros) buf.Append(tmp);
1526
else buf.Append(tmp, i, digits - i);
1529
public override int GetHashCode() {
1530
if (data.Length == 0) return 0;
1531
// HashCode must be same as int for values in the range of a single int
1533
return -(int)data[0];
1535
return (int)data[0];
1538
public override bool Equals(object obj) {
1539
BigInteger o = obj as BigInteger;
1540
if (object.ReferenceEquals(o, null)) return false;
1544
public bool IsNegative() {
1548
public bool IsZero() {
1552
public bool IsPositive() {
1556
private bool IsOdd() {
1557
// must have the lowest-order bit set to 1
1558
return (data != null && data.Length > 0 && ((data[0] & 1) != 0));
1561
#region IComparable Members
1563
public int CompareTo(object obj) {
1567
BigInteger o = obj as BigInteger;
1568
if (object.ReferenceEquals(o, null)) {
1569
throw new ArgumentException(MathResources.ExpectedInteger);
1571
return Compare(this, o);
1576
#region IConvertible Members
1578
public TypeCode GetTypeCode() {
1579
return TypeCode.Object;
1582
public bool ToBoolean(IFormatProvider provider) {
1583
return this != Zero;
1586
public byte ToByte(IFormatProvider provider) {
1588
if (AsUInt32(out ret) && (ret & ~0xFF) == 0) {
1591
throw new OverflowException(MathResources.BigIntWontFitByte);
1595
/// Return the value of this BigInteger as a little-endian twos-complement
1596
/// byte array, using the fewest number of bytes possible. If the value is zero,
1597
/// return an array of one byte whose element is 0x00.
1599
public byte[] ToByteArray() {
1600
// We could probably make this more efficient by eliminating one of the passes.
1601
// The current code does one pass for uint array -> byte array conversion,
1602
// and then a another pass to remove unneeded bytes at the top of the array.
1603
if (0 == sign) return new byte[] { 0 };
1609
dwords = (uint[])this.data.Clone();
1610
makeTwosComplement(dwords);
1617
byte[] bytes = new byte[4 * dwords.Length];
1620
for (int i = 0; i < dwords.Length; i++) {
1622
for (int j = 0; j < 4; j++) {
1623
bytes[curByte++] = (byte)(dword & 0xff);
1628
// find highest significant byte
1630
for (msb = bytes.Length - 1; msb > 0; msb--) {
1631
if (bytes[msb] != highByte) break;
1633
// ensure high bit is 0 if positive, 1 if negative
1634
bool needExtraByte = (bytes[msb] & 0x80) != (highByte & 0x80);
1636
byte[] trimmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
1637
Array.Copy(bytes, trimmedBytes, msb + 1);
1639
if (needExtraByte) trimmedBytes[trimmedBytes.Length - 1] = highByte;
1641
return trimmedBytes;
1644
public char ToChar(IFormatProvider provider) {
1646
if (AsInt32(out ret) && (ret <= Char.MaxValue) && (ret >= Char.MinValue)) {
1649
throw new OverflowException(MathResources.BigIntWontFitChar);
1652
public DateTime ToDateTime(IFormatProvider provider) {
1653
throw new NotImplementedException();
1656
public decimal ToDecimal(IFormatProvider provider) {
1658
if (AsDecimal(out ret)) return ret;
1659
throw new OverflowException(MathResources.BigIntWontFitDecimal);
1662
public double ToDouble(IFormatProvider provider) {
1666
public short ToInt16(IFormatProvider provider) {
1668
if (AsInt32(out ret) && (ret <= short.MaxValue) && (ret >= short.MinValue)) {
1671
throw new OverflowException(MathResources.BigIntWontFitShort);
1674
public int ToInt32(IFormatProvider provider) {
1676
if (AsInt32(out ret)) {
1679
throw new OverflowException(MathResources.BigIntWontFitInt);
1682
public long ToInt64(IFormatProvider provider) {
1684
if (AsInt64(out ret)) {
1687
throw new OverflowException(MathResources.BigIntWontFitLong);
1690
[CLSCompliant(false)]
1691
public sbyte ToSByte(IFormatProvider provider) {
1693
if (AsInt32(out ret) && (ret <= sbyte.MaxValue) && (ret >= sbyte.MinValue)) {
1696
throw new OverflowException(MathResources.BigIntWontFitSByte);
1699
public float ToSingle(IFormatProvider provider) {
1700
return checked((float)ToDouble(provider));
1703
public string ToString(IFormatProvider provider) {
1707
public object ToType(Type conversionType, IFormatProvider provider) {
1708
if (conversionType == typeof(BigInteger)) {
1711
throw new NotImplementedException();
1714
[CLSCompliant(false)]
1715
public ushort ToUInt16(IFormatProvider provider) {
1717
if (AsUInt32(out ret) && ret <= ushort.MaxValue) {
1720
throw new OverflowException(MathResources.BigIntWontFitUShort);
1723
[CLSCompliant(false)]
1724
public uint ToUInt32(IFormatProvider provider) {
1726
if (AsUInt32(out ret)) {
1729
throw new OverflowException(MathResources.BigIntWontFitUInt);
1732
[CLSCompliant(false)]
1733
public ulong ToUInt64(IFormatProvider provider) {
1735
if (AsUInt64(out ret)) {
1738
throw new OverflowException(MathResources.BigIntWontFitULong);
1743
#region IFormattable Members
1745
string IFormattable.ToString(string format, IFormatProvider formatProvider) {
1746
if (format == null) return this.ToString();
1748
switch (format[0]) {
1751
if (format.Length > 1) {
1752
int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
1753
string baseStr = ToString(10);
1754
if (baseStr.Length < precision) {
1755
string additional = new String('0', precision - baseStr.Length);
1756
if (baseStr[0] != '-') {
1757
return additional + baseStr;
1759
return "-" + additional + baseStr.Substring(1);
1764
return ToString(10);
1767
StringBuilder res = new StringBuilder(ToString(16));
1768
if (format[0] == 'x') {
1769
for (int i = 0; i < res.Length; i++) {
1770
if (res[i] >= 'A' && res[i] <= 'F') {
1771
res[i] = Char.ToLowerInvariant(res[i]);
1776
if (format.Length > 1) {
1777
int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
1778
if (res.Length < precision) {
1779
string additional = new String('0', precision - res.Length);
1780
if (res[0] != '-') {
1781
res.Insert(0, additional);
1783
res.Insert(1, additional);
1788
return res.ToString();
1790
throw new NotImplementedException(MathResources.FormatNotImplemented);