예제 #1
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;
             }
         }
     }
 }
예제 #2
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 });
            }
        }
예제 #3
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));
        }
예제 #4
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()));
        }
예제 #5
0
 public FastInteger ToFastInteger()
 {
     if (this.integerMode == IntegerMode.SmallValue)
     {
         return(new FastInteger(this.smallValue));
     }
     else
     {
         return(FastInteger.FromBig(this.largeValue));
     }
 }
예제 #6
0
 public static FastIntegerFixed FromFastInteger(FastInteger fi)
 {
     if (fi.CanFitInInt32())
     {
         return(FromInt32(fi.ToInt32()));
     }
     else
     {
         return(FastIntegerFixed.FromBig(fi.ToEInteger()));
     }
 }
예제 #7
0
 public BitShiftAccumulator(BigInteger bigint,
                        int lastDiscarded,
                        int olderDiscarded
                       )
 {
     if (bigint.Sign < 0)
     throw new ArgumentException("bigint is negative");
       shiftedBigInt = bigint;
       discardedBitCount = new FastInteger(0);
       bitsAfterLeftmost = (olderDiscarded != 0) ? 1 : 0;
       bitLeftmost = (lastDiscarded != 0) ? 1 : 0;
 }
예제 #8
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);
            }
        }
예제 #9
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();
            }
        }
예제 #10
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);
        }
예제 #11
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;
 }
예제 #12
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;
        }
예제 #13
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 });
            }
        }
예제 #14
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;
 }
예제 #15
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);
            }
        }
예제 #16
0
 public FastInteger GetDigitLength() {
   this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
   return FastInteger.CopyFrozen(this.knownBitLength);
 }
예제 #17
0
        private void ShiftRightBig(int digits)
        {
            if (digits <= 0) return;
              if (shiftedBigInt.IsZero) {
            if(discardedBitCount==null)
              discardedBitCount=new FastInteger(0);
            discardedBitCount.AddInt(digits);
            bitsAfterLeftmost |= bitLeftmost;
            bitLeftmost = 0;
            knownBitLength = new FastInteger(1);
            return;
              }
              //Console.WriteLine("digits={0}",digits);
              if(digits==1){
            BigInteger bigrem;
            BigInteger bigquo=BigInteger.DivRem(shiftedBigInt,(BigInteger)10,
                                            out bigrem);
            bitsAfterLeftmost|=bitLeftmost;
            bitLeftmost=(int)bigrem;
            shiftedBigInt=bigquo;
            if(discardedBitCount==null)
              discardedBitCount=new FastInteger(0);
            discardedBitCount.AddInt(digits);
            if(knownBitLength!=null){
              if(bigquo.IsZero)
            knownBitLength.SetInt(0);
              else
            knownBitLength.Decrement();
            }
            return;
              }
              int startCount=Math.Min(4,digits-1);
              if(startCount>0){
            BigInteger bigrem;
            BigInteger radixPower=DecimalUtility.FindPowerOfTen(startCount);
            BigInteger bigquo=BigInteger.DivRem(shiftedBigInt,radixPower,
                                            out bigrem);
            if(!bigrem.IsZero)
              bitsAfterLeftmost|=1;
            bitsAfterLeftmost|=bitLeftmost;
            shiftedBigInt=bigquo;
            if(discardedBitCount==null)
              discardedBitCount=new FastInteger(0);
            discardedBitCount.AddInt(startCount);
            digits-=startCount;
            if(shiftedBigInt.IsZero){
              // Shifted all the way to 0
              isSmall=true;
              shiftedSmall=0;
              knownBitLength=new FastInteger(1);
              bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
              bitLeftmost=0;
              return;
            }
              }

              String str = shiftedBigInt.ToString();
              // NOTE: Will be 1 if the value is 0
              int digitLength = str.Length;
              int bitDiff = 0;
              if (digits > digitLength) {
            bitDiff = digits - digitLength;
              }
              if(discardedBitCount==null)
            discardedBitCount=new FastInteger(0);
              discardedBitCount.AddInt(digits);
              bitsAfterLeftmost |= bitLeftmost;
              int digitShift = Math.Min(digitLength, digits);
              if (digits >= digitLength) {
            isSmall = true;
            shiftedSmall = 0;
            knownBitLength = new FastInteger(1);
              } else {
            int newLength = (int)(digitLength - digitShift);
            knownBitLength = new FastInteger(newLength);
            if (newLength <= 9) {
              // Fits in a small number
              isSmall = true;
              shiftedSmall = FastParseLong(str, 0, newLength);
            } else {
              shiftedBigInt = BigInteger.fromSubstring(str, 0, newLength);
            }
              }
              for (int i = str.Length - 1; i >= 0; i--) {
            bitsAfterLeftmost |= bitLeftmost;
            bitLeftmost = (int)(str[i] - '0');
            digitShift--;
            if (digitShift <= 0) {
              break;
            }
              }
              bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
              if (bitDiff > 0) {
            // Shifted more digits than the digit length
            bitsAfterLeftmost |= bitLeftmost;
            bitLeftmost = 0;
              }
        }
