Beispiel #1
0
        private T ReturnQuietNaN(T thisValue, EContext ctx)
        {
            EInteger mant        = this.GetHelper().GetMantissa(thisValue).Abs();
            var      mantChanged = false;

            if (!mant.IsZero && ctx != null && ctx.HasMaxPrecision)
            {
                EInteger limit = this.GetHelper().MultiplyByRadixPower(
                    EInteger.One,
                    FastInteger.FromBig(ctx.Precision));
                if (mant.CompareTo(limit) >= 0)
                {
                    mant       %= (EInteger)limit;
                    mantChanged = true;
                }
            }
            int flags = this.GetHelper().GetFlags(thisValue);

            if (!mantChanged && (flags & BigNumberFlags.FlagQuietNaN) != 0)
            {
                return(thisValue);
            }
            flags &= BigNumberFlags.FlagNegative;
            flags |= BigNumberFlags.FlagQuietNaN;
            return(this.GetHelper().CreateNewWithFlags(mant, EInteger.Zero, flags));
        }
Beispiel #2
0
        private FastInteger CalcKnownBitLength()
        {
            if (this.isSmall)
            {
                int kb = SmallBitLength;
                for (int i = SmallBitLength - 1; i >= 0; --i)
                {
                    if ((this.shiftedSmall & (1 << i)) != 0)
                    {
                        break;
                    }
                    --kb;
                }
                // Make sure bit length is 1 if value is 0
                if (kb == 0)
                {
                    ++kb;
                }
                return(new FastInteger(kb));
            }
            if (this.shiftedBigInt.IsZero)
            {
                { return(new FastInteger(1)); }
            }
            long sbe = this.shiftedBigInt.GetSignedBitLengthAsInt64();

            return((sbe < Int32.MaxValue) ? new FastInteger((int)sbe) :
                   FastInteger.FromBig(this.shiftedBigInt.GetSignedBitLengthAsEInteger()));
        }
Beispiel #3
0
        public static FastIntegerFixed[] DigitLengthBoundsFixed <THelper>(
            IRadixMathHelper <THelper> helper,
            FastIntegerFixed fei)
        {
            int radix = helper.GetRadix();
            FastIntegerFixed fastpath = FastPathDigitLength(fei, radix);

            if (fastpath != null)
            {
                return(new FastIntegerFixed[] { fastpath, fastpath });
            }
            if (radix == 10)
            {
                EInteger[] fi = DecimalDigitLengthBoundsAsEI(fei.ToEInteger());
                return(new FastIntegerFixed[] {
                    FastIntegerFixed.FromBig(fi[0]),
                    FastIntegerFixed.FromBig(fi[1]),
                });
            }
            else
            {
                FastInteger      fi  = helper.GetDigitLength(fei.ToEInteger());
                FastIntegerFixed fif = FastIntegerFixed.FromFastInteger(fi);
                return(new FastIntegerFixed[] { fif, fif });
            }
        }
