コード例 #1
0
        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();
            }
        }
コード例 #2
0
ファイル: NumberUtility.cs プロジェクト: ulfendk/Numbers
   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);
   }
コード例 #3
0
ファイル: SimpleRadixMath.cs プロジェクト: ulfendk/Numbers
        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);
        }
コード例 #4
0
ファイル: SimpleRadixMath.cs プロジェクト: ulfendk/Numbers
        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);
        }
コード例 #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();
            }
        }
コード例 #6
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);
        }
コード例 #7
0
   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 ||" +
                                       "\u0020digits!=null");
       }
       if (!(bigmant.Sign >= 0))
       {
           throw new ArgumentException("doesn't satisfy bigmant.Sign >= 0");
       }
 #endif
       if (bigmant.IsZero)
       {
           exponentMutable.SetInt(0);
           return(bigmant);
       }
       if (radix == 2)
       {
           if (!bigmant.IsEven)
           {
               return(bigmant);
           }
           long lowbit = bigmant.GetLowBitAsInt64();
           if (lowbit != Int64.MaxValue)
           {
               if (precision != null && digits.CompareTo(precision) >= 0)
               {
                   // Limit by digits minus precision
                   EInteger tmp = digits.ToEInteger().Subtract(precision.ToEInteger());
                   if (tmp.CompareTo(EInteger.FromInt64(lowbit)) < 0)
                   {
                       lowbit = tmp.ToInt64Checked();
                   }
               }
               if (idealExp != null && exponentMutable.CompareTo(idealExp) <= 0)
               {
                   // Limit by idealExp minus exponentMutable
                   EInteger tmp =
                       idealExp.ToEInteger().Subtract(exponentMutable.ToEInteger());
                   if (tmp.CompareTo(EInteger.FromInt64(lowbit)) < 0)
                   {
                       lowbit = tmp.ToInt64Checked();
                   }
               }
               bigmant = (lowbit <= Int32.MaxValue) ?
                         bigmant.ShiftRight((int)lowbit) :
                         bigmant.ShiftRight(EInteger.FromInt64(lowbit));
               if (digits != null)
               {
                   digits.SubtractInt64(lowbit);
               }
               if (exponentMutable != null)
               {
                   exponentMutable.AddInt64(lowbit);
               }
               return(bigmant);
           }
       }
       var bigradix    = (EInteger)radix;
       var bitsToShift = new FastInteger(0);
       while (!bigmant.IsZero)
       {
           if (precision != null && digits.CompareTo(precision) == 0)
           {
               break;
           }
           if (idealExp != null && exponentMutable.CompareTo(idealExp) == 0)
           {
               break;
           }
           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();
           }
       }
       return(bigmant);
   }
コード例 #8
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);
             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);
                 VerifyKnownLength();
                 return;
             }
             else
             {
                 // NOTE: For BitShiftAccumulator, truncating and shifting
                 // are the same, unlike in DigitShiftAccumulator
                 this.ShiftRight(bitDiff);
                 VerifyKnownLength();
                 return;
             }
         }
     }
     if (bits.CanFitInInt32())
     {
         this.ShiftToDigitsInt(bits.ToInt32());
         VerifyKnownLength();
     }
     else
     {
         this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
         EInteger bigintDiff = this.knownBitLength.ToEInteger();
         EInteger bitsBig    = bits.ToEInteger();
         bigintDiff -= (EInteger)bitsBig;
         if (bigintDiff.Sign > 0)
         {
             // current length is greater than the
             // desired bit length
             this.ShiftRight(FastInteger.FromBig(bigintDiff));
         }
         VerifyKnownLength();
     }
 }