예제 #18
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;
 }
예제 #19
0
        private void ShiftRightSmall(int digits)
        {
            if (digits <= 0) return;
              if (shiftedSmall == 0) {
            if(discardedBitCount==null)
              discardedBitCount=new FastInteger(0);
            discardedBitCount.AddInt(digits);
            bitsAfterLeftmost |= bitLeftmost;
            bitLeftmost = 0;
            knownBitLength = new FastInteger(1);
            return;
              }

              int kb = 0;
              int tmp = shiftedSmall;
              while (tmp > 0) {
            kb++;
            tmp /= 10;
              }
              // Make sure digit length is 1 if value is 0
              if (kb == 0) kb++;
              knownBitLength=new FastInteger(kb);
              if(discardedBitCount==null)
            discardedBitCount=new FastInteger(0);
              discardedBitCount.AddInt(digits);
              while (digits > 0) {
            if (shiftedSmall == 0) {
              bitsAfterLeftmost |= bitLeftmost;
              bitLeftmost = 0;
              knownBitLength = new FastInteger(0);
              break;
            } else {
              int digit = (int)(shiftedSmall % 10);
              bitsAfterLeftmost |= bitLeftmost;
              bitLeftmost = digit;
              digits--;
              shiftedSmall /= 10;
              knownBitLength.Decrement();
            }
              }
              bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
        }
예제 #20
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);
        }
예제 #21
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();
     }
 }
예제 #22
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;
    }
예제 #23
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;
      }
    }
예제 #24
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;
   }
 }
예제 #25
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;
 }
예제 #26
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;
 }
예제 #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;
    }
  }
예제 #28
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();
   }
 }
예제 #29
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);
   }
 }
예제 #30
0
 private void ShiftBigToBits(int bits) {
   // Shifts a number until it reaches the given number of bits,
   // gathering information on whether the last bit discarded is set and
   // whether the discarded bits to the right of that bit are set. Assumes
   // that the big integer being shifted is positive.
   if (this.knownBitLength != null) {
     if (this.knownBitLength.CompareToInt(bits) <= 0) {
       return;
     }
   }
   this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
   if (this.knownBitLength.CompareToInt(bits) <= 0) {
     return;
   }
   // Shift by the difference in bit length
   if (this.knownBitLength.CompareToInt(bits) > 0) {
     var bs = 0;
     if (this.knownBitLength.CanFitInInt32()) {
       bs = this.knownBitLength.AsInt32();
       bs -= bits;
     } else {
       FastInteger bitShift =
       this.knownBitLength.Copy().SubtractInt(bits);
       if (!bitShift.CanFitInInt32()) {
         this.ShiftRight(bitShift);
         return;
       }
       bs = bitShift.AsInt32();
     }
     this.knownBitLength.SetInt(bits);
     this.discardedBitCount.AddInt(bs);
     if (bs == 1) {
       bool odd = !this.shiftedBigInt.IsEven;
       this.shiftedBigInt >>= 1;
       this.bitsAfterLeftmost |= this.bitLeftmost;
       this.bitLeftmost = odd ? 1 : 0;
     } else {
       this.bitsAfterLeftmost |= this.bitLeftmost;
       int lowestSetBit = this.shiftedBigInt.GetLowBit();
       if (lowestSetBit < bs - 1) {
         // One of the discarded bits after
         // the last one is set
         this.bitsAfterLeftmost |= 1;
         this.bitLeftmost = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 : 0;
       } else if (lowestSetBit > bs - 1) {
         // Means all discarded bits are zero
         this.bitLeftmost = 0;
       } else {
         // Only the last discarded bit is set
         this.bitLeftmost = 1;
       }
       this.shiftedBigInt >>= bs;
     }
     if (bits < SmallBitLength) {
       // Shifting to small number of bits,
       // convert to small integer
       this.isSmall = true;
       this.shiftedSmall = (int)this.shiftedBigInt;
     }
     this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
   }
 }
