diff options
Diffstat (limited to 'runtime/VMProtect.Runtime/Numerics/BigInteger.cs')
-rw-r--r-- | runtime/VMProtect.Runtime/Numerics/BigInteger.cs | 2012 |
1 files changed, 2012 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 |