Esempio n. 1
0
        public TrappableRadixMath(IRadixMath <T> math)
        {
#if DEBUG
            if (math == null)
            {
                throw new ArgumentNullException("math");
            }
#endif
            this.math = math;
        }
Esempio n. 2
0
 public SimpleRadixMath(IRadixMath <T> wrapper)
 {
     this.wrapper = wrapper;
 }
Esempio n. 3
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);
        }