예제 #31
0
 private void TruncateRightLong(long shiftedLong, int digits) {
   if (digits <= 0) {
     return;
   }
   if (shiftedLong == 0 || digits >= 21) {
     this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
     this.discardedBitCount.AddInt(digits);
     this.bitsAfterLeftmost |= this.bitLeftmost;
     this.bitLeftmost = shiftedLong == 0 ? 0 : 1;
     this.shiftedSmall = 0;
     this.isSmall = true;
     this.knownDigitLength = new FastInteger(1);
     return;
   }
   if (digits >= 1 && digits <= TenPowersLong.Length - 1) {
     if (shiftedLong >= TenPowersLong[digits]) {
       long bigPower = TenPowersLong[digits];
       if (this.discardedBitCount != null) {
         this.discardedBitCount.AddInt(digits);
       } else {
         this.discardedBitCount = new FastInteger(digits);
       }
       long quo = shiftedLong / bigPower;
       this.bitsAfterLeftmost |= this.bitLeftmost;
       this.bitLeftmost = (shiftedLong & 1) == 1 ? 1 :
         (shiftedLong - (quo * bigPower) == 0 ? 0 : 1);
       shiftedLong = quo;
       this.isSmall = shiftedLong <= Int32.MaxValue;
       if (this.isSmall) {
         this.shiftedSmall = (int)shiftedLong;
       } else {
         this.shiftedBigInt = EInteger.FromInt64(shiftedLong);
       }
       this.UpdateKnownLengthInt(digits);
       return;
     } else {
       if (this.discardedBitCount != null) {
         this.discardedBitCount.AddInt(digits);
       } else {
         this.discardedBitCount = new FastInteger(digits);
       }
       this.bitsAfterLeftmost |= this.bitLeftmost;
       this.bitLeftmost = shiftedLong == 0 ? 0 : 1;
       shiftedLong = 0;
       this.isSmall = shiftedLong <= Int32.MaxValue;
       if (this.isSmall) {
         this.shiftedSmall = (int)shiftedLong;
       } else {
         this.shiftedBigInt = EInteger.FromInt64(shiftedLong);
       }
       this.UpdateKnownLengthInt(digits);
       return;
     }
   }
   this.ShiftRightInt(digits);
 }
예제 #32
0
 private void ShiftBigToBits(int bits)
 {
     // Shifts a number until it reaches the given number of bits,
     // gathering information on whether the last bit discarded is set and
     // whether the discarded bits to the right of that bit are set. Assumes
     // that the big integer being shifted is positive.
     if (this.knownBitLength != null)
     {
         if (this.knownBitLength.CompareToInt(bits) <= 0)
         {
             return;
         }
     }
     this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
     if (this.knownBitLength.CompareToInt(bits) <= 0)
     {
         return;
     }
     // Shift by the difference in bit length
     if (this.knownBitLength.CompareToInt(bits) > 0)
     {
         var bs = 0;
         if (this.knownBitLength.CanFitInInt32())
         {
             bs  = this.knownBitLength.ToInt32();
             bs -= bits;
         }
         else
         {
             FastInteger bitShift =
                 this.knownBitLength.Copy().SubtractInt(bits);
             if (!bitShift.CanFitInInt32())
             {
                 this.ShiftRight(bitShift);
                 return;
             }
             bs = bitShift.ToInt32();
         }
         this.knownBitLength.SetInt(bits);
         this.discardedBitCount.AddInt(bs);
         if (bs == 1)
         {
             bool odd = !this.shiftedBigInt.IsEven;
             this.shiftedBigInt    >>= 1;
             this.bitsAfterLeftmost |= this.bitLeftmost;
             this.bitLeftmost        = odd ? 1 : 0;
         }
         else
         {
             this.bitsAfterLeftmost |= this.bitLeftmost;
             long lowestSet = this.shiftedBigInt.GetLowBitAsInt64();
             if (lowestSet == Int64.MaxValue)
             {
                 EInteger lowestSetBit = this.shiftedBigInt.GetLowBitAsEInteger();
                 if (lowestSetBit.CompareTo(bs - 1) < 0)
                 {
                     // One of the discarded bits after
                     // the last one is set
                     this.bitsAfterLeftmost |= 1;
                     this.bitLeftmost        = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 :
                                               0;
                 }
                 else if (lowestSetBit.CompareTo(bs - 1) > 0)
                 {
                     // Means all discarded bits are zero
                     this.bitLeftmost = 0;
                 }
                 else
                 {
                     // Only the last discarded bit is set
                     this.bitLeftmost = 1;
                 }
             }
             else
             {
                 if (lowestSet < bs - 1)
                 {
                     // One of the discarded bits after
                     // the last one is set
                     this.bitsAfterLeftmost |= 1;
                     this.bitLeftmost        = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 :
                                               0;
                 }
                 else if (lowestSet > bs - 1)
                 {
                     // Means all discarded bits are zero
                     this.bitLeftmost = 0;
                 }
                 else
                 {
                     // Only the last discarded bit is set
                     this.bitLeftmost = 1;
                 }
             }
             this.shiftedBigInt >>= bs;
         }
         if (bits < SmallBitLength)
         {
             // Shifting to small number of bits,
             // convert to small integer
             this.isSmall      = true;
             this.shiftedSmall = (int)this.shiftedBigInt;
         }
         this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
     }
 }
