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); }
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; } }
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; }
/// <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; } }