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); }
private void ConstructFrom(byte[] array, int offset, int length) { if (array == null) { throw new ArgumentNullException("array"); } if (offset > array.Length || length > array.Length) { throw new ArgumentOutOfRangeException("offset"); } if (length > array.Length || (offset + length) > array.Length) { throw new ArgumentOutOfRangeException("length"); } int estSize = length / 4; int leftOver = length & 3; if (leftOver != 0) { ++estSize; } m_digits = new DigitsArray(estSize + 1, 0); // alloc one extra since we can't init -'s from here. for (int i = offset + length - 1, j = 0; (i - offset) >= 3; i -= 4, j++) { m_digits[j] = (DType)((array[i - 3] << 24) + (array[i - 2] << 16) + (array[i - 1] << 8) + array[i]); m_digits.DataUsed++; } DType accumulator = 0; for (int i = leftOver; i > 0; i--) { DType digit = array[offset + leftOver - i]; digit = (digit << ((i - 1) * 8)); accumulator |= digit; } m_digits[m_digits.DataUsed] = accumulator; m_digits.ResetDataUsed(); }
/// <summary> /// Copy constructor, doesn't copy the digits parameter, assumes <code>this</code> owns the DigitsArray. /// </summary> /// <remarks>The <paramef name="digits" /> parameter is saved and reset.</remarks> /// <param name="digits"></param> private BigInteger(DigitsArray digits) { digits.ResetDataUsed(); this.m_digits = digits; }
/// <summary> /// Creates a BigInteger with the value of the operand. Can never be negative. /// </summary> /// <param name="number">A unsigned long.</param> public BigInteger(ulong number) { m_digits = new DigitsArray((8 / DigitsArray.DataSizeOf) + 1, 0); while (number != 0 && m_digits.DataUsed < m_digits.Count) { m_digits[m_digits.DataUsed] = (DType)(number & DigitsArray.AllBits); number >>= DigitsArray.DataSizeBits; m_digits.DataUsed++; } m_digits.ResetDataUsed(); }