Beispiel #1
0
        public T Quantize(T thisValue, T otherValue, EContext ctx)
        {
            T ret = this.CheckNotANumber1(thisValue, ctx);

            if ((object)ret != (object)default(T))
            {
                return(ret);
            }
            EContext ctx2 = GetContextWithFlags(ctx);

            // Console.WriteLine("was: "+thisValue+", "+otherValue);
            thisValue = this.RoundBeforeOp(thisValue, ctx2);
            // Console.WriteLine("now: "+thisValue+", "+otherValue);
            otherValue = this.RoundBeforeOp(otherValue, ctx2);
            // Apparently, subnormal values of "otherValue" raise
            // an invalid operation flag, according to the test cases
            EContext ctx3 = ctx2 == null ? null : ctx2.WithBlankFlags();

            this.wrapper.RoundToPrecision(otherValue, ctx3);
            if (ctx3 != null && (ctx3.Flags & EContext.FlagSubnormal) != 0)
            {
                return(this.SignalInvalid(ctx));
            }
            thisValue = this.wrapper.Quantize(thisValue, otherValue, ctx2);
            // Console.WriteLine("result: "+thisValue);
            return(this.PostProcessAfterQuantize(thisValue, ctx, ctx2));
        }
Beispiel #2
0
 private static EContext GetTrappableContext(EContext ctx)
 {
     return((ctx == null) ? null : ((ctx.Traps == 0) ? ctx :
                                    ctx.WithBlankFlags()));
 }
Beispiel #3
0
 private static EContext GetContextWithFlags(EContext ctx)
 {
     return((ctx == null) ? ctx : ctx.WithBlankFlags());
 }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        public static THelper PreRound <THelper>(
            THelper val,
            EContext ctx,
            IRadixMath <THelper> wrapper)
        {
            if (ctx == null || !ctx.HasMaxPrecision)
            {
                return(val);
            }
            IRadixMathHelper <THelper> helper = wrapper.GetHelper();
            int thisFlags = helper.GetFlags(val);

            if ((thisFlags & BigNumberFlags.FlagSpecial) != 0)
            {
                // Infinity or NaN
                return(val);
            }
            FastInteger fastPrecision = FastInteger.FromBig(ctx.Precision);
            EInteger    mant          = helper.GetMantissa(val).Abs();

            // 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)
            FastInteger[] digitBounds = NumberUtility.DigitLengthBounds(
                helper,
                mant);
            if (digitBounds[1].CompareTo(fastPrecision) <= 0)
            {
                // Upper bound is less than or equal to precision
                return(val);
            }
            EContext ctx2 = ctx;

            if (digitBounds[0].CompareTo(fastPrecision) <= 0)
            {
                // Lower bound is less than or equal to precision, so
                // calculate digit length more precisely
                FastInteger digits = helper.GetDigitLength(mant);
                ctx2 = ctx.WithBlankFlags().WithTraps(0);
                if (digits.CompareTo(fastPrecision) <= 0)
                {
                    return(val);
                }
            }
            val = wrapper.RoundToPrecision(val, ctx2);
            // the only time rounding can signal an invalid
            // operation is if an operand is a signaling NaN, but
            // this was already checked beforehand
      #if DEBUG
            if ((ctx2.Flags & EContext.FlagInvalid) != 0)
            {
                throw new ArgumentException("doesn't" +
                                            "\u0020satisfy(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.FlagOverflow) != 0)
            {
                bool neg = (thisFlags & BigNumberFlags.FlagNegative) != 0;
                if (ctx.HasFlags)
                {
                    ctx.Flags |= EContext.FlagLostDigits;
                    ctx.Flags |= EContext.FlagOverflow |
                                 EContext.FlagInexact | EContext.FlagRounded;
                }
            }
            return(val);
        }