private T ReturnQuietNaN(T thisValue, EContext ctx) { EInteger mant = this.GetHelper().GetMantissa(thisValue).Abs(); var mantChanged = false; if (!mant.IsZero && ctx != null && ctx.HasMaxPrecision) { EInteger limit = this.GetHelper().MultiplyByRadixPower( EInteger.One, FastInteger.FromBig(ctx.Precision)); if (mant.CompareTo(limit) >= 0) { mant %= (EInteger)limit; mantChanged = true; } } int flags = this.GetHelper().GetFlags(thisValue); if (!mantChanged && (flags & BigNumberFlags.FlagQuietNaN) != 0) { return(thisValue); } flags &= BigNumberFlags.FlagNegative; flags |= BigNumberFlags.FlagQuietNaN; return(this.GetHelper().CreateNewWithFlags(mant, EInteger.Zero, flags)); }
private FastInteger CalcKnownBitLength() { if (this.isSmall) { int kb = SmallBitLength; for (int i = SmallBitLength - 1; i >= 0; --i) { if ((this.shiftedSmall & (1 << i)) != 0) { break; } --kb; } // Make sure bit length is 1 if value is 0 if (kb == 0) { ++kb; } return(new FastInteger(kb)); } if (this.shiftedBigInt.IsZero) { { return(new FastInteger(1)); } } long sbe = this.shiftedBigInt.GetSignedBitLengthAsInt64(); return((sbe < Int32.MaxValue) ? new FastInteger((int)sbe) : FastInteger.FromBig(this.shiftedBigInt.GetSignedBitLengthAsEInteger())); }
public static FastIntegerFixed[] DigitLengthBoundsFixed <THelper>( IRadixMathHelper <THelper> helper, FastIntegerFixed fei) { int radix = helper.GetRadix(); FastIntegerFixed fastpath = FastPathDigitLength(fei, radix); if (fastpath != null) { return(new FastIntegerFixed[] { fastpath, fastpath }); } if (radix == 10) { EInteger[] fi = DecimalDigitLengthBoundsAsEI(fei.ToEInteger()); return(new FastIntegerFixed[] { FastIntegerFixed.FromBig(fi[0]), FastIntegerFixed.FromBig(fi[1]), }); } else { FastInteger fi = helper.GetDigitLength(fei.ToEInteger()); FastIntegerFixed fif = FastIntegerFixed.FromFastInteger(fi); return(new FastIntegerFixed[] { fif, fif }); } }
public void ShiftRight(FastInteger fastint) { if (fastint.Sign <= 0) { return; } if (fastint.CanFitInInt32()) { this.ShiftRightInt(fastint.ToInt32()); } else { EInteger bi = fastint.ToEInteger(); 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; } } } }
private void ShiftToDigitsSmall(int digits) { var kb = 0; int v2 = this.shiftedSmall; kb = (v2 >= 1000000000) ? 10 : ((v2 >= 100000000) ? 9 : ((v2 >= 10000000) ? 8 : ((v2 >= 1000000) ? 7 : ((v2 >= 100000) ? 6 : ((v2 >= 10000) ? 5 : ((v2 >= 1000) ? 4 : ((v2 >= 100) ? 3 : ((v2 >= 10) ? 2 : 1)))))))); this.knownDigitLength = new FastInteger(kb); if (kb > digits) { var digitShift = (int)(kb - digits); this.UpdateKnownLengthInt(digitShift); this.discardedBitCount = this.discardedBitCount != null? this.discardedBitCount.AddInt(digitShift) : (new FastInteger(digitShift)); for (var i = 0; i < digitShift; ++i) { var digit = (int)(this.shiftedSmall % 10); this.shiftedSmall /= 10; this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = digit; } this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; } }
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 static FastIntegerFixed FromFastInteger(FastInteger fi) { if (fi.CanFitInInt32()) { return(new FastIntegerFixed(fi.AsInt32())); } else { return(FastIntegerFixed.FromBig(fi.AsEInteger())); } }
public static FastIntegerFixed FromFastInteger(FastInteger fi) { if (fi.CanFitInInt32()) { return(FromInt32(fi.ToInt32())); } else { return(FastIntegerFixed.FromBig(fi.ToEInteger())); } }
public FastInteger ToFastInteger() { if (this.integerMode == IntegerMode.SmallValue) { return(new FastInteger(this.smallValue)); } else { return(FastInteger.FromBig(this.largeValue)); } }
private void UpdateKnownLength(FastInteger digitsFast) { if (this.knownDigitLength != null) { this.knownDigitLength.Subtract(digitsFast); if (this.knownDigitLength.CompareToInt(1) < 0) { this.knownDigitLength.SetInt(1); } this.VerifyKnownLength(); } }
/// <summary>This is an internal API.</summary> /// <returns>A text string.</returns> public override string ToString() { switch (this.integerMode) { case IntegerMode.SmallValue: return(FastInteger.IntToString(this.smallValue)); case IntegerMode.LargeValue: return(this.largeValue.ToString()); default: return(String.Empty); } }
public int CompareTo(FastInteger fint) { switch (this.integerMode) { case IntegerMode.SmallValue: return(-fint.CompareToInt(this.smallValue)); case IntegerMode.LargeValue: return(-fint.CompareTo(this.largeValue)); default: throw new InvalidOperationException(); } }
public static FastIntegerFixed DigitLengthFixed <THelper>( IRadixMathHelper <THelper> helper, FastIntegerFixed fei) { FastIntegerFixed fastpath = FastPathDigitLength(fei, helper.GetRadix()); if (fastpath != null) { return(fastpath); } FastInteger fi = helper.GetDigitLength(fei.ToEInteger()); FastIntegerFixed fif = FastIntegerFixed.FromFastInteger(fi); return(fif); }
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 BitShiftAccumulator( int smallint, int lastDiscarded, int olderDiscarded) { this.shiftedSmall = smallint; if (this.shiftedSmall < 0) { throw new ArgumentException("shiftedSmall(" + this.shiftedSmall + ") is less than 0"); } this.isSmall = true; this.discardedBitCount = new FastInteger(0); this.bitsAfterLeftmost = (olderDiscarded != 0) ? 1 : 0; this.bitLeftmost = (lastDiscarded != 0) ? 1 : 0; }
private void ShiftRightSmall(int bits) { if (bits <= 0) { return; } if (this.shiftedSmall == 0) { this.discardedBitCount.AddInt(bits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; this.knownBitLength = new FastInteger(1); return; } int kb = SmallBitLength; for (int i = SmallBitLength - 1; i >= 0; --i) { if ((this.shiftedSmall & (1 << i)) != 0) { break; } --kb; } var shift = (int)Math.Min(kb, bits); bool shiftingMoreBits = bits > kb; kb -= shift; this.knownBitLength = new FastInteger(kb); this.discardedBitCount.AddInt(bits); this.bitsAfterLeftmost |= this.bitLeftmost; // Get the bottommost shift minus 1 bits this.bitsAfterLeftmost |= (shift > 1 && (this.shiftedSmall << (SmallBitLength - shift + 1)) != 0) ? 1 : 0; // Get the bit just above that bit this.bitLeftmost = (int)((this.shiftedSmall >> (shift - 1)) & 0x01); this.shiftedSmall >>= shift; if (shiftingMoreBits) { // Shifted more bits than the bit length this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; } this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; }
#pragma warning disable CS0618 // certain ERounding values are obsolete private T SignalOverflow2(EContext pc, bool neg) { if (pc != null) { ERounding roundingOnOverflow = pc.Rounding; if (pc.HasFlags) { pc.Flags |= EContext.FlagOverflow | EContext.FlagInexact | EContext.FlagRounded; } if (pc.HasMaxPrecision && pc.HasExponentRange && (roundingOnOverflow == ERounding.Down || roundingOnOverflow == ERounding.ZeroFiveUp || roundingOnOverflow == ERounding.OddOrZeroFiveUp || roundingOnOverflow == ERounding.Odd || (roundingOnOverflow == ERounding.Ceiling && neg) || (roundingOnOverflow == ERounding.Floor && !neg))) { // Set to the highest possible value for // the given precision EInteger overflowMant = EInteger.Zero; FastInteger fastPrecision = FastInteger.FromBig(pc.Precision); overflowMant = this.GetHelper().MultiplyByRadixPower( EInteger.One, fastPrecision); overflowMant -= EInteger.One; FastInteger clamp = FastInteger.FromBig(pc.EMax).Increment().Subtract(fastPrecision); return(this.GetHelper().CreateNewWithFlags( overflowMant, clamp.AsEInteger(), neg ? BigNumberFlags.FlagNegative : 0)); } } int flagneg = neg ? BigNumberFlags.FlagNegative : 0; return(this.GetHelper().GetArithmeticSupport() == BigNumberFlags.FiniteOnly ? default(T) : this.GetHelper().CreateNewWithFlags( EInteger.Zero, EInteger.Zero, flagneg | BigNumberFlags.FlagInfinity)); }
public void ShiftRight(FastInteger fastint) { if (fastint == null) { throw new ArgumentNullException("fastint"); } if (fastint.CanFitInInt32()) { int fi = fastint.AsInt32(); if (fi < 0) { return; } this.ShiftRightInt(fi); } else { if (fastint.Sign <= 0) { return; } 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 FastInteger[] DigitLengthBounds <THelper>( IRadixMathHelper <THelper> helper, EInteger ei) { int radix = helper.GetRadix(); if (radix == 2) { FastInteger fi = FastInteger.FromBig(ei.GetUnsignedBitLengthAsEInteger()); return(new FastInteger[] { fi, fi }); } else if (radix == 10) { return(DecimalDigitLengthBounds(ei)); } else { FastInteger fi = helper.GetDigitLength(ei); return(new FastInteger[] { fi, fi }); } }
public BitShiftAccumulator( EInteger bigint, int lastDiscarded, int olderDiscarded) { if (bigint.Sign < 0) { throw new ArgumentException("bigint's sign(" + bigint.Sign + ") is less than 0"); } if (bigint.CanFitInInt32()) { this.isSmall = true; this.shiftedSmall = (int)bigint; } else { this.shiftedBigInt = bigint; } this.discardedBitCount = new FastInteger(0); this.bitsAfterLeftmost = (olderDiscarded != 0) ? 1 : 0; this.bitLeftmost = (lastDiscarded != 0) ? 1 : 0; }
private void ShiftSmallToBits(int bits) { if (this.knownBitLength != null) { if (this.knownBitLength.CompareToInt(bits) <= 0) { return; } } this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength(); if (this.knownBitLength.CompareToInt(bits) <= 0) { return; } int kbl = this.knownBitLength.ToInt32(); // Shift by the difference in bit length if (kbl > bits) { int bitShift = kbl - (int)bits; var shift = (int)bitShift; this.knownBitLength = new FastInteger(bits); this.discardedBitCount.AddInt(bitShift); this.bitsAfterLeftmost |= this.bitLeftmost; // Get the bottommost shift minus 1 bits this.bitsAfterLeftmost |= (shift > 1 && (this.shiftedSmall << (SmallBitLength - shift + 1)) != 0) ? 1 : 0; // Get the bit just above that bit this.bitLeftmost = (int)((this.shiftedSmall >> (shift - 1)) & 0x01); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; this.shiftedSmall >>= shift; } else { this.knownBitLength = new FastInteger(kbl); } }
private FastInteger CalcKnownBitLength() { if (this.isSmall) { int kb = SmallBitLength; for (int i = SmallBitLength - 1; i >= 0; --i) { if ((this.shiftedSmall & (1 << i)) != 0) { break; } --kb; } // Make sure bit length is 1 if value is 0 if (kb == 0) { ++kb; } // Console.WriteLine("{0:X8} kbl=" + kb); return(new FastInteger(kb)); } return(this.shiftedBigInt.IsZero ? new FastInteger(1) : FastInteger.FromBig(this.shiftedBigInt.GetSignedBitLengthAsEInteger())); }
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); }
private T PostProcessEx( T thisValue, EContext ctxDest, EContext ctxSrc, bool afterDivision, bool afterQuantize) { int thisFlags = this.GetHelper().GetFlags(thisValue); if (ctxDest != null && ctxSrc != null) { if (ctxDest.HasFlags) { if (!ctxSrc.ClampNormalExponents) { ctxSrc.Flags &= ~EContext.FlagClamped; } ctxDest.Flags |= ctxSrc.Flags; if ((ctxSrc.Flags & EContext.FlagSubnormal) != 0) { // Treat subnormal numbers as underflows ctxDest.Flags |= BigNumberFlags.UnderflowFlags; } } } if ((thisFlags & BigNumberFlags.FlagSpecial) != 0) { return((ctxDest.Flags == 0) ? this.SignalInvalid(ctxDest) : thisValue); } EInteger mant = this.GetHelper().GetMantissa(thisValue).Abs(); if (mant.IsZero) { return(afterQuantize ? this.GetHelper().CreateNewWithFlags( mant, this.GetHelper().GetExponent(thisValue), 0) : this.wrapper.RoundToPrecision( this.GetHelper().ValueOf(0), ctxDest)); } if (afterQuantize) { return(thisValue); } EInteger exp = this.GetHelper().GetExponent(thisValue); if (exp.Sign > 0) { FastInteger fastExp = FastInteger.FromBig(exp); if (ctxDest == null || !ctxDest.HasMaxPrecision) { mant = this.GetHelper().MultiplyByRadixPower(mant, fastExp); return(this.GetHelper().CreateNewWithFlags( mant, EInteger.Zero, thisFlags)); } if (!ctxDest.ExponentWithinRange(exp)) { return(thisValue); } FastInteger prec = FastInteger.FromBig(ctxDest.Precision); FastInteger digits = this.GetHelper().CreateShiftAccumulator(mant).GetDigitLength(); prec.Subtract(digits); if (prec.Sign > 0 && prec.CompareTo(fastExp) >= 0) { mant = this.GetHelper().MultiplyByRadixPower(mant, fastExp); return(this.GetHelper().CreateNewWithFlags( mant, EInteger.Zero, thisFlags)); } if (afterDivision) { int radix = this.GetHelper().GetRadix(); mant = NumberUtility.ReduceTrailingZeros( mant, fastExp, radix, null, null, null); thisValue = this.GetHelper().CreateNewWithFlags( mant, fastExp.AsEInteger(), thisFlags); } } else if (afterDivision && exp.Sign < 0) { FastInteger fastExp = FastInteger.FromBig(exp); int radix = this.GetHelper().GetRadix(); mant = NumberUtility.ReduceTrailingZeros( mant, fastExp, radix, null, null, new FastInteger(0)); thisValue = this.GetHelper().CreateNewWithFlags( mant, fastExp.AsEInteger(), thisFlags); } return(thisValue); }
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 T RoundBeforeOp(T val, EContext ctx) { if (ctx == null || !ctx.HasMaxPrecision) { return(val); } int thisFlags = this.GetHelper().GetFlags(val); if ((thisFlags & BigNumberFlags.FlagSpecial) != 0) { return(val); } FastInteger fastPrecision = FastInteger.FromBig(ctx.Precision); EInteger mant = this.GetHelper().GetMantissa(val).Abs(); FastInteger digits = this.GetHelper().CreateShiftAccumulator(mant).GetDigitLength(); EContext ctx2 = ctx.WithBlankFlags().WithTraps(0); if (digits.CompareTo(fastPrecision) <= 0) { // Rounding is only to be done if the digit count is // too big (distinguishing this case is material // if the value also has an exponent that's out of range) return(val); } val = this.wrapper.RoundToPrecision(val, ctx2); // the only time rounding can signal an invalid // operation is if an operand is signaling NaN, but // this was already checked beforehand #if DEBUG if ((ctx2.Flags & EContext.FlagInvalid) != 0) { throw new ArgumentException("doesn't satisfy (ctx2.Flags&FlagInvalid)==0"); } #endif if ((ctx2.Flags & EContext.FlagInexact) != 0) { if (ctx.HasFlags) { ctx.Flags |= BigNumberFlags.LostDigitsFlags; } } if ((ctx2.Flags & EContext.FlagRounded) != 0) { if (ctx.HasFlags) { ctx.Flags |= EContext.FlagRounded; } } if ((ctx2.Flags & EContext.FlagSubnormal) != 0) { // Console.WriteLine("Subnormal input: " + val); } if ((ctx2.Flags & EContext.FlagUnderflow) != 0) { // Console.WriteLine("Underflow"); } if ((ctx2.Flags & EContext.FlagOverflow) != 0) { bool neg = (thisFlags & BigNumberFlags.FlagNegative) != 0; ctx.Flags |= EContext.FlagLostDigits; return(this.SignalOverflow2(ctx, neg)); } return(val); }
private void ShiftRightBig(int digits, bool truncate) { if (digits <= 0) { return; } if (this.shiftedBigInt.IsZero) { this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; this.knownDigitLength = new FastInteger(1); return; } if (truncate) { EInteger bigquo; if (digits > 50) { // To avoid having to calculate a very big power of 10, // check the digit count to see if doing so can be avoided int bitLength = this.shiftedBigInt.GetUnsignedBitLength(); var bigPower = false; // 10^48 has 160 bits; 10^98 has 326; bit length is cheaper // to calculate than base-10 digit length if (bitLength < 160 || (digits > 100 && bitLength < 326)) { bigPower = true; } else { FastInteger knownDigits = this.GetDigitLength(); bigPower = knownDigits.Copy().SubtractInt(digits) .CompareToInt(-2) < 0; if (!bigPower) { // DebugUtility.Log("digitlength {0} [todiscard: {1}]" // , knownDigits, digits); } } if (bigPower) { // Power of 10 to be divided would be much bigger this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitsAfterLeftmost |= this.shiftedBigInt.IsZero ? 0 : 1; this.bitLeftmost = 0; this.knownDigitLength = new FastInteger(1); this.isSmall = true; this.shiftedSmall = 0; return; } } if (this.shiftedBigInt.IsEven && this.bitLeftmost == 0) { EInteger[] quorem = this.shiftedBigInt.DivRem( NumberUtility.FindPowerOfTen(digits)); bigquo = quorem[0]; this.bitLeftmost |= quorem[1].IsZero ? 0 : 1; } else { this.bitLeftmost = 1; bigquo = this.shiftedBigInt.Divide( NumberUtility.FindPowerOfTen(digits)); } this.bitsAfterLeftmost |= this.bitLeftmost; this.discardedBitCount = this.discardedBitCount == null ? new FastInteger(digits) : this.discardedBitCount.AddInt(digits); if (bigquo.IsZero) { // Shifted all the way to 0 this.isSmall = true; this.shiftedBigInt = null; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); } else if (bigquo.CanFitInInt32()) { this.isSmall = true; this.shiftedSmall = bigquo.ToInt32Unchecked(); this.shiftedBigInt = null; this.UpdateKnownLengthInt(digits); } else { this.isSmall = false; this.shiftedBigInt = bigquo; this.UpdateKnownLengthInt(digits); } return; } if (digits == 1) { EInteger bigrem; EInteger bigquo; EInteger[] divrem = this.shiftedBigInt.DivRem((EInteger)10); 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.AddInt(digits); this.UpdateKnownLengthInt(digits); return; } if (digits >= 2 && digits <= 8) { EInteger bigrem; EInteger bigquo; EInteger[] divrem = this.shiftedBigInt.DivRem(NumberUtility.FindPowerOfTen(digits)); bigquo = divrem[0]; bigrem = divrem[1]; var intRem = (int)bigrem; int smallPower = ValueTenPowers[digits - 1]; int leftBit = intRem / smallPower; int otherBits = intRem - (leftBit * smallPower); this.bitsAfterLeftmost |= otherBits | this.bitLeftmost; this.bitLeftmost = leftBit; this.shiftedBigInt = bigquo; this.discardedBitCount = (this.discardedBitCount != null) ? this.discardedBitCount.AddInt(digits) : (new FastInteger(digits)); this.UpdateKnownLengthInt(digits); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; if (this.shiftedBigInt.CanFitInInt32()) { this.isSmall = true; this.shiftedSmall = this.shiftedBigInt.ToInt32Unchecked(); this.shiftedBigInt = null; } return; } this.knownDigitLength = this.knownDigitLength ?? this.CalcKnownDigitLength(); if (new FastInteger(digits).Decrement().CompareTo(this.knownDigitLength) >= 0) { // Shifting more bits than available this.bitsAfterLeftmost |= this.shiftedBigInt.IsZero ? 0 : 1; this.isSmall = true; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; return; } if (this.shiftedBigInt.CanFitInInt32()) { this.isSmall = true; this.shiftedSmall = (int)this.shiftedBigInt; this.ShiftRightSmall(digits); return; } if (this.shiftedBigInt.CanFitInInt64()) { this.ShiftRightLong(this.shiftedBigInt.ToInt64Unchecked(), digits); return; } string str = this.shiftedBigInt.ToString(); // NOTE: Will be 1 if the value is 0 int digitLength = str.Length; var bitDiff = 0; if (digits > digitLength) { bitDiff = digits - digitLength; } this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; int digitShift = Math.Min(digitLength, digits); if (digits >= digitLength) { this.isSmall = true; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); } else { var newLength = (int)(digitLength - digitShift); if (newLength <= 9) { // Fits in a small number this.isSmall = true; this.shiftedSmall = FastParseLong(str, 0, newLength); } else { this.shiftedBigInt = EInteger.FromSubstring(str, 0, newLength); } this.UpdateKnownLengthInt(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; } } this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; if (bitDiff > 0) { // Shifted more digits than the digit length this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; } }
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; } }
private void ShiftRightSmall(int digits) { if (digits <= 0) { return; } if (this.shiftedSmall == 0) { this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; this.knownDigitLength = new FastInteger(1); return; } if (digits >= 2 && digits <= 8) { if (this.shiftedSmall >= ValueTenPowers[digits]) { int bigPower = ValueTenPowers[digits]; int smallPower = ValueTenPowers[digits - 1]; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); int div = this.shiftedSmall / bigPower; int rem = this.shiftedSmall - (div * bigPower); int rem2 = rem / smallPower; this.bitLeftmost = rem2; this.bitsAfterLeftmost |= rem - (rem2 * smallPower); this.shiftedSmall = div; this.knownDigitLength = (div < 10) ? (new FastInteger(1)) : this.CalcKnownDigitLength(); return; } else if (this.shiftedSmall >= ValueTenPowers[digits - 1]) { int smallPower = ValueTenPowers[digits - 1]; if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } int rem = this.shiftedSmall; int rem2 = rem / smallPower; this.bitLeftmost = rem2; this.bitsAfterLeftmost |= rem - (rem2 * smallPower); this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); return; } else { if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } int rem = this.shiftedSmall; this.bitLeftmost = 0; this.bitsAfterLeftmost |= rem; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); return; } } int v2 = this.shiftedSmall; int kb = (v2 >= 1000000000) ? 10 : ((v2 >= 100000000) ? 9 : ((v2 >= 10000000) ? 8 : ((v2 >= 1000000) ? 7 : ((v2 >= 100000) ? 6 : ((v2 >= 10000) ? 5 : ((v2 >= 1000) ? 4 : ((v2 >= 100) ? 3 : ((v2 >= 10) ? 2 : 1)))))))); this.knownDigitLength = new FastInteger(kb); if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } var digitsShifted = 0; while (digits > 0) { if (this.shiftedSmall == 0) { this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; this.knownDigitLength = new FastInteger(1); break; } else { var digit = (int)(this.shiftedSmall % 10); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = digit; --digits; ++digitsShifted; this.shiftedSmall /= 10; } } this.UpdateKnownLengthInt(digitsShifted); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; }
private void ShiftRightLong(long shiftedLong, int digits) { if (digits <= 0) { return; } if (shiftedLong == 0) { this.shiftedSmall = 0; this.isSmall = true; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; this.knownDigitLength = new FastInteger(1); return; } if (digits >= 2 && digits <= 8) { if (shiftedLong >= ValueTenPowers[digits]) { long bigPower = ValueTenPowers[digits]; long smallPower = ValueTenPowers[digits - 1]; this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0)); this.discardedBitCount.AddInt(digits); long div = shiftedLong / bigPower; long rem = shiftedLong - (div * bigPower); long rem2 = rem / smallPower; this.bitLeftmost = (int)rem2; this.bitsAfterLeftmost |= ((rem - (rem2 * smallPower)) == 0) ? 0 : 1; this.isSmall = div <= Int32.MaxValue; if (this.isSmall) { this.shiftedSmall = (int)div; this.knownDigitLength = (div < 10) ? (new FastInteger(1)) : new FastInteger(LongDigitLength(div)); } else { this.shiftedBigInt = EInteger.FromInt64(div); this.knownDigitLength = (div < 10) ? (new FastInteger(1)) : this.CalcKnownDigitLength(); } return; } else if (this.shiftedSmall >= ValueTenPowers[digits - 1]) { int smallPower = ValueTenPowers[digits - 1]; if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } long rem = shiftedLong; long rem2 = rem / smallPower; this.bitLeftmost = (int)rem2; this.bitsAfterLeftmost |= ((rem - (rem2 * smallPower)) == 0) ? 0 : 1; this.isSmall = true; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); return; } else { if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } this.bitLeftmost = 0; this.bitsAfterLeftmost |= (shiftedLong == 0) ? 0 : 1; this.isSmall = true; this.shiftedSmall = 0; this.knownDigitLength = new FastInteger(1); return; } } this.knownDigitLength = new FastInteger( LongDigitLength(shiftedLong)); if (this.discardedBitCount != null) { this.discardedBitCount.AddInt(digits); } else { this.discardedBitCount = new FastInteger(digits); } var digitsShifted = 0; while (digits > 0) { if (shiftedLong == 0) { this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = 0; break; } else { long newShift = (shiftedLong < 43698) ? ((shiftedLong * 26215) >> 18) : (shiftedLong / 10); var digit = (int)(shiftedLong - (newShift * 10)); this.bitsAfterLeftmost |= this.bitLeftmost; this.bitLeftmost = digit; --digits; ++digitsShifted; shiftedLong = newShift; } } this.isSmall = shiftedLong <= Int32.MaxValue; if (this.isSmall) { this.shiftedSmall = (int)shiftedLong; } else { this.shiftedBigInt = EInteger.FromInt64(shiftedLong); } this.UpdateKnownLengthInt(digitsShifted); this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0; }