Beispiel #4
0
 public void ShiftRight(FastInteger fastint)
 {
     if (fastint.Sign <= 0)
     {
         return;
     }
     if (fastint.CanFitInInt32())
     {
         this.ShiftRightInt(fastint.ToInt32());
     }
     else
     {
         EInteger bi = fastint.ToEInteger();
         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 #5
0
        private void ShiftToDigitsSmall(int digits)
        {
            var kb = 0;
            int v2 = this.shiftedSmall;

            kb = (v2 >= 1000000000) ? 10 : ((v2 >= 100000000) ? 9 : ((v2 >=
                                                                      10000000) ? 8 : ((v2 >= 1000000) ? 7 : ((v2 >= 100000) ? 6 : ((v2 >=
                                                                                                                                     10000) ? 5 : ((v2 >= 1000) ? 4 : ((v2 >= 100) ? 3 : ((v2 >= 10) ? 2 :
                                                                                                                                                                                          1))))))));
            this.knownDigitLength = new FastInteger(kb);
            if (kb > digits)
            {
                var digitShift = (int)(kb - digits);
                this.UpdateKnownLengthInt(digitShift);
                this.discardedBitCount = this.discardedBitCount != null?
                                         this.discardedBitCount.AddInt(digitShift) :
                                             (new FastInteger(digitShift));

                for (var i = 0; i < digitShift; ++i)
                {
                    var digit = (int)(this.shiftedSmall % 10);
                    this.shiftedSmall      /= 10;
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = digit;
                }
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
            }
        }
Beispiel #6
0
 public void TruncateRight(FastInteger fastint)
 {
     if (fastint == null)
     {
         throw new ArgumentNullException("fastint");
     }
     if (fastint.CanFitInInt32())
     {
         int fi = fastint.AsInt32();
         if (fi < 0)
         {
             return;
         }
         if (!this.isSmall)
         {
             if (this.shiftedBigInt.CanFitInInt64())
             {
                 this.TruncateRightLong(this.shiftedBigInt.ToInt64Checked(), fi);
             }
             else
             {
                 this.ShiftRightBig(fi, true);
             }
         }
         else
         {
             this.TruncateRightSmall(fi);
         }
     }
     else
     {
         this.ShiftRight(fastint);
     }
 }
Beispiel #7
0
 public static FastIntegerFixed FromFastInteger(FastInteger fi)
 {
     if (fi.CanFitInInt32())
     {
         return(new FastIntegerFixed(fi.AsInt32()));
     }
     else
     {
         return(FastIntegerFixed.FromBig(fi.AsEInteger()));
     }
 }
Beispiel #8
0
 public static FastIntegerFixed FromFastInteger(FastInteger fi)
 {
     if (fi.CanFitInInt32())
     {
         return(FromInt32(fi.ToInt32()));
     }
     else
     {
         return(FastIntegerFixed.FromBig(fi.ToEInteger()));
     }
 }
Beispiel #9
0
 public FastInteger ToFastInteger()
 {
     if (this.integerMode == IntegerMode.SmallValue)
     {
         return(new FastInteger(this.smallValue));
     }
     else
     {
         return(FastInteger.FromBig(this.largeValue));
     }
 }
Beispiel #10
0
 private void UpdateKnownLength(FastInteger digitsFast)
 {
     if (this.knownDigitLength != null)
     {
         this.knownDigitLength.Subtract(digitsFast);
         if (this.knownDigitLength.CompareToInt(1) < 0)
         {
             this.knownDigitLength.SetInt(1);
         }
         this.VerifyKnownLength();
     }
 }
Beispiel #11
0
        /// <summary>This is an internal API.</summary>
        /// <returns>A text string.</returns>
        public override string ToString()
        {
            switch (this.integerMode)
            {
            case IntegerMode.SmallValue:
                return(FastInteger.IntToString(this.smallValue));

            case IntegerMode.LargeValue:
                return(this.largeValue.ToString());

            default: return(String.Empty);
            }
        }
Beispiel #12
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();
            }
        }
Beispiel #13
0
        public static FastIntegerFixed DigitLengthFixed <THelper>(
            IRadixMathHelper <THelper> helper,
            FastIntegerFixed fei)
        {
            FastIntegerFixed fastpath = FastPathDigitLength(fei, helper.GetRadix());

            if (fastpath != null)
            {
                return(fastpath);
            }
            FastInteger      fi  = helper.GetDigitLength(fei.ToEInteger());
            FastIntegerFixed fif = FastIntegerFixed.FromFastInteger(fi);

            return(fif);
        }
        internal static EInteger FindPowerOfTenFromBig(EInteger
                                                       bigintExponent)
        {
            int sign = bigintExponent.Sign;

            if (sign < 0)
            {
                return(EInteger.Zero);
            }
            if (sign == 0)
            {
                return(EInteger.One);
            }
            if (bigintExponent.CompareTo(ValueBigInt36) <= 0)
            {
                return(FindPowerOfTen((int)bigintExponent));
            }
            FastInteger intcurexp = FastInteger.FromBig(bigintExponent);
            EInteger    mantissa  = EInteger.One;
            EInteger    bigpow    = EInteger.Zero;

            // DebugUtility.Log("Getting power of ten from big "+bigintExponent);
            while (intcurexp.Sign > 0)
            {
                if (intcurexp.CompareToInt(18) <= 0)
                {
                    bigpow    = FindPowerOfTen(intcurexp.AsInt32());
                    mantissa *= (EInteger)bigpow;
                    break;
                }
                if (intcurexp.CompareToInt(9999999) <= 0)
                {
                    int val = intcurexp.AsInt32();
                    bigpow    = FindPowerOfFive(val);
                    bigpow  <<= val;
                    mantissa *= (EInteger)bigpow;
                    break;
                }
                if (bigpow.IsZero)
                {
                    bigpow   = FindPowerOfFive(9999999);
                    bigpow <<= 9999999;
                }
                mantissa *= bigpow;
                intcurexp.AddInt(-9999999);
            }
            return(mantissa);
        }
