public static IntNum remainder(IntNum x, IntNum y) { if (y.isZero()) return x; IntNum rem = new IntNum (); divide (x, y, null, rem, TRUNCATE); return rem.canonicalize (); }
/** Calculate the integral power of an IntNum. * @param x the value (base) to exponentiate * @param y the exponent (must be non-negative) */ public static IntNum power(IntNum x, int y) { if (y <= 0) { if (y == 0) return one (); else throw new Exception ("negative exponent"); } if (x.isZero ()) return x; int plen = x.words == null ? 1 : x.ival; // Length of pow2. int blen = ((x.intLength () * y) >> 5) + 2 * plen; bool negative = x.isNegative () && (y & 1) != 0; int[] pow2 = new int [blen]; int[] rwords = new int [blen]; int[] work = new int [blen]; x.getAbsolute (pow2); // pow2 = abs(x); int rlen = 1; rwords[0] = 1; // rwords = 1; for (;;) // for (i = 0; ; i++) { // pow2 == x**(2**i) // prod = x**(sum(j=0..i-1, (y>>j)&1)) if ((y & 1) != 0) { // r *= pow2 MPN.mul (work, pow2, plen, rwords, rlen); int[] tempx = work; work = rwords; rwords = tempx; rlen += plen; while (rwords[rlen-1] == 0) rlen--; } y >>= 1; if (y == 0) break; // pow2 *= pow2; MPN.mul (work, pow2, plen, pow2, plen); int[] temp = work; work = pow2; pow2 = temp; // swap to avoid a copy plen *= 2; while (pow2[plen-1] == 0) plen--; } if (rwords[rlen-1] < 0) rlen++; if (negative) negate (rwords, rwords, rlen); return IntNum.make (rwords, rlen); }
public static IntNum modulo(IntNum x, IntNum y) { if (y.isZero()) return x; IntNum rem = new IntNum (); divide (x, y, null, rem, FLOOR); return rem.canonicalize (); }
public static IntNum lcm(IntNum x, IntNum y) { if (x.isZero () || y.isZero ()) return IntNum.zero (); x = IntNum.abs (x); y = IntNum.abs (y); IntNum quotient = new IntNum (); divide (times (x, y), gcd (x, y), quotient, null, TRUNCATE); return quotient.canonicalize (); }
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 ()); }
/** 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; }