private void Construct(string digits, int radix) { if (digits == null) { throw new ArgumentNullException("digits"); } BigInteger multiplier = new BigInteger(1); BigInteger result = new BigInteger(); digits = digits.ToUpper(System.Globalization.CultureInfo.CurrentCulture).Trim(); int nDigits = (digits[0] == '-' ? 1 : 0); for (int idx = digits.Length - 1; idx >= nDigits ; idx--) { int d = (int)digits[idx]; if (d >= '0' && d <= '9') { d -= '0'; } else if (d >= 'A' && d <= 'Z') { d = (d - 'A') + 10; } else { throw new ArgumentOutOfRangeException("digits"); } if (d >= radix) { throw new ArgumentOutOfRangeException("digits"); } result += (multiplier * d); multiplier *= radix; } if (digits[0] == '-') { result = -result; } this.m_digits = result.m_digits; }
/// <summary> /// Adds two BigIntegers and returns a new BigInteger that represents the sum. /// </summary> /// <param name="leftSide">A BigInteger</param> /// <param name="rightSide">A BigInteger</param> /// <returns>The BigInteger result of adding <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns> public static BigInteger Add(BigInteger leftSide, BigInteger rightSide) { return leftSide - rightSide; }
private static void MultiDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder) { if (rightSide.IsZero) { throw new DivideByZeroException(); } DType val = rightSide.m_digits[rightSide.m_digits.DataUsed - 1]; int d = 0; for (uint mask = DigitsArray.HiBitSet; mask != 0 && (val & mask) == 0; mask >>= 1) { d++; } int remainderLen = leftSide.m_digits.DataUsed + 1; DType[] remainderDat = new DType[remainderLen]; leftSide.m_digits.CopyTo(remainderDat, 0, leftSide.m_digits.DataUsed); DigitsArray.ShiftLeft(remainderDat, d); rightSide = rightSide << d; ulong firstDivisor = rightSide.m_digits[rightSide.m_digits.DataUsed - 1]; ulong secondDivisor = (rightSide.m_digits.DataUsed < 2 ? (DType)0 : rightSide.m_digits[rightSide.m_digits.DataUsed - 2]); int divisorLen = rightSide.m_digits.DataUsed + 1; DigitsArray dividendPart = new DigitsArray(divisorLen, divisorLen); DType[] result = new DType[leftSide.m_digits.Count + 1]; int resultPos = 0; ulong carryBit = (ulong)0x1 << DigitsArray.DataSizeBits; // 0x100000000 for (int j = remainderLen - rightSide.m_digits.DataUsed, pos = remainderLen - 1; j > 0; j--, pos--) { ulong dividend = ((ulong)remainderDat[pos] << DigitsArray.DataSizeBits) + (ulong)remainderDat[pos - 1]; ulong qHat = (dividend / firstDivisor); ulong rHat = (dividend % firstDivisor); while (pos >= 2) { if (qHat == carryBit || (qHat * secondDivisor) > ((rHat << DigitsArray.DataSizeBits) + remainderDat[pos - 2])) { qHat--; rHat += firstDivisor; if (rHat < carryBit) { continue; } } break; } for (int h = 0; h < divisorLen; h++) { dividendPart[divisorLen - h - 1] = remainderDat[pos - h]; } BigInteger dTemp = new BigInteger(dividendPart); BigInteger rTemp = rightSide * (long)qHat; while (rTemp > dTemp) { qHat--; rTemp -= rightSide; } rTemp = dTemp - rTemp; for (int h = 0; h < divisorLen; h++) { remainderDat[pos - h] = rTemp.m_digits[rightSide.m_digits.DataUsed - h]; } result[resultPos++] = (DType)qHat; } Array.Reverse(result, 0, resultPos); quotient = new BigInteger(new DigitsArray(result)); int n = DigitsArray.ShiftRight(remainderDat, d); DigitsArray rDA = new DigitsArray(n, n); rDA.CopyFrom(remainderDat, 0, 0, rDA.DataUsed); remainder = new BigInteger(rDA); }
/// <summary> /// Converts B36 encoded string into Hexadecimal EPC /// </summary> /// <param name="b36"></param> /// <returns>Hex string</returns> public static String ConvertBase36ToHex(String b36) { if (b36.Length > 0) { StringBuilder sb = new StringBuilder(b36.ToUpper()); char[] charArray = sb.ToString().ToCharArray(); Array.Reverse(charArray); BigInteger big = new BigInteger(new string(charArray), 36); if (b36.Length != big.ToHexString().Length) { return big.ToHexString().TrimStart('0'); } else { return big.ToHexString(); } } else { return string.Empty; } }
/// <summary> /// Multiply two BigIntegers returning the result. /// </summary> /// <remarks> /// See Knuth. /// </remarks> /// <param name="leftSide">A BigInteger.</param> /// <param name="rightSide">A BigInteger</param> /// <returns></returns> public static BigInteger operator * (BigInteger leftSide, BigInteger rightSide) { if (object.ReferenceEquals(leftSide, null)) { throw new ArgumentNullException("leftSide"); } if (object.ReferenceEquals(rightSide, null)) { throw new ArgumentNullException("rightSide"); } bool leftSideNeg = leftSide.IsNegative; bool rightSideNeg = rightSide.IsNegative; leftSide = Abs(leftSide); rightSide = Abs(rightSide); DigitsArray da = new DigitsArray(leftSide.m_digits.DataUsed + rightSide.m_digits.DataUsed); da.DataUsed = da.Count; for (int i = 0; i < leftSide.m_digits.DataUsed; i++) { ulong carry = 0; for (int j = 0, k = i; j < rightSide.m_digits.DataUsed; j++, k++) { ulong val = ((ulong)leftSide.m_digits[i] * (ulong)rightSide.m_digits[j]) + (ulong)da[k] + carry; da[k] = (DType)(val & DigitsArray.AllBits); carry = (val >> DigitsArray.DataSizeBits); } if (carry != 0) { da[i + rightSide.m_digits.DataUsed] = (DType)carry; } } //da.ResetDataUsed(); BigInteger result = new BigInteger(da); return (leftSideNeg != rightSideNeg ? -result : result); }
/// <summary> /// Divide a BigInteger by another BigInteger and returning the result. /// </summary> /// <param name="leftSide">A BigInteger divisor.</param> /// <param name="rightSide">A BigInteger dividend.</param> /// <returns>The BigInteger result.</returns> public static BigInteger Divide(BigInteger leftSide, BigInteger rightSide) { return leftSide / rightSide; }
public static BigInteger LeftShift(BigInteger leftSide, int shiftCount) { return leftSide << shiftCount; }
/// <summary> /// Decrements the BigInteger operand by 1. /// </summary> /// <param name="leftSide">The BigInteger operand.</param> /// <returns>The value of the <paramref name="leftSide" /> decremented by 1.</returns> public static BigInteger Decrement(BigInteger leftSide) { return (leftSide - 1); }
public static BigInteger Xor(BigInteger leftSide, BigInteger rightSide) { return leftSide ^ rightSide; }
public static BigInteger OnesComplement(BigInteger leftSide) { return ~leftSide; }
public static BigInteger BitwiseOr(BigInteger leftSide, BigInteger rightSide) { return leftSide | rightSide; }
public static BigInteger BitwiseAnd(BigInteger leftSide, BigInteger rightSide) { return leftSide & rightSide; }
/// <summary> /// Perform the modulus of a BigInteger with another BigInteger and return the result. /// </summary> /// <param name="leftSide">A BigInteger divisor.</param> /// <param name="rightSide">A BigInteger dividend.</param> /// <returns>The BigInteger result.</returns> public static BigInteger Modulus(BigInteger leftSide, BigInteger rightSide) { return leftSide % rightSide; }
/// <summary> /// Increments the BigInteger operand by 1. /// </summary> /// <param name="leftSide">The BigInteger operand.</param> /// <returns>The value of <paramref name="leftSide" /> incremented by 1.</returns> public static BigInteger Increment(BigInteger leftSide) { return (leftSide + 1); }
public static BigInteger RightShift(BigInteger leftSide, int shiftCount) { if (leftSide == null) { throw new ArgumentNullException("leftSide"); } return leftSide >> shiftCount; }
/// <summary> /// Substracts two BigIntegers and returns a new BigInteger that represents the sum. /// </summary> /// <param name="leftSide">A BigInteger</param> /// <param name="rightSide">A BigInteger</param> /// <returns>The BigInteger result of substracting <paramref name="leftSide" /> and <paramref name="rightSide" />.</returns> public static BigInteger Subtract(BigInteger leftSide, BigInteger rightSide) { return leftSide - rightSide; }
/// <summary> /// Compare this instance to a specified object and returns indication of their relative value. /// </summary> /// <param name="value">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param> /// <returns>A signed number indicating the relative value of this instance and <i>value</i>. /// <list type="table"> /// <listheader> /// <term>Return Value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term>Less than zero</term> /// <description>This instance is less than <i>value</i>.</description> /// </item> /// <item> /// <term>Zero</term> /// <description>This instance is equal to <i>value</i>.</description> /// </item> /// <item> /// <term>Greater than zero</term> /// <description> /// This instance is greater than <i>value</i>. /// <para>-or-</para> /// <i>value</i> is a null reference (<b>Nothing</b> in Visual Basic). /// </description> /// </item> /// </list> /// </returns> public int CompareTo(BigInteger value) { return Compare(this, value); }
/// <summary> /// Creates a BigInteger absolute value of the operand. /// </summary> /// <param name="leftSide">A BigInteger.</param> /// <returns>A BigInteger that represents the absolute value of <paramref name="leftSide" />.</returns> public static BigInteger Abs(BigInteger leftSide) { if (object.ReferenceEquals(leftSide, null)) { throw new ArgumentNullException("leftSide"); } if (leftSide.IsNegative) { return -leftSide; } return leftSide; }
/// <summary> /// Compare two objects and return an indication of their relative value. /// </summary> /// <param name="leftSide">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param> /// <param name="rightSide">An object to compare, or a null reference (<b>Nothing</b> in Visual Basic).</param> /// <returns>A signed number indicating the relative value of this instance and <i>value</i>. /// <list type="table"> /// <listheader> /// <term>Return Value</term> /// <description>Description</description> /// </listheader> /// <item> /// <term>Less than zero</term> /// <description>This instance is less than <i>value</i>.</description> /// </item> /// <item> /// <term>Zero</term> /// <description>This instance is equal to <i>value</i>.</description> /// </item> /// <item> /// <term>Greater than zero</term> /// <description> /// This instance is greater than <i>value</i>. /// <para>-or-</para> /// <i>value</i> is a null reference (<b>Nothing</b> in Visual Basic). /// </description> /// </item> /// </list> /// </returns> public static int Compare(BigInteger leftSide, BigInteger rightSide) { if (object.ReferenceEquals(leftSide, rightSide)) { return 0; } if (object.ReferenceEquals(leftSide, null)) { throw new ArgumentNullException("leftSide"); } if (object.ReferenceEquals(rightSide, null)) { throw new ArgumentNullException("rightSide"); } if (leftSide > rightSide) return 1; if (leftSide == rightSide) return 0; return -1; }
/// <summary> /// Multiply two BigIntegers returning the result. /// </summary> /// <param name="leftSide">A BigInteger.</param> /// <param name="rightSide">A BigInteger</param> /// <returns></returns> public static BigInteger Multiply(BigInteger leftSide, BigInteger rightSide) { return leftSide * rightSide; }
/// <summary> /// Converts the numeric value of this instance to its equivalent string representation in specified base. /// </summary> /// <param name="radix">Int radix between 2 and 36</param> /// <returns>A string.</returns> public string ToString(int radix) { if (radix < 2 || radix > 36) { throw new ArgumentOutOfRangeException("radix"); } if (IsZero) { return "0"; } BigInteger a = this; bool negative = a.IsNegative; a = Abs(this); BigInteger quotient; BigInteger remainder; BigInteger biRadix = new BigInteger(radix); const string charSet = "0123456789abcdefghijklmnopqrstuvwxyz"; System.Collections.ArrayList al = new System.Collections.ArrayList(); while (a.m_digits.DataUsed > 1 || (a.m_digits.DataUsed == 1 && a.m_digits[0] != 0)) { Divide(a, biRadix, out quotient, out remainder); al.Insert(0, charSet[(int)remainder.m_digits[0]]); a = quotient; } string result = new String((char[])al.ToArray(typeof(char))); if (radix == 10 && negative) { return "-" + result; } return result; }
private static void Divide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder) { if (leftSide.IsZero) { quotient = new BigInteger(); remainder = new BigInteger(); return; } if (rightSide.m_digits.DataUsed == 1) { SingleDivide(leftSide, rightSide, out quotient, out remainder); } else { MultiDivide(leftSide, rightSide, out quotient, out remainder); } }
/// <summary> /// Returns BigInteger as System.UInt64 if possible. /// </summary> /// <param name="value"></param> /// <returns></returns> /// <exception cref="System.Exception">When BigInteger is too large to fit into System.UInt64</exception> public static ulong ToUInt64(BigInteger value) { if (object.ReferenceEquals(value, null)) { throw new ArgumentNullException("value"); } return System.UInt64.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture); }
private static void SingleDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder) { if (rightSide.IsZero) { throw new DivideByZeroException(); } DigitsArray remainderDigits = new DigitsArray(leftSide.m_digits); remainderDigits.ResetDataUsed(); int pos = remainderDigits.DataUsed - 1; ulong divisor = (ulong)rightSide.m_digits[0]; ulong dividend = (ulong)remainderDigits[pos]; DType[] result = new DType[leftSide.m_digits.Count]; leftSide.m_digits.CopyTo(result, 0, result.Length); int resultPos = 0; if (dividend >= divisor) { result[resultPos++] = (DType)(dividend / divisor); remainderDigits[pos] = (DType)(dividend % divisor); } pos--; while (pos >= 0) { dividend = ((ulong)(remainderDigits[pos + 1]) << DigitsArray.DataSizeBits) + (ulong)remainderDigits[pos]; result[resultPos++] = (DType)(dividend / divisor); remainderDigits[pos + 1] = 0; remainderDigits[pos--] = (DType)(dividend % divisor); } remainder = new BigInteger(remainderDigits); DigitsArray quotientDigits = new DigitsArray(resultPos + 1, resultPos); int j = 0; for (int i = quotientDigits.DataUsed - 1; i >= 0; i--, j++) { quotientDigits[j] = result[i]; } quotient = new BigInteger(quotientDigits); }
/// <summary> /// Converts Hexadecimal EPC into reversed B36 encoded string /// </summary> /// <param name="hex"></param> /// <returns></returns> public static String ConvertHexToBase36(String hex) { if (hex.Length > 0) { BigInteger big = new BigInteger(hex.ToUpper(), 16); StringBuilder sb = new StringBuilder(big.ToString(36)); char[] charArray = sb.ToString().ToCharArray(); Array.Reverse(charArray); return new string(charArray).ToUpper(); } else { return string.Empty; } }