예제 #33
0
 private void TruncateRightSmall(int digits) {
   if (digits <= 0) {
     return;
   }
   if (this.shiftedSmall == 0 || digits >= 11) {
     this.discardedBitCount = this.discardedBitCount ?? (new FastInteger(0));
     this.discardedBitCount.AddInt(digits);
     this.bitsAfterLeftmost |= this.bitLeftmost;
     this.bitLeftmost = (this.shiftedSmall == 0) ? 0 : 1;
     this.shiftedSmall = 0;
     this.knownDigitLength = new FastInteger(1);
     return;
   }
   if (digits >= 1 && digits <= 8) {
     if (this.shiftedSmall >= ValueTenPowers[digits]) {
       int bigPower = ValueTenPowers[digits];
       if (this.discardedBitCount != null) {
         this.discardedBitCount.AddInt(digits);
       } else {
         this.discardedBitCount = new FastInteger(digits);
       }
       this.bitsAfterLeftmost |= this.bitLeftmost;
       if ((this.shiftedSmall & 1) == 1) {
         this.bitLeftmost = 1;
         this.shiftedSmall /= bigPower;
       } else {
         int quo = this.shiftedSmall / bigPower;
         int rem = this.shiftedSmall - (quo * bigPower);
         this.shiftedSmall = quo;
         this.bitLeftmost |= (rem == 0) ? 0 : 1;
       }
       this.UpdateKnownLengthInt(digits);
       return;
     } else {
       if (this.discardedBitCount != null) {
         this.discardedBitCount.AddInt(digits);
       } else {
         this.discardedBitCount = new FastInteger(digits);
       }
       this.bitsAfterLeftmost |= this.bitLeftmost;
       this.bitLeftmost = (this.shiftedSmall == 0) ? 0 : 1;
       this.shiftedSmall = 0;
       this.knownDigitLength = new FastInteger(1);
       return;
     }
   }
   this.ShiftRightSmall(digits);
 }
예제 #34
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();
      }
    }
예제 #35
0
  public FastInteger GetDigitLength() {
this.knownDigitLength = this.knownDigitLength ??
      this.CalcKnownDigitLength();
    return this.knownDigitLength;
  }
예제 #36
0
 /// <summary> 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. </summary>
 private void ShiftToBitsBig(int digits)
 {
     if(knownBitLength!=null){
     if(knownBitLength.CompareToInt(digits)<=0){
       return;
     }
       }
       String str;
       if(knownBitLength==null)
     knownBitLength=GetDigitLength();
       if(knownBitLength.CompareToInt(digits)<=0){
     return;
       }
       FastInteger digitDiff=FastInteger.Copy(knownBitLength).SubtractInt(digits);
       if(digitDiff.CompareToInt(1)==0){
     BigInteger bigrem;
     BigInteger bigquo=BigInteger.DivRem(shiftedBigInt,Ten,out bigrem);
     bitsAfterLeftmost|=bitLeftmost;
     bitLeftmost=(int)bigrem;
     shiftedBigInt=bigquo;
     if(discardedBitCount==null)
       discardedBitCount=new FastInteger(0);
     discardedBitCount.Add(digitDiff);
     knownBitLength.Subtract(digitDiff);
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
     return;
       } else if(digitDiff.CompareToInt(9)<=0){
     BigInteger bigrem;
     int diffInt=digitDiff.AsInt32();
     BigInteger radixPower=DecimalUtility.FindPowerOfTen(diffInt);
     BigInteger bigquo=BigInteger.DivRem(shiftedBigInt,radixPower,
                                     out bigrem);
     int rem=(int)bigrem;
     bitsAfterLeftmost|=bitLeftmost;
     for(int i=0;i<diffInt;i++){
       if(i==diffInt-1){
     bitLeftmost=rem%10;
       } else {
     bitsAfterLeftmost|=(rem%10);
     rem/=10;
       }
     }
     shiftedBigInt=bigquo;
     if(discardedBitCount==null)
       discardedBitCount=new FastInteger(0);
     discardedBitCount.Add(digitDiff);
     knownBitLength.Subtract(digitDiff);
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
     return;
       } else if(digitDiff.CompareToInt(Int32.MaxValue)<=0){
     BigInteger bigrem;
     BigInteger radixPower=DecimalUtility.FindPowerOfTen(digitDiff.AsInt32()-1);
     BigInteger bigquo=BigInteger.DivRem(shiftedBigInt,radixPower,
                                     out bigrem);
     bitsAfterLeftmost|=bitLeftmost;
     if(!bigrem.IsZero)
       bitsAfterLeftmost|=1;
     {
       BigInteger bigquo2=BigInteger.DivRem(bigquo,Ten,out bigrem);
       this.bitLeftmost=(int)bigrem;
       shiftedBigInt=bigquo2;
     }
     if(discardedBitCount==null)
       discardedBitCount=new FastInteger(0);
     discardedBitCount.Add(digitDiff);
     knownBitLength.Subtract(digitDiff);
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
     return;
       }
       str=shiftedBigInt.ToString();
       // NOTE: Will be 1 if the value is 0
       int digitLength = str.Length;
       knownBitLength = new FastInteger(digitLength);
       // Shift by the difference in digit length
       if (digitLength > digits) {
     int digitShift = digitLength - digits;
     knownBitLength.SubtractInt(digitShift);
     int newLength = (int)(digitLength - digitShift);
     //Console.WriteLine("dlen={0} dshift={1} newlen={2}",digitLength,
     //                digitShift,newLength);
     if(discardedBitCount==null)
       discardedBitCount=new FastInteger(0);
     if(digitShift<=Int32.MaxValue)
       discardedBitCount.AddInt((int)digitShift);
     else
       discardedBitCount.AddBig((BigInteger)digitShift);
     for (int i = str.Length - 1; i >= 0; i--) {
       bitsAfterLeftmost |= bitLeftmost;
       bitLeftmost = (int)(str[i] - '0');
       digitShift--;
       if (digitShift <= 0) {
     break;
       }
     }
     if (newLength <= 9) {
       isSmall = true;
       shiftedSmall = FastParseLong(str, 0, newLength);
     } else {
       shiftedBigInt = BigInteger.fromSubstring(str, 0, newLength);
     }
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
       }
 }
