Beispiel #1
0
        public static EInteger IntegerDigitLengthUpperBound <THelper>(
            IRadixMathHelper <THelper> helper,
            THelper val)
        {
            // Gets an upper bound on the number of digits in the integer
            // part of the given number 'val'.
            int flags = helper.GetFlags(val);

            if ((flags & BigNumberFlags.FlagSpecial) != 0)
            {
                // Infinity and NaN are not supported
                throw new NotSupportedException();
            }
            EInteger expo = helper.GetExponent(val);
            EInteger mant = helper.GetMantissa(val).Abs();

            if (expo.Sign <= 0)
            {
                // Exponent Y in X*digits^Y is 0 or negative, so upper bound
                // of significand's digit count works by itself.
                return(DigitLengthUpperBound(helper, mant).ToEInteger());
            }
            else
            {
                return(DigitLengthUpperBound(helper, mant).ToEInteger().Add(expo));
            }
        }
Beispiel #2
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);
        }