public static MyBigType operator >>(MyBigType leftSide, int shiftCount) { if (leftSide == null) { throw new ArgumentNullException("leftSide"); } ArrayForDigits da = new ArrayForDigits(leftSide.m_digits); da.DataUsed = da.ShiftRight(shiftCount); if (leftSide.IsNegative) { for (int i = da.Count - 1; i >= da.DataUsed; i--) { da[i] = ArrayForDigits.AllBits; } unsignIn mask = ArrayForDigits.HiBitSet; for (int i = 0; i < ArrayForDigits.DataSizeBits; i++) { if ((da[da.DataUsed - 1] & mask) == ArrayForDigits.HiBitSet) { break; } da[da.DataUsed - 1] |= mask; mask >>= 1; } da.DataUsed = da.Count; } return(new MyBigType(da)); }
static ArrayForDigits() { unchecked { AllBits = (unsignIn) ~((unsignIn)0); HiBitSet = (unsignIn)(((unsignIn)1) << (DataSizeBits) - 1); } }
private static void SingleDivide(MyBigType leftSide, MyBigType rightSide, out MyBigType quotient, out MyBigType remainder) { if (rightSide.IsZero) { throw new DivideByZeroException(); } ArrayForDigits remainderDigits = new ArrayForDigits(leftSide.m_digits); remainderDigits.ResetDataUsed(); int pos = remainderDigits.DataUsed - 1; ulong divisor = (ulong)rightSide.m_digits[0]; ulong dividend = (ulong)remainderDigits[pos]; unsignIn[] result = new unsignIn[leftSide.m_digits.Count]; leftSide.m_digits.CopyTo(result, 0, result.Length); int resultPos = 0; if (dividend >= divisor) { result[resultPos++] = (unsignIn)(dividend / divisor); remainderDigits[pos] = (unsignIn)(dividend % divisor); } pos--; while (pos >= 0) { dividend = ((ulong)(remainderDigits[pos + 1]) << ArrayForDigits.DataSizeBits) + (ulong)remainderDigits[pos]; result[resultPos++] = (unsignIn)(dividend / divisor); remainderDigits[pos + 1] = 0; remainderDigits[pos--] = (unsignIn)(dividend % divisor); } remainder = new MyBigType(remainderDigits); ArrayForDigits quotientDigits = new ArrayForDigits(resultPos + 1, resultPos); int j = 0; for (int i = quotientDigits.DataUsed - 1; i >= 0; i--, j++) { quotientDigits[j] = result[i]; } quotient = new MyBigType(quotientDigits); }
internal int ShiftLeftWithoutOverflow(int shiftCount) { if (shiftCount == 0) { return(m_data.Length); } List <unsignIn> temporary = new List <unsignIn>(m_data); int shiftAmount = ArrayForDigits.DataSizeBits; for (int count = shiftCount; count > 0; count -= shiftAmount) { if (count < shiftAmount) { shiftAmount = count; } ulong carry = 0; for (int i = 0; i < temporary.Count; i++) { ulong val = ((ulong)temporary[i]) << shiftAmount; val |= carry; temporary[i] = (unsignIn)(val & ArrayForDigits.AllBits); carry = (val >> ArrayForDigits.DataSizeBits); } if (carry != 0) { unsignIn lastNum = (unsignIn)carry; if (IsNegative) { int byteCount = (int)Math.Floor(Math.Log(carry, 2)); lastNum = (0xffffffff << byteCount) | (unsignIn)carry; } temporary.Add(lastNum); } } m_data = new unsignIn[temporary.Count]; temporary.CopyTo(m_data); return(m_data.Length); }
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 isSize = length / 4; int leftOver = length & 3; if (leftOver != 0) { ++isSize; } m_digits = new ArrayForDigits(isSize + 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] = (unsignIn)((array[i - 3] << 24) + (array[i - 2] << 16) + (array[i - 1] << 8) + array[i]); m_digits.DataUsed++; } unsignIn accumulator = 0; for (int i = leftOver; i > 0; i--) { unsignIn digit = array[offset + leftOver - i]; digit = (digit << ((i - 1) * 8)); accumulator |= digit; } m_digits[m_digits.DataUsed] = accumulator; m_digits.ResetDataUsed(); }
private static void MultiDivide(MyBigType leftSide, MyBigType rightSide, out MyBigType quotient, out MyBigType remainder) { if (rightSide.IsZero) { throw new DivideByZeroException(); } unsignIn val = rightSide.m_digits[rightSide.m_digits.DataUsed - 1]; int d = 0; for (uint mask = ArrayForDigits.HiBitSet; mask != 0 && (val & mask) == 0; mask >>= 1) { d++; } int remainderLen = leftSide.m_digits.DataUsed + 1; unsignIn[] remainderDat = new unsignIn[remainderLen]; leftSide.m_digits.CopyTo(remainderDat, 0, leftSide.m_digits.DataUsed); ArrayForDigits.ShiftLeft(remainderDat, d); rightSide = rightSide << d; ulong firstDivisor = rightSide.m_digits[rightSide.m_digits.DataUsed - 1]; ulong secondDivisor = (rightSide.m_digits.DataUsed < 2 ? (unsignIn)0 : rightSide.m_digits[rightSide.m_digits.DataUsed - 2]); int divisorLen = rightSide.m_digits.DataUsed + 1; ArrayForDigits dividendPart = new ArrayForDigits(divisorLen, divisorLen); unsignIn[] result = new unsignIn[leftSide.m_digits.Count + 1]; int resultPos = 0; ulong carryBit = (ulong)0x1 << ArrayForDigits.DataSizeBits; // 0x100000000 for (int j = remainderLen - rightSide.m_digits.DataUsed, pos = remainderLen - 1; j > 0; j--, pos--) { ulong dividend = ((ulong)remainderDat[pos] << ArrayForDigits.DataSizeBits) + (ulong)remainderDat[pos - 1]; ulong qHat = (dividend / firstDivisor); ulong rHat = (dividend % firstDivisor); while (pos >= 2) { if (qHat == carryBit || (qHat * secondDivisor) > ((rHat << ArrayForDigits.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]; } MyBigType dTemp = new MyBigType(dividendPart); MyBigType 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++] = (unsignIn)qHat; } Array.Reverse(result, 0, resultPos); quotient = new MyBigType(new ArrayForDigits(result)); int n = ArrayForDigits.ShiftRight(remainderDat, d); ArrayForDigits rDA = new ArrayForDigits(n, n); rDA.CopyFrom(remainderDat, 0, 0, rDA.DataUsed); remainder = new MyBigType(rDA); }