예제 #37
0
 /// <summary> </summary>
 /// <param name='fastint'>A FastInteger object.</param>
 /// <returns></returns>
 public void ShiftRight(FastInteger fastint)
 {
     if (fastint.Sign <= 0) return;
       if (fastint.CanFitInInt32()) {
     ShiftRightInt(fastint.AsInt32());
       } else {
     BigInteger bi = fastint.AsBigInteger();
     while (bi.Sign > 0) {
       int count = 1000000;
       if (bi.CompareTo((BigInteger)1000000) < 0) {
     count = (int)bi;
       }
       ShiftRightInt(count);
       bi -= (BigInteger)count;
       if(isSmall ? shiftedSmall==0 : shiftedBigInt.IsZero){
     break;
       }
     }
       }
 }
예제 #38
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);
   }
예제 #39
0
 /// <summary> </summary>
 /// <param name='bits'>A FastInteger object.</param>
 /// <returns></returns>
 public void ShiftToDigits(FastInteger bits)
 {
     if(bits.Sign<0)
     throw new ArgumentException("bits is negative");
       if(bits.CanFitInInt32()){
     ShiftToDigitsInt(bits.AsInt32());
       } else {
     knownBitLength=CalcKnownBitLength();
     BigInteger bigintDiff=knownBitLength.AsBigInteger();
     BigInteger bitsBig=bits.AsBigInteger();
     bigintDiff-=(BigInteger)bitsBig;
     if(bigintDiff.Sign>0){
       // current length is greater than the
       // desired bit length
       ShiftRight(FastInteger.FromBig(bigintDiff));
     }
       }
 }
예제 #40
0
        public static FastInteger[] DecimalDigitLengthBounds(EInteger ei)
        {
            long longBitLength = ei.GetUnsignedBitLengthAsInt64();

            if (longBitLength < 33)
            {
                // Can easily be calculated without estimation
                var fi = new FastInteger((int)ei.GetDigitCountAsInt64());
                return(new FastInteger[] { fi, fi });
            }
            else if (longBitLength <= 2135)
            {
                var bitlen    = (int)longBitLength;
                int minDigits = 1 + (((bitlen - 1) * 631305) >> 21);
                int maxDigits = 1 + ((bitlen * 631305) >> 21);
                if (minDigits == maxDigits)
                {
                    var fi = new FastInteger(minDigits);
                    return(new FastInteger[] { fi, fi });
                }
                else
                {
                    return(new FastInteger[] {
                        new FastInteger(minDigits), // lower bound
                        new FastInteger(maxDigits), // upper bound
                    });
                }
            }
            else if (longBitLength <= 6432162)
            {
                var bitlen = (int)longBitLength;
                // Approximation of ln(2)/ln(10)
                int minDigits = 1 + (int)(((long)(bitlen - 1) * 661971961083L) >> 41);
                int maxDigits = 1 + (int)(((long)bitlen * 661971961083L) >> 41);
                if (minDigits == maxDigits)
                {
                    var fi = new FastInteger(minDigits);
                    return(new FastInteger[] { fi, fi });
                }
                else
                {
                    return(new FastInteger[] {
                        new FastInteger(minDigits), // lower bound
                        new FastInteger(maxDigits), // upper bound
                    });
                }
            }
            else
            {
                // Bit length is big enough that these bounds will
                // overestimate or underestimate the true base-10 digit length
                // as appropriate.
                EInteger bigBitLength = ei.GetUnsignedBitLengthAsEInteger();
                EInteger lowerBound   = bigBitLength.Multiply(100).Divide(335);
                EInteger upperBound   = bigBitLength.Divide(3);
                return(new FastInteger[] {
                    FastInteger.FromBig(lowerBound), // lower bound
                    FastInteger.FromBig(upperBound), // upper bound
                });
            }
        }
