/** Return this raised to an integer power. * Implemented by repeated squaring and multiplication. * If y < 0, returns div_inv of the result. */ public virtual Numeric power(IntNum y) { if (y.isNegative()) { return(power(IntNum.neg(y)).div_inv()); } Numeric pow2 = this; Numeric r = null; for (;;) // for (i = 0; ; i++) { // pow2 == x**(2**i) // prod = x**(sum(j=0..i-1, (y>>j)&1)) if (y.isOdd()) { r = r == null ? pow2 : r.mul(pow2); // r *= pow2 } y = IntNum.shift(y, -1); if (y.isZero()) { break; } // pow2 *= pow2; pow2 = pow2.mul(pow2); } return(r == null?mul_ident() : r); }
/** Converts an integral double (such as a toInt result) to an IntNum. */ public static IntNum toExactInt(double value) { if (Double.IsInfinity(value) || Double.IsNaN(value)) { throw new ArithmeticException("cannot convert " + value + " to exact integer"); } long bits = BitConverter.DoubleToInt64Bits(value); bool neg = bits < 0; int exp = (int)(bits >> 52) & 0x7FF; bits &= 0xfffffffffffffL; if (exp == 0) { bits <<= 1; } else { bits |= 0x10000000000000L; } if (exp <= 1075) { int rshift = 1075 - exp; if (rshift > 53) { return(IntNum.zero()); } bits >>= rshift; return(IntNum.make(neg ? -bits : bits)); } return(IntNum.shift(IntNum.make(neg ? -bits : bits), exp - 1075)); }
public override double doubleValue() { bool neg = num.isNegative(); if (den.isZero()) { return(neg ? Double.NegativeInfinity : num.isZero() ? Double.NaN : Double.PositiveInfinity); } IntNum n = num; if (neg) { n = IntNum.neg(n); } int num_len = n.intLength(); int den_len = den.intLength(); int exp = 0; if (num_len < den_len + 54) { exp = den_len + 54 - num_len; n = IntNum.shift(n, exp); exp = -exp; } // Divide n (which is shifted num) by den, using truncating division, // and return quot and remainder. IntNum quot = new IntNum(); IntNum remainder = new IntNum(); IntNum.divide(n, den, quot, remainder, TRUNCATE); quot = quot.canonicalize(); remainder = remainder.canonicalize(); return(quot.roundToDouble(exp, neg, !remainder.isZero())); }