aboutsummaryrefslogtreecommitdiff
path: root/runtime/VMProtect.Runtime/Numerics
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/VMProtect.Runtime/Numerics')
-rw-r--r--runtime/VMProtect.Runtime/Numerics/BigInteger.cs2012
-rw-r--r--runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs1529
-rw-r--r--runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs425
3 files changed, 3966 insertions, 0 deletions
diff --git a/runtime/VMProtect.Runtime/Numerics/BigInteger.cs b/runtime/VMProtect.Runtime/Numerics/BigInteger.cs
new file mode 100644
index 0000000..b124460
--- /dev/null
+++ b/runtime/VMProtect.Runtime/Numerics/BigInteger.cs
@@ -0,0 +1,2012 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+/*=============================================================================
+**
+** Struct: BigInteger
+**
+** Purpose: Represents an arbitrary precision integer.
+**
+=============================================================================*/
+
+using System;
+
+using Contracts = System.Diagnostics.Debug;
+using Contract = System.Diagnostics.Debug;
+//using System.Globalization;
+// ReSharper disable InconsistentNaming
+
+// ReSharper disable once CheckNamespace
+namespace Numerics
+{
+#if !SILVERLIGHT
+ [Serializable]
+#endif // !SILVERLIGHT
+ internal struct BigInteger /*: IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>*/
+ {
+ // ---- SECTION: members supporting exposed properties -------------*
+ #region members supporting exposed properties
+ private const uint kuMaskHighBit = unchecked((uint)int.MinValue);
+ private const int kcbitUint = 32;
+ //private const int kcbitUlong = 64;
+ //private const int DecimalScaleFactorMask = 0x00FF0000;
+ //private const int DecimalSignMask = unchecked((int)0x80000000);
+
+ // For values int.MinValue < n <= int.MaxValue, the value is stored in sign
+ // and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits
+ private readonly int _sign;
+ private readonly uint[] _bits;
+
+ // We have to make a choice of how to represent int.MinValue. This is the one
+ // value that fits in an int, but whose negation does not fit in an int.
+ // We choose to use a large representation, so we're symmetric with respect to negation.
+ private static readonly BigInteger s_bnMinInt = new BigInteger(-1, new[] { kuMaskHighBit });
+ private static readonly BigInteger s_bnOneInt = new BigInteger(1);
+ private static readonly BigInteger s_bnZeroInt = new BigInteger(0);
+ private static readonly BigInteger s_bnMinusOneInt = new BigInteger(-1);
+
+#if CONTRACTS_FULL
+ [ContractInvariantMethod]
+ private void ObjectInvariant()
+ {
+ Contract.Invariant((_bits == null) ? _sign > Int32.MinValue :
+ ((_sign == 1 || _sign == -1) && Length(_bits) > 0));
+ Contract.Invariant(_bits == null || Length(_bits) > 1 || _bits[0] >= kuMaskHighBit
+ , "One element array stores integers whose absolute value is between 0x80000000 and 0xFFFFFFFF");
+ }
+#endif
+
+ [System.Diagnostics.Conditional("DEBUG")]
+ private void AssertValid()
+ {
+ if (_bits != null)
+ {
+ Contracts.Assert(_sign == 1 || _sign == -1 /*, "_sign must be +1 or -1 when _bits is non-null"*/);
+ Contracts.Assert(Length(_bits) > 0 /*, "_bits must contain at least 1 element or be null"*/);
+ if (Length(_bits) == 1)
+ Contracts.Assert(_bits[0] >= kuMaskHighBit /*, "Wasted space _bits[0] could have been packed into _sign"*/);
+ }
+ else
+ Contracts.Assert(_sign > int.MinValue /*, "Int32.MinValue should not be stored in the _sign field"*/);
+ }
+ #endregion members supporting exposed properties
+
+ // ---- SECTION: internal properties --------------*
+ #region internal properties
+
+ /*internal static BigInteger Zero
+ {
+ get { return s_bnZeroInt; }
+ }*/
+
+ private static BigInteger One
+ {
+ get { return s_bnOneInt; }
+ }
+
+/*
+ internal static BigInteger MinusOne
+ {
+ get { return s_bnMinusOneInt; }
+ }
+
+ internal bool IsPowerOfTwo
+ {
+ get
+ {
+ AssertValid();
+
+ if (_bits == null)
+ return (_sign & (_sign - 1)) == 0 && _sign != 0;
+
+ if (_sign != 1)
+ return false;
+ int iu = Length(_bits) - 1;
+ if ((_bits[iu] & (_bits[iu] - 1)) != 0)
+ return false;
+ while (--iu >= 0)
+ {
+ if (_bits[iu] != 0)
+ return false;
+ }
+ return true;
+ }
+ }
+*/
+
+/*
+ internal bool IsZero { get { AssertValid(); return _sign == 0; } }
+*/
+
+/*
+ internal bool IsOne { get { AssertValid(); return _sign == 1 && _bits == null; } }
+*/
+
+ private bool IsEven { get { AssertValid(); return _bits == null ? (_sign & 1) == 0 : (_bits[0] & 1) == 0; } }
+
+ private int Sign
+ {
+ get { AssertValid(); return (_sign >> (kcbitUint - 1)) - (-_sign >> (kcbitUint - 1)); }
+ }
+
+ #endregion internal properties
+
+
+ // ---- SECTION: internal instance methods --------------*
+ #region internal instance methods
+
+ public override bool Equals(object obj)
+ {
+ AssertValid();
+
+ if (!(obj is BigInteger))
+ return false;
+ return Equals((BigInteger)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ AssertValid();
+
+ // ReSharper disable NonReadonlyMemberInGetHashCode
+ if (_bits == null)
+ return _sign;
+ var hash = _sign;
+ for (var iv = Length(_bits); --iv >= 0; )
+ hash = NumericsHelpers.CombineHash(hash, (int)_bits[iv]);
+ return hash;
+ }
+
+ /*public bool Equals(Int64 other)
+ {
+ AssertValid();
+
+ if (_bits == null)
+ return _sign == other;
+
+ int cu;
+ if ((_sign ^ other) < 0 || (cu = Length(_bits)) > 2)
+ return false;
+
+ var uu = other < 0 ? (ulong)-other : (ulong)other;
+ if (cu == 1)
+ return _bits[0] == uu;
+
+ return NumericsHelpers.MakeUlong(_bits[1], _bits[0]) == uu;
+ }
+
+ public bool Equals(UInt64 other)
+ {
+ AssertValid();
+
+ if (_sign < 0)
+ return false;
+ if (_bits == null)
+ return (ulong)_sign == other;
+
+ var cu = Length(_bits);
+ if (cu > 2)
+ return false;
+ if (cu == 1)
+ return _bits[0] == other;
+ return NumericsHelpers.MakeUlong(_bits[1], _bits[0]) == other;
+ }*/
+
+ /*public bool Equals(BigInteger other)
+ {
+ AssertValid();
+ other.AssertValid();
+
+ if (_sign != other._sign)
+ return false;
+ if (_bits == other._bits)
+ // _sign == other._sign && _bits == null && other._bits == null
+ return true;
+
+ if (_bits == null || other._bits == null)
+ return false;
+ var cu = Length(_bits);
+ if (cu != Length(other._bits))
+ return false;
+ var cuDiff = GetDiffLength(_bits, other._bits, cu);
+ return cuDiff == 0;
+ }*/
+
+ /*internal int CompareTo(Int64 other)
+ {
+ AssertValid();
+
+ if (_bits == null)
+ return ((long)_sign).CompareTo(other);
+ int cu;
+ if ((_sign ^ other) < 0 || (cu = Length(_bits)) > 2)
+ return _sign;
+ var uu = other < 0 ? (ulong)-other : (ulong)other;
+ var uuTmp = cu == 2 ? NumericsHelpers.MakeUlong(_bits[1], _bits[0]) : _bits[0];
+ return _sign * uuTmp.CompareTo(uu);
+ }
+
+ internal int CompareTo(UInt64 other)
+ {
+ AssertValid();
+
+ if (_sign < 0)
+ return -1;
+ if (_bits == null)
+ return ((ulong)_sign).CompareTo(other);
+ var cu = Length(_bits);
+ if (cu > 2)
+ return +1;
+ var uuTmp = cu == 2 ? NumericsHelpers.MakeUlong(_bits[1], _bits[0]) : _bits[0];
+ return uuTmp.CompareTo(other);
+ }*/
+
+ private int CompareTo(BigInteger other)
+ {
+ AssertValid();
+ other.AssertValid();
+
+ if ((_sign ^ other._sign) < 0)
+ {
+ // Different signs, so the comparison is easy.
+ return _sign < 0 ? -1 : +1;
+ }
+
+ // Same signs
+ if (_bits == null)
+ {
+ if (other._bits == null)
+ return _sign < other._sign ? -1 : _sign > other._sign ? +1 : 0;
+ return -other._sign;
+ }
+ int cuThis, cuOther;
+ if (other._bits == null || (cuThis = Length(_bits)) > (cuOther = Length(other._bits)))
+ return _sign;
+ if (cuThis < cuOther)
+ return -_sign;
+
+ var cuDiff = GetDiffLength(_bits, other._bits, cuThis);
+ if (cuDiff == 0)
+ return 0;
+ return _bits[cuDiff - 1] < other._bits[cuDiff - 1] ? -_sign : _sign;
+ }
+
+/*
+ public int CompareTo(Object obj)
+ {
+ if (obj == null)
+ return 1;
+ if (!(obj is BigInteger))
+ throw new ArgumentException("Argument must be BigInteger", "obj");
+ return CompareTo((BigInteger)obj);
+ }
+*/
+
+
+ // Return the value of this BigInteger as a little-endian twos-complement
+ // byte array, using the fewest number of bytes possible. If the value is zero,
+ // return an array of one byte whose element is 0x00.
+ internal byte[] ToByteArray()
+ {
+ if (_bits == null && _sign == 0)
+ return new byte[] { 0 };
+
+ // We could probably make this more efficient by eliminating one of the passes.
+ // The current code does one pass for uint array -> byte array conversion,
+ // and then another pass to remove unneeded bytes at the top of the array.
+ uint[] dwords;
+ byte highByte;
+
+ if (_bits == null)
+ {
+ dwords = new[] { (uint)_sign };
+ highByte = (byte)(_sign < 0 ? 0xff : 0x00);
+ }
+ else if (_sign == -1)
+ {
+ dwords = (uint[])_bits.Clone();
+ NumericsHelpers.DangerousMakeTwosComplement(dwords); // mutates dwords
+ highByte = 0xff;
+ }
+ else
+ {
+ dwords = _bits;
+ highByte = 0x00;
+ }
+
+ var bytes = new byte[checked(4 * dwords.Length)];
+ var curByte = 0;
+ foreach (var t in dwords)
+ {
+ var dword = t;
+ for (var j = 0; j < 4; j++)
+ {
+ bytes[curByte++] = (byte)(dword & 0xff);
+ dword >>= 8;
+ }
+ }
+
+ // ensure high bit is 0 if positive, 1 if negative
+ if ((bytes[bytes.Length - 1] & 0x80) == (highByte & 0x80))
+ return bytes;
+
+ var trimmedBytes = new byte[bytes.Length + 1];
+ Array.Copy(bytes, trimmedBytes, bytes.Length);
+ trimmedBytes[trimmedBytes.Length - 1] = highByte;
+ return trimmedBytes;
+ }
+
+ // Return the value of this BigInteger as a little-endian twos-complement
+ // uint array, using the fewest number of uints possible. If the value is zero,
+ // return an array of one uint whose element is 0.
+/*
+ private UInt32[] ToUInt32Array()
+ {
+ if (_bits == null && _sign == 0)
+ return new uint[] { 0 };
+
+ uint[] dwords;
+ uint highDWord;
+
+ if (_bits == null)
+ {
+ dwords = new[] { (uint)_sign };
+ highDWord = _sign < 0 ? UInt32.MaxValue : 0;
+ }
+ else if (_sign == -1)
+ {
+ dwords = (uint[])_bits.Clone();
+ NumericsHelpers.DangerousMakeTwosComplement(dwords); // mutates dwords
+ highDWord = UInt32.MaxValue;
+ }
+ else
+ {
+ dwords = _bits;
+ highDWord = 0;
+ }
+
+ // find highest significant byte
+ int msb;
+ for (msb = dwords.Length - 1; msb > 0; msb--)
+ {
+ if (dwords[msb] != highDWord) break;
+ }
+ // ensure high bit is 0 if positive, 1 if negative
+ var needExtraByte = (dwords[msb] & 0x80000000) != (highDWord & 0x80000000);
+
+ var trimmed = new uint[msb + 1 + (needExtraByte ? 1 : 0)];
+ Array.Copy(dwords, trimmed, msb + 1);
+
+ if (needExtraByte) trimmed[trimmed.Length - 1] = highDWord;
+ return trimmed;
+ }
+*/
+
+ /*public override String ToString()
+ {
+ return BigNumber.FormatBigInteger(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ internal String ToString(IFormatProvider provider)
+ {
+ return BigNumber.FormatBigInteger(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ internal String ToString(String format)
+ {
+ return BigNumber.FormatBigInteger(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider)
+ {
+ return BigNumber.FormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider));
+ }*/
+ #endregion internal instance methods
+
+ // -------- SECTION: constructors -----------------*
+ #region constructors
+
+ private BigInteger(int value)
+ {
+ if (value == Int32.MinValue)
+ this = s_bnMinInt;
+ else
+ {
+ _sign = value;
+ _bits = null;
+ }
+ AssertValid();
+ }
+
+/*
+ internal BigInteger(uint value)
+ {
+ if (value <= Int32.MaxValue)
+ {
+ _sign = (int)value;
+ _bits = null;
+ }
+ else
+ {
+ _sign = +1;
+ _bits = new uint[1];
+ _bits[0] = value;
+ }
+ AssertValid();
+ }
+*/
+
+/*
+ internal BigInteger(Int64 value)
+ {
+ if (Int32.MinValue <= value && value <= Int32.MaxValue)
+ {
+ if (value == Int32.MinValue)
+ this = s_bnMinInt;
+ else
+ {
+ _sign = (int)value;
+ _bits = null;
+ }
+ AssertValid();
+ return;
+ }
+
+ ulong x;
+ if (value < 0)
+ {
+ x = (ulong)-value;
+ _sign = -1;
+ }
+ else
+ {
+ Contract.Assert(value != 0);
+ x = (ulong)value;
+ _sign = +1;
+ }
+
+ _bits = new uint[2];
+ _bits[0] = (uint)x;
+ _bits[1] = (uint)(x >> kcbitUint);
+ AssertValid();
+ }
+*/
+
+/*
+ internal BigInteger(UInt64 value)
+ {
+ if (value <= Int32.MaxValue)
+ {
+ _sign = (int)value;
+ _bits = null;
+ }
+ else
+ {
+ _sign = +1;
+ _bits = new uint[2];
+ _bits[0] = (uint)value;
+ _bits[1] = (uint)(value >> kcbitUint);
+ }
+ AssertValid();
+ }
+*/
+
+ /*internal BigInteger(Single value)
+ {
+ if (Single.IsInfinity(value))
+ throw new OverflowException("Overflow BigIntInfinity");
+ if (Single.IsNaN(value))
+ throw new OverflowException("Overflow not a number");
+ ////Contract.EndContractBlock();
+
+ _sign = 0;
+ _bits = null;
+ // ReSharper disable once ExpressionIsAlwaysNull
+ SetBitsFromDouble(value);
+ AssertValid();
+ }
+
+ internal BigInteger(Double value)
+ {
+ if (Double.IsInfinity(value))
+ throw new OverflowException("Overflow BigIntInfinity");
+ if (Double.IsNaN(value))
+ throw new OverflowException("Overflow not a number");
+ ////Contract.EndContractBlock();
+
+ _sign = 0;
+ _bits = null;
+ // ReSharper disable once ExpressionIsAlwaysNull
+ SetBitsFromDouble(value);
+ AssertValid();
+ }*/
+
+ /*internal BigInteger(Decimal value)
+ {
+ // First truncate to get scale to 0 and extract bits
+ var bits = Decimal.GetBits(Decimal.Truncate(value));
+
+ Contract.Assert(bits.Length == 4 && (bits[3] & DecimalScaleFactorMask) == 0);
+
+ var size = 3;
+ while (size > 0 && bits[size - 1] == 0)
+ size--;
+ if (size == 0)
+ {
+ this = s_bnZeroInt;
+ }
+ else if (size == 1 && bits[0] > 0)
+ {
+ // bits[0] is the absolute value of this decimal
+ // if bits[0] < 0 then it is too large to be packed into _sign
+ _sign = bits[0];
+ _sign *= (bits[3] & DecimalSignMask) != 0 ? -1 : +1;
+ _bits = null;
+ }
+ else
+ {
+ _bits = new UInt32[size];
+ _bits[0] = (UInt32)bits[0];
+ if (size > 1)
+ _bits[1] = (UInt32)bits[1];
+ if (size > 2)
+ _bits[2] = (UInt32)bits[2];
+ _sign = (bits[3] & DecimalSignMask) != 0 ? -1 : +1;
+ }
+ AssertValid();
+ }*/
+
+ //
+ // Create a BigInteger from a little-endian twos-complement byte array
+ //
+ internal BigInteger(Byte[] value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ //Contract.EndContractBlock();
+
+ var byteCount = value.Length;
+ var isNegative = byteCount > 0 && ((value[byteCount - 1] & 0x80) == 0x80);
+
+ // Try to conserve space as much as possible by checking for wasted leading byte[] entries
+ while (byteCount > 0 && value[byteCount - 1] == 0) byteCount--;
+
+ if (byteCount == 0)
+ {
+ // BigInteger.Zero
+ _sign = 0;
+ _bits = null;
+ // ReSharper disable once ExpressionIsAlwaysNull
+ AssertValid();
+ return;
+ }
+
+
+ if (byteCount <= 4)
+ {
+ if (isNegative)
+ _sign = unchecked((int)0xffffffff);
+ else
+ _sign = 0;
+ for (var i = byteCount - 1; i >= 0; i--)
+ {
+ _sign <<= 8;
+ _sign |= value[i];
+ }
+ _bits = null;
+
+ if (_sign < 0 && !isNegative)
+ {
+ // int32 overflow
+ // example: Int64 value 2362232011 (0xCB, 0xCC, 0xCC, 0x8C, 0x0)
+ // can be naively packed into 4 bytes (due to the leading 0x0)
+ // it overflows into the int32 sign bit
+ _bits = new uint[1];
+ _bits[0] = (uint)_sign;
+ _sign = +1;
+ }
+ if (_sign == Int32.MinValue)
+ this = s_bnMinInt;
+ }
+ else
+ {
+ var unalignedBytes = byteCount % 4;
+ var dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
+ var isZero = true;
+ var val = new uint[dwordCount];
+
+ // Copy all dwords, except but don't do the last one if it's not a full four bytes
+ int curDword;
+ var curByte = 3;
+ for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++)
+ {
+ var byteInDword = 0;
+ while (byteInDword < 4)
+ {
+ if (value[curByte] != 0x00) isZero = false;
+ val[curDword] <<= 8;
+ val[curDword] |= value[curByte];
+ curByte--;
+ byteInDword++;
+ }
+ curByte += 8;
+ }
+
+ // Copy the last dword specially if it's not aligned
+ if (unalignedBytes != 0)
+ {
+ if (isNegative) val[dwordCount - 1] = 0xffffffff;
+ for (curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--)
+ {
+ if (value[curByte] != 0x00) isZero = false;
+ val[curDword] <<= 8;
+ val[curDword] |= value[curByte];
+ }
+ }
+
+ if (isZero)
+ {
+ this = s_bnZeroInt;
+ }
+ else if (isNegative)
+ {
+ NumericsHelpers.DangerousMakeTwosComplement(val); // mutates val
+
+ // pack _bits to remove any wasted space after the twos complement
+ var len = val.Length;
+ while (len > 0 && val[len - 1] == 0)
+ len--;
+ if (len == 1 && (int)val[0] > 0)
+ {
+ if (val[0] == 1 /* abs(-1) */)
+ {
+ this = s_bnMinusOneInt;
+ }
+ else if (val[0] == kuMaskHighBit /* abs(Int32.MinValue) */) //TODO: V3022 https://www.viva64.com/en/w/V3022 Expression 'val[0] == kuMaskHighBit' is always false.
+ {
+ this = s_bnMinInt;
+ }
+ else
+ {
+ _sign = -1 * (int)val[0];
+ _bits = null;
+ }
+ }
+ else if (len != val.Length)
+ {
+ _sign = -1;
+ _bits = new uint[len];
+ Array.Copy(val, _bits, len);
+ }
+ else
+ {
+ _sign = -1;
+ _bits = val;
+ }
+ }
+ else
+ {
+ _sign = +1;
+ _bits = val;
+ }
+ }
+ AssertValid();
+ }
+
+ internal BigInteger(int n, uint[] rgu)
+ {
+ _sign = n;
+ _bits = rgu;
+ AssertValid();
+ }
+
+ //
+ // BigInteger(uint[] value, bool negative)
+ //
+ // Constructor used during bit manipulation and arithmetic
+ //
+ // The uint[] value is expected to be the absolute value of the number
+ // with the bool negative indicating the Sign of the value.
+ //
+ // When possible the uint[] will be packed into _sign to conserve space
+ //
+/*
+ internal BigInteger(uint[] value, bool negative)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ //Contract.EndContractBlock();
+
+ int len;
+
+ // Try to conserve space as much as possible by checking for wasted leading uint[] entries
+ // sometimes the uint[] has leading zeros from bit manipulation operations & and ^
+ for (len = value.Length; len > 0 && value[len - 1] == 0; len--)
+ {
+ }
+
+ if (len == 0)
+ this = s_bnZeroInt;
+ // values like (Int32.MaxValue+1) are stored as "0x80000000" and as such cannot be packed into _sign
+ else if (len == 1 && value[0] < kuMaskHighBit)
+ {
+ _sign = negative ? -(int)value[0] : (int)value[0];
+ _bits = null;
+ // Although Int32.MinValue fits in _sign, we represent this case differently for negate
+ if (_sign == Int32.MinValue)
+ this = s_bnMinInt;
+ }
+ else
+ {
+ _sign = negative ? -1 : +1;
+ _bits = new uint[len];
+ Array.Copy(value, _bits, len);
+ }
+ AssertValid();
+ }
+*/
+
+
+ //
+ // Create a BigInteger from a little-endian twos-complement UInt32 array
+ // When possible, value is assigned directly to this._bits without an array copy
+ // so use this ctor with care
+ //
+// private BigInteger(uint[] value)
+// {
+// if (value == null)
+// throw new ArgumentNullException("value");
+//
+// var dwordCount = value.Length;
+// var isNegative = dwordCount > 0 && ((value[dwordCount - 1] & 0x80000000) == 0x80000000);
+//
+// // Try to conserve space as much as possible by checking for wasted leading uint[] entries
+// while (dwordCount > 0 && value[dwordCount - 1] == 0) dwordCount--;
+//
+// if (dwordCount == 0)
+// {
+// // BigInteger.Zero
+// this = s_bnZeroInt;
+// AssertValid();
+// return;
+// }
+// if (dwordCount == 1)
+// {
+// if ((int)value[0] < 0 && !isNegative)
+// {
+// _bits = new uint[1];
+// _bits[0] = value[0];
+// _sign = +1;
+// }
+// // handle the special cases where the BigInteger likely fits into _sign
+// else if (Int32.MinValue == (int)value[0])
+// {
+// this = s_bnMinInt;
+// }
+// else
+// {
+// _sign = (int)value[0];
+// _bits = null;
+// }
+// AssertValid();
+// return;
+// }
+//
+// if (!isNegative)
+// {
+// // handle the simple postive value cases where the input is already in sign magnitude
+// if (dwordCount != value.Length)
+// {
+// _sign = +1;
+// _bits = new uint[dwordCount];
+// Array.Copy(value, _bits, dwordCount);
+// }
+// // no trimming is possible. Assign value directly to _bits.
+// else
+// {
+// _sign = +1;
+// _bits = value;
+// }
+// AssertValid();
+// return;
+// }
+//
+//
+// // finally handle the more complex cases where we must transform the input into sign magnitude
+// NumericsHelpers.DangerousMakeTwosComplement(value); // mutates val
+//
+// // pack _bits to remove any wasted space after the twos complement
+// var len = value.Length;
+// while (len > 0 && value[len - 1] == 0) len--;
+//
+// // the number is represented by a single dword
+// if (len == 1 && (int)value[0] > 0)
+// {
+// if (value[0] == 1 /* abs(-1) */)
+// {
+// this = s_bnMinusOneInt;
+// }
+// else if (value[0] == kuMaskHighBit /* abs(Int32.MinValue) */)
+// {
+// this = s_bnMinInt;
+// }
+// else
+// {
+// _sign = -1 * (int)value[0];
+// _bits = null;
+// }
+// }
+// // the number is represented by multiple dwords
+// // trim off any wasted uint values when possible
+// else if (len != value.Length)
+// {
+// _sign = -1;
+// _bits = new uint[len];
+// Array.Copy(value, _bits, len);
+// }
+// // no trimming is possible. Assign value directly to _bits.
+// else
+// {
+// _sign = -1;
+// _bits = value;
+// }
+// AssertValid();
+// }
+
+
+ #endregion constructors
+
+
+ // -------- SECTION: internal static methods -----------------*
+ #region internal static methods
+#if !SILVERLIGHT || FEATURE_NETCORE
+/*
+ internal static BigInteger Parse(String value)
+ {
+ return BigNumber.ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+*/
+
+/*
+ internal static BigInteger Parse(String value, NumberStyles style)
+ {
+ return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.CurrentInfo);
+ }
+*/
+
+/*
+ internal static BigInteger Parse(String value, IFormatProvider provider)
+ {
+ return BigNumber.ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+*/
+
+/*
+ internal static BigInteger Parse(String value, NumberStyles style, IFormatProvider provider)
+ {
+ return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider));
+ }
+*/
+
+/*
+ internal static Boolean TryParse(String value, out BigInteger result)
+ {
+ return BigNumber.TryParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+*/
+
+/*
+ internal static Boolean TryParse(String value, NumberStyles style, IFormatProvider provider, out BigInteger result)
+ {
+ return BigNumber.TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+*/
+#endif //!SILVERLIGHT || FEATURE_NETCORE
+
+/*
+ internal static Int32 Compare(BigInteger left, BigInteger right)
+ {
+ return left.CompareTo(right);
+ }
+*/
+
+/*
+ internal static BigInteger Abs(BigInteger value)
+ {
+ return value >= Zero ? value : -value;
+ }
+*/
+
+/*
+ internal static BigInteger Add(BigInteger left, BigInteger right)
+ {
+ return left + right;
+ }
+*/
+
+/*
+ internal static BigInteger Subtract(BigInteger left, BigInteger right)
+ {
+ return left - right;
+ }
+*/
+
+/*
+ internal static BigInteger Multiply(BigInteger left, BigInteger right)
+ {
+ return left * right;
+ }
+*/
+
+/*
+ internal static BigInteger Divide(BigInteger dividend, BigInteger divisor)
+ {
+ return dividend / divisor;
+ }
+*/
+
+/*
+ internal static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
+ {
+ return dividend % divisor;
+ }
+*/
+
+/*
+ internal static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
+ {
+ dividend.AssertValid();
+ divisor.AssertValid();
+
+ var signNum = +1;
+ var signDen = +1;
+ var regNum = new BigIntegerBuilder(dividend, ref signNum);
+ var regDen = new BigIntegerBuilder(divisor, ref signDen);
+ var regQuo = new BigIntegerBuilder();
+
+ // regNum and regQuo are overwritten with the remainder and quotient, respectively
+ regNum.ModDiv(ref regDen, ref regQuo);
+ remainder = regNum.GetInteger(signNum);
+ return regQuo.GetInteger(signNum * signDen);
+ }
+*/
+
+
+/*
+ internal static BigInteger Negate(BigInteger value)
+ {
+ return -value;
+ }
+*/
+
+ // Returns the natural (base e) logarithm of a specified number.
+/*
+ internal static Double Log(BigInteger value, Double baseValue = Math.E)
+ {
+ // ReSharper disable CompareOfFloatsByEqualityOperator
+ if (value._sign < 0 || baseValue == 1.0D)
+ return Double.NaN;
+ if (baseValue == Double.PositiveInfinity)
+ return value.IsOne ? 0.0D : Double.NaN;
+ if (baseValue == 0.0D && !value.IsOne)
+ return Double.NaN;
+ if (value._bits == null)
+ return Math.Log(value._sign, baseValue);
+ // ReSharper restore CompareOfFloatsByEqualityOperator
+
+ Double c = 0, d = 0.5D;
+ const Double log2 = 0.69314718055994529D;
+
+ var uintLength = Length(value._bits);
+ var topbits = BitLengthOfUInt(value._bits[uintLength - 1]);
+ var bitlen = (uintLength - 1) * kcbitUint + topbits;
+ var indbit = (uint)(1 << (topbits - 1));
+
+ for (var index = uintLength - 1; index >= 0; --index)
+ {
+ while (indbit != 0)
+ {
+ if ((value._bits[index] & indbit) != 0)
+ c += d;
+ d *= 0.5;
+ indbit >>= 1;
+ }
+ indbit = 0x80000000;
+ }
+ return (Math.Log(c) + log2 * bitlen) / Math.Log(baseValue);
+ }
+*/
+
+
+/*
+ internal static Double Log10(BigInteger value)
+ {
+ return Log(value, 10);
+ }
+*/
+
+/*
+ internal static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)
+ {
+ left.AssertValid();
+ right.AssertValid();
+
+ // gcd(0, 0) = 0
+ // gcd(a, 0) = |a|, for a != 0, since any number is a divisor of 0, and the greatest divisor of a is |a|
+ if (left._sign == 0) return Abs(right);
+ if (right._sign == 0) return Abs(left);
+
+ var reg1 = new BigIntegerBuilder(left);
+ var reg2 = new BigIntegerBuilder(right);
+ BigIntegerBuilder.GCD(ref reg1, ref reg2);
+
+ return reg1.GetInteger(+1);
+ }
+*/
+
+/*
+ internal static BigInteger Max(BigInteger left, BigInteger right)
+ {
+ if (left.CompareTo(right) < 0)
+ return right;
+ return left;
+ }
+*/
+
+/*
+ internal static BigInteger Min(BigInteger left, BigInteger right)
+ {
+ if (left.CompareTo(right) <= 0)
+ return left;
+ return right;
+ }
+*/
+
+
+ private static void ModPowUpdateResult(ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
+ {
+ NumericsHelpers.Swap(ref regRes, ref regTmp);
+ regRes.Mul(ref regTmp, ref regVal); // result = result * value;
+ regRes.Mod(ref regMod); // result = result % modulus;
+ }
+
+ private static void ModPowSquareModValue(ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
+ {
+ NumericsHelpers.Swap(ref regVal, ref regTmp);
+ regVal.Mul(ref regTmp, ref regTmp); // value = value * value;
+ regVal.Mod(ref regMod); // value = value % modulus;
+ }
+
+ private static void ModPowInner(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
+ {
+ while (exp != 0) // !(Exponent.IsZero)
+ {
+ if ((exp & 1) == 1) // !(Exponent.IsEven)
+ ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
+ if (exp == 1) // Exponent.IsOne - we can exit early
+ break;
+ ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
+ exp >>= 1;
+ }
+ }
+
+ private static void ModPowInner32(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
+ {
+ for (var i = 0; i < 32; i++)
+ {
+ if ((exp & 1) == 1) // !(Exponent.IsEven)
+ ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
+ ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
+ exp >>= 1;
+ }
+ }
+
+ internal static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
+ {
+ if (exponent.Sign < 0)
+ throw new ArgumentOutOfRangeException("exponent", "ArgumentOutOfRange must be non negative");
+ //Contract.EndContractBlock();
+
+ value.AssertValid();
+ exponent.AssertValid();
+ modulus.AssertValid();
+
+ var signRes = +1;
+ var signVal = +1;
+ var signMod = +1;
+ var expIsEven = exponent.IsEven;
+ var regRes = new BigIntegerBuilder(One, ref signRes);
+ var regVal = new BigIntegerBuilder(value, ref signVal);
+ var regMod = new BigIntegerBuilder(modulus, ref signMod);
+ var regTmp = new BigIntegerBuilder(regVal.Size);
+
+ regRes.Mod(ref regMod); // Handle special case of exponent=0, modulus=1
+
+ if (exponent._bits == null)
+ { // exponent fits into an Int32
+ ModPowInner((uint)exponent._sign, ref regRes, ref regVal, ref regMod, ref regTmp);
+ }
+ else
+ { // very large exponent
+ var len = Length(exponent._bits);
+ for (var i = 0; i < len - 1; i++)
+ {
+ var exp = exponent._bits[i];
+ ModPowInner32(exp, ref regRes, ref regVal, ref regMod, ref regTmp);
+ }
+ ModPowInner(exponent._bits[len - 1], ref regRes, ref regVal, ref regMod, ref regTmp);
+ }
+
+ return regRes.GetInteger(value._sign > 0 ? +1 : expIsEven ? +1 : -1);
+ }
+
+/*
+ internal static BigInteger Pow(BigInteger value, Int32 exponent)
+ {
+ if (exponent < 0)
+ throw new ArgumentOutOfRangeException("exponent", "ArgumentOutOfRange must be non negative");
+ //Contract.EndContractBlock();
+
+ value.AssertValid();
+
+ if (exponent == 0)
+ return One;
+ if (exponent == 1)
+ return value;
+ if (value._bits == null)
+ {
+ if (value._sign == 1)
+ return value;
+ if (value._sign == -1)
+ return (exponent & 1) != 0 ? value : 1;
+ if (value._sign == 0)
+ return value;
+ }
+
+ var sign = +1;
+ var regSquare = new BigIntegerBuilder(value, ref sign);
+
+ // Get an estimate of the size needed for regSquare and regRes, so we can minimize allocations.
+ var cuSquareMin = regSquare.Size;
+ var cuSquareMax = cuSquareMin;
+ var uSquareMin = regSquare.High;
+ var uSquareMax = uSquareMin + 1;
+ if (uSquareMax == 0)
+ {
+ cuSquareMax++;
+ uSquareMax = 1;
+ }
+ var cuResMin = 1;
+ var cuResMax = 1;
+ uint uResMin = 1;
+ uint uResMax = 1;
+
+ for (var expTmp = exponent; ; )
+ {
+ if ((expTmp & 1) != 0)
+ {
+ MulUpper(ref uResMax, ref cuResMax, uSquareMax, cuSquareMax);
+ MulLower(ref uResMin, ref cuResMin, uSquareMin, cuSquareMin);
+ }
+
+ if ((expTmp >>= 1) == 0)
+ break;
+
+ MulUpper(ref uSquareMax, ref cuSquareMax, uSquareMax, cuSquareMax);
+ MulLower(ref uSquareMin, ref cuSquareMin, uSquareMin, cuSquareMin);
+ }
+
+ if (cuResMax > 1)
+ regSquare.EnsureWritable(cuResMax, 0);
+ var regTmp = new BigIntegerBuilder(cuResMax);
+ var regRes = new BigIntegerBuilder(cuResMax);
+ regRes.Set(1);
+
+ if ((exponent & 1) == 0)
+ sign = +1;
+
+ for (var expTmp = exponent; ; )
+ {
+ if ((expTmp & 1) != 0)
+ {
+ NumericsHelpers.Swap(ref regRes, ref regTmp);
+ regRes.Mul(ref regSquare, ref regTmp);
+ }
+ if ((expTmp >>= 1) == 0)
+ break;
+ NumericsHelpers.Swap(ref regSquare, ref regTmp);
+ regSquare.Mul(ref regTmp, ref regTmp);
+ }
+
+ return regRes.GetInteger(sign);
+ }
+*/
+
+ #endregion internal static methods
+
+ // -------- SECTION: internal static operators -----------------*
+ #region internal static operators
+ /*public static implicit operator BigInteger(Byte value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(SByte value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(Int16 value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(UInt16 value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(int value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(uint value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(long value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInteger(ulong value)
+ {
+ return new BigInteger(value);
+ }*/
+
+ /*public static explicit operator BigInteger(Single value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static explicit operator BigInteger(Double value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static explicit operator BigInteger(Decimal value)
+ {
+ return new BigInteger(value);
+ }
+
+ public static explicit operator Byte(BigInteger value)
+ {
+ return checked((byte)(int)value);
+ }
+
+ public static explicit operator SByte(BigInteger value)
+ {
+ return checked((sbyte)(int)value);
+ }
+
+ public static explicit operator Int16(BigInteger value)
+ {
+ return checked((short)(int)value);
+ }
+
+ public static explicit operator UInt16(BigInteger value)
+ {
+ return checked((ushort)(int)value);
+ }
+
+ public static explicit operator Int32(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ {
+ return value._sign; // value packed into int32 sign
+ }
+ else if (Length(value._bits) > 1)
+ { // more than 32 bits
+ throw new OverflowException("Overflow Int32");
+ }
+ else if (value._sign > 0)
+ {
+ return checked((int)value._bits[0]);
+ }
+ else
+ {
+ if (value._bits[0] > kuMaskHighBit)
+ { // value > Int32.MinValue
+ throw new OverflowException("Overflow Int32");
+ }
+ return unchecked(-(int)value._bits[0]);
+ }
+ }
+
+ public static explicit operator UInt32(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ {
+ return checked((uint)value._sign);
+ }
+ else if (Length(value._bits) > 1 || value._sign < 0)
+ {
+ throw new OverflowException("Overflow UInt32");
+ }
+ else
+ {
+ return value._bits[0];
+ }
+ }
+
+ public static explicit operator Int64(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ {
+ return value._sign;
+ }
+
+ var len = Length(value._bits);
+ if (len > 2)
+ {
+ throw new OverflowException("Overflow Int64");
+ }
+
+ var uu = len > 1 ? NumericsHelpers.MakeUlong(value._bits[1], value._bits[0]) : value._bits[0];
+
+ var ll = value._sign > 0 ? (long)uu : -(long)uu;
+ if ((ll > 0 && value._sign > 0) || (ll < 0 && value._sign < 0))
+ {
+ // signs match, no overflow
+ return ll;
+ }
+ throw new OverflowException("Overflow Int64");
+ }
+
+ public static explicit operator UInt64(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ {
+ return checked((ulong)value._sign);
+ }
+
+ var len = Length(value._bits);
+ if (len > 2 || value._sign < 0)
+ {
+ throw new OverflowException("Overflow UInt64");
+ }
+
+ if (len > 1)
+ {
+ return NumericsHelpers.MakeUlong(value._bits[1], value._bits[0]);
+ }
+ else
+ {
+ return value._bits[0];
+ }
+ }*/
+
+ /*public static explicit operator Single(BigInteger value)
+ {
+ return (Single)(Double)value;
+ }*/
+
+ /*public static explicit operator Double(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ return value._sign;
+
+ ulong man;
+ int exp;
+ var sign = +1;
+ var reg = new BigIntegerBuilder(value, ref sign);
+ reg.GetApproxParts(out exp, out man);
+ return NumericsHelpers.GetDoubleFromParts(sign, exp, man);
+ }
+
+ public static explicit operator Decimal(BigInteger value)
+ {
+ value.AssertValid();
+ if (value._bits == null)
+ return value._sign;
+
+ var length = Length(value._bits);
+ if (length > 3) throw new OverflowException("Overflow Decimal");
+
+ int lo = 0, mi = 0, hi = 0;
+ if (length > 2) hi = (Int32)value._bits[2];
+ if (length > 1) mi = (Int32)value._bits[1];
+ if (length > 0) lo = (Int32)value._bits[0];
+
+ return new Decimal(lo, mi, hi, value._sign < 0, 0);
+ }
+
+ public static BigInteger operator &(BigInteger left, BigInteger right)
+ {
+ if (left.IsZero || right.IsZero)
+ {
+ return Zero;
+ }
+
+ var x = left.ToUInt32Array();
+ var y = right.ToUInt32Array();
+ var z = new uint[Math.Max(x.Length, y.Length)];
+ var xExtend = left._sign < 0 ? UInt32.MaxValue : 0;
+ var yExtend = right._sign < 0 ? UInt32.MaxValue : 0;
+
+ for (var i = 0; i < z.Length; i++)
+ {
+ var xu = i < x.Length ? x[i] : xExtend;
+ var yu = i < y.Length ? y[i] : yExtend;
+ z[i] = xu & yu;
+ }
+ return new BigInteger(z);
+ }
+
+ public static BigInteger operator |(BigInteger left, BigInteger right)
+ {
+ if (left.IsZero)
+ return right;
+ if (right.IsZero)
+ return left;
+
+ var x = left.ToUInt32Array();
+ var y = right.ToUInt32Array();
+ var z = new uint[Math.Max(x.Length, y.Length)];
+ var xExtend = left._sign < 0 ? UInt32.MaxValue : 0;
+ var yExtend = right._sign < 0 ? UInt32.MaxValue : 0;
+
+ for (var i = 0; i < z.Length; i++)
+ {
+ var xu = i < x.Length ? x[i] : xExtend;
+ var yu = i < y.Length ? y[i] : yExtend;
+ z[i] = xu | yu;
+ }
+ return new BigInteger(z);
+ }
+
+ public static BigInteger operator ^(BigInteger left, BigInteger right)
+ {
+ var x = left.ToUInt32Array();
+ var y = right.ToUInt32Array();
+ var z = new uint[Math.Max(x.Length, y.Length)];
+ var xExtend = left._sign < 0 ? UInt32.MaxValue : 0;
+ var yExtend = right._sign < 0 ? UInt32.MaxValue : 0;
+
+ for (var i = 0; i < z.Length; i++)
+ {
+ var xu = i < x.Length ? x[i] : xExtend;
+ var yu = i < y.Length ? y[i] : yExtend;
+ z[i] = xu ^ yu;
+ }
+
+ return new BigInteger(z);
+ }
+
+ public static BigInteger operator <<(BigInteger value, int shift)
+ {
+
+ if (shift == 0) return value;
+ else if (shift == Int32.MinValue) return value >> Int32.MaxValue >> 1;
+ else if (shift < 0) return value >> -shift;
+
+ var digitShift = shift / kcbitUint;
+ var smallShift = shift - digitShift * kcbitUint;
+
+ uint[] xd; int xl;
+ var negx = GetPartsForBitManipulation(ref value, out xd, out xl);
+
+ var zl = xl + digitShift + 1;
+ var zd = new uint[zl];
+
+ if (smallShift == 0)
+ {
+ for (var i = 0; i < xl; i++)
+ {
+ zd[i + digitShift] = xd[i];
+ }
+ }
+ else
+ {
+ var carryShift = kcbitUint - smallShift;
+ uint carry = 0;
+ int i;
+ for (i = 0; i < xl; i++)
+ {
+ var rot = xd[i];
+ zd[i + digitShift] = rot << smallShift | carry;
+ carry = rot >> carryShift;
+ }
+ zd[i + digitShift] = carry;
+ }
+ return new BigInteger(zd, negx);
+ }
+
+ public static BigInteger operator >>(BigInteger value, int shift)
+ {
+ if (shift == 0) return value;
+ else if (shift == Int32.MinValue) return value << Int32.MaxValue << 1;
+ else if (shift < 0) return value << -shift;
+
+ var digitShift = shift / kcbitUint;
+ var smallShift = shift - digitShift * kcbitUint;
+
+ uint[] xd; int xl;
+ var negx = GetPartsForBitManipulation(ref value, out xd, out xl);
+
+ if (negx)
+ {
+ if (shift >= kcbitUint * xl)
+ {
+ return MinusOne;
+ }
+ var temp = new uint[xl];
+ Array.Copy(xd , temp , xl ); // make a copy of immutable value._bits
+ xd = temp;
+ NumericsHelpers.DangerousMakeTwosComplement(xd); // mutates xd
+ }
+
+ var zl = xl - digitShift;
+ if (zl < 0) zl = 0;
+ var zd = new uint[zl];
+
+ if (smallShift == 0)
+ {
+ for (var i = xl - 1; i >= digitShift; i--)
+ {
+ zd[i - digitShift] = xd[i];
+ }
+ }
+ else
+ {
+ var carryShift = kcbitUint - smallShift;
+ uint carry = 0;
+ for (var i = xl - 1; i >= digitShift; i--)
+ {
+ var rot = xd[i];
+ if (negx && i == xl - 1)
+ // sign-extend the first shift for negative ints then let the carry propagate
+ zd[i - digitShift] = (rot >> smallShift) | (0xFFFFFFFF << carryShift);
+ else
+ zd[i - digitShift] = (rot >> smallShift) | carry;
+ carry = rot << carryShift;
+ }
+ }
+ if (negx)
+ {
+ NumericsHelpers.DangerousMakeTwosComplement(zd); // mutates zd
+ }
+ return new BigInteger(zd, negx);
+ }
+
+
+ public static BigInteger operator ~(BigInteger value)
+ {
+ return -(value + One);
+ }
+
+ public static BigInteger operator -(BigInteger value)
+ {
+ value.AssertValid();
+ value._sign = -value._sign;
+ value.AssertValid();
+ return value;
+ }
+
+ public static BigInteger operator +(BigInteger value)
+ {
+ value.AssertValid();
+ return value;
+ }
+
+
+ public static BigInteger operator ++(BigInteger value)
+ {
+ return value + One;
+ }
+
+ public static BigInteger operator --(BigInteger value)
+ {
+ return value - One;
+ }
+
+
+ public static BigInteger operator +(BigInteger left, BigInteger right)
+ {
+ left.AssertValid();
+ right.AssertValid();
+
+ if (right.IsZero) return left;
+ if (left.IsZero) return right;
+
+ var sign1 = +1;
+ var sign2 = +1;
+ var reg1 = new BigIntegerBuilder(left, ref sign1);
+ var reg2 = new BigIntegerBuilder(right, ref sign2);
+
+ if (sign1 == sign2)
+ reg1.Add(ref reg2);
+ else
+ reg1.Sub(ref sign1, ref reg2);
+
+ return reg1.GetInteger(sign1);
+ }
+
+ public static BigInteger operator -(BigInteger left, BigInteger right)
+ {
+ left.AssertValid();
+ right.AssertValid();
+
+ if (right.IsZero) return left;
+ if (left.IsZero) return -right;
+
+ var sign1 = +1;
+ var sign2 = -1;
+ var reg1 = new BigIntegerBuilder(left, ref sign1);
+ var reg2 = new BigIntegerBuilder(right, ref sign2);
+
+ if (sign1 == sign2)
+ reg1.Add(ref reg2);
+ else
+ reg1.Sub(ref sign1, ref reg2);
+
+ return reg1.GetInteger(sign1);
+ }
+
+ public static BigInteger operator *(BigInteger left, BigInteger right)
+ {
+ left.AssertValid();
+ right.AssertValid();
+
+ var sign = +1;
+ var reg1 = new BigIntegerBuilder(left, ref sign);
+ var reg2 = new BigIntegerBuilder(right, ref sign);
+
+ reg1.Mul(ref reg2);
+ return reg1.GetInteger(sign);
+ }
+
+ public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
+ {
+ dividend.AssertValid();
+ divisor.AssertValid();
+
+ var sign = +1;
+ var regNum = new BigIntegerBuilder(dividend, ref sign);
+ var regDen = new BigIntegerBuilder(divisor, ref sign);
+
+ regNum.Div(ref regDen);
+ return regNum.GetInteger(sign);
+ }
+
+ public static BigInteger operator %(BigInteger dividend, BigInteger divisor)
+ {
+ dividend.AssertValid();
+ divisor.AssertValid();
+
+ var signNum = +1;
+ var signDen = +1;
+ var regNum = new BigIntegerBuilder(dividend, ref signNum);
+ var regDen = new BigIntegerBuilder(divisor, ref signDen);
+
+ regNum.Mod(ref regDen);
+ return regNum.GetInteger(signNum);
+ }*/
+
+ public static bool operator <(BigInteger left, BigInteger right)
+ {
+ return left.CompareTo(right) < 0;
+ }
+ public static bool operator <=(BigInteger left, BigInteger right)
+ {
+ return left.CompareTo(right) <= 0;
+ }
+ public static bool operator >(BigInteger left, BigInteger right)
+ {
+ return left.CompareTo(right) > 0;
+ }
+ public static bool operator >=(BigInteger left, BigInteger right)
+ {
+ return left.CompareTo(right) >= 0;
+ }
+ public static bool operator ==(BigInteger left, BigInteger right)
+ {
+ return left.Equals(right);
+ }
+ public static bool operator !=(BigInteger left, BigInteger right)
+ {
+ return !left.Equals(right);
+ }
+
+ /*public static bool operator <(BigInteger left, Int64 right)
+ {
+ return left.CompareTo(right) < 0;
+ }
+ public static bool operator <=(BigInteger left, Int64 right)
+ {
+ return left.CompareTo(right) <= 0;
+ }
+ public static bool operator >(BigInteger left, Int64 right)
+ {
+ return left.CompareTo(right) > 0;
+ }
+ public static bool operator >=(BigInteger left, Int64 right)
+ {
+ return left.CompareTo(right) >= 0;
+ }
+ public static bool operator ==(BigInteger left, Int64 right)
+ {
+ return left.Equals(right);
+ }
+ public static bool operator !=(BigInteger left, Int64 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(Int64 left, BigInteger right)
+ {
+ return right.CompareTo(left) > 0;
+ }
+ public static bool operator <=(Int64 left, BigInteger right)
+ {
+ return right.CompareTo(left) >= 0;
+ }
+ public static bool operator >(Int64 left, BigInteger right)
+ {
+ return right.CompareTo(left) < 0;
+ }
+ public static bool operator >=(Int64 left, BigInteger right)
+ {
+ return right.CompareTo(left) <= 0;
+ }
+ public static bool operator ==(Int64 left, BigInteger right)
+ {
+ return right.Equals(left);
+ }
+ public static bool operator !=(Int64 left, BigInteger right)
+ {
+ return !right.Equals(left);
+ }
+
+ public static bool operator <(BigInteger left, UInt64 right)
+ {
+ return left.CompareTo(right) < 0;
+ }
+ public static bool operator <=(BigInteger left, UInt64 right)
+ {
+ return left.CompareTo(right) <= 0;
+ }
+ public static bool operator >(BigInteger left, UInt64 right)
+ {
+ return left.CompareTo(right) > 0;
+ }
+ public static bool operator >=(BigInteger left, UInt64 right)
+ {
+ return left.CompareTo(right) >= 0;
+ }
+ public static bool operator ==(BigInteger left, UInt64 right)
+ {
+ return left.Equals(right);
+ }
+ public static bool operator !=(BigInteger left, UInt64 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(UInt64 left, BigInteger right)
+ {
+ return right.CompareTo(left) > 0;
+ }
+ public static bool operator <=(UInt64 left, BigInteger right)
+ {
+ return right.CompareTo(left) >= 0;
+ }
+ public static bool operator >(UInt64 left, BigInteger right)
+ {
+ return right.CompareTo(left) < 0;
+ }
+ public static bool operator >=(UInt64 left, BigInteger right)
+ {
+ return right.CompareTo(left) <= 0;
+ }
+ public static bool operator ==(UInt64 left, BigInteger right)
+ {
+ return right.Equals(left);
+ }
+ public static bool operator !=(UInt64 left, BigInteger right)
+ {
+ return !right.Equals(left);
+ }*/
+
+ #endregion internal static operators
+
+
+ // ----- SECTION: private serialization instance methods ----------------
+ #region private serialization instance methods
+ #endregion private serialization instance methods
+
+
+ // ----- SECTION: internal instance utility methods ----------------*
+ #region internal instance utility methods
+
+ /*private void SetBitsFromDouble(Double value)
+ {
+ int sign, exp;
+ ulong man;
+ bool fFinite;
+ NumericsHelpers.GetDoubleParts(value, out sign, out exp, out man, out fFinite);
+ Contract.Assert(sign == +1 || sign == -1);
+
+ if (man == 0)
+ {
+ this = Zero;
+ return;
+ }
+
+ Contract.Assert(man < 1UL << 53);
+ Contract.Assert(exp <= 0 || man >= 1UL << 52);
+
+ if (exp <= 0)
+ {
+ if (exp <= -kcbitUlong)
+ {
+ this = Zero;
+ return;
+ }
+ this = man >> -exp;
+ if (sign < 0)
+ _sign = -_sign;
+ }
+ else if (exp <= 11)
+ {
+ this = man << exp;
+ if (sign < 0)
+ _sign = -_sign;
+ }
+ else
+ {
+ // Overflow into at least 3 uints.
+ // Move the leading 1 to the high bit.
+ man <<= 11;
+ exp -= 11;
+
+ // Compute cu and cbit so that exp == 32 * cu - cbit and 0 <= cbit < 32.
+ var cu = (exp - 1) / kcbitUint + 1;
+ var cbit = cu * kcbitUint - exp;
+ Contract.Assert(0 <= cbit && cbit < kcbitUint);
+ Contract.Assert(cu >= 1);
+
+ // Populate the uints.
+ _bits = new uint[cu + 2];
+ _bits[cu + 1] = (uint)(man >> (cbit + kcbitUint));
+ _bits[cu] = (uint)(man >> cbit);
+ if (cbit > 0)
+ _bits[cu - 1] = (uint)man << (kcbitUint - cbit);
+ _sign = sign;
+ }
+ }*/
+ #endregion internal instance utility methods
+
+
+ // ----- SECTION: internal static utility methods ----------------*
+ #region internal static utility methods
+ //[Pure]
+ private static int Length(uint[] rgu)
+ {
+ var cu = rgu.Length;
+ if (rgu[cu - 1] != 0)
+ return cu;
+ Contract.Assert(cu >= 2 && rgu[cu - 2] != 0);
+ return cu - 1;
+ }
+
+ internal int _Sign { get { return _sign; } }
+ internal uint[] _Bits { get { return _bits; } }
+
+
+/*
+ internal static int BitLengthOfUInt(uint x)
+ {
+ var numBits = 0;
+ while (x > 0)
+ {
+ x >>= 1;
+ numBits++;
+ }
+ return numBits;
+ }
+*/
+
+ //
+ // GetPartsForBitManipulation -
+ //
+ // Encapsulate the logic of normalizing the "small" and "large" forms of BigInteger
+ // into the "large" form so that Bit Manipulation algorithms can be simplified
+ //
+ // uint[] xd = the UInt32 array containing the entire big integer in "large" (denormalized) form
+ // E.g., the number one (1) and negative one (-1) are both stored as 0x00000001
+ // BigInteger values Int32.MinValue < x <= Int32.MaxValue are converted to this
+ // format for convenience.
+ // int xl = the length of xd
+ // return bool = true for negative numbers
+ //
+ /*private static bool GetPartsForBitManipulation(ref BigInteger x, out uint[] xd, out int xl)
+ {
+ if (x._bits == null)
+ {
+ xd = x._sign < 0 ? new[] { (uint)-x._sign } : new[] { (uint)x._sign };
+ }
+ else
+ {
+ xd = x._bits;
+ }
+ xl = x._bits == null ? 1 : x._bits.Length;
+ return x._sign < 0;
+ }*/
+
+ // Gets an upper bound on the product of uHiRes * (2^32)^(cuRes-1) and uHiMul * (2^32)^(cuMul-1).
+ // The result is put int uHiRes and cuRes.
+/*
+ private static void MulUpper(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
+ {
+ var uu = (ulong)uHiRes * uHiMul;
+ var uHi = NumericsHelpers.GetHi(uu);
+ if (uHi != 0)
+ {
+ if (NumericsHelpers.GetLo(uu) != 0 && ++uHi == 0)
+ {
+ uHi = 1;
+ cuRes++;
+ }
+ uHiRes = uHi;
+ cuRes += cuMul;
+ }
+ else
+ {
+ uHiRes = NumericsHelpers.GetLo(uu);
+ cuRes += cuMul - 1;
+ }
+ }
+*/
+
+ // Gets a lower bound on the product of uHiRes * (2^32)^(cuRes-1) and uHiMul * (2^32)^(cuMul-1).
+ // The result is put int uHiRes and cuRes.
+/*
+ private static void MulLower(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
+ {
+ var uu = (ulong)uHiRes * uHiMul;
+ var uHi = NumericsHelpers.GetHi(uu);
+ if (uHi != 0)
+ {
+ uHiRes = uHi;
+ cuRes += cuMul;
+ }
+ else
+ {
+ uHiRes = NumericsHelpers.GetLo(uu);
+ cuRes += cuMul - 1;
+ }
+ }
+*/
+
+ private static int GetDiffLength(uint[] rgu1, uint[] rgu2, int cu)
+ {
+ for (var iv = cu; --iv >= 0; )
+ {
+ if (rgu1[iv] != rgu2[iv])
+ return iv + 1;
+ }
+ return 0;
+ }
+ #endregion internal static utility methods
+ }
+} \ No newline at end of file
diff --git a/runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs b/runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs
new file mode 100644
index 0000000..02ec6aa
--- /dev/null
+++ b/runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs
@@ -0,0 +1,1529 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+
+using System;
+
+using Contracts = System.Diagnostics.Debug;
+using Contract = System.Diagnostics.Debug;
+using Conditional = System.Diagnostics.ConditionalAttribute;
+
+// ReSharper disable once CheckNamespace
+namespace Numerics
+{
+ /// <summary>
+ /// BigIntegerBuilder holds a multiprecision unsigned integer value. It is mutable and
+ /// supports common arithmetic operations. Be careful NOT to simply assign one
+ /// BigIntegerBuilder to another, unless you really know what you are doing. The proper
+ /// way to replicate a BigIntegerBuilder is via the constructor "BigIntegerBuilder(ref BigIntegerBuilder reg)",
+ /// or with reg1.Load(ref reg2). Using the ctor marks the buffer as shared so changing the
+ /// value of one register will not affect the other. Using Load copies the contents from
+ /// one to the other. Either way, the internal buffer isn't aliased incorrectly.
+ /// </summary>
+ internal struct BigIntegerBuilder
+ {
+ // ReSharper disable once InconsistentNaming
+ private const int kcbitUint = 32;
+
+ // For a single uint, _iuLast is 0.
+ private int _iuLast;
+
+ // Used if _iuLast == 0.
+ private uint _uSmall;
+
+ // Used if _iuLast > 0.
+ private uint[] _rgu;
+
+ // This is false whenever _rgu is null or is shared with a NewBigInteger
+ // or with another BigIntegerBuilder.
+ private bool _fWritable;
+
+ [Conditional("DEBUG")]
+ // ReSharper disable once UnusedParameter.Local
+ private void AssertValid(bool fTrimmed)
+ {
+ if (_iuLast <= 0)
+ {
+ Contract.Assert(_iuLast == 0);
+ Contract.Assert(!_fWritable || _rgu != null);
+ }
+ else
+ {
+ Contract.Assert(_rgu != null && _rgu.Length > _iuLast);
+ Contract.Assert(!fTrimmed || _rgu[_iuLast] != 0);
+ }
+ }
+
+#if CONTRACTS_FULL
+ [ContractInvariantMethod]
+ private void ObjectInvariant()
+ {
+ Contract.Invariant(_iuLast >=0);
+ Contract.Invariant(!(_iuLast == 0) || (!_fWritable || _rgu != null));
+ Contract.Invariant(!(_iuLast > 0) || (_rgu != null && _rgu.Length > _iuLast));
+ }
+#endif
+
+/*
+ internal BigIntegerBuilder(ref BigIntegerBuilder reg)
+ {
+ reg.AssertValid(true);
+ this = reg;
+ if (_fWritable)
+ {
+ _fWritable = false;
+ if (_iuLast == 0)
+ _rgu = null;
+ else
+ reg._fWritable = false;
+ }
+ AssertValid(true);
+ }
+*/
+
+ internal BigIntegerBuilder(int cuAlloc)
+ {
+ _iuLast = 0;
+ _uSmall = 0;
+ if (cuAlloc > 1)
+ {
+ _rgu = new uint[cuAlloc];
+ _fWritable = true;
+ }
+ else
+ {
+ _rgu = null;
+ _fWritable = false;
+ }
+ AssertValid(true);
+ }
+
+/*
+ internal BigIntegerBuilder(BigInteger bn)
+ {
+ _fWritable = false;
+ _rgu = bn._Bits;
+ if (_rgu == null)
+ {
+ _iuLast = 0;
+ _uSmall = NumericsHelpers.Abs(bn._Sign);
+ }
+ else
+ {
+ _iuLast = _rgu.Length - 1;
+ _uSmall = _rgu[0];
+ while (_iuLast > 0 && _rgu[_iuLast] == 0)
+ --_iuLast;
+ }
+ AssertValid(true);
+ }
+*/
+
+ internal BigIntegerBuilder(BigInteger bn, ref int sign)
+ {
+ Contract.Assert(sign == +1 || sign == -1);
+
+ _fWritable = false;
+ _rgu = bn._Bits;
+ int n = bn._Sign;
+ int mask = n >> (kcbitUint - 1);
+ sign = (sign ^ mask) - mask;
+ if (_rgu == null)
+ {
+ _iuLast = 0;
+ _uSmall = (uint)((n ^ mask) - mask);
+ }
+ else
+ {
+ _iuLast = _rgu.Length - 1;
+ _uSmall = _rgu[0];
+ while (_iuLast > 0 && _rgu[_iuLast] == 0)
+ --_iuLast;
+ }
+ AssertValid(true);
+ }
+
+ internal BigInteger GetInteger(int sign)
+ {
+ Contract.Assert(sign == +1 || sign == -1);
+ AssertValid(true);
+
+ uint[] bits;
+ GetIntegerParts(sign, out sign, out bits);
+ return new BigInteger(sign, bits);
+ }
+
+ private void GetIntegerParts(int signSrc, out int sign, out uint[] bits)
+ {
+ Contract.Assert(signSrc == +1 || signSrc == -1);
+ AssertValid(true);
+
+ if (_iuLast == 0)
+ {
+ if (_uSmall <= int.MaxValue)
+ {
+ sign = signSrc * (int)_uSmall;
+ bits = null;
+ return;
+ }
+ if (_rgu == null)
+ _rgu = new[] { _uSmall };
+ else if (_fWritable)
+ _rgu[0] = _uSmall;
+ else if (_rgu[0] != _uSmall)
+ _rgu = new[] { _uSmall };
+ }
+
+ // The sign is +/- 1.
+ sign = signSrc;
+
+ int cuExtra = _rgu.Length - _iuLast - 1;
+ Contract.Assert(cuExtra >= 0);
+ if (cuExtra <= 1)
+ {
+ if (cuExtra == 0 || _rgu[_iuLast + 1] == 0)
+ {
+ _fWritable = false;
+ bits = _rgu;
+ return;
+ }
+ if (_fWritable)
+ {
+ _rgu[_iuLast + 1] = 0;
+ _fWritable = false;
+ bits = _rgu;
+ return;
+ }
+ // The buffer isn't writable, but has an extra uint that is non-zero,
+ // so we have to allocate a new buffer.
+ }
+
+ // Keep the bigger buffer (if it is writable), but create a smaller one for the BigInteger.
+ bits = _rgu;
+ Array.Resize(ref bits, _iuLast + 1);
+ if (!_fWritable)
+ _rgu = bits;
+ }
+
+ private void Set(uint u)
+ {
+ _uSmall = u;
+ _iuLast = 0;
+ AssertValid(true);
+ }
+
+ private void Set(ulong uu)
+ {
+ uint uHi = NumericsHelpers.GetHi(uu);
+ if (uHi == 0)
+ {
+ _uSmall = NumericsHelpers.GetLo(uu);
+ _iuLast = 0;
+ }
+ else
+ {
+ SetSizeLazy(2);
+ _rgu[0] = (uint) uu;
+ _rgu[1] = uHi;
+ }
+ }
+
+ internal int Size { get { return _iuLast + 1; } }
+
+ //internal uint High { get { return _iuLast == 0 ? _uSmall : _rgu[_iuLast]; } }
+
+
+ /*internal void GetApproxParts(out int exp, out ulong man)
+ {
+ AssertValid(true);
+ if (_iuLast == 0)
+ {
+ man = _uSmall;
+ exp = 0;
+ return;
+ }
+
+ int cuLeft = _iuLast - 1;
+ man = NumericsHelpers.MakeUlong(_rgu[cuLeft + 1], _rgu[cuLeft]);
+ exp = cuLeft * kcbitUint;
+
+ int cbit;
+ if (cuLeft > 0 && (cbit = NumericsHelpers.CbitHighZero(_rgu[cuLeft + 1])) > 0)
+ {
+ // Get 64 bits.
+ Contract.Assert(cbit < kcbitUint);
+ man = (man << cbit) | (_rgu[cuLeft - 1] >> (kcbitUint - cbit));
+ exp -= cbit;
+ }
+ }*/
+
+ private void Trim()
+ {
+ AssertValid(false);
+ if (_iuLast > 0 && _rgu[_iuLast] == 0)
+ {
+ _uSmall = _rgu[0];
+ while (--_iuLast > 0 && _rgu[_iuLast] == 0)
+ {
+ }
+ }
+ AssertValid(true);
+ }
+
+ private int CuNonZero
+ {
+ get
+ {
+ Contract.Assert(_iuLast > 0);
+ int cu = 0;
+ for (int iu = _iuLast; iu >= 0; --iu)
+ {
+ if (_rgu[iu] != 0)
+ cu++;
+ }
+ return cu;
+ }
+ }
+
+ // Sets the size to cu and makes sure the buffer is writable (if cu > 1),
+ // but makes no guarantees about the contents of the buffer.
+ private void SetSizeLazy(int cu)
+ {
+ Contract.Assert(cu > 0);
+ AssertValid(false);
+ if (cu <= 1)
+ {
+ _iuLast = 0;
+ return;
+ }
+ if (!_fWritable || _rgu.Length < cu)
+ {
+ _rgu = new uint[cu];
+ _fWritable = true;
+ }
+ _iuLast = cu - 1;
+ AssertValid(false);
+ }
+
+ // Sets the size to cu, makes sure the buffer is writable (if cu > 1),
+ // and set the contents to all zero.
+ private void SetSizeClear(int cu)
+ {
+ Contract.Assert(cu > 0);
+ AssertValid(false);
+ if (cu <= 1)
+ {
+ _iuLast = 0;
+ _uSmall = 0;
+ return;
+ }
+ if (!_fWritable || _rgu.Length < cu)
+ {
+ _rgu = new uint[cu];
+ _fWritable = true;
+ }
+ else
+ Array.Clear(_rgu, 0, cu);
+ _iuLast = cu - 1;
+ AssertValid(false);
+ }
+
+ // Sets the size to cu, makes sure the buffer is writable (if cu > 1),
+ // and maintains the contents. If the buffer is reallocated, cuExtra
+ // uints are also allocated.
+ private void SetSizeKeep(int cu, int cuExtra)
+ {
+ Contract.Assert(cu > 0 && cuExtra >= 0);
+ AssertValid(false);
+
+ if (cu <= 1)
+ {
+ if (_iuLast > 0)
+ _uSmall = _rgu[0];
+ _iuLast = 0;
+ return;
+ }
+ if (!_fWritable || _rgu.Length < cu)
+ {
+ uint[] rgu = new uint[cu + cuExtra];
+ if (_iuLast == 0)
+ rgu[0] = _uSmall;
+ else
+ Array.Copy(_rgu, rgu, Math.Min(cu, _iuLast + 1));
+ _rgu = rgu;
+ _fWritable = true;
+ }
+ else if (_iuLast + 1 < cu)
+ {
+ Array.Clear(_rgu, _iuLast + 1, cu - _iuLast - 1);
+ if (_iuLast == 0)
+ _rgu[0] = _uSmall;
+ }
+ _iuLast = cu - 1;
+ AssertValid(false);
+ }
+
+ // Makes sure the buffer is writable and can support cu uints.
+ // Preserves the contents of the buffer up to min(_iuLast + 1, cu).
+ // Changes the size if cu <= _iuLast and the buffer needs to be allocated.
+/*
+ internal void EnsureWritable(int cu, int cuExtra)
+ {
+ Contract.Assert(cu > 1 && cuExtra >= 0);
+ AssertValid(false);
+
+ if (_fWritable && _rgu.Length >= cu)
+ return;
+
+ uint[] rgu = new uint[cu + cuExtra];
+ if (_iuLast > 0)
+ {
+ if (_iuLast >= cu)
+ _iuLast = cu - 1;
+ Array.Copy(_rgu, rgu, _iuLast + 1);
+ }
+ _rgu = rgu;
+ _fWritable = true;
+ AssertValid(false);
+ }
+*/
+
+ // Makes sure the buffer is writable and can support _iuLast + 1 uints.
+ // Preserves the contents of the buffer.
+ private void EnsureWritable(int cuExtra = 0)
+ {
+ Contract.Assert(cuExtra >= 0);
+ AssertValid(false);
+ Contract.Assert(_iuLast > 0);
+
+ if (_fWritable)
+ return;
+
+ uint[] rgu = new uint[_iuLast + 1 + cuExtra];
+ Array.Copy(_rgu, rgu, _iuLast + 1);
+ _rgu = rgu;
+ _fWritable = true;
+ AssertValid(false);
+ }
+
+ // Loads the value of reg into this register.
+ /*internal void Load(ref BigIntegerBuilder reg)
+ {
+ Load(ref reg, 0);
+ }*/
+
+ // Loads the value of reg into this register. If we need to allocate memory
+ // to perform the load, allocate cuExtra elements.
+ private void Load(ref BigIntegerBuilder reg, int cuExtra)
+ {
+ Contract.Assert(cuExtra >= 0);
+ AssertValid(false);
+ reg.AssertValid(true);
+
+ if (reg._iuLast == 0)
+ {
+ _uSmall = reg._uSmall;
+ _iuLast = 0;
+ }
+ else
+ {
+ if (!_fWritable || _rgu.Length <= reg._iuLast)
+ {
+ _rgu = new uint[reg._iuLast + 1 + cuExtra];
+ _fWritable = true;
+ }
+ _iuLast = reg._iuLast;
+ Array.Copy(reg._rgu, _rgu, _iuLast + 1);
+ }
+ AssertValid(true);
+ }
+
+ /*internal void Add(uint u)
+ {
+ AssertValid(true);
+ if (_iuLast == 0)
+ {
+ if ((_uSmall += u) >= u)
+ return;
+ SetSizeLazy(2);
+ _rgu[0] = _uSmall;
+ _rgu[1] = 1;
+ return;
+ }
+
+ if (u == 0)
+ return;
+
+ uint uNew = _rgu[0] + u;
+ if (uNew < u)
+ {
+ // Have carry.
+ EnsureWritable(1);
+ ApplyCarry(1);
+ }
+ else if (!_fWritable)
+ EnsureWritable();
+ _rgu[0] = uNew;
+ AssertValid(true);
+ }
+
+ internal void Add(ref BigIntegerBuilder reg)
+ {
+ AssertValid(true);
+ reg.AssertValid(true);
+
+ if (reg._iuLast == 0)
+ {
+ Add(reg._uSmall);
+ return;
+ }
+ if (_iuLast == 0)
+ {
+ uint u = _uSmall;
+ if (u == 0)
+ this = new BigIntegerBuilder(ref reg);
+ else
+ {
+ Load(ref reg, 1);
+ Add(u);
+ }
+ return;
+ }
+
+ EnsureWritable(Math.Max(_iuLast, reg._iuLast) + 1, 1);
+
+ int cuAdd = reg._iuLast + 1;
+ if (_iuLast < reg._iuLast)
+ {
+ cuAdd = _iuLast + 1;
+ Array.Copy(reg._rgu, _iuLast + 1, _rgu, _iuLast + 1, reg._iuLast - _iuLast);
+ Contract.Assert(_iuLast > 0);
+ _iuLast = reg._iuLast;
+ }
+
+ // Add, tracking carry.
+ uint uCarry = 0;
+ for (int iu = 0; iu < cuAdd; iu++)
+ {
+ uCarry = AddCarry(ref _rgu[iu], reg._rgu[iu], uCarry);
+ Contract.Assert(uCarry <= 1);
+ }
+
+ // Deal with extra carry.
+ if (uCarry != 0)
+ ApplyCarry(cuAdd);
+ AssertValid(true);
+ }
+
+ internal void Sub(ref int sign, uint u)
+ {
+ Contract.Assert(sign == +1 || sign == -1);
+ AssertValid(true);
+ if (_iuLast == 0)
+ {
+ if (u <= _uSmall)
+ _uSmall -= u;
+ else
+ {
+ _uSmall = u - _uSmall;
+ sign = -sign;
+ }
+ AssertValid(true);
+ return;
+ }
+
+ if (u == 0)
+ return;
+
+ EnsureWritable();
+
+ uint uTmp = _rgu[0];
+ _rgu[0] = uTmp - u;
+ if (uTmp < u)
+ {
+ ApplyBorrow(1);
+ Trim();
+ }
+ AssertValid(true);
+ }
+
+ internal void Sub(ref int sign, ref BigIntegerBuilder reg)
+ {
+ Contract.Assert(sign == +1 || sign == -1);
+ AssertValid(true);
+ reg.AssertValid(true);
+
+ if (reg._iuLast == 0)
+ {
+ Sub(ref sign, reg._uSmall);
+ return;
+ }
+ if (_iuLast == 0)
+ {
+ uint u = _uSmall;
+ if (u == 0)
+ this = new BigIntegerBuilder(ref reg);
+ else
+ {
+ Load(ref reg);
+ Sub(ref sign, u);
+ }
+ sign = -sign;
+ return;
+ }
+
+ if (_iuLast < reg._iuLast)
+ {
+ SubRev(ref reg);
+ sign = -sign;
+ return;
+ }
+
+ int cuSub = reg._iuLast + 1;
+ if (_iuLast == reg._iuLast)
+ {
+ // Determine which is larger.
+ _iuLast = BigInteger.GetDiffLength(_rgu, reg._rgu, _iuLast + 1) - 1;
+ if (_iuLast < 0)
+ {
+ _iuLast = 0;
+ _uSmall = 0;
+ return;
+ }
+
+ uint u1 = _rgu[_iuLast];
+ uint u2 = reg._rgu[_iuLast];
+ if (_iuLast == 0)
+ {
+ if (u1 < u2)
+ {
+ _uSmall = u2 - u1;
+ sign = -sign;
+ }
+ else
+ _uSmall = u1 - u2;
+ AssertValid(true);
+ return;
+ }
+
+ if (u1 < u2)
+ {
+ Contract.Assert(_iuLast > 0);
+ reg._iuLast = _iuLast;
+ SubRev(ref reg);
+ reg._iuLast = cuSub - 1;
+ Contract.Assert(reg._iuLast > 0);
+ sign = -sign;
+ return;
+ }
+ cuSub = _iuLast + 1;
+ }
+
+ EnsureWritable();
+
+ // Subtract, tracking borrow.
+ uint uBorrow = 0;
+ for (int iu = 0; iu < cuSub; iu++)
+ {
+ uBorrow = SubBorrow(ref _rgu[iu], reg._rgu[iu], uBorrow);
+ Contract.Assert(uBorrow <= 1);
+ }
+ if (uBorrow != 0)
+ {
+ Contract.Assert(uBorrow == 1 && cuSub <= _iuLast);
+ ApplyBorrow(cuSub);
+ }
+ Trim();
+ }
+
+ // Subtract this register from the given one and put the result in this one.
+ // Asserts that reg is larger in the most significant uint.
+ private void SubRev(ref BigIntegerBuilder reg)
+ {
+ Contract.Assert(0 < _iuLast && _iuLast <= reg._iuLast);
+ Contract.Assert(_iuLast < reg._iuLast || _rgu[_iuLast] < reg._rgu[_iuLast]);
+
+ EnsureWritable(reg._iuLast + 1, 0);
+
+ int cuSub = _iuLast + 1;
+ if (_iuLast < reg._iuLast)
+ {
+ Array.Copy(reg._rgu, _iuLast + 1, _rgu, _iuLast + 1, reg._iuLast - _iuLast);
+ Contract.Assert(_iuLast > 0);
+ _iuLast = reg._iuLast;
+ }
+
+ uint uBorrow = 0;
+ for (int iu = 0; iu < cuSub; iu++)
+ {
+ uBorrow = SubRevBorrow(ref _rgu[iu], reg._rgu[iu], uBorrow);
+ Contract.Assert(uBorrow <= 1);
+ }
+ if (uBorrow != 0)
+ {
+ Contract.Assert(uBorrow == 1);
+ ApplyBorrow(cuSub);
+ }
+ Trim();
+ }*/
+
+ private void Mul(uint u)
+ {
+ if (u == 0)
+ {
+ Set(0);
+ return;
+ }
+ if (u == 1)
+ return;
+
+ if (_iuLast == 0)
+ {
+ Set((ulong)_uSmall * u);
+ return;
+ }
+
+ EnsureWritable(1);
+
+ uint uCarry = 0;
+ for (int iu = 0; iu <= _iuLast; iu++)
+ uCarry = MulCarry(ref _rgu[iu], u, uCarry);
+
+ if (uCarry != 0)
+ {
+ SetSizeKeep(_iuLast + 2, 0);
+ _rgu[_iuLast] = uCarry;
+ }
+ }
+
+ // This version may share memory with regMul.
+ /*internal void Mul(ref BigIntegerBuilder regMul)
+ {
+ AssertValid(true);
+ regMul.AssertValid(true);
+
+ if (regMul._iuLast == 0)
+ Mul(regMul._uSmall);
+ else if (_iuLast == 0)
+ {
+ uint u = _uSmall;
+ if (u == 1)
+ this = new BigIntegerBuilder(ref regMul);
+ else if (u != 0)
+ {
+ Load(ref regMul, 1);
+ Mul(u);
+ }
+ }
+ else
+ {
+ int cuBase = _iuLast + 1;
+ SetSizeKeep(cuBase + regMul._iuLast, 1);
+
+ for (int iu = cuBase; --iu >= 0; )
+ {
+ uint uMul = _rgu[iu];
+ _rgu[iu] = 0;
+ uint uCarry = 0;
+ for (int iuSrc = 0; iuSrc <= regMul._iuLast; iuSrc++)
+ uCarry = AddMulCarry(ref _rgu[iu + iuSrc], regMul._rgu[iuSrc], uMul, uCarry);
+ if (uCarry != 0)
+ {
+ for (int iuDst = iu + regMul._iuLast + 1; uCarry != 0 && iuDst <= _iuLast; iuDst++)
+ uCarry = AddCarry(ref _rgu[iuDst], 0, uCarry);
+ if (uCarry != 0)
+ {
+ SetSizeKeep(_iuLast + 2, 0);
+ _rgu[_iuLast] = uCarry;
+ }
+ }
+ }
+ AssertValid(true);
+ }
+ }*/
+
+ // Multiply reg1 times reg2, putting the result in 'this'. This version never shares memory
+ // with either of the operands. This is useful when performing a series of arithmetic operations
+ // and large working buffers are allocated up front.
+ internal void Mul(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
+ {
+ AssertValid(true);
+ reg1.AssertValid(true);
+ reg2.AssertValid(true);
+
+ if (reg1._iuLast == 0)
+ {
+ if (reg2._iuLast == 0)
+ Set((ulong)reg1._uSmall * reg2._uSmall);
+ else
+ {
+ Load(ref reg2, 1);
+ Mul(reg1._uSmall);
+ }
+ }
+ else if (reg2._iuLast == 0)
+ {
+ Load(ref reg1, 1);
+ Mul(reg2._uSmall);
+ }
+ else
+ {
+ Contract.Assert(reg1._iuLast > 0 && reg2._iuLast > 0);
+ SetSizeClear(reg1._iuLast + reg2._iuLast + 2);
+
+ uint[] rgu1, rgu2;
+ int cu1, cu2;
+
+ // We prefer more iterations on the inner loop and fewer on the outer.
+ if (reg1.CuNonZero <= reg2.CuNonZero)
+ {
+ rgu1 = reg1._rgu; cu1 = reg1._iuLast + 1;
+ rgu2 = reg2._rgu; cu2 = reg2._iuLast + 1;
+ }
+ else
+ {
+ rgu1 = reg2._rgu; cu1 = reg2._iuLast + 1;
+ rgu2 = reg1._rgu; cu2 = reg1._iuLast + 1;
+ }
+
+ for (int iu1 = 0; iu1 < cu1; iu1++)
+ {
+ uint uCur = rgu1[iu1];
+ if (uCur == 0)
+ continue;
+
+ uint uCarry = 0;
+ int iuRes = iu1;
+ for (int iu2 = 0; iu2 < cu2; iu2++, iuRes++)
+ uCarry = AddMulCarry(ref _rgu[iuRes], uCur, rgu2[iu2], uCarry);
+ while (uCarry != 0)
+ uCarry = AddCarry(ref _rgu[iuRes++], 0, uCarry);
+ }
+ Trim();
+ }
+ }
+
+ // Divide 'this' by uDen, leaving the quotient in 'this' and returning the remainder.
+ /*internal uint DivMod(uint uDen)
+ {
+ AssertValid(true);
+
+ if (uDen == 1)
+ return 0;
+ if (_iuLast == 0)
+ {
+ uint uTmp = _uSmall;
+ _uSmall = uTmp / uDen;
+ return uTmp % uDen;
+ }
+
+ EnsureWritable();
+
+ ulong uu = 0;
+ for (int iv = _iuLast; iv >= 0; iv--)
+ {
+ uu = NumericsHelpers.MakeUlong((uint)uu, _rgu[iv]);
+ _rgu[iv] = (uint)(uu / uDen);
+ uu %= uDen;
+ }
+ Trim();
+ return (uint)uu;
+ }*/
+
+ // Divide regNum by uDen, returning the remainder and tossing the quotient.
+ private static uint Mod(ref BigIntegerBuilder regNum, uint uDen)
+ {
+ regNum.AssertValid(true);
+
+ if (uDen == 1)
+ return 0;
+ if (regNum._iuLast == 0)
+ return regNum._uSmall % uDen;
+
+ ulong uu = 0;
+ for (int iv = regNum._iuLast; iv >= 0; iv--)
+ {
+ uu = NumericsHelpers.MakeUlong((uint)uu, regNum._rgu[iv]);
+ uu %= uDen;
+ }
+ return (uint)uu;
+ }
+
+ // Divide 'this' by regDen, leaving the remainder in 'this' and tossing the quotient.
+ internal void Mod(ref BigIntegerBuilder regDen)
+ {
+ AssertValid(true);
+ regDen.AssertValid(true);
+
+ if (regDen._iuLast == 0)
+ {
+ Set(Mod(ref this, regDen._uSmall));
+ return;
+ }
+ if (_iuLast == 0)
+ return;
+
+ BigIntegerBuilder regTmp = new BigIntegerBuilder();
+ ModDivCore(ref this, ref regDen, false, ref regTmp);
+ }
+
+ // Divide 'this' by regDen, leaving the quotient in 'this' and tossing the remainder.
+ /*internal void Div(ref BigIntegerBuilder regDen)
+ {
+ AssertValid(true);
+ regDen.AssertValid(true);
+
+ if (regDen._iuLast == 0)
+ {
+ DivMod(regDen._uSmall);
+ return;
+ }
+ if (_iuLast == 0)
+ {
+ _uSmall = 0;
+ return;
+ }
+
+ BigIntegerBuilder regTmp = new BigIntegerBuilder();
+ ModDivCore(ref this, ref regDen, true, ref regTmp);
+ NumericsHelpers.Swap(ref this, ref regTmp);
+ }*/
+
+ // Divide regNum by regDen, leaving the remainder in regNum and the quotient in regQuo (if fQuo is true).
+/*
+ internal void ModDiv(ref BigIntegerBuilder regDen, ref BigIntegerBuilder regQuo)
+ {
+ if (regDen._iuLast == 0)
+ {
+ regQuo.Set(DivMod(regDen._uSmall));
+ NumericsHelpers.Swap(ref this, ref regQuo);
+ return;
+ }
+ if (_iuLast == 0)
+ return;
+
+ ModDivCore(ref this, ref regDen, true, ref regQuo);
+ }
+*/
+
+ private static void ModDivCore(ref BigIntegerBuilder regNum, ref BigIntegerBuilder regDen, bool fQuo, ref BigIntegerBuilder regQuo)
+ {
+ Contract.Assert(regNum._iuLast > 0 && regDen._iuLast > 0);
+
+ regQuo.Set(0);
+ if (regNum._iuLast < regDen._iuLast)
+ return;
+
+ Contract.Assert(0 < regDen._iuLast && regDen._iuLast <= regNum._iuLast);
+ int cuDen = regDen._iuLast + 1;
+ int cuDiff = regNum._iuLast - regDen._iuLast;
+
+ // Determine whether the result will have cuDiff "digits" or cuDiff+1 "digits".
+ int cuQuo = cuDiff;
+ for (int iu = regNum._iuLast; ; iu--)
+ {
+ if (iu < cuDiff)
+ {
+ cuQuo++;
+ break;
+ }
+ if (regDen._rgu[iu - cuDiff] != regNum._rgu[iu])
+ {
+ if (regDen._rgu[iu - cuDiff] < regNum._rgu[iu])
+ cuQuo++;
+ break;
+ }
+ }
+
+ if (cuQuo == 0)
+ return;
+
+ if (fQuo)
+ regQuo.SetSizeLazy(cuQuo);
+
+ // Get the uint to use for the trial divisions. We normalize so the high bit is set.
+ uint uDen = regDen._rgu[cuDen - 1];
+ uint uDenNext = regDen._rgu[cuDen - 2];
+ int cbitShiftLeft = NumericsHelpers.CbitHighZero(uDen);
+ int cbitShiftRight = kcbitUint - cbitShiftLeft;
+ if (cbitShiftLeft > 0)
+ {
+ uDen = (uDen << cbitShiftLeft) | (uDenNext >> cbitShiftRight);
+ uDenNext <<= cbitShiftLeft;
+ if (cuDen > 2)
+ uDenNext |= regDen._rgu[cuDen - 3] >> cbitShiftRight;
+ }
+ Contract.Assert((uDen & 0x80000000) != 0);
+
+ // Allocate and initialize working space.
+ Contract.Assert(cuQuo + cuDen == regNum._iuLast + 1 || cuQuo + cuDen == regNum._iuLast + 2);
+ regNum.EnsureWritable();
+
+ for (int iu = cuQuo; --iu >= 0; )
+ {
+ // Get the high (normalized) bits of regNum.
+ uint uNumHi = iu + cuDen <= regNum._iuLast ? regNum._rgu[iu + cuDen] : 0;
+ Contract.Assert(uNumHi <= regDen._rgu[cuDen - 1]);
+
+ ulong uuNum = NumericsHelpers.MakeUlong(uNumHi, regNum._rgu[iu + cuDen - 1]);
+ uint uNumNext = regNum._rgu[iu + cuDen - 2];
+ if (cbitShiftLeft > 0)
+ {
+ uuNum = (uuNum << cbitShiftLeft) | (uNumNext >> cbitShiftRight);
+ uNumNext <<= cbitShiftLeft;
+ if (iu + cuDen >= 3)
+ uNumNext |= regNum._rgu[iu + cuDen - 3] >> cbitShiftRight;
+ }
+
+ // Divide to get the quotient digit.
+ ulong uuQuo = uuNum / uDen;
+ ulong uuRem = (uint)(uuNum % uDen);
+ Contract.Assert(uuQuo <= (ulong)uint.MaxValue + 2);
+ if (uuQuo > uint.MaxValue)
+ {
+ uuRem += uDen * (uuQuo - uint.MaxValue);
+ uuQuo = uint.MaxValue;
+ }
+ while (uuRem <= uint.MaxValue && uuQuo * uDenNext > NumericsHelpers.MakeUlong((uint)uuRem, uNumNext))
+ {
+ uuQuo--;
+ uuRem += uDen;
+ }
+
+ // Multiply and subtract. Note that uuQuo may be 1 too large. If we have a borrow
+ // at the end, we'll add the denominator back on and decrement uuQuo.
+ if (uuQuo > 0)
+ {
+ ulong uuBorrow = 0;
+ for (int iu2 = 0; iu2 < cuDen; iu2++)
+ {
+ uuBorrow += regDen._rgu[iu2] * uuQuo;
+ uint uSub = (uint)uuBorrow;
+ uuBorrow >>= kcbitUint;
+ if (regNum._rgu[iu + iu2] < uSub)
+ uuBorrow++;
+ regNum._rgu[iu + iu2] -= uSub;
+ }
+
+ Contract.Assert(uNumHi == uuBorrow || uNumHi == uuBorrow - 1);
+ if (uNumHi < uuBorrow)
+ {
+ // Add, tracking carry.
+ uint uCarry = 0;
+ for (int iu2 = 0; iu2 < cuDen; iu2++)
+ {
+ uCarry = AddCarry(ref regNum._rgu[iu + iu2], regDen._rgu[iu2], uCarry);
+ Contract.Assert(uCarry <= 1);
+ }
+ Contract.Assert(uCarry == 1);
+ uuQuo--;
+ }
+ regNum._iuLast = iu + cuDen - 1;
+ }
+
+ if (fQuo)
+ {
+ if (cuQuo == 1)
+ regQuo._uSmall = (uint)uuQuo;
+ else
+ regQuo._rgu[iu] = (uint)uuQuo;
+ }
+ }
+
+ Contract.Assert(cuDen > 1 && regNum._iuLast > 0);
+ regNum._iuLast = cuDen - 1;
+ regNum.Trim();
+ }
+
+ //private static readonly double kdblLn2To32 = 32 * Math.Log(2);
+
+ /*internal void ShiftRight(int cbit)
+ {
+ AssertValid(true);
+ if (cbit <= 0)
+ {
+ if (cbit < 0)
+ ShiftLeft(-cbit);
+ return;
+ }
+ ShiftRight(cbit / kcbitUint, cbit % kcbitUint);
+ }
+
+ internal void ShiftRight(int cuShift, int cbitShift)
+ {
+ Contract.Assert(cuShift >= 0);
+ Contract.Assert(0 <= cbitShift);
+ Contract.Assert(cbitShift < kcbitUint);
+ AssertValid(true);
+
+ if ((cuShift | cbitShift) == 0)
+ return;
+ if (cuShift > _iuLast)
+ {
+ Set(0);
+ return;
+ }
+ if (_iuLast == 0)
+ {
+ _uSmall >>= cbitShift;
+ AssertValid(true);
+ return;
+ }
+
+ uint[] rguSrc = _rgu;
+ int cuSrc = _iuLast + 1;
+ _iuLast -= cuShift;
+ if (_iuLast == 0)
+ _uSmall = rguSrc[cuShift] >> cbitShift;
+ else
+ {
+ Contract.Assert(_rgu.Length > _iuLast);
+ if (!_fWritable)
+ {
+ _rgu = new uint[_iuLast + 1];
+ _fWritable = true;
+ }
+ if (cbitShift > 0)
+ {
+ for (int iuSrc = cuShift + 1, iuDst = 0; iuSrc < cuSrc; iuSrc++, iuDst++)
+ _rgu[iuDst] = (rguSrc[iuSrc - 1] >> cbitShift) | (rguSrc[iuSrc] << (kcbitUint - cbitShift));
+ _rgu[_iuLast] = rguSrc[cuSrc - 1] >> cbitShift;
+ Trim();
+ }
+ else
+ Array.Copy(rguSrc, cuShift, _rgu, 0, _iuLast + 1);
+ }
+ AssertValid(true);
+ }*/
+
+ /*internal void ShiftLeft(int cbit)
+ {
+ AssertValid(true);
+ if (cbit <= 0)
+ {
+ if (cbit < 0)
+ ShiftRight(-cbit);
+ return;
+ }
+ ShiftLeft(cbit / kcbitUint, cbit % kcbitUint);
+ }
+
+ internal void ShiftLeft(int cuShift, int cbitShift)
+ {
+ Contract.Assert(cuShift >= 0);
+ Contract.Assert(0 <= cbitShift);
+ Contract.Assert(cbitShift < kcbitUint);
+ AssertValid(true);
+
+ int iuLastNew = _iuLast + cuShift;
+ uint uHigh = 0;
+ if (cbitShift > 0)
+ {
+ uHigh = High >> (kcbitUint - cbitShift);
+ if (uHigh != 0)
+ iuLastNew++;
+ }
+ if (iuLastNew == 0)
+ {
+ _uSmall <<= cbitShift;
+ return;
+ }
+
+ uint[] rguSrc = _rgu;
+ bool fClearLow = cuShift > 0;
+ if (!_fWritable || _rgu.Length <= iuLastNew)
+ {
+ _rgu = new uint[iuLastNew + 1];
+ _fWritable = true;
+ fClearLow = false;
+ }
+ if (_iuLast == 0)
+ {
+ if (uHigh != 0)
+ _rgu[cuShift + 1] = uHigh;
+ _rgu[cuShift] = _uSmall << cbitShift;
+ }
+ else if (cbitShift == 0)
+ Array.Copy(rguSrc, 0, _rgu, cuShift, _iuLast + 1);
+ else
+ {
+ int iuSrc = _iuLast;
+ int iuDst = _iuLast + cuShift;
+ if (iuDst < iuLastNew)
+ _rgu[iuLastNew] = uHigh;
+ for (; iuSrc > 0; iuSrc--, iuDst--)
+ _rgu[iuDst] = (rguSrc[iuSrc] << cbitShift) | (rguSrc[iuSrc - 1] >> (kcbitUint - cbitShift));
+ _rgu[cuShift] = rguSrc[0] << cbitShift;
+ }
+ _iuLast = iuLastNew;
+ if (fClearLow)
+ Array.Clear(_rgu, 0, cuShift);
+ }*/
+
+ // Get the high two uints, combined into a ulong, zero extending to
+ // length cu if necessary. Asserts cu > _iuLast and _iuLast > 0.
+/*
+ private ulong GetHigh2(int cu)
+ {
+ Contract.Assert(cu >= 2);
+ Contract.Assert(_iuLast > 0);
+ Contract.Assert(cu > _iuLast);
+
+ if (cu - 1 <= _iuLast)
+ return NumericsHelpers.MakeUlong(_rgu[cu - 1], _rgu[cu - 2]);
+ if (cu - 2 == _iuLast)
+ return _rgu[cu - 2];
+ return 0;
+ }
+*/
+
+ // Apply a single carry starting at iu, extending the register
+ // if needed.
+/*
+ private void ApplyCarry(int iu)
+ {
+ Contract.Assert(0 <= iu);
+ Contract.Assert(_fWritable && _iuLast > 0);
+ Contract.Assert(iu <= _iuLast + 1);
+
+ for (; ; iu++)
+ {
+ if (iu > _iuLast)
+ {
+ if (_iuLast + 1 == _rgu.Length)
+ Array.Resize(ref _rgu, _iuLast + 2);
+ _rgu[++_iuLast] = 1;
+ break;
+ }
+ if (++_rgu[iu] > 0)
+ break;
+ }
+ }
+*/
+
+ // Apply a single borrow starting at iu. This does NOT trim the result.
+/*
+ private void ApplyBorrow(int iuMin)
+ {
+ Contract.Assert(0 < iuMin);
+ Contract.Assert(_fWritable && _iuLast > 0);
+ Contract.Assert(iuMin <= _iuLast);
+
+ for (int iu = iuMin; iu <= _iuLast; iu++)
+ {
+ uint u = _rgu[iu]--;
+ if (u > 0)
+ return;
+ }
+ // Borrowed off the end!
+ Contract.Assert(false, "Invalid call to ApplyBorrow");
+ }
+*/
+
+ private static uint AddCarry(ref uint u1, uint u2, uint uCarry)
+ {
+ ulong uu = (ulong)u1 + u2 + uCarry;
+ u1 = (uint)uu;
+ return (uint)(uu >> kcbitUint);
+ }
+
+ /*private static uint SubBorrow(ref uint u1, uint u2, uint uBorrow)
+ {
+ ulong uu = (ulong)u1 - u2 - uBorrow;
+ u1 = (uint)uu;
+ return (uint)-(int)(uu >> kcbitUint);
+ }
+
+ private static uint SubRevBorrow(ref uint u1, uint u2, uint uBorrow)
+ {
+ ulong uu = (ulong)u2 - u1 - uBorrow;
+ u1 = (uint)uu;
+ return (uint)-(int)(uu >> kcbitUint);
+ }*/
+
+ private static uint MulCarry(ref uint u1, uint u2, uint uCarry)
+ {
+ // This is guaranteed not to overflow.
+ ulong uuRes = (ulong)u1 * u2 + uCarry;
+ u1 = (uint)uuRes;
+ return (uint)(uuRes >> kcbitUint);
+ }
+
+ private static uint AddMulCarry(ref uint uAdd, uint uMul1, uint uMul2, uint uCarry)
+ {
+ // This is guaranteed not to overflow.
+ ulong uuRes = (ulong)uMul1 * uMul2 + uAdd + uCarry;
+ uAdd = (uint)uuRes;
+ return (uint)(uuRes >> kcbitUint);
+ }
+
+ // ReSharper disable once InconsistentNaming
+/*
+ internal static void GCD(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
+ {
+ // Use Lehmer's GCD, with improvements, after eliminating common powers of 2.
+ if (reg1._iuLast > 0 && reg1._rgu[0] == 0 || reg2._iuLast > 0 && reg2._rgu[0] == 0)
+ {
+ int cbit1 = reg1.MakeOdd();
+ int cbit2 = reg2.MakeOdd();
+ LehmerGcd(ref reg1, ref reg2);
+ int cbitMin = Math.Min(cbit1, cbit2);
+ if (cbitMin > 0)
+ reg1.ShiftLeft(cbitMin);
+ }
+ else
+ LehmerGcd(ref reg1, ref reg2);
+ }
+*/
+
+ // This leaves the GCD in reg1 and trash in reg2.
+ // This uses Lehmer's method, with test due to Jebelean / Belnkiy and Vidunas.
+ // See Knuth, vol 2, page 345; Jebelean (1993) "Improving the Multiprecision Euclidean Algorithm";
+ // and Belenkiy & Vidunas (1998) "A Greatest Common Divisor Algorithm".
+/*
+ private static void LehmerGcd(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
+ {
+ // This value has no real significance. Occ----ionally we want to subtract
+ // the two registers and keep the absolute value of the difference. To do
+ // so we need to pass a ref sign to Sub.
+ int signTmp = +1;
+
+ for (; ; )
+ {
+ reg1.AssertValid(true);
+ reg2.AssertValid(true);
+
+ int cuMax = reg1._iuLast + 1;
+ int cuMin = reg2._iuLast + 1;
+ if (cuMax < cuMin)
+ {
+ NumericsHelpers.Swap(ref reg1, ref reg2);
+ NumericsHelpers.Swap(ref cuMax, ref cuMin);
+ }
+ Contract.Assert(cuMax == reg1._iuLast + 1);
+ Contract.Assert(cuMin == reg2._iuLast + 1);
+
+ if (cuMin == 1)
+ {
+ if (cuMax == 1)
+ reg1._uSmall = NumericsHelpers.GCD(reg1._uSmall, reg2._uSmall);
+ else if (reg2._uSmall != 0)
+ reg1.Set(NumericsHelpers.GCD(Mod(ref reg1, reg2._uSmall), reg2._uSmall));
+ return;
+ }
+
+ if (cuMax == 2)
+ {
+ reg1.Set(NumericsHelpers.GCD(reg1.GetHigh2(2), reg2.GetHigh2(2)));
+ return;
+ }
+
+ if (cuMin <= cuMax - 2)
+ {
+ // reg1 is much larger than reg2, so just mod.
+ reg1.Mod(ref reg2);
+ continue;
+ }
+
+ ulong uu1 = reg1.GetHigh2(cuMax);
+ ulong uu2 = reg2.GetHigh2(cuMax);
+ Contract.Assert(uu1 != 0 && uu2 != 0);
+
+ int cbit = NumericsHelpers.CbitHighZero(uu1 | uu2);
+ if (cbit > 0)
+ {
+ uu1 = (uu1 << cbit) | (reg1._rgu[cuMax - 3] >> (kcbitUint - cbit));
+ // Note that [cuMax - 3] is correct, NOT [cuMin - 3].
+ uu2 = (uu2 << cbit) | (reg2._rgu[cuMax - 3] >> (kcbitUint - cbit));
+ }
+ if (uu1 < uu2)
+ {
+ NumericsHelpers.Swap(ref uu1, ref uu2);
+ NumericsHelpers.Swap(ref reg1, ref reg2);
+ }
+
+ // Make sure we don't overflow.
+ if (uu1 == ulong.MaxValue || uu2 == ulong.MaxValue)
+ {
+ uu1 >>= 1;
+ uu2 >>= 1;
+ }
+ Contract.Assert(uu1 >= uu2); // We ensured this above.
+ if (uu1 == uu2)
+ {
+ // The high bits are the same, so we don't know which
+ // is larger. No matter, just subtract one from the other
+ // and keep the absolute value of the result.
+ Contract.Assert(cuMax == cuMin);
+ reg1.Sub(ref signTmp, ref reg2);
+ Contract.Assert(reg1._iuLast < cuMin - 1);
+ continue;
+ }
+ if (NumericsHelpers.GetHi(uu2) == 0)
+ {
+ // reg1 is much larger than reg2, so just mod.
+ reg1.Mod(ref reg2);
+ continue;
+ }
+
+ // These are the coefficients to apply to reg1 and reg2 to get
+ // the new values, using: a * reg1 - b * reg2 and -c * reg1 + d * reg2.
+ uint a = 1, b = 0;
+ uint c = 0, d = 1;
+
+ for (; ; )
+ {
+ Contract.Assert(uu1 + a > a); // no overflow
+ Contract.Assert(uu2 + d > d);
+ Contract.Assert(uu1 > b);
+ Contract.Assert(uu2 > c);
+ Contract.Assert(uu2 + d <= uu1 - b);
+
+ uint uQuo = 1;
+ ulong uuNew = uu1 - uu2;
+ while (uuNew >= uu2 && uQuo < 32)
+ {
+ uuNew -= uu2;
+ uQuo++;
+ }
+ if (uuNew >= uu2)
+ {
+ ulong uuQuo = uu1 / uu2;
+ if (uuQuo > uint.MaxValue)
+ break;
+ uQuo = (uint)uuQuo;
+ uuNew = uu1 - uQuo * uu2;
+ }
+ ulong uuAdNew = a + (ulong)uQuo * c;
+ ulong uuBcNew = b + (ulong)uQuo * d;
+ if (uuAdNew > int.MaxValue || uuBcNew > int.MaxValue)
+ break;
+ // Jebelean / Belenkiy-Vidunas conditions
+ if (uuNew < uuBcNew || uuNew + uuAdNew > uu2 - c)
+ break;
+
+ Contract.Assert(uQuo == (uu1 + a - 1) / (uu2 - c));
+ Contract.Assert(uQuo == (uu1 - b) / (uu2 + d));
+
+ a = (uint)uuAdNew;
+ b = (uint)uuBcNew;
+ uu1 = uuNew;
+
+ if (uu1 <= b)
+ {
+ Contract.Assert(uu1 == b);
+ break;
+ }
+
+ Contract.Assert(uu1 + a > a); // no overflow
+ Contract.Assert(uu2 + d > d);
+ Contract.Assert(uu2 > c);
+ Contract.Assert(uu1 > b);
+ Contract.Assert(uu1 + a <= uu2 - c);
+
+ uQuo = 1;
+ uuNew = uu2 - uu1;
+ while (uuNew >= uu1 && uQuo < 32)
+ {
+ uuNew -= uu1;
+ uQuo++;
+ }
+ if (uuNew >= uu1)
+ {
+ ulong uuQuo = uu2 / uu1;
+ if (uuQuo > uint.MaxValue)
+ break;
+ uQuo = (uint)uuQuo;
+ uuNew = uu2 - uQuo * uu1;
+ }
+ uuAdNew = d + (ulong)uQuo * b;
+ uuBcNew = c + (ulong)uQuo * a;
+ if (uuAdNew > int.MaxValue || uuBcNew > int.MaxValue)
+ break;
+ // Jebelean / Belenkiy-Vidunas conditions
+ if (uuNew < uuBcNew || uuNew + uuAdNew > uu1 - b)
+ break;
+
+ Contract.Assert(uQuo == (uu2 + d - 1) / (uu1 - b));
+ Contract.Assert(uQuo == (uu2 - c) / (uu1 + a));
+
+ d = (uint)uuAdNew;
+ c = (uint)uuBcNew;
+ uu2 = uuNew;
+
+ if (uu2 <= c)
+ {
+ Contract.Assert(uu2 == c);
+ break;
+ }
+ }
+
+ if (b == 0)
+ {
+ Contract.Assert(a == 1 && c == 0 && d == 1);
+ Contract.Assert(uu1 > uu2); // We ensured this above.
+ if (uu1 / 2 >= uu2)
+ reg1.Mod(ref reg2);
+ else
+ reg1.Sub(ref signTmp, ref reg2);
+ }
+ else
+ {
+ // Replace reg1 with a * reg1 - b * reg2.
+ // Replace reg2 with -c * reg1 + d * reg2.
+ // Do everything mod cuMin uint's.
+ reg1.SetSizeKeep(cuMin, 0);
+ reg2.SetSizeKeep(cuMin, 0);
+ int nCarry1 = 0;
+ int nCarry2 = 0;
+ for (int iu = 0; iu < cuMin; iu++)
+ {
+ uint u1 = reg1._rgu[iu];
+ uint u2 = reg2._rgu[iu];
+ long nn1 = (long)u1 * a - (long)u2 * b + nCarry1;
+ long nn2 = (long)u2 * d - (long)u1 * c + nCarry2;
+ nCarry1 = (int)(nn1 >> kcbitUint);
+ nCarry2 = (int)(nn2 >> kcbitUint);
+ reg1._rgu[iu] = (uint)nn1;
+ reg2._rgu[iu] = (uint)nn2;
+ }
+ reg1.Trim();
+ reg2.Trim();
+ }
+ }
+ }
+*/
+
+ /*internal int CbitLowZero()
+ {
+ AssertValid(true);
+ if (_iuLast == 0)
+ {
+ if ((_uSmall & 1) != 0 || _uSmall == 0)
+ return 0;
+ return NumericsHelpers.CbitLowZero(_uSmall);
+ }
+
+ int iuMin = 0;
+ while (_rgu[iuMin] == 0)
+ iuMin++;
+ int cbit = NumericsHelpers.CbitLowZero(_rgu[iuMin]);
+ return cbit + iuMin * kcbitUint;
+ }*/
+
+ // Shift right until the number is odd. Return the number of bits
+ // shifted. Asserts that the register is trimmed.
+/*
+ internal int MakeOdd()
+ {
+ AssertValid(true);
+ int cbit = CbitLowZero();
+ if (cbit > 0)
+ ShiftRight(cbit);
+ return cbit;
+ }
+*/
+ }
+}
diff --git a/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs b/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
new file mode 100644
index 0000000..68c61bc
--- /dev/null
+++ b/runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
@@ -0,0 +1,425 @@
+// ==++==
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// ==--==
+
+using System;
+
+using Contracts = System.Diagnostics.Debug;
+using Contract = System.Diagnostics.Debug;
+//using System.Runtime.InteropServices;
+
+// ReSharper disable once CheckNamespace
+namespace Numerics
+{
+
+/*
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct DoubleUlong
+ {
+ [FieldOffset(0)]
+ internal double dbl;
+ [FieldOffset(0)]
+ internal ulong uu;
+ }
+*/
+
+
+ internal static class NumericsHelpers
+ {
+ private const int KcbitUint = 32;
+
+ /*internal static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite)
+ {
+ //Contract.Ensures(Contract.ValueAtReturn(out sign) == +1 || Contract.ValueAtReturn(out sign) == -1);
+
+ DoubleUlong du;
+ du.uu = 0;
+ du.dbl = dbl;
+
+ sign = 1 - ((int)(du.uu >> 62) & 2);
+ man = du.uu & 0x000FFFFFFFFFFFFF;
+ exp = (int)(du.uu >> 52) & 0x7FF;
+ if (exp == 0)
+ {
+ // Denormalized number.
+ fFinite = true;
+ if (man != 0)
+ exp = -1074;
+ }
+ else if (exp == 0x7FF)
+ {
+ // NaN or Inifite.
+ fFinite = false;
+ exp = int.MaxValue;
+ }
+ else
+ {
+ fFinite = true;
+ man |= 0x0010000000000000;
+ exp -= 1075;
+ }
+ }
+
+ internal static double GetDoubleFromParts(int sign, int exp, ulong man)
+ {
+ DoubleUlong du;
+ du.dbl = 0;
+
+ if (man == 0)
+ du.uu = 0;
+ else
+ {
+ // Normalize so that 0x0010 0000 0000 0000 is the highest bit set.
+ int cbitShift = CbitHighZero(man) - 11;
+ if (cbitShift < 0)
+ man >>= -cbitShift;
+ else
+ man <<= cbitShift;
+ exp -= cbitShift;
+ Contract.Assert((man & 0xFFF0000000000000) == 0x0010000000000000);
+
+ // Move the point to just behind the leading 1: 0x001.0 0000 0000 0000
+ // (52 bits) and skew the exponent (by 0x3FF == 1023).
+ exp += 1075;
+
+ if (exp >= 0x7FF)
+ {
+ // Infinity.
+ du.uu = 0x7FF0000000000000;
+ }
+ else if (exp <= 0)
+ {
+ // Denormalized.
+ exp--;
+ if (exp < -52)
+ {
+ // Underflow to zero.
+ du.uu = 0;
+ }
+ else
+ {
+ du.uu = man >> -exp;
+ Contract.Assert(du.uu != 0);
+ }
+ }
+ else
+ {
+ // Mask off the implicit high bit.
+ du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52);
+ }
+ }
+
+ if (sign < 0)
+ du.uu |= 0x8000000000000000;
+
+ return du.dbl;
+ }
+ */
+
+
+ // Do an in-place twos complement of d and also return the result.
+ // "Dangerous" because it causes a mutation and needs to be used
+ // with care for immutable types
+ internal static void DangerousMakeTwosComplement(uint[] d)
+ {
+ // first do complement and +1 as long as carry is needed
+ int i = 0;
+ uint v = 0;
+ for (; i < d.Length; i++)
+ {
+ v = ~d[i] + 1;
+ d[i] = v;
+ if (v != 0) { i++; break; }
+ }
+ if (v != 0)
+ {
+ // now ones complement is sufficient
+ for (; i < d.Length; i++)
+ {
+ d[i] = ~d[i];
+ }
+ }
+ else
+ {
+ //??? this is weird
+ d = resize(d, d.Length + 1);
+ d[d.Length - 1] = 1;
+ }
+ }
+
+ // ReSharper disable once InconsistentNaming
+ private static uint[] resize(uint[] v, int len)
+ {
+ if (v.Length == len) return v;
+ uint[] ret = new uint[len];
+ int n = Math.Min(v.Length, len);
+ for (int i = 0; i < n; i++)
+ {
+ ret[i] = v[i];
+ }
+ return ret;
+ }
+
+ internal static void Swap<T>(ref T a, ref T b)
+ {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ // ReSharper disable once InconsistentNaming
+/*
+ internal static uint GCD(uint u1, uint u2)
+ {
+ const int cvMax = 32;
+ if (u1 < u2)
+ goto LOther;
+ LTop:
+ Contract.Assert(u2 <= u1);
+ if (u2 == 0)
+ return u1;
+ for (int cv = cvMax; ; )
+ {
+ u1 -= u2;
+ if (u1 < u2)
+ break;
+ if (--cv == 0)
+ {
+ u1 %= u2;
+ break;
+ }
+ }
+ LOther:
+ Contract.Assert(u1 < u2);
+ if (u1 == 0)
+ return u2;
+ for (int cv = cvMax; ; )
+ {
+ u2 -= u1;
+ if (u2 < u1)
+ break;
+ if (--cv == 0)
+ {
+ u2 %= u1;
+ break;
+ }
+ }
+ goto LTop;
+ }
+*/
+
+ // ReSharper disable once InconsistentNaming
+/*
+ internal static ulong GCD(ulong uu1, ulong uu2)
+ {
+ const int cvMax = 32;
+ if (uu1 < uu2)
+ goto LOther;
+ LTop:
+ Contract.Assert(uu2 <= uu1);
+ if (uu1 <= uint.MaxValue)
+ goto LSmall;
+ if (uu2 == 0)
+ return uu1;
+ for (int cv = cvMax; ; )
+ {
+ uu1 -= uu2;
+ if (uu1 < uu2)
+ break;
+ if (--cv == 0)
+ {
+ uu1 %= uu2;
+ break;
+ }
+ }
+ LOther:
+ Contract.Assert(uu1 < uu2);
+ if (uu2 <= uint.MaxValue)
+ goto LSmall;
+ if (uu1 == 0)
+ return uu2;
+ for (int cv = cvMax; ; )
+ {
+ uu2 -= uu1;
+ if (uu2 < uu1)
+ break;
+ if (--cv == 0)
+ {
+ uu2 %= uu1;
+ break;
+ }
+ }
+ goto LTop;
+
+ LSmall:
+ uint u1 = (uint)uu1;
+ uint u2 = (uint)uu2;
+ if (u1 < u2)
+ goto LOtherSmall;
+ LTopSmall:
+ Contract.Assert(u2 <= u1);
+ if (u2 == 0)
+ return u1;
+ for (int cv = cvMax; ; )
+ {
+ u1 -= u2;
+ if (u1 < u2)
+ break;
+ if (--cv == 0)
+ {
+ u1 %= u2;
+ break;
+ }
+ }
+ LOtherSmall:
+ Contract.Assert(u1 < u2);
+ if (u1 == 0)
+ return u2;
+ for (int cv = cvMax; ; )
+ {
+ u2 -= u1;
+ if (u2 < u1)
+ break;
+ if (--cv == 0)
+ {
+ u2 %= u1;
+ break;
+ }
+ }
+ goto LTopSmall;
+ }
+*/
+
+ internal static ulong MakeUlong(uint uHi, uint uLo)
+ {
+ return ((ulong)uHi << KcbitUint) | uLo;
+ }
+
+ internal static uint GetLo(ulong uu)
+ {
+ return (uint)uu;
+ }
+
+ internal static uint GetHi(ulong uu)
+ {
+ return (uint)(uu >> KcbitUint);
+ }
+
+/*
+ internal static uint Abs(int a)
+ {
+ uint mask = (uint)(a >> 31);
+ return ((uint)a ^ mask) - mask;
+ }
+*/
+
+ // internal static ulong Abs(long a) {
+ // ulong mask = (ulong)(a >> 63);
+ // return ((ulong)a ^ mask) - mask;
+ // }
+
+ private static uint CombineHash(uint u1, uint u2)
+ {
+ return ((u1 << 7) | (u1 >> 25)) ^ u2;
+ }
+
+ internal static int CombineHash(int n1, int n2)
+ {
+ return (int)CombineHash((uint)n1, (uint)n2);
+ }
+ internal static int CbitHighZero(uint u)
+ {
+ if (u == 0)
+ return 32;
+
+ int cbit = 0;
+ if ((u & 0xFFFF0000) == 0)
+ {
+ cbit += 16;
+ u <<= 16;
+ }
+ if ((u & 0xFF000000) == 0)
+ {
+ cbit += 8;
+ u <<= 8;
+ }
+ if ((u & 0xF0000000) == 0)
+ {
+ cbit += 4;
+ u <<= 4;
+ }
+ if ((u & 0xC0000000) == 0)
+ {
+ cbit += 2;
+ u <<= 2;
+ }
+ if ((u & 0x80000000) == 0)
+ cbit += 1;
+ return cbit;
+ }
+
+ /*internal static int CbitLowZero(uint u)
+ {
+ if (u == 0)
+ return 32;
+
+ int cbit = 0;
+ if ((u & 0x0000FFFF) == 0)
+ {
+ cbit += 16;
+ u >>= 16;
+ }
+ if ((u & 0x000000FF) == 0)
+ {
+ cbit += 8;
+ u >>= 8;
+ }
+ if ((u & 0x0000000F) == 0)
+ {
+ cbit += 4;
+ u >>= 4;
+ }
+ if ((u & 0x00000003) == 0)
+ {
+ cbit += 2;
+ u >>= 2;
+ }
+ if ((u & 0x00000001) == 0)
+ cbit += 1;
+ return cbit;
+ }
+
+ internal static int CbitHighZero(ulong uu)
+ {
+ if ((uu & 0xFFFFFFFF00000000) == 0)
+ return 32 + CbitHighZero((uint)uu);
+ return CbitHighZero((uint)(uu >> 32));
+ }*/
+
+ // internal static int CbitLowZero(ulong uu) {
+ // if ((uint)uu == 0)
+ // return 32 + CbitLowZero((uint)(uu >> 32));
+ // return CbitLowZero((uint)uu);
+ // }
+ //
+ // internal static int Cbit(uint u) {
+ // u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
+ // u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
+ // u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
+ // u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
+ // return (int)((ushort)u + (ushort)(u >> 16));
+ // }
+ //
+ // static int Cbit(ulong uu) {
+ // uu = (uu & 0x5555555555555555) + ((uu >> 1) & 0x5555555555555555);
+ // uu = (uu & 0x3333333333333333) + ((uu >> 2) & 0x3333333333333333);
+ // uu = (uu & 0x0F0F0F0F0F0F0F0F) + ((uu >> 4) & 0x0F0F0F0F0F0F0F0F);
+ // uu = (uu & 0x00FF00FF00FF00FF) + ((uu >> 8) & 0x00FF00FF00FF00FF);
+ // uu = (uu & 0x0000FFFF0000FFFF) + ((uu >> 16) & 0x0000FFFF0000FFFF);
+ // return (int)((uint)uu + (uint)(uu >> 32));
+ // }
+ }
+}
+