예제 #41
0
 private static FastInteger ByteArrayBitLength(byte[] bytes)
 {
     FastInteger fastKB = new FastInteger(bytes.Length).Multiply(8);
       for (int i = bytes.Length - 1; i >= 0; i--) {
     int b = (int)bytes[i];
     if (b != 0) {
       if ((b & 0x80) != 0) { break; }
       if ((b & 0x40) != 0) { fastKB.Decrement(); break; }
       if ((b & 0x20) != 0) { fastKB.SubtractInt(2); break; }
       if ((b & 0x10) != 0) { fastKB.SubtractInt(3); break; }
       if ((b & 0x08) != 0) { fastKB.SubtractInt(4); break; }
       if ((b & 0x04) != 0) { fastKB.SubtractInt(5); break; }
       if ((b & 0x02) != 0) { fastKB.SubtractInt(6); break; }
       if ((b & 0x01) != 0) { fastKB.SubtractInt(7); break; }
     }
     fastKB.SubtractInt(8);
       }
       // Make sure bit length is 1 if value is 0
       if (fastKB.Sign == 0) fastKB.Increment();
       return fastKB;
 }
예제 #42
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.AsInt32();
   // 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);
   }
 }
예제 #43
0
 /// <summary> Shifts a number until it reaches the given number of bits,
 /// gathering information on whether the last bit discarded is set and
 /// whether the discarded bits to the right of that bit are set. Assumes
 /// that the big integer being shifted is positive. </summary>
 private void ShiftBigToBits(int bits)
 {
     byte[] bytes = shiftedBigInt.ToByteArray();
       knownBitLength = ByteArrayBitLength(bytes);
       // Shift by the difference in bit length
       if (knownBitLength.CompareToInt(bits) > 0) {
     FastInteger bitShift = FastInteger.Copy(knownBitLength).SubtractInt(bits);
     FastInteger tmpBitShift = FastInteger.Copy(bitShift);
     while (tmpBitShift.Sign > 0 && !shiftedBigInt.IsZero) {
       int bs = tmpBitShift.MinInt32(1000000);
       shiftedBigInt >>= bs;
       tmpBitShift.SubtractInt(bs);
     }
     knownBitLength.SetInt(bits);
     if (bits < SmallBitLength) {
       // Shifting to small number of bits,
       // convert to small integer
       isSmall = true;
       shiftedSmall = (int)shiftedBigInt;
     }
     bitsAfterLeftmost |= bitLeftmost;
     discardedBitCount.Add(bitShift);
     for (int i = 0; i < bytes.Length; i++) {
       if (bitShift.CompareToInt(8)>0) {
     // Discard all the bits, they come
     // after the leftmost bit
     bitsAfterLeftmost |= bytes[i];
     bitShift.SubtractInt(8);
       } else {
     // 8 or fewer bits left.
     // Get the bottommost bitShift minus 1 bits
     bitsAfterLeftmost |= ((bytes[i] << (9 - bitShift.AsInt32())) & 0xFF);
     // Get the bit just above those bits
     bitLeftmost = (bytes[i] >> ((bitShift.AsInt32()) - 1)) & 0x01;
     break;
       }
     }
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
       }
 }
예제 #44
0
 public void TruncateOrShiftRight(FastInteger fastint, bool truncate)
 {
     this.ShiftRight(fastint);
 }
