public void MmodInverseBigInteger() { BigInteger a = zero, mod, inv; for (int j = 3; j < 50; j++) { mod = BigInteger.FromInt64(j); for (int i = -j + 1; i < j; i++) { try { a = BigInteger.FromInt64(i); inv = BigMath.ModInverse(a, mod); Assert.True(one.Equals(((a * inv) % mod)), "bad inverse: " + a + " inv mod " + mod + " equals " + inv); Assert.True(inv.CompareTo(mod) < 0, "inverse greater than modulo: " + a + " inv mod " + mod + " equals " + inv); Assert.True(inv.CompareTo(BigInteger.Zero) >= 0, "inverse less than zero: " + a + " inv mod " + mod + " equals " + inv); } catch (ArithmeticException) { Assert.True(!one.Equals(BigMath.Gcd(a, mod)), "should have found inverse for " + a + " mod " + mod); } } } for (int j = 1; j < 10; j++) { mod = bi2 + BigInteger.FromInt64(j); for (int i = 0; i < 20; i++) { try { a = bi3 + (BigInteger.FromInt64(i)); inv = BigMath.ModInverse(a, mod); Assert.True(one.Equals((a * inv) % mod), "bad inverse: " + a + " inv mod " + mod + " equals " + inv); Assert.True(inv.CompareTo(mod) < 0, "inverse greater than modulo: " + a + " inv mod " + mod + " equals " + inv); Assert.True(inv.CompareTo(BigInteger.Zero) >= 0, "inverse less than zero: " + a + " inv mod " + mod + " equals " + inv); } catch (ArithmeticException) { Assert.True(!one.Equals(BigMath.Gcd(a, mod)), "should have found inverse for " + a + " mod " + mod); } } } }
public static BigDecimal Divide(BigDecimal dividend, BigDecimal divisor) { BigInteger p = dividend.UnscaledValue; BigInteger q = divisor.UnscaledValue; BigInteger gcd; // greatest common divisor between 'p' and 'q' BigInteger quotient; BigInteger remainder; long diffScale = (long)dividend.Scale - divisor.Scale; int newScale; // the new scale for final quotient int k; // number of factors "2" in 'q' int l = 0; // number of factors "5" in 'q' int i = 1; int lastPow = BigDecimal.FivePow.Length - 1; if (divisor.IsZero) { // math.04=Division by zero throw new ArithmeticException(Messages.math04); //$NON-NLS-1$ } if (p.Sign == 0) { return(BigDecimal.GetZeroScaledBy(diffScale)); } // To divide both by the GCD gcd = BigMath.Gcd(p, q); p = p / gcd; q = q / gcd; // To simplify all "2" factors of q, dividing by 2^k k = q.LowestSetBit; q = q >> k; // To simplify all "5" factors of q, dividing by 5^l do { quotient = BigMath.DivideAndRemainder(q, BigDecimal.FivePow[i], out remainder); if (remainder.Sign == 0) { l += i; if (i < lastPow) { i++; } q = quotient; } else { if (i == 1) { break; } i = 1; } } while (true); // If abs(q) != 1 then the quotient is periodic if (!BigMath.Abs(q).Equals(BigInteger.One)) { // math.05=Non-terminating decimal expansion; no exact representable decimal result. throw new ArithmeticException(Messages.math05); //$NON-NLS-1$ } // The sign of the is fixed and the quotient will be saved in 'p' if (q.Sign < 0) { p = -p; } // Checking if the new scale is out of range newScale = BigDecimal.ToIntScale(diffScale + System.Math.Max(k, l)); // k >= 0 and l >= 0 implies that k - l is in the 32-bit range i = k - l; p = (i > 0) ? Multiplication.MultiplyByFivePow(p, i) : p << -i; return(new BigDecimal(p, newScale)); }