private static BigInteger GetNearby(BigInteger significand, int binExp, int offset) { int nExtraBits = 1; int nDec = (int)Math.Round(3.0 + (64 + nExtraBits) * Math.Log10(2.0)); BigInteger newFrac = (significand << nExtraBits).Add(new BigInteger(offset)); int gg = 64 + nExtraBits - binExp - 1; decimal bd = new decimal(newFrac.LongValue()); if (gg > 0) { bd = bd / (new decimal((BigInteger.ONE << gg).LongValue())); } else { BigInteger frac = newFrac; while (frac.BitLength() + binExp < 180) { frac = frac * (BigInteger.TEN); } int binaryExp = binExp - newFrac.BitLength() + frac.BitLength(); bd = new decimal((frac >> (frac.BitLength() - binaryExp - 1)).LongValue()); } /*int excessPrecision = bd.Precision() - nDec; * if (excessPrecision > 0) * { * bd = bd.SetScale(bd.Scale() - excessPrecision, BigDecimal.ROUND_HALF_UP); * } * return bd.unscaledValue();*/ throw new NotImplementedException(); }
private TenPower(int index) { //BigInteger fivePowIndex = FIVE.ModPow(new BigInteger(index),FIVE); BigInteger fivePowIndex = FIVE.Pow(index); int bitsDueToFiveFactors = fivePowIndex.BitLength(); int px = 80 + bitsDueToFiveFactors; BigInteger fx = (BigInteger.ONE << px) / (fivePowIndex); int adj = fx.BitLength() - 80; _divisor = fx >> (adj); bitsDueToFiveFactors -= adj; _divisorShift = -(bitsDueToFiveFactors + index + 80); int sc = fivePowIndex.BitLength() - 68; if (sc > 0) { _multiplierShift = index + sc; _multiplicand = fivePowIndex >> (sc); } else { _multiplierShift = index; _multiplicand = fivePowIndex; } }
public void KeyGenerationProtocol_PublishKey( IOutputChannel output_channel) { // proof of knowledge [CaS97] for the public key // commitment BigInteger v = mpz_srandom.mpz_srandomm(q); BigInteger t = g.ModPow(v, p); // challenge // Here we use the well-known "Fiat-Shamir heuristic" to make // the PK non-interactive, i.e. we turn it into a statistically // zero-knowledge (Schnorr signature scheme style) proof of // knowledge (SPK) in the random oracle model. BigInteger c = mpz_shash_tools.mpz_shash(new BigInteger [] { g, h_i, t }); // response BigInteger r = c * x_i; r = r.FlipSign(); r += v; r = r % q; output_channel.Send(h_i); output_channel.Send(c); output_channel.Send(r); System.Diagnostics.Debug.WriteLine("g " + g.BitLength() + " h_i " + h_i.BitLength() + " t " + t.BitLength()); }
public void Normalise64bit() { int oldBitLen = _significand.BitLength(); int sc = oldBitLen - C_64; if (sc == 0) { return; } if (sc < 0) { throw new InvalidOperationException("Not enough precision"); } _binaryExponent += sc; if (sc > 32) { int highShift = (sc - 1) & 0xFFFFE0; _significand = _significand >> (highShift); sc -= highShift; oldBitLen -= highShift; } if (sc < 1) { throw new InvalidOperationException(); } _significand = Rounder.Round(_significand, sc); if (_significand.BitLength() > oldBitLen) { sc++; _binaryExponent++; } _significand = _significand >> (sc); }
public static BigInteger GetNearby(NormalisedDecimal md, int offset) { BigInteger frac = md.ComposeFrac(); int be = frac.BitLength() - 24 - 1; int sc = frac.BitLength() - 64; return(GetNearby(frac >> (sc), be, offset)); }
public static void KeyGen(int key_size, out BigInteger oe, out BigInteger od, out BigInteger on) { RandomBigInteger rand = new RandomBigInteger(); BigInteger p = rand.NextBigInteger(key_size / 2); p = p.GetNextPrime(); int qBitLen = key_size - p.BitLength(); BigInteger q, n; do { q = rand.NextBigInteger(qBitLen); q = q.GetNextPrime(); n = p * q; qBitLen++; } while (n.BitLength() < key_size + 1); BigInteger phi = (p - 1) * (q - 1); BigInteger e = 3; while (BigInteger.GreatestCommonDivisor(e, phi) != 1) { e += 2; } BigInteger d = (e.ModInverse(phi)); oe = e; od = d; on = n; }
public FpParameter(FpCurve curve, EcPoint g, BigInteger n) { Curve = curve; G = g; N = n; BitLength = (ushort)n.BitLength(); }
static void MoTest(BigInteger a, BigInteger n) { if (!n.IsProbablyPrime(20)) { Console.WriteLine("Not computed. Modulus must be prime for this algorithm."); return; } if (a.BitLength() < 100) { Console.Write("ord({0})", a); } else { Console.Write("ord([big])"); } if (n.BitLength() < 100) { Console.Write(" mod {0} ", n); } else { Console.Write(" mod [big] "); } BigInteger mob = MoBachShallit58(a, n, Factor(n - 1)); Console.WriteLine("= {0}", mob); }
public HabboRSACrypto(string e, string n, string d) { _e = BigInteger.Parse('0' + e, NumberStyles.HexNumber); _n = BigInteger.Parse('0' + n, NumberStyles.HexNumber); _d = BigInteger.Parse('0' + d, NumberStyles.HexNumber); _blockSize = (_n.BitLength() + 7) / 8; }
public TSelf Mul(BigInteger s) { if (s.IsZero) // P * 0 = 0 { return(Zero); } if (IsZero()) { return((TSelf)this); // 0 * s = 0 } TSelf res = Zero; for (int i = s.BitLength() - 1; i >= 0; i--) { res = res.Double(); if (s.TestBit(i)) { res = res.Add((TSelf)this); } } return(res); }
private static void CheckNormaliseBaseTenResult(ExpandedDouble orig, NormalisedDecimal result) { String sigDigs = result.GetSignificantDecimalDigits(); BigInteger frac = orig.GetSignificand(); while (frac.BitLength() + orig.GetBinaryExponent() < 200) { frac = frac * (BIG_POW_10); } int binaryExp = orig.GetBinaryExponent() - orig.GetSignificand().BitLength(); String origDigs = (frac << (binaryExp + 1)).ToString(10); if (!origDigs.StartsWith(sigDigs)) { throw new AssertionException("Expected '" + origDigs + "' but got '" + sigDigs + "'."); } double dO = Double.Parse("0." + origDigs.Substring(sigDigs.Length)); double d1 = Double.Parse(result.GetFractionalPart().ToString()); BigInteger subDigsO = new BigInteger((int)(dO * 32768 + 0.5)); BigInteger subDigsB = new BigInteger((int)(d1 * 32768 + 0.5)); if (subDigsO.Equals(subDigsB)) { return; } BigInteger diff = (subDigsB - subDigsO).Abs(); if (diff.IntValue() > 100) { // 100/32768 ~= 0.003 throw new AssertionException("minor mistake"); } }
public ExpandedDouble(BigInteger frac, int binaryExp) { if (frac.BitLength() != 64) { throw new ArgumentException("bad bit length"); } _significand = frac; _binaryExponent = binaryExp; }
public FpCurve(BigInteger p, BigInteger a, BigInteger b) { P = p; A = a; B = b; BitLength = (ushort)p.BitLength(); _eulerPower = (p - 1) / 2; _inv2 = 2; _inv2 = _inv2.InvMod(p); }
public Montgomery(BigInteger m) { if (m < 0 || m.IsEven) { throw new ArgumentException(); } this.m = m; n = m.BitLength(); rrm = (BigInteger.One << (n * 2)) % m; }
public void TestSubnormal() { ExpandedDouble hd = new ExpandedDouble(0x0000000000000001L); if (hd.GetBinaryExponent() == -1023) { throw new AssertionException("identified bug - subnormal numbers not decoded properly"); } Assert.AreEqual(-1086, hd.GetBinaryExponent()); BigInteger frac = hd.GetSignificand(); Assert.AreEqual(64, frac.BitLength()); Assert.AreEqual(1, frac.BitCount()); }
public void PublishGroup( IOutputChannel output_channel) { System.Diagnostics.Debug.WriteLine("GrothVSSHE::PublishGroup:p " + p.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::PublishGroup:q " + q.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::PublishGroup:g " + g.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::PublishGroup:h " + h.BitLength()); output_channel.Send(p); output_channel.Send(q); output_channel.Send(g); output_channel.Send(h); com.PublishGroup(output_channel); }
public void TestNegative() { ExpandedDouble hd = new ExpandedDouble(unchecked ((long)0xC010000000000000L)); if (hd.GetBinaryExponent() == -2046) { throw new AssertionException("identified bug - sign bit not masked out of exponent"); } Assert.AreEqual(2, hd.GetBinaryExponent()); BigInteger frac = hd.GetSignificand(); Assert.AreEqual(64, frac.BitLength()); Assert.AreEqual(1, frac.BitCount()); }
public GrothVSSHE( int n, BigInteger p_ENC, BigInteger q_ENC, BigInteger k_ENC, BigInteger g_ENC, BigInteger h_ENC, long ell_e, long fieldsize, long subgroupsize) { l_e = ell_e; p = p_ENC; q = q_ENC; g = g_ENC; h = h_ENC; System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE p " + p_ENC.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE q " + q_ENC.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE k " + k_ENC.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE g " + g_ENC.BitLength()); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE h " + h_ENC.BitLength()); // Initialize the commitment scheme and Groth's SKC argument com = new PedersenCommitmentScheme(n, p_ENC, q_ENC, k_ENC, h_ENC, fieldsize, subgroupsize); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE h " + h_ENC.BitLength()); IChannel lej = new ChannelOneWay();//TODO this is ugly as hell!!! constructors should not take streams they should take symbols com.PublishGroup(lej); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE h " + h_ENC.BitLength()); skc = new GrothSKC(n, lej, ell_e, fieldsize, subgroupsize); // Compute $2^{\ell_e}$ for the input reduction. exp2l_e = new BigInteger(2).Pow((int)ell_e); System.Diagnostics.Debug.WriteLine("GrothVSSHE::GrothVSSHE h " + h_ENC.BitLength()); }
public bool KeyGenerationProtocol_UpdateKey( IInputChannel input_channel) { BigInteger foo = input_channel.Recieve(); BigInteger c = input_channel.Recieve(); BigInteger r = input_channel.Recieve(); // verify the in-group property if (!CheckElement(foo)) { System.Diagnostics.Debug.WriteLine("CheckElement incorrect"); return(false); } // check the size of $r$ if (ToolsMathBigInteger.CompareAbs(r, q) >= 0) { System.Diagnostics.Debug.WriteLine("compare_absolutes incorrect"); return(false); } // verify the proof of knowledge [CaS97] BigInteger t = g.ModPow(r, p); r = foo.ModPow(c, p); t = t * r; t = t % p; r = mpz_shash_tools.mpz_shash(new BigInteger [] { g, foo, t }); // c = mpz_shash_tools.mpz_shash(new BigInteger [] {g, h_i, t}); if (c != r) { System.Diagnostics.Debug.WriteLine("c != r " + c.BitLength() + " " + r.BitLength()); System.Diagnostics.Debug.WriteLine("g " + g.BitLength() + " foo " + foo.BitLength() + " t " + t.BitLength()); return(false); } // update the global key h h *= foo; h = h % p; // store the public key BigInteger tmp = foo; t = mpz_shash_tools.mpz_shash(foo); h_j.Add(t.ToString(), tmp); // finish return(true); }
private void mulShift(BigInteger multiplicand, int multiplierShift) { _significand = _significand * multiplicand; _binaryExponent += multiplierShift; // check for too much precision int sc = (_significand.BitLength() - MIN_PRECISION) & unchecked ((int)0xFFFFFFE0); // mask Makes multiples of 32 which optimises BigInt32.ShiftRight if (sc > 0) { // no need to round because we have at least 8 bits of extra precision _significand = _significand >> (sc); _binaryExponent += sc; } }
public Fp12 CyclotomicExp(BigInteger pow) { Fp12 res = FieldParams <Fp12> .One; for (int i = pow.BitLength() - 1; i >= 0; i--) { res = res.CyclotomicSquare(); if (pow.TestBit(i)) { res = res.Mul(this); } } return(res); }
// Mersenne prime are in P and at the cost of very little public static bool IsPrimeByLucasLehmer(BigInteger input) { if (input == 3) { return(true); } long p = input.BitLength(); BigInteger s = 4; for (int i = 0; i < p - 2; i++) { s = ((s * s) - 2) % input; } return(s == BigInteger.Zero); }
public ExpandedDouble(long rawBits) { int biasedExp = (int)(rawBits >> 52); if (biasedExp == 0) { // sub-normal numbers BigInteger frac = new BigInteger(rawBits)&BI_FRAC_MASK; int expAdj = 64 - frac.BitLength(); _significand = frac<<expAdj; _binaryExponent = (biasedExp & 0x07FF) - 1023 - expAdj; } else { BigInteger frac = GetFrac(rawBits); _significand = frac; _binaryExponent = (biasedExp & 0x07FF) - 1023; } }
public static BigInteger mpz_oprime( long psize, int mr_iterations) { BigInteger p = 0; /* Choose randomly an odd number $p$ of appropriate size. */ do { p = mpz_srandom.mpz_srandomb(psize); }while ((p.BitLength() < psize) || p.IsEven); /* Add two as long as $p$ is not probable prime. */ while (!p.IsProbablePrime((int)mr_iterations)) { p = p + 2; } return(p); }
public ExpandedDouble(long rawBits) { int biasedExp = (int)(rawBits >> 52); if (biasedExp == 0) { // sub-normal numbers BigInteger frac = new BigInteger(rawBits) & BI_FRAC_MASK; int expAdj = 64 - frac.BitLength(); _significand = frac << expAdj; _binaryExponent = (biasedExp & 0x07FF) - 1023 - expAdj; } else { BigInteger frac = GetFrac(rawBits); _significand = frac; _binaryExponent = (biasedExp & 0x07FF) - 1023; } }
public bool CheckGroup() { // Check whether $p$ and $q$ have appropriate sizes. if ((p.BitLength() < F_size) || (q.BitLength() < G_size)) { //return false; throw new Exception("Bitlenght mismatch"); } // Check whether $p$ has the correct form, i.e. $p = qk + 1$. if ((q * k) + 1 != p) { throw new Exception("p of incorrect form: (q * k) + 1 != p"); } // Check whether $p$ and $q$ are both (probable) prime with // a soundness error probability ${} \le 4^{-TMCG_MR_ITERATIONS}$. if (!p.IsProbablePrime(Constants.TMCG_MR_ITERATIONS) || !q.IsProbablePrime(Constants.TMCG_MR_ITERATIONS)) { //return false; throw new Exception("p or q not prime"); } // Check whether $k$ is not divisible by $q$, i.e. $q$ and $k$ are // coprime. if (!ToolsMathBigInteger.AreCoprime(q, k)) { //return false; throw new Exception("p or q not coprime"); //TODO this seems redundant given the former test } // Check whether $g$ is a generator for the subgroup $G$ of prime // order $q$. We have to assert that $g^q \equiv 1 \pmod{p}$, // which means that the order of $g$ is $q$. Of course, we must // ensure that $g$ is not trivial, i.e., $1 < g < p-1$. if (g <= 1 || p - 1 <= g || g.ModPow(q, p) != 1) { //return false; throw new Exception("g not a subgroup generator of G: $1 < g < p-1 && g.ModPow(q, p) == 1 fails"); } // finish return(true); }
private RandomBigInteger(BigInteger minValue, BigInteger maxValue, int bitCount) { if (minValue >= maxValue) { throw new ArgumentOutOfRangeException("minValue must be less than maxValue"); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount must be greater than 0"); } this.minValue = minValue; this.range = (maxValue - minValue) - 1; this.rangeBits = (bitCount == 0) ? range.BitLength() : bitCount; // make byte array have an extra bit so we can insert a zero // in the most significant bit to ensure we get values >= 0 // (the most significant bit is interpreted as sign bit in // the BigInteger constructor that takes a byte array). this.bytes = new byte[((this.rangeBits + 7 + 1) / 8)]; this.rangeShift = ((this.bytes.Length) * 8) - this.rangeBits - 1; this.random = new Random(); }
/** A naive generator for safe primes (slow for $\log_2 p \ge 1024$). */ public static void mpz_sprime_test_naive( BigInteger p, BigInteger q, long qsize, IFunction <Tuple <BigInteger, BigInteger>, bool> test, int mr_iterations) { int i = 0; /* Choose randomly an odd number $q$ of appropriate size. */ do { q = mpz_srandom.mpz_srandomb(qsize); }while ((q.BitLength() < qsize) || q.IsEven); while (true) { /* Increase $q$ by 2 (incremental prime number generator). */ q = q + 2; /* Compute $p = 2q + 1$. */ p = (q * 2) + 1; // TODO q.shiftLeft(1) + 1; /* Additional tests? */ if (!test.Compute(new Tuple <BigInteger, BigInteger>(p, q))) { continue; } /* * Check whether either $q$ or $p$ are not divisable by any primes up to * some bound $B$. (We use the bound $B = 5000$ here.) */ for (i = 0; i < PRIMES_SIZE; i++) { if (mpz_congruent_ui_p(q, primes_m1d2[i], primes[i]) || mpz_congruent_ui_p(p, primes_m1d2[i], primes[i]) || mpz_congruent_ui_p(q, 0L, primes[i]) || mpz_congruent_ui_p(p, 0L, primes[i])) { break; } } if (i < PRIMES_SIZE) { continue; } if (p.IsProbablePrime(1)) { continue; } if (q.IsProbablePrime(mr_iterations)) { continue; } if (p.IsProbablePrime(mr_iterations - 1)) { break; } } Debug.Assert(p.IsProbablePrime(mr_iterations)); Debug.Assert(q.IsProbablePrime(mr_iterations)); }
/** * The fast generation of safe primes is implemented according to [CS00] * and M.J. Wiener's "Safe Prime Generation with a Combined Sieve". */ public static void mpz_sprime_test( BigInteger p, BigInteger q, long qsize, IFunction <Tuple <BigInteger, BigInteger>, bool> test, int mr_iterations) { long [] R_q = new long [SIEVE_SIZE]; long [] R_p = new long [SIEVE_SIZE]; int i = 0; int fail = 0; BigInteger tmp, y, pm1; BigInteger a = 2; /* Step 1. [CS00]: choose randomly an odd number $q$ of appropriate size */ do { q = mpz_srandom.mpz_srandomb(qsize); }while ((q.BitLength() < qsize) || (q.IsEven)); /* Compute $p = 2q + 1$. */ pm1 = q * 2; p = pm1 + 1; /* Initalize the sieves for testing divisability by small primes. */ for (i = 0; i < SIEVE_SIZE; i++) { tmp = new BigInteger(primes[i]); /* R_q[i] = q mod primes[i] */ y = q % tmp; R_q[i] = (long)y; /* R_p[i] = (2q+1) mod primes[i] */ y = p % tmp; R_p[i] = (long)y; } while (true) { /* Increase $q$ by 2 (incremental prime number generator). */ q = q = 2; /* Increase $p$ by 4 (actually compute $p = 2q + 1$). */ p = p + 4; pm1 = pm1 + 4; /* Use the sieve optimization procedure of Note 4.51(ii) [HAC]. */ for (i = 0, fail = 0; i < SIEVE_SIZE; i++) { /* Update the sieves. */ R_q[i] += 2; R_q[i] %= primes[i]; R_p[i] += 4; R_p[i] %= primes[i]; /* * Check whether R_q[i] or R_p[i] is zero. We cannot break this loop, * because we have to update our sieves completely for the next try. */ if ((R_q[i] == 0) || (R_p[i] == 0)) { fail = 1; } } if (0 < fail) { continue; } /* Additional tests? */ if (!test.Compute(new Tuple <BigInteger, BigInteger>(q, p))) { continue; } /* * Step 2. [CS00]: M.J. Wiener's "Combined Sieve" * Test whether either $q$ or $p$ are not divisable by any primes up to * some bound $B$. (We use the bound $B = 5000$ here.) */ for (i = 0; i < PRIMES_SIZE; i++) { if (mpz_congruent_ui_p(q, primes_m1d2[i], primes[i]) || mpz_congruent_ui_p(p, primes_m1d2[i], primes[i])) { break; } if (i >= SIEVE_SIZE) { if (mpz_congruent_ui_p(q, 0L, primes[i]) || mpz_congruent_ui_p(p, 0L, primes[i])) { break; } } else { Debug.Assert(!mpz_congruent_ui_p(q, 0L, primes[i])); Debug.Assert(!mpz_congruent_ui_p(p, 0L, primes[i])); } } if (i < PRIMES_SIZE) { continue; } /* Optimization: do a single test for $q$ first */ if (!q.IsProbablePrime(1)) { continue; } /* * Step 3. [CS00]: Test whether 2 is not a Miller-Rabin witness to the * compositeness of $q$. */ if (ToolsMathBigIntegerPrime.IsCompositeByMillerRabinWitness(q, a)) { continue; } /* Step 4. [CS00]: Test whether $2^q \equiv \pm 1 \pmod{p}$. */ y = a.ModPow(q, p); if ((y.CompareTo(1) != 0) && (y.CompareTo(0) != 0)) { continue; } /* * Step 5. [CS00]: Apply the Miller-Rabin test to $q$ a defined number * of times (maximum error probability $4^{-mr_iterations}$) using * randomly selected bases. */ if (q.IsProbablePrime(mr_iterations - 1)) { break; } } Debug.Assert(p.IsProbablePrime(mr_iterations)); Debug.Assert(q.IsProbablePrime(mr_iterations)); }
public static byte[] BigIntToFixedLenArr(ref BigInteger bi, int len) { byte[] b = bi.ToByteArray(); if (b.Length > len + 1) // + 1 bcz 1 zero byte maybe added to hold sign bit { throw new ArgumentException("Byte array of length " + len + " too short to hold given big integer. Required length: " + bi.BitLength()); } List <byte> l = new List <byte>(b); if (b.Length == len + 1 && b[len] == 0) // if extra byte containing sign bit { l.RemoveAt(l.Count - 1); // remove sign bit } //for (int i = 0, n = len - l.Count; i < n; i++) // l.Add(0); l.AddRange(new byte[len - l.Count]); return(l.ToArray()); }
public static bool IsProbablePrime(this BigInteger source, int certainty, RandomNumberGenerator random) { if (source == 2 || source == 3) { return(true); } if (source < 2 || source % 2 == 0) { return(false); } BigInteger d = source - 1; int s = 0; while (d % 2 == 0) { d /= 2; s += 1; } if (random == null) { random = Randomizer.GetRandom(); } byte[] bytes = new byte[(source.BitLength() + 7) / 8]; BigInteger a; for (int i = 0; i < certainty; i++) { do { random.GetBytes(bytes); //bytes[bytes.Length - 1] = 0; a = new BigInteger(bytes); }while (a < 2 || a >= source - 2); BigInteger x = BigInteger.ModPow(a, d, source); if (x == 1 || x == source - 1) { continue; } for (int r = 1; r < s; r++) { x = BigInteger.ModPow(x, 2, source); if (x == 1) { return(false); } if (x == source - 1) { break; } } if (x != source - 1) { return(false); } } return(true); }
private void mulShift(BigInteger multiplicand, int multiplierShift) { _significand = _significand*multiplicand; _binaryExponent += multiplierShift; // check for too much precision int sc = (_significand.BitLength() - MIN_PRECISION) & unchecked((int)0xFFFFFFE0); // mask Makes multiples of 32 which optimises BigInt32.ShiftRight if (sc > 0) { // no need to round because we have at least 8 bits of extra precision _significand = _significand>>(sc); _binaryExponent += sc; } }
public void Normalise64bit() { int oldBitLen = _significand.BitLength(); int sc = oldBitLen - C_64; if (sc == 0) { return; } if (sc < 0) { throw new InvalidOperationException("Not enough precision"); } _binaryExponent += sc; if (sc > 32) { int highShift = (sc - 1) & 0xFFFFE0; _significand = _significand>>(highShift); sc -= highShift; oldBitLen -= highShift; } if (sc < 1) { throw new InvalidOperationException(); } _significand = Rounder.Round(_significand, sc); if (_significand.BitLength() > oldBitLen) { sc++; _binaryExponent++; } _significand = _significand>>(sc); }