internal static EInteger FindPowerOfTenFromBig(EInteger bigintExponent) { int sign = bigintExponent.Sign; if (sign < 0) { return(EInteger.Zero); } if (sign == 0) { return(EInteger.One); } if (bigintExponent.CompareTo(ValueBigInt36) <= 0) { return(FindPowerOfTen((int)bigintExponent)); } FastInteger intcurexp = FastInteger.FromBig(bigintExponent); EInteger mantissa = EInteger.One; EInteger bigpow = EInteger.Zero; // DebugUtility.Log("Getting power of ten from big "+bigintExponent); while (intcurexp.Sign > 0) { if (intcurexp.CompareToInt(18) <= 0) { bigpow = FindPowerOfTen(intcurexp.AsInt32()); mantissa *= (EInteger)bigpow; break; } if (intcurexp.CompareToInt(9999999) <= 0) { int val = intcurexp.AsInt32(); bigpow = FindPowerOfFive(val); bigpow <<= val; mantissa *= (EInteger)bigpow; break; } if (bigpow.IsZero) { bigpow = FindPowerOfFive(9999999); bigpow <<= 9999999; } mantissa *= bigpow; intcurexp.AddInt(-9999999); } return(mantissa); }
public void TruncateRight(FastInteger fastint) { if (fastint == null) { throw new ArgumentNullException("fastint"); } if (fastint.CanFitInInt32()) { int fi = fastint.AsInt32(); if (fi < 0) { return; } if (!this.isSmall) { if (this.shiftedBigInt.CanFitInInt64()) { this.TruncateRightLong(this.shiftedBigInt.ToInt64Checked(), fi); } else { this.ShiftRightBig(fi, true); } } else { this.TruncateRightSmall(fi); } } else { this.ShiftRight(fastint); } }
public void ShiftRight(FastInteger fastint) { if (fastint.Sign <= 0) { return; } if (fastint.CanFitInInt32()) { this.ShiftRightInt(fastint.AsInt32()); } else { EInteger bi = fastint.AsEInteger(); while (bi.Sign > 0) { var count = 1000000; if (bi.CompareTo((EInteger)1000000) < 0) { count = (int)bi; } this.ShiftRightInt(count); bi -= (EInteger)count; if (this.isSmall ? this.shiftedSmall == 0 : this.shiftedBigInt.IsZero) { break; } } } }
public static FastIntegerFixed FromFastInteger(FastInteger fi) { if (fi.CanFitInInt32()) { return(FromInt32(fi.AsInt32())); } else { return(FastIntegerFixed.FromBig(fi.AsEInteger())); } }
public static EInteger ReduceTrailingZeros( EInteger bigmant, FastInteger exponentMutable, int radix, FastInteger digits, FastInteger precision, FastInteger idealExp) { #if DEBUG if (precision != null && digits == null) { throw new ArgumentException("doesn't satisfy precision==null || digits!=null"); } #endif if (bigmant.IsZero) { exponentMutable.SetInt(0); return(bigmant); } var bigradix = (EInteger)radix; var bitToTest = 0; var bitsToShift = new FastInteger(0); while (!bigmant.IsZero) { if (precision != null && digits.CompareTo(precision) == 0) { break; } if (idealExp != null && exponentMutable.CompareTo(idealExp) == 0) { break; } if (radix == 2) { if (bitToTest < Int32.MaxValue) { if (bigmant.GetSignedBit(bitToTest)) { break; } ++bitToTest; bitsToShift.Increment(); } else { if (!bigmant.IsEven) { break; } bigmant >>= 1; } } else { EInteger bigrem; EInteger bigquo; { EInteger[] divrem = bigmant.DivRem(bigradix); bigquo = divrem[0]; bigrem = divrem[1]; } if (!bigrem.IsZero) { break; } bigmant = bigquo; } exponentMutable.Increment(); if (digits != null) { digits.Decrement(); } } if (radix == 2 && !bitsToShift.IsValueZero) { while (bitsToShift.CompareToInt(1000000) > 0) { bigmant >>= 1000000; bitsToShift.SubtractInt(1000000); } int tmpshift = bitsToShift.AsInt32(); bigmant >>= tmpshift; } return(bigmant); }
internal static EInteger FindPowerOfFiveFromBig(EInteger diff) { int sign = diff.Sign; if (sign < 0) { return(EInteger.Zero); } if (sign == 0) { return(EInteger.One); } FastInteger intcurexp = FastInteger.FromBig(diff); if (intcurexp.CompareToInt(54) <= 0) { return(FindPowerOfFive(intcurexp.AsInt32())); } EInteger mantissa = EInteger.One; EInteger bigpow; EInteger origdiff = diff; bigpow = ValuePowerOfFiveCache.GetCachedPower(origdiff); if (bigpow != null) { return(bigpow); } EInteger[] otherPower = ValuePowerOfFiveCache.FindCachedPowerOrSmaller(origdiff); if (otherPower != null) { intcurexp.SubtractBig(otherPower[0]); bigpow = otherPower[1]; mantissa = bigpow; } else { bigpow = EInteger.Zero; } while (intcurexp.Sign > 0) { if (intcurexp.CompareToInt(27) <= 0) { bigpow = FindPowerOfFive(intcurexp.AsInt32()); mantissa *= (EInteger)bigpow; break; } if (intcurexp.CompareToInt(9999999) <= 0) { bigpow = FindPowerOfFive(1).Pow(intcurexp.AsInt32()); mantissa *= (EInteger)bigpow; break; } if (bigpow.IsZero) { bigpow = FindPowerOfFive(1).Pow(9999999); } mantissa *= bigpow; intcurexp.AddInt(-9999999); } ValuePowerOfFiveCache.AddPower(origdiff, mantissa); return(mantissa); }
private void ShiftToDigitsBig(int digits, bool truncate) { // Shifts a number until it reaches the given number of digits, // gathering information on whether the last digit discarded is set // and whether the discarded digits to the right of that digit are set. // Assumes that the big integer being shifted is positive. if (this.knownDigitLength != null) { if (this.knownDigitLength.CompareToInt(digits) <= 0) { return; } } string str; this.knownDigitLength = this.knownDigitLength ?? this.CalcKnownDigitLength(); if (this.knownDigitLength.CompareToInt(digits) <= 0) { return; } FastInteger digitDiff = this.knownDigitLength.Copy().SubtractInt(digits); if (truncate && digitDiff.CanFitInInt32()) { this.TruncateRight(digitDiff); return; } if (digitDiff.CompareToInt(1) == 0) { EInteger bigrem; EInteger bigquo; EInteger[] divrem = this.shiftedBigInt.DivRem(ValueTen); bigquo = divrem[0]; bigrem = divrem[1]; this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = (int)bigrem; this.shiftedBigInt = bigquo; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.Add(digitDiff); this.UpdateKnownLength(digitDiff); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; return; } if (digitDiff.CompareToInt(9) <= 0) { EInteger bigrem; int diffInt = digitDiff.AsInt32(); EInteger radixPower = NumberUtility.FindPowerOfTen(diffInt); EInteger bigquo; EInteger[] divrem = this.shiftedBigInt.DivRem(radixPower); bigquo = divrem[0]; bigrem = divrem[1]; var rem = (int)bigrem; this.bitsAfterLeftmost |= this.bitLeftmost; for (var i = 0; i < diffInt; ++i) { if (i == diffInt - 1) { this.bitLeftmost = rem % 10; } else { int intQuot = (rem < 43698) ? ((rem * 26215) >> 18) : (rem / 10); this.bitsAfterLeftmost |= rem - (intQuot * 10); rem = intQuot; } } this.shiftedBigInt = bigquo; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.Add(digitDiff); this.UpdateKnownLength(digitDiff); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; return; } if (digitDiff.CanFitInInt32()) { #if DEBUG if (!(digitDiff.CompareToInt(2) > 0)) { throw new ArgumentException( "doesn't satisfy digitDiff.CompareToInt(2)>0"); } #endif EInteger bigrem = null; EInteger bigquo; EInteger[] divrem; if (!this.shiftedBigInt.IsEven || this.bitsAfterLeftmost != 0) { EInteger radixPower = NumberUtility.FindPowerOfTen(digitDiff.AsInt32() - 1); this.bitsAfterLeftmost |= 1; bigquo = this.shiftedBigInt.Divide(radixPower); } else { EInteger radixPower = NumberUtility.FindPowerOfTen(digitDiff.AsInt32() - 1); divrem = this.shiftedBigInt.DivRem(radixPower); bigquo = divrem[0]; bigrem = divrem[1]; this.bitsAfterLeftmost |= this.bitLeftmost; if (!bigrem.IsZero) { this.bitsAfterLeftmost |= 1; } } EInteger bigquo2; divrem = bigquo.DivRem(ValueTen); bigquo2 = divrem[0]; bigrem = divrem[1]; this.bitLeftmost = (int)bigrem; this.shiftedBigInt = bigquo2; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.Add(digitDiff); this.UpdateKnownLength(digitDiff); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; return; } str = this.shiftedBigInt.ToString(); // NOTE: Will be 1 if the value is 0 int digitLength = str.Length; this.knownDigitLength = new FastInteger(digitLength); // Shift by the difference in digit length if (digitLength > digits) { int digitShift = digitLength - digits; this.UpdateKnownLengthInt(digitShift); var newLength = (int)(digitLength - digitShift); // Console.WriteLine("dlen= " + digitLength + " dshift=" + // digitShift + " newlen= " + newLength); this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); if (digitShift <= Int32.MaxValue) { this.discardedBitCount.AddInt((int)digitShift); } else { this.discardedBitCount.AddBig((EInteger)digitShift); } for (int i = str.Length - 1; i >= 0; --i) { this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = (int)(str[i] - '0'); --digitShift; if (digitShift <= 0) { break; } } if (newLength <= 9) { this.isSmall = true; this.shiftedSmall = FastParseLong(str, 0, newLength); } else { this.shiftedBigInt = EInteger.FromSubstring(str, 0, newLength); } this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; } }
public void ShiftToDigits( FastInteger bits, FastInteger preShift, bool truncate) { #if DEBUG if (bits.Sign < 0) { throw new ArgumentException("bits's sign (" + bits.Sign + ") is less than 0"); } #endif if (preShift != null && preShift.Sign > 0) { FastInteger kdl = this.knownDigitLength ?? this.CalcKnownDigitLength(); this.knownDigitLength = kdl; // DebugUtility.Log("bits=" + bits + " pre=" + preShift + " known=" + // (//kdl) + " [" + this.shiftedBigInt + "]"); if (kdl.CompareTo(bits) <= 0) { // Known digit length is already small enough if (truncate) { this.TruncateRight(preShift); } else { this.ShiftRight(preShift); } this.VerifyKnownLength(); return; } else { FastInteger bitDiff = kdl.Copy().Subtract(bits); // DebugUtility.Log("bitDiff=" + bitDiff); int cmp = bitDiff.CompareTo(preShift); if (cmp <= 0) { // Difference between desired digit length and current // length is smaller than the shift, make it the shift if (truncate) { this.TruncateRight(preShift); } else { this.ShiftRight(preShift); } this.VerifyKnownLength(); return; } else { if (truncate) { this.TruncateRight(bitDiff); } else { this.ShiftRight(bitDiff); } this.VerifyKnownLength(); return; } } } if (bits.CanFitInInt32()) { int intval = bits.AsInt32(); if (intval < 0) { throw new ArgumentException("intval (" + intval + ") is less than " + "0"); } if (this.isSmall) { this.ShiftToDigitsSmall(intval); } else { this.ShiftToDigitsBig(intval, truncate); } this.VerifyKnownLength(); } else { FastInteger kdl = this.knownDigitLength ?? this.CalcKnownDigitLength(); this.knownDigitLength = kdl; this.VerifyKnownLength(); EInteger bigintDiff = kdl.AsEInteger(); EInteger bitsBig = bits.AsEInteger(); bigintDiff -= (EInteger)bitsBig; if (bigintDiff.Sign > 0) { // current length is greater than the // desired bit length this.ShiftRight(FastInteger.FromBig(bigintDiff)); } this.VerifyKnownLength(); } }
internal static EInteger FindPowerOfFiveFromBig(EInteger diff) { int sign = diff.Sign; if (sign < 0) { return(EInteger.Zero); } if (sign == 0) { return(EInteger.One); } FastInteger intcurexp = FastInteger.FromBig(diff); if (intcurexp.CompareToInt(54) <= 0) { return(FindPowerOfFive(intcurexp.AsInt32())); } // DebugUtility.Log("Getting power of five from big "+diff); EInteger mantissa = EInteger.One; EInteger bigpow; EInteger origdiff = diff; bigpow = ValuePowerOfFiveCache.GetCachedPower(origdiff); if (bigpow != null) { return(bigpow); } EInteger[] otherPower = ValuePowerOfFiveCache.FindCachedPowerOrSmaller(origdiff); if (otherPower != null) { // DebugUtility.Log("Found cached power " +otherPower[0]+", " // +otherPower[1]); intcurexp.SubtractBig(otherPower[0]); bigpow = otherPower[1]; mantissa = bigpow; } else { bigpow = EInteger.Zero; } while (intcurexp.Sign > 0) { if (intcurexp.CompareToInt(27) <= 0) { bigpow = FindPowerOfFive(intcurexp.AsInt32()); mantissa *= (EInteger)bigpow; break; } if (intcurexp.CompareToInt(9999999) <= 0) { int icurexp = intcurexp.AsInt32(); int halficurexp = icurexp / 2; bigpow = FindPowerOfFive(halficurexp); bigpow = bigpow.Multiply( FindPowerOfFive(icurexp - halficurexp)); mantissa *= (EInteger)bigpow; break; } if (bigpow.IsZero) { bigpow = FindPowerOfFive(1).Pow(9999999); } mantissa *= bigpow; intcurexp.AddInt(-9999999); } ValuePowerOfFiveCache.AddPower(origdiff, mantissa); return(mantissa); }
private void ShiftBigToBits(int bits) { // Shifts a number until it reaches the given number of bits, // gathering information on whether the last bit discarded is set and // whether the discarded bits to the right of that bit are set. Assumes // that the big integer being shifted is positive. if (this.knownBitLength != null) { if (this.knownBitLength.CompareToInt(bits) <= 0) { return; } } this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength(); if (this.knownBitLength.CompareToInt(bits) <= 0) { return; } // Shift by the difference in bit length if (this.knownBitLength.CompareToInt(bits) > 0) { var bs = 0; if (this.knownBitLength.CanFitInInt32()) { bs = this.knownBitLength.AsInt32(); bs -= bits; } else { FastInteger bitShift = this.knownBitLength.Copy().SubtractInt(bits); if (!bitShift.CanFitInInt32()) { this.ShiftRight(bitShift); return; } bs = bitShift.AsInt32(); } this.knownBitLength.SetInt(bits); this.discardedBitCount.AddInt(bs); if (bs == 1) { bool odd = !this.shiftedBigInt.IsEven; this.shiftedBigInt >>= 1; this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = odd ? 1 : 0; } else { this.bitsAfterLeftmost |= this.bitLeftmost; int lowestSetBit = this.shiftedBigInt.GetLowBit(); if (lowestSetBit < bs - 1) { // One of the discarded bits after // the last one is set this.bitsAfterLeftmost |= 1; this.bitLeftmost = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 : 0; } else if (lowestSetBit > bs - 1) { // Means all discarded bits are zero this.bitLeftmost = 0; } else { // Only the last discarded bit is set this.bitLeftmost = 1; } this.shiftedBigInt >>= bs; } if (bits < SmallBitLength) { // Shifting to small number of bits, // convert to small integer this.isSmall = true; this.shiftedSmall = (int)this.shiftedBigInt; } this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; } }
public void ShiftToDigits( FastInteger bits, FastInteger preShift, bool truncate) { if (bits.Sign < 0) { throw new ArgumentException("bits's sign(" + bits.Sign + ") is less than 0"); } if (preShift != null && preShift.Sign > 0) { this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength(); // DebugUtility.Log("bits=" + bits + " pre=" + preShift + " known=" + // (//kbl) + " [" + this.shiftedBigInt + "]"); if (this.knownBitLength.CompareTo(bits) <= 0) { // Known digit length is already small enough // NOTE: For BitShiftAccumulator, truncating and shifting // are the same, unlike in DigitShiftAccumulator this.ShiftRight(preShift); this.VerifyKnownLength(); return; } else { FastInteger bitDiff = this.knownBitLength.Copy() .Subtract(bits); // DebugUtility.Log("bitDiff=" + bitDiff); int cmp = bitDiff.CompareTo(preShift); if (cmp <= 0) { // NOTE: For BitShiftAccumulator, truncating and shifting // are the same, unlike in DigitShiftAccumulator this.ShiftRight(preShift); this.VerifyKnownLength(); return; } else { // NOTE: For BitShiftAccumulator, truncating and shifting // are the same, unlike in DigitShiftAccumulator this.ShiftRight(bitDiff); this.VerifyKnownLength(); return; } } } if (bits.CanFitInInt32()) { this.ShiftToDigitsInt(bits.AsInt32()); this.VerifyKnownLength(); } else { this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength(); EInteger bigintDiff = this.knownBitLength.AsEInteger(); EInteger bitsBig = bits.AsEInteger(); bigintDiff -= (EInteger)bitsBig; if (bigintDiff.Sign > 0) { // current length is greater than the // desired bit length this.ShiftRight(FastInteger.FromBig(bigintDiff)); } this.VerifyKnownLength(); } }