예제 #45
0
 private void ShiftRightBig(int bits)
 {
     if (bits <= 0) return;
       if (shiftedBigInt.IsZero) {
     discardedBitCount.AddInt(bits);
     bitsAfterLeftmost |= bitLeftmost;
     bitLeftmost = 0;
     knownBitLength=new FastInteger(1);
     return;
       }
       byte[] bytes = shiftedBigInt.ToByteArray();
       knownBitLength = ByteArrayBitLength(bytes);
       FastInteger bitDiff = new FastInteger(0);
       FastInteger bitShift=null;
       if (knownBitLength.CompareToInt(bits)<0) {
     bitDiff = new FastInteger(bits).Subtract(knownBitLength);
     bitShift=FastInteger.Copy(knownBitLength);
       } else {
     bitShift=new FastInteger(bits);
       }
       if (knownBitLength.CompareToInt(bits)<=0) {
     isSmall = true;
     shiftedSmall = 0;
     knownBitLength.SetInt(1);
       } else {
     FastInteger tmpBitShift = FastInteger.Copy(bitShift);
     while (tmpBitShift.Sign > 0 && !shiftedBigInt.IsZero) {
       int bs = tmpBitShift.MinInt32(1000000);
       shiftedBigInt >>= bs;
       tmpBitShift.SubtractInt(bs);
     }
     knownBitLength.Subtract(bitShift);
       }
       discardedBitCount.AddInt(bits);
       bitsAfterLeftmost |= bitLeftmost;
       for (int i = 0; i < bytes.Length; i++) {
     if (bitShift.CompareToInt(8)>0) {
       // Discard all the bits, they come
       // after the leftmost bit
       bitsAfterLeftmost |= bytes[i];
       bitShift.SubtractInt(8);
     } else {
       // 8 or fewer bits left.
       // Get the bottommost bitShift minus 1 bits
       bitsAfterLeftmost |= ((bytes[i] << (9 - bitShift.AsInt32())) & 0xFF);
       // Get the bit just above those bits
       bitLeftmost = (bytes[i] >> ((bitShift.AsInt32()) - 1)) & 0x01;
       break;
     }
       }
       bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
       if (bitDiff.Sign > 0) {
     // Shifted more bits than the bit length
     bitsAfterLeftmost |= bitLeftmost;
     bitLeftmost = 0;
       }
 }
예제 #46
0
        private void ShiftRightBig(int bits)
        {
            if (bits <= 0)
            {
                return;
            }
            if (this.shiftedBigInt.IsZero)
            {
                this.discardedBitCount.AddInt(bits);
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitLeftmost        = 0;
                this.isSmall            = true;
                this.shiftedSmall       = 0;
                this.knownBitLength     = new FastInteger(1);
                return;
            }
            this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
            this.discardedBitCount.AddInt(bits);
            int cmp = this.knownBitLength.CompareToInt(bits);

            if (cmp < 0)
            {
                // too few bits
                this.bitsAfterLeftmost |= this.bitLeftmost;
                this.bitsAfterLeftmost |= this.shiftedBigInt.IsZero ? 0 : 1;
                this.bitLeftmost        = 0;
                this.isSmall            = true;
                this.shiftedSmall       = 0;
                this.knownBitLength     = new FastInteger(1);
            }
            else
            {
                // enough bits in the current value
                int bs = bits;
                this.knownBitLength.SubtractInt(bits);
                if (bs == 1)
                {
                    bool odd = !this.shiftedBigInt.IsEven;
                    this.shiftedBigInt    >>= 1;
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    this.bitLeftmost        = odd ? 1 : 0;
                }
                else
                {
                    this.bitsAfterLeftmost |= this.bitLeftmost;
                    long lowestSet = this.shiftedBigInt.GetLowBitAsInt64();
                    if (lowestSet == Int64.MaxValue)
                    {
                        EInteger lowestSetBit = this.shiftedBigInt.GetLowBitAsEInteger();
                        if (lowestSetBit.CompareTo(bs - 1) < 0)
                        {
                            // One of the discarded bits after
                            // the last one is set
                            this.bitsAfterLeftmost |= 1;
                            this.bitLeftmost        = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 :
                                                      0;
                        }
                        else if (lowestSetBit.CompareTo(bs - 1) > 0)
                        {
                            // Means all discarded bits are zero
                            this.bitLeftmost = 0;
                        }
                        else
                        {
                            // Only the last discarded bit is set
                            this.bitLeftmost = 1;
                        }
                    }
                    else
                    {
                        if (lowestSet < bs - 1)
                        {
                            // One of the discarded bits after
                            // the last one is set
                            this.bitsAfterLeftmost |= 1;
                            this.bitLeftmost        = this.shiftedBigInt.GetSignedBit(bs - 1) ? 1 :
                                                      0;
                        }
                        else if (lowestSet > bs - 1)
                        {
                            // Means all discarded bits are zero
                            this.bitLeftmost = 0;
                        }
                        else
                        {
                            // Only the last discarded bit is set
                            this.bitLeftmost = 1;
                        }
                    }
                    this.shiftedBigInt >>= bs;
                }
                if (this.knownBitLength.CompareToInt(SmallBitLength) < 0)
                {
                    // Shifting to small number of bits,
                    // convert to small integer
                    this.isSmall      = true;
                    this.shiftedSmall = (int)this.shiftedBigInt;
                }
                this.bitsAfterLeftmost = (this.bitsAfterLeftmost != 0) ? 1 : 0;
            }
        }