Beispiel #15
0
 public BitShiftAccumulator(
     int smallint,
     int lastDiscarded,
     int olderDiscarded)
 {
     this.shiftedSmall = smallint;
     if (this.shiftedSmall < 0)
     {
         throw new ArgumentException("shiftedSmall(" + this.shiftedSmall +
                                     ") is less than 0");
     }
     this.isSmall           = true;
     this.discardedBitCount = new FastInteger(0);
     this.bitsAfterLeftmost = (olderDiscarded != 0) ? 1 : 0;
     this.bitLeftmost       = (lastDiscarded != 0) ? 1 : 0;
 }
Beispiel #16
0
        private void ShiftRightSmall(int bits)
        {
            if (bits <= 0)
            {
                return;
            }
            if (this.shiftedSmall == 0)
            {
                this.discardedBitCount.AddInt(bits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                this.knownBitLength     = new FastInteger(1);
                return;
            }
            int kb = SmallBitLength;

            for (int i = SmallBitLength - 1; i >= 0; --i)
            {
                if ((this.shiftedSmall & (1 << i)) != 0)
                {
                    break;
                }
                --kb;
            }
            var  shift            = (int)Math.Min(kb, bits);
            bool shiftingMoreBits = bits > kb;

            kb -= shift;
            this.knownBitLength = new FastInteger(kb);
            this.discardedBitCount.AddInt(bits);
            this.bitsAfterLeftmost |= this.bitLeftmost;
            // Get the bottommost shift minus 1 bits
            this.bitsAfterLeftmost |= (shift > 1 && (this.shiftedSmall <<
                                                     (SmallBitLength - shift + 1)) != 0) ? 1 : 0;
            // Get the bit just above that bit
            this.bitLeftmost    = (int)((this.shiftedSmall >> (shift - 1)) & 0x01);
            this.shiftedSmall >>= shift;
            if (shiftingMoreBits)
            {
                // Shifted more bits than the bit length
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
            }
            this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
        }
#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 #18
0
 public void ShiftRight(FastInteger fastint)
 {
     if (fastint == null)
     {
         throw new ArgumentNullException("fastint");
     }
     if (fastint.CanFitInInt32())
     {
         int fi = fastint.AsInt32();
         if (fi < 0)
         {
             return;
         }
         this.ShiftRightInt(fi);
     }
     else
     {
         if (fastint.Sign <= 0)
         {
             return;
         }
         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 #19
0
        public static FastInteger[] DigitLengthBounds <THelper>(
            IRadixMathHelper <THelper> helper,
            EInteger ei)
        {
            int radix = helper.GetRadix();

            if (radix == 2)
            {
                FastInteger fi =
                    FastInteger.FromBig(ei.GetUnsignedBitLengthAsEInteger());
                return(new FastInteger[] { fi, fi });
            }
            else if (radix == 10)
            {
                return(DecimalDigitLengthBounds(ei));
            }
            else
            {
                FastInteger fi = helper.GetDigitLength(ei);
                return(new FastInteger[] { fi, fi });
            }
        }
Beispiel #20
0
 public BitShiftAccumulator(
     EInteger bigint,
     int lastDiscarded,
     int olderDiscarded)
 {
     if (bigint.Sign < 0)
     {
         throw new ArgumentException("bigint's sign(" + bigint.Sign +
                                     ") is less than 0");
     }
     if (bigint.CanFitInInt32())
     {
         this.isSmall      = true;
         this.shiftedSmall = (int)bigint;
     }
     else
     {
         this.shiftedBigInt = bigint;
     }
     this.discardedBitCount = new FastInteger(0);
     this.bitsAfterLeftmost = (olderDiscarded != 0) ? 1 : 0;
     this.bitLeftmost       = (lastDiscarded != 0) ? 1 : 0;
 }
Beispiel #21
0
        private void ShiftSmallToBits(int bits)
        {
            if (this.knownBitLength != null)
            {
                if (this.knownBitLength.CompareToInt(bits) <= 0)
                {
                    return;
                }
            }
            this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
            if (this.knownBitLength.CompareToInt(bits) <= 0)
            {
                return;
            }
            int kbl = this.knownBitLength.ToInt32();

            // Shift by the difference in bit length
            if (kbl > bits)
            {
                int bitShift = kbl - (int)bits;
                var shift    = (int)bitShift;
                this.knownBitLength = new FastInteger(bits);
                this.discardedBitCount.AddInt(bitShift);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                // Get the bottommost shift minus 1 bits
                this.bitsAfterLeftmost |= (shift > 1 && (this.shiftedSmall <<
                                                         (SmallBitLength - shift + 1)) != 0) ? 1 : 0;
                // Get the bit just above that bit
                this.bitLeftmost       = (int)((this.shiftedSmall >> (shift - 1)) & 0x01);
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
                this.shiftedSmall    >>= shift;
            }
            else
            {
                this.knownBitLength = new FastInteger(kbl);
            }
        }
Beispiel #22
0
 private FastInteger CalcKnownBitLength()
 {
     if (this.isSmall)
     {
         int kb = SmallBitLength;
         for (int i = SmallBitLength - 1; i >= 0; --i)
         {
             if ((this.shiftedSmall & (1 << i)) != 0)
             {
                 break;
             }
             --kb;
         }
         // Make sure bit length is 1 if value is 0
         if (kb == 0)
         {
             ++kb;
         }
         // Console.WriteLine("{0:X8} kbl=" + kb);
         return(new FastInteger(kb));
     }
     return(this.shiftedBigInt.IsZero ? new FastInteger(1) :
            FastInteger.FromBig(this.shiftedBigInt.GetSignedBitLengthAsEInteger()));
 }
Beispiel #23
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 || 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);
   }
Beispiel #24
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 #25
0
        internal static EInteger FindPowerOfFiveFromBig(EInteger diff)
        {
            int sign = diff.Sign;

            if (sign < 0)
            {
                return(EInteger.Zero);
            }
            if (sign == 0)
            {
                return(EInteger.One);
            }
            FastInteger intcurexp = FastInteger.FromBig(diff);

            if (intcurexp.CompareToInt(54) <= 0)
            {
                return(FindPowerOfFive(intcurexp.AsInt32()));
            }
            EInteger mantissa = EInteger.One;
            EInteger bigpow;
            EInteger origdiff = diff;

            bigpow = ValuePowerOfFiveCache.GetCachedPower(origdiff);
            if (bigpow != null)
            {
                return(bigpow);
            }
            EInteger[] otherPower =
                ValuePowerOfFiveCache.FindCachedPowerOrSmaller(origdiff);
            if (otherPower != null)
            {
                intcurexp.SubtractBig(otherPower[0]);
                bigpow   = otherPower[1];
                mantissa = bigpow;
            }
            else
            {
                bigpow = EInteger.Zero;
            }
            while (intcurexp.Sign > 0)
            {
                if (intcurexp.CompareToInt(27) <= 0)
                {
                    bigpow    = FindPowerOfFive(intcurexp.AsInt32());
                    mantissa *= (EInteger)bigpow;
                    break;
                }
                if (intcurexp.CompareToInt(9999999) <= 0)
                {
                    bigpow    = FindPowerOfFive(1).Pow(intcurexp.AsInt32());
                    mantissa *= (EInteger)bigpow;
                    break;
                }
                if (bigpow.IsZero)
                {
                    bigpow = FindPowerOfFive(1).Pow(9999999);
                }
                mantissa *= bigpow;
                intcurexp.AddInt(-9999999);
            }
            ValuePowerOfFiveCache.AddPower(origdiff, mantissa);
            return(mantissa);
        }
Beispiel #26
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 #27
0
        private void ShiftRightBig(int digits, bool truncate)
        {
            if (digits <= 0)
            {
                return;
            }
            if (this.shiftedBigInt.IsZero)
            {
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.AddInt(digits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                this.knownDigitLength   = new FastInteger(1);
                return;
            }
            if (truncate)
            {
                EInteger bigquo;
                if (digits > 50)
                {
                    // To avoid having to calculate a very big power of 10,
                    // check the digit count to see if doing so can be avoided
                    int bitLength = this.shiftedBigInt.GetUnsignedBitLength();
                    var bigPower  = false;
                    // 10^48 has 160 bits; 10^98 has 326; bit length is cheaper
                    // to calculate than base-10 digit length
                    if (bitLength < 160 || (digits > 100 && bitLength < 326))
                    {
                        bigPower = true;
                    }
                    else
                    {
                        FastInteger knownDigits = this.GetDigitLength();
                        bigPower = knownDigits.Copy().SubtractInt(digits)
                                   .CompareToInt(-2) < 0;
                        if (!bigPower)
                        {
                            // DebugUtility.Log("digitlength {0} [todiscard: {1}]"
                            // , knownDigits, digits);
                        }
                    }
                    if (bigPower)
                    {
                        // Power of 10 to be divided would be much bigger
                        this.discardedBitCount = this.discardedBitCount ?? (new
                                                                            FastInteger(0));
                        this.discardedBitCount.AddInt(digits);
                        this.bitsAfterLeftmost |= this.bitLeftmost;
                        this.bitsAfterLeftmost |= this.shiftedBigInt.IsZero ? 0 : 1;
                        this.bitLeftmost        = 0;
                        this.knownDigitLength   = new FastInteger(1);
                        this.isSmall            = true;
                        this.shiftedSmall       = 0;
                        return;
                    }
                }
                if (this.shiftedBigInt.IsEven && this.bitLeftmost == 0)
                {
                    EInteger[] quorem = this.shiftedBigInt.DivRem(
                        NumberUtility.FindPowerOfTen(digits));
                    bigquo            = quorem[0];
                    this.bitLeftmost |= quorem[1].IsZero ? 0 : 1;
                }
                else
                {
                    this.bitLeftmost = 1;
                    bigquo           = this.shiftedBigInt.Divide(
                        NumberUtility.FindPowerOfTen(digits));
                }
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.discardedBitCount  = this.discardedBitCount == null ?
                                          new FastInteger(digits) : this.discardedBitCount.AddInt(digits);
                if (bigquo.IsZero)
                {
                    // Shifted all the way to 0
                    this.isSmall          = true;
                    this.shiftedBigInt    = null;
                    this.shiftedSmall     = 0;
                    this.knownDigitLength = new FastInteger(1);
                }
                else if (bigquo.CanFitInInt32())
                {
                    this.isSmall       = true;
                    this.shiftedSmall  = bigquo.ToInt32Unchecked();
                    this.shiftedBigInt = null;
                    this.UpdateKnownLengthInt(digits);
                }
                else
                {
                    this.isSmall       = false;
                    this.shiftedBigInt = bigquo;
                    this.UpdateKnownLengthInt(digits);
                }
                return;
            }
            if (digits == 1)
            {
                EInteger   bigrem;
                EInteger   bigquo;
                EInteger[] divrem = this.shiftedBigInt.DivRem((EInteger)10);
                bigquo = divrem[0];
                bigrem = divrem[1];
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = (int)bigrem;
                this.shiftedBigInt      = bigquo;
                this.discardedBitCount  = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.AddInt(digits);
                this.UpdateKnownLengthInt(digits);
                return;
            }
            if (digits >= 2 && digits <= 8)
            {
                EInteger   bigrem;
                EInteger   bigquo;
                EInteger[] divrem =
                    this.shiftedBigInt.DivRem(NumberUtility.FindPowerOfTen(digits));
                bigquo = divrem[0];
                bigrem = divrem[1];
                var intRem     = (int)bigrem;
                int smallPower = ValueTenPowers[digits - 1];
                int leftBit    = intRem / smallPower;
                int otherBits  = intRem - (leftBit * smallPower);
                this.bitsAfterLeftmost |= otherBits | this.bitLeftmost;
                this.bitLeftmost        = leftBit;
                this.shiftedBigInt      = bigquo;
                this.discardedBitCount  = (this.discardedBitCount != null) ?
                                          this.discardedBitCount.AddInt(digits) : (new FastInteger(digits));
                this.UpdateKnownLengthInt(digits);
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
                if (this.shiftedBigInt.CanFitInInt32())
                {
                    this.isSmall       = true;
                    this.shiftedSmall  = this.shiftedBigInt.ToInt32Unchecked();
                    this.shiftedBigInt = null;
                }
                return;
            }
            this.knownDigitLength = this.knownDigitLength ??
                                    this.CalcKnownDigitLength();
            if (new FastInteger(digits).Decrement().CompareTo(this.knownDigitLength)
                >= 0)
            {
                // Shifting more bits than available
                this.bitsAfterLeftmost |= this.shiftedBigInt.IsZero ? 0 : 1;
                this.isSmall            = true;
                this.shiftedSmall       = 0;
                this.knownDigitLength   = new FastInteger(1);
                this.discardedBitCount  = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.AddInt(digits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                return;
            }
            if (this.shiftedBigInt.CanFitInInt32())
            {
                this.isSmall      = true;
                this.shiftedSmall = (int)this.shiftedBigInt;
                this.ShiftRightSmall(digits);
                return;
            }
            if (this.shiftedBigInt.CanFitInInt64())
            {
                this.ShiftRightLong(this.shiftedBigInt.ToInt64Unchecked(), digits);
                return;
            }
            string str = this.shiftedBigInt.ToString();
            // NOTE: Will be 1 if the value is 0
            int digitLength = str.Length;
            var bitDiff     = 0;

            if (digits > digitLength)
            {
                bitDiff = digits - digitLength;
            }
            this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
            this.discardedBitCount.AddInt(digits);
            this.bitsAfterLeftmost |= this.bitLeftmost;
            int digitShift = Math.Min(digitLength, digits);

            if (digits >= digitLength)
            {
                this.isSmall          = true;
                this.shiftedSmall     = 0;
                this.knownDigitLength = new FastInteger(1);
            }
            else
            {
                var newLength = (int)(digitLength - digitShift);
                if (newLength <= 9)
                {
                    // Fits in a small number
                    this.isSmall      = true;
                    this.shiftedSmall = FastParseLong(str, 0, newLength);
                }
                else
                {
                    this.shiftedBigInt = EInteger.FromSubstring(str, 0, newLength);
                }
                this.UpdateKnownLengthInt(digitShift);
            }
            for (int i = str.Length - 1; i >= 0; --i)
            {
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = (int)(str[i] - '0');
                --digitShift;
                if (digitShift <= 0)
                {
                    break;
                }
            }
            this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
            if (bitDiff > 0)
            {
                // Shifted more digits than the digit length
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
            }
        }
Beispiel #28
0
        private void ShiftToDigitsBig(int digits, bool truncate)
        {
            // Shifts a number until it reaches the given number of digits,
            // gathering information on whether the last digit discarded is set
            // and whether the discarded digits to the right of that digit are set.
            // Assumes that the big integer being shifted is positive.
            if (this.knownDigitLength != null)
            {
                if (this.knownDigitLength.CompareToInt(digits) <= 0)
                {
                    return;
                }
            }
            string str;

            this.knownDigitLength = this.knownDigitLength ??
                                    this.CalcKnownDigitLength();
            if (this.knownDigitLength.CompareToInt(digits) <= 0)
            {
                return;
            }
            FastInteger digitDiff = this.knownDigitLength.Copy().SubtractInt(digits);

            if (truncate && digitDiff.CanFitInInt32())
            {
                this.TruncateRight(digitDiff);
                return;
            }
            if (digitDiff.CompareToInt(1) == 0)
            {
                EInteger   bigrem;
                EInteger   bigquo;
                EInteger[] divrem = this.shiftedBigInt.DivRem(ValueTen);
                bigquo = divrem[0];
                bigrem = divrem[1];
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = (int)bigrem;
                this.shiftedBigInt      = bigquo;
                this.discardedBitCount  = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.Add(digitDiff);
                this.UpdateKnownLength(digitDiff);
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
                return;
            }
            if (digitDiff.CompareToInt(9) <= 0)
            {
                EInteger   bigrem;
                int        diffInt    = digitDiff.AsInt32();
                EInteger   radixPower = NumberUtility.FindPowerOfTen(diffInt);
                EInteger   bigquo;
                EInteger[] divrem = this.shiftedBigInt.DivRem(radixPower);
                bigquo = divrem[0];
                bigrem = divrem[1];
                var rem = (int)bigrem;
                this.bitsAfterLeftmost |= this.bitLeftmost;
                for (var i = 0; i < diffInt; ++i)
                {
                    if (i == diffInt - 1)
                    {
                        this.bitLeftmost = rem % 10;
                    }
                    else
                    {
                        int intQuot = (rem < 43698) ? ((rem * 26215) >> 18) : (rem / 10);
                        this.bitsAfterLeftmost |= rem - (intQuot * 10);
                        rem = intQuot;
                    }
                }
                this.shiftedBigInt     = bigquo;
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.Add(digitDiff);
                this.UpdateKnownLength(digitDiff);
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
                return;
            }
            if (digitDiff.CanFitInInt32())
            {
#if DEBUG
                if (!(digitDiff.CompareToInt(2) > 0))
                {
                    throw new ArgumentException(
                              "doesn't satisfy digitDiff.CompareToInt(2)>0");
                }
#endif
                EInteger   bigrem = null;
                EInteger   bigquo;
                EInteger[] divrem;
                if (!this.shiftedBigInt.IsEven || this.bitsAfterLeftmost != 0)
                {
                    EInteger radixPower =
                        NumberUtility.FindPowerOfTen(digitDiff.AsInt32() - 1);
                    this.bitsAfterLeftmost |= 1;
                    bigquo = this.shiftedBigInt.Divide(radixPower);
                }
                else
                {
                    EInteger radixPower =
                        NumberUtility.FindPowerOfTen(digitDiff.AsInt32() - 1);
                    divrem = this.shiftedBigInt.DivRem(radixPower);
                    bigquo = divrem[0];
                    bigrem = divrem[1];
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    if (!bigrem.IsZero)
                    {
                        this.bitsAfterLeftmost |= 1;
                    }
                }
                EInteger bigquo2;
                divrem                 = bigquo.DivRem(ValueTen);
                bigquo2                = divrem[0];
                bigrem                 = divrem[1];
                this.bitLeftmost       = (int)bigrem;
                this.shiftedBigInt     = bigquo2;
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.Add(digitDiff);
                this.UpdateKnownLength(digitDiff);
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
                return;
            }
            str = this.shiftedBigInt.ToString();
            // NOTE: Will be 1 if the value is 0
            int digitLength = str.Length;
            this.knownDigitLength = new FastInteger(digitLength);
            // Shift by the difference in digit length
            if (digitLength > digits)
            {
                int digitShift = digitLength - digits;
                this.UpdateKnownLengthInt(digitShift);
                var newLength = (int)(digitLength - digitShift);
                // Console.WriteLine("dlen= " + digitLength + " dshift=" +
                // digitShift + " newlen= " + newLength);
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                if (digitShift <= Int32.MaxValue)
                {
                    this.discardedBitCount.AddInt((int)digitShift);
                }
                else
                {
                    this.discardedBitCount.AddBig((EInteger)digitShift);
                }
                for (int i = str.Length - 1; i >= 0; --i)
                {
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = (int)(str[i] - '0');
                    --digitShift;
                    if (digitShift <= 0)
                    {
                        break;
                    }
                }
                if (newLength <= 9)
                {
                    this.isSmall      = true;
                    this.shiftedSmall = FastParseLong(str, 0, newLength);
                }
                else
                {
                    this.shiftedBigInt = EInteger.FromSubstring(str, 0, newLength);
                }
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
            }
        }
Beispiel #29
0
        private void ShiftRightSmall(int digits)
        {
            if (digits <= 0)
            {
                return;
            }
            if (this.shiftedSmall == 0)
            {
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.AddInt(digits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                this.knownDigitLength   = new FastInteger(1);
                return;
            }
            if (digits >= 2 && digits <= 8)
            {
                if (this.shiftedSmall >= ValueTenPowers[digits])
                {
                    int bigPower   = ValueTenPowers[digits];
                    int smallPower = ValueTenPowers[digits - 1];
                    this.discardedBitCount = this.discardedBitCount ?? (new
                                                                        FastInteger(0));
                    this.discardedBitCount.AddInt(digits);
                    int div  = this.shiftedSmall / bigPower;
                    int rem  = this.shiftedSmall - (div * bigPower);
                    int rem2 = rem / smallPower;
                    this.bitLeftmost        = rem2;
                    this.bitsAfterLeftmost |= rem - (rem2 * smallPower);
                    this.shiftedSmall       = div;
                    this.knownDigitLength   = (div < 10) ? (new FastInteger(1)) :
                                              this.CalcKnownDigitLength();
                    return;
                }
                else if (this.shiftedSmall >= ValueTenPowers[digits - 1])
                {
                    int smallPower = ValueTenPowers[digits - 1];
                    if (this.discardedBitCount != null)
                    {
                        this.discardedBitCount.AddInt(digits);
                    }
                    else
                    {
                        this.discardedBitCount = new FastInteger(digits);
                    }
                    int rem  = this.shiftedSmall;
                    int rem2 = rem / smallPower;
                    this.bitLeftmost        = rem2;
                    this.bitsAfterLeftmost |= rem - (rem2 * smallPower);
                    this.shiftedSmall       = 0;
                    this.knownDigitLength   = new FastInteger(1);
                    return;
                }
                else
                {
                    if (this.discardedBitCount != null)
                    {
                        this.discardedBitCount.AddInt(digits);
                    }
                    else
                    {
                        this.discardedBitCount = new FastInteger(digits);
                    }
                    int rem = this.shiftedSmall;
                    this.bitLeftmost        = 0;
                    this.bitsAfterLeftmost |= rem;
                    this.shiftedSmall       = 0;
                    this.knownDigitLength   = new FastInteger(1);
                    return;
                }
            }
            int v2 = this.shiftedSmall;
            int kb = (v2 >= 1000000000) ? 10 : ((v2 >= 100000000) ? 9 : ((v2 >=
                                                                          10000000) ? 8 : ((v2 >= 1000000) ? 7 : ((v2 >= 100000) ? 6 : ((v2 >=
                                                                                                                                         10000) ? 5 : ((v2 >= 1000) ? 4 : ((v2 >= 100) ? 3 : ((v2 >= 10) ? 2 :
                                                                                                                                                                                              1))))))));

            this.knownDigitLength = new FastInteger(kb);
            if (this.discardedBitCount != null)
            {
                this.discardedBitCount.AddInt(digits);
            }
            else
            {
                this.discardedBitCount = new FastInteger(digits);
            }
            var digitsShifted = 0;

            while (digits > 0)
            {
                if (this.shiftedSmall == 0)
                {
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = 0;
                    this.knownDigitLength   = new FastInteger(1);
                    break;
                }
                else
                {
                    var digit = (int)(this.shiftedSmall % 10);
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = digit;
                    --digits;
                    ++digitsShifted;
                    this.shiftedSmall /= 10;
                }
            }
            this.UpdateKnownLengthInt(digitsShifted);
            this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
        }
Beispiel #30
0
        private void ShiftRightLong(long shiftedLong, int digits)
        {
            if (digits <= 0)
            {
                return;
            }
            if (shiftedLong == 0)
            {
                this.shiftedSmall      = 0;
                this.isSmall           = true;
                this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
                this.discardedBitCount.AddInt(digits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                this.knownDigitLength   = new FastInteger(1);
                return;
            }
            if (digits >= 2 && digits <= 8)
            {
                if (shiftedLong >= ValueTenPowers[digits])
                {
                    long bigPower   = ValueTenPowers[digits];
                    long smallPower = ValueTenPowers[digits - 1];
                    this.discardedBitCount = this.discardedBitCount ?? (new
                                                                        FastInteger(0));
                    this.discardedBitCount.AddInt(digits);
                    long div  = shiftedLong / bigPower;
                    long rem  = shiftedLong - (div * bigPower);
                    long rem2 = rem / smallPower;
                    this.bitLeftmost        = (int)rem2;
                    this.bitsAfterLeftmost |= ((rem - (rem2 * smallPower)) == 0) ? 0 : 1;
                    this.isSmall            = div <= Int32.MaxValue;
                    if (this.isSmall)
                    {
                        this.shiftedSmall     = (int)div;
                        this.knownDigitLength = (div < 10) ? (new FastInteger(1)) :
                                                new FastInteger(LongDigitLength(div));
                    }
                    else
                    {
                        this.shiftedBigInt    = EInteger.FromInt64(div);
                        this.knownDigitLength = (div < 10) ? (new FastInteger(1)) :
                                                this.CalcKnownDigitLength();
                    }
                    return;
                }
                else if (this.shiftedSmall >= ValueTenPowers[digits - 1])
                {
                    int smallPower = ValueTenPowers[digits - 1];
                    if (this.discardedBitCount != null)
                    {
                        this.discardedBitCount.AddInt(digits);
                    }
                    else
                    {
                        this.discardedBitCount = new FastInteger(digits);
                    }
                    long rem  = shiftedLong;
                    long rem2 = rem / smallPower;
                    this.bitLeftmost        = (int)rem2;
                    this.bitsAfterLeftmost |= ((rem - (rem2 * smallPower)) == 0) ? 0 : 1;
                    this.isSmall            = true;
                    this.shiftedSmall       = 0;
                    this.knownDigitLength   = new FastInteger(1);
                    return;
                }
                else
                {
                    if (this.discardedBitCount != null)
                    {
                        this.discardedBitCount.AddInt(digits);
                    }
                    else
                    {
                        this.discardedBitCount = new FastInteger(digits);
                    }
                    this.bitLeftmost        = 0;
                    this.bitsAfterLeftmost |= (shiftedLong == 0) ? 0 : 1;
                    this.isSmall            = true;
                    this.shiftedSmall       = 0;
                    this.knownDigitLength   = new FastInteger(1);
                    return;
                }
            }
            this.knownDigitLength = new FastInteger(
                LongDigitLength(shiftedLong));
            if (this.discardedBitCount != null)
            {
                this.discardedBitCount.AddInt(digits);
            }
            else
            {
                this.discardedBitCount = new FastInteger(digits);
            }
            var digitsShifted = 0;

            while (digits > 0)
            {
                if (shiftedLong == 0)
                {
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = 0;
                    break;
                }
                else
                {
                    long newShift = (shiftedLong < 43698) ? ((shiftedLong * 26215) >>
                                                             18) : (shiftedLong / 10);
                    var digit = (int)(shiftedLong - (newShift * 10));
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = digit;
                    --digits;
                    ++digitsShifted;
                    shiftedLong = newShift;
                }
            }
            this.isSmall = shiftedLong <= Int32.MaxValue;
            if (this.isSmall)
            {
                this.shiftedSmall = (int)shiftedLong;
            }
            else
            {
                this.shiftedBigInt = EInteger.FromInt64(shiftedLong);
            }
            this.UpdateKnownLengthInt(digitsShifted);
            this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
        }