def factorial(n): """Returns the factorial of n. Parameters * n: int (n >= 0) Returns: * prod: int Raises: * ValueError: If n < 0. Examples: >>> factorial(10) 3628800 >>> factorial(40) 815915283247897734345611269596115894272000000000L >>> factorial(-1) Traceback (most recent call last): ... ValueError: factorial: Must have n >= 0. Details: The algorithm used is a binary splitting method. See Section 10.2.3 of "Pi and the AGM" by Borwein and Borwein for information about this method. """ if n < 0: raise ValueError("factorial: Must have n >= 0.") elif n in (0, 1): return 1 prod = 1 for k in xrange(1, n.bit_length()): lower = (n >> k) + 1 upper = (n >> (k - 1)) + 1 if lower % 2 == 0: lower += 1 partial = 1 for j in xrange(lower, upper, 2): partial *= j prod *= (partial**k) return prod << (n - bit_count(n))
def test_bit_count(self): for k in xrange(20): self.assertTrue(bit_count(-k) == bit_count(k) == bin(k).count('1'))