[pypy-issue] [issue1654] math.factorial is slow

anon tracker at bugs.pypy.org
Sat Dec 7 00:30:10 CET 2013


New submission from anon <b10419697 at klzlk.com>:

math.factorial uses a very simple algorithm multiplying by each value in
range(1,x+1) in turn. A better method would be to do binary splitting. I am
unfamiliar with PyPy internals, however I believe app_math.py implements
factorial in pure Python.

Provided below is a patch that uses binary splitting. It seems much faster for
large factorials, but maybe uses slightly more memory and seems 10% slower for
very small factorials.

def factorial(x):
    """Find x!."""
    if isinstance(x, float):
        fl = int(x)
        if fl != x:
            raise ValueError("float arguments must be integral")
        x = fl
    if x < 0:
        raise ValueError("x must be >= 0")
    
    #Experimentally this gap seems good
    gap = max(100, x>>7)
    def _fac(low, high):
        if low+gap >= high:
            t = 1
            for i in range(low, high):
                t *= i
            return t
        
        mid = (low + high) >> 1
        return _fac(low, mid) * _fac(mid, high)
    
    return _fac(1, x+1)

If someone can improve it further, that would be great. The code is public domain.

________________________________________
PyPy bug tracker <tracker at bugs.pypy.org>
<https://bugs.pypy.org/issue1654>
________________________________________


More information about the pypy-issue mailing list