MCPcopy Create free account
hub / github.com/antlr/codebuff / factorial

Method factorial

output/java_guava/1.4.18/BigIntegerMath.java:338–391  ·  view source on GitHub ↗

Returns n!, that is, the product of the first n positive integers, or 1 if n == 0. Warning: the result takes O(n log n) space, so use cautiously. This uses an efficient binary recursive algorithm to compute the factorial with balanced multiplies.

(int n)

Source from the content-addressed store, hash-verified

336
337
338 public static BigInteger factorial(int n) {
339 checkNonNegative("n", n);
340
341 // If the factorial is small enough, just use LongMath to do it.
342 if (n < LongMath.factorials.length) {
343 return BigInteger.valueOf(LongMath.factorials[n]);
344 }
345
346 // Pre-allocate space for our list of intermediate BigIntegers.
347 int approxSize = IntMath.divide(n * IntMath.log2(n, CEILING), Long.SIZE, CEILING);
348 ArrayList<BigInteger> bignums = new ArrayList<BigInteger>(approxSize);
349
350 // Start from the pre-computed maximum long factorial.
351 int startingNumber = LongMath.factorials.length;
352 long product = LongMath.factorials[startingNumber - 1];
353 // Strip off 2s from this value.
354 int shift = Long.numberOfTrailingZeros(product);
355 product >>= shift;
356
357 // Use floor(log2(num)) + 1 to prevent overflow of multiplication.
358 int productBits = LongMath.log2(product, FLOOR) + 1;
359 int bits = LongMath.log2(startingNumber, FLOOR) + 1;
360 // Check for the next power of two boundary, to save us a CLZ operation.
361 int nextPowerOfTwo = 1 << (bits - 1);
362
363 // Iteratively multiply the longs as big as they can go.
364 for (long num = startingNumber; num <= n; num++) {
365 // Check to see if the floor(log2(num)) + 1 has changed.
366 if ((num & nextPowerOfTwo) != 0) {
367 nextPowerOfTwo <<= 1;
368 bits++;
369 }
370 // Get rid of the 2s in num.
371 int tz = Long.numberOfTrailingZeros(num);
372 long normalizedNum = num >> tz;
373 shift += tz;
374 // Adjust floor(log2(num)) + 1.
375 int normalizedBits = bits - tz;
376 // If it won't fit in a long, then we store off the intermediate product.
377 if (normalizedBits + productBits >= Long.SIZE) {
378 bignums.add(BigInteger.valueOf(product));
379 product = 1;
380 productBits = 0;
381 }
382 product *= normalizedNum;
383 productBits = LongMath.log2(product, FLOOR) + 1;
384 }
385 // Check for leftovers.
386 if (product > 1) {
387 bignums.add(BigInteger.valueOf(product));
388 }
389 // Efficiently multiply all the intermediate products together.
390 return listProduct(bignums).shiftLeft(shift);
391 }
392
393
394 static BigInteger listProduct(List<BigInteger> nums) {

Callers

nothing calls this directly

Calls 7

divideMethod · 0.95
log2Method · 0.95
log2Method · 0.95
listProductMethod · 0.95
addMethod · 0.65
checkNonNegativeMethod · 0.45
valueOfMethod · 0.45

Tested by

no test coverage detected