/** * Returns {@code n!}, that is, the product of the first {@code n} positive integers, or {@code 1} * if {@code n == 0}. * * <p><b>Warning:</b> the result takes <i>O(n log n)</i> space, so use cautiously. * * <p>This uses an efficient binary recursive algorithm to compute the factorial with balanced * multiplies. It also removes all the 2s from the intermediate products (shifting them back in at * the end). * * @throws IllegalArgumentException if {@code n < 0} */ public static BigInteger factorial(int n) { checkNonNegative("n", n); // If the factorial is small enough, just use LongMath to do it. if (n < LongMath.factorials.length) { return BigInteger.valueOf(LongMath.factorials[n]); } // Pre-allocate space for our list of intermediate BigIntegers. int approxSize = IntMath.divide(n * IntMath.log2(n, CEILING), Long.SIZE, CEILING); ArrayList<BigInteger> bignums = new ArrayList<BigInteger>(approxSize); // Start from the pre-computed maximum long factorial. int startingNumber = LongMath.factorials.length; long product = LongMath.factorials[startingNumber - 1]; // Strip off 2s from this value. int shift = Long.numberOfTrailingZeros(product); product >>= shift; // Use floor(log2(num)) + 1 to prevent overflow of multiplication. int productBits = LongMath.log2(product, FLOOR) + 1; int bits = LongMath.log2(startingNumber, FLOOR) + 1; // Check for the next power of two boundary, to save us a CLZ operation. int nextPowerOfTwo = 1 << (bits - 1); // Iteratively multiply the longs as big as they can go. for (long num = startingNumber; num <= n; num++) { // Check to see if the floor(log2(num)) + 1 has changed. if ((num & nextPowerOfTwo) != 0) { nextPowerOfTwo <<= 1; bits++; } // Get rid of the 2s in num. int tz = Long.numberOfTrailingZeros(num); long normalizedNum = num >> tz; shift += tz; // Adjust floor(log2(num)) + 1. int normalizedBits = bits - tz; // If it won't fit in a long, then we store off the intermediate product. if (normalizedBits + productBits >= Long.SIZE) { bignums.add(BigInteger.valueOf(product)); product = 1; productBits = 0; } product *= normalizedNum; productBits = LongMath.log2(product, FLOOR) + 1; } // Check for leftovers. if (product > 1) { bignums.add(BigInteger.valueOf(product)); } // Efficiently multiply all the intermediate products together. return listProduct(bignums).shiftLeft(shift); }
/** * Returns the square root of {@code x}, rounded with the specified rounding mode. * * @throws IllegalArgumentException if {@code x < 0} * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code * sqrt(x)} is not an integer */ @GwtIncompatible // TODO @SuppressWarnings("fallthrough") public static BigInteger sqrt(BigInteger x, RoundingMode mode) { checkNonNegative("x", x); if (fitsInLong(x)) { return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode)); } BigInteger sqrtFloor = sqrtFloor(x); switch (mode) { case UNNECESSARY: checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x)); // fall through case FLOOR: case DOWN: return sqrtFloor; case CEILING: case UP: int sqrtFloorInt = sqrtFloor.intValue(); boolean sqrtFloorIsExact = (sqrtFloorInt * sqrtFloorInt == x.intValue()) // fast check mod 2^32 && sqrtFloor.pow(2).equals(x); // slow exact check return sqrtFloorIsExact ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); case HALF_DOWN: case HALF_UP: case HALF_EVEN: BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor); /* * We wish to test whether or not x <= (sqrtFloor + 0.5)^2 = halfSquare + 0.25. Since both x * and halfSquare are integers, this is equivalent to testing whether or not x <= * halfSquare. */ return (halfSquare.compareTo(x) >= 0) ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); default: throw new AssertionError(); } }
/** * Returns {@code n} choose {@code k}, also known as the binomial coefficient of {@code n} and * {@code k}, that is, {@code n! / (k! (n - k)!)}. * * <p><b>Warning:</b> the result can take as much as <i>O(k log n)</i> space. * * @throws IllegalArgumentException if {@code n < 0}, {@code k < 0}, or {@code k > n} */ public static BigInteger binomial(int n, int k) { checkNonNegative("n", n); checkNonNegative("k", k); checkArgument(k <= n, "k (%s) > n (%s)", k, n); if (k > (n >> 1)) { k = n - k; } if (k < LongMath.biggestBinomials.length && n <= LongMath.biggestBinomials[k]) { return BigInteger.valueOf(LongMath.binomial(n, k)); } BigInteger accum = BigInteger.ONE; long numeratorAccum = n; long denominatorAccum = 1; int bits = LongMath.log2(n, RoundingMode.CEILING); int numeratorBits = bits; for (int i = 1; i < k; i++) { int p = n - i; int q = i + 1; // log2(p) >= bits - 1, because p >= n/2 if (numeratorBits + bits >= Long.SIZE - 1) { // The numerator is as big as it can get without risking overflow. // Multiply numeratorAccum / denominatorAccum into accum. accum = accum .multiply(BigInteger.valueOf(numeratorAccum)) .divide(BigInteger.valueOf(denominatorAccum)); numeratorAccum = p; denominatorAccum = q; numeratorBits = bits; } else { // We can definitely multiply into the long accumulators without overflowing them. numeratorAccum *= p; denominatorAccum *= q; numeratorBits += bits; } } return accum .multiply(BigInteger.valueOf(numeratorAccum)) .divide(BigInteger.valueOf(denominatorAccum)); }
/** * Returns the base-10 logarithm of {@code x}, rounded according to the specified rounding mode. * * @throws IllegalArgumentException if {@code x <= 0} * @throws ArithmeticException if {@code mode} is {@link RoundingMode#UNNECESSARY} and {@code x} * is not a power of ten */ @GwtIncompatible // TODO @SuppressWarnings("fallthrough") public static int log10(BigInteger x, RoundingMode mode) { checkPositive("x", x); if (fitsInLong(x)) { return LongMath.log10(x.longValue(), mode); } int approxLog10 = (int) (log2(x, FLOOR) * LN_2 / LN_10); BigInteger approxPow = BigInteger.TEN.pow(approxLog10); int approxCmp = approxPow.compareTo(x); /* * We adjust approxLog10 and approxPow until they're equal to floor(log10(x)) and * 10^floor(log10(x)). */ if (approxCmp > 0) { /* * The code is written so that even completely incorrect approximations will still yield the * correct answer eventually, but in practice this branch should almost never be entered, and * even then the loop should not run more than once. */ do { approxLog10--; approxPow = approxPow.divide(BigInteger.TEN); approxCmp = approxPow.compareTo(x); } while (approxCmp > 0); } else { BigInteger nextPow = BigInteger.TEN.multiply(approxPow); int nextCmp = nextPow.compareTo(x); while (nextCmp <= 0) { approxLog10++; approxPow = nextPow; approxCmp = nextCmp; nextPow = BigInteger.TEN.multiply(approxPow); nextCmp = nextPow.compareTo(x); } } int floorLog = approxLog10; BigInteger floorPow = approxPow; int floorCmp = approxCmp; switch (mode) { case UNNECESSARY: checkRoundingUnnecessary(floorCmp == 0); // fall through case FLOOR: case DOWN: return floorLog; case CEILING: case UP: return floorPow.equals(x) ? floorLog : floorLog + 1; case HALF_DOWN: case HALF_UP: case HALF_EVEN: // Since sqrt(10) is irrational, log10(x) - floorLog can never be exactly 0.5 BigInteger x2 = x.pow(2); BigInteger halfPowerSquared = floorPow.pow(2).multiply(BigInteger.TEN); return (x2.compareTo(halfPowerSquared) <= 0) ? floorLog : floorLog + 1; default: throw new AssertionError(); } }