Beispiel #1
0
 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;
             }
         }
     }
 }
Beispiel #2
0
 public static FastIntegerFixed FromFastInteger(FastInteger fi)
 {
     if (fi.CanFitInInt32())
     {
         return(FromInt32(fi.AsInt32()));
     }
     else
     {
         return(FastIntegerFixed.FromBig(fi.AsEInteger()));
     }
 }
#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));
        }
Beispiel #4
0
        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);
        }
Beispiel #5
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();
            }
        }
Beispiel #6
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();
     }
 }