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

Method factorial

output/java_guava/1.4.19/BigIntegerMath.java:339–392  ·  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

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