예제 #47
0
 private void ShiftRightSmall(int bits)
 {
     if (bits <= 0) return;
       if (shiftedSmall == 0) {
     discardedBitCount.AddInt(bits);
     bitsAfterLeftmost |= bitLeftmost;
     bitLeftmost = 0;
     knownBitLength = new FastInteger(1);
     return;
       }
       int kb = SmallBitLength;
       for (int i = SmallBitLength-1; i >= 0; i++) {
     if ((shiftedSmall & (1 << i)) != 0) {
       break;
     } else {
       kb--;
     }
       }
       int shift = (int)Math.Min(kb, bits);
       bool shiftingMoreBits = (bits > kb);
       kb = kb - shift;
       knownBitLength=new FastInteger(kb);
       discardedBitCount.AddInt(bits);
       bitsAfterLeftmost |= bitLeftmost;
       // Get the bottommost shift minus 1 bits
       bitsAfterLeftmost |= (((shiftedSmall << (SmallBitLength + 1 - shift)) != 0) ? 1 : 0);
       // Get the bit just above that bit
       bitLeftmost = (int)((shiftedSmall >> ((shift) - 1)) & 0x01);
       shiftedSmall >>= shift;
       if (shiftingMoreBits) {
     // Shifted more bits than the bit length
     bitsAfterLeftmost |= bitLeftmost;
     bitLeftmost = 0;
       }
       bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
 }
예제 #48
0
 public FastInteger GetDigitLength()
 {
     this.knownBitLength = this.knownBitLength ?? this.CalcKnownBitLength();
     return(FastInteger.CopyFrozen(this.knownBitLength));
 }
예제 #49
0
 private void ShiftToBitsSmall(int digits)
 {
     int kb=0;
       int v2=shiftedSmall;
       if(v2>=1000000000)kb=10;
       else if(v2>=100000000)kb=9;
       else if(v2>=10000000)kb=8;
       else if(v2>=1000000)kb=7;
       else if(v2>=100000)kb=6;
       else if(v2>=10000)kb=5;
       else if(v2>=1000)kb=4;
       else if(v2>=100)kb=3;
       else if(v2>=10)kb=2;
       else kb=1;
       knownBitLength=new FastInteger(kb);
       if (kb > digits) {
     int digitShift = (int)(kb - digits);
     int newLength = (int)(kb - digitShift);
     knownBitLength = new FastInteger(Math.Max(1, newLength));
     if(discardedBitCount==null)
       discardedBitCount=new FastInteger(digitShift);
     else
       discardedBitCount.AddInt(digitShift);
     for (int i = 0; i < digitShift; i++) {
       int digit = (int)(shiftedSmall % 10);
       shiftedSmall /= 10;
       bitsAfterLeftmost |= bitLeftmost;
       bitLeftmost = digit;
     }
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
       }
 }
예제 #50
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 |= EContext.FlagUnderflow |
                                         EContext.FlagSubnormal | EContext.FlagInexact | EContext.FlagRounded;
                    }
                }
            }
            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().GetDigitLength(mant);
                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.ToEInteger(),
                        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.ToEInteger(),
                    thisFlags);
            }
            return(thisValue);
        }
예제 #51
0
 private void ShiftSmallToBits(int bits)
 {
     int kbl = SmallBitLength;
       for (int i = SmallBitLength - 1; i >= 0; i++) {
     if ((shiftedSmall & (1L << i)) != 0) {
       break;
     } else {
       kbl--;
     }
       }
       if (kbl == 0) kbl++;
       // Shift by the difference in bit length
       if (kbl > bits) {
     int bitShift = kbl - (int)bits;
     int shift = (int)bitShift;
     knownBitLength = new FastInteger(bits);
     discardedBitCount.AddInt(bitShift);
     bitsAfterLeftmost |= bitLeftmost;
     // Get the bottommost shift minus 1 bits
     bitsAfterLeftmost |= (((shiftedSmall << (SmallBitLength + 1 - shift)) != 0) ? 1 : 0);
     // Get the bit just above that bit
     bitLeftmost = (int)((shiftedSmall >> (((int)shift) - 1)) & 0x01);
     bitsAfterLeftmost = (bitsAfterLeftmost != 0) ? 1 : 0;
     shiftedSmall >>= shift;
       } else {
     knownBitLength=new FastInteger(kbl);
       }
 }
예제 #52
0
 /// <summary> </summary>
 /// <returns>A FastInteger object.</returns>
 public FastInteger GetDigitLength()
 {
     if (knownBitLength==null) {
     knownBitLength = CalcKnownBitLength();
       }
       return FastInteger.Copy(knownBitLength);
 }
예제 #53
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;
       }
     }
   }
 }