Как вызвать math.factorial из numba без режима python? - PullRequest
1 голос
/ 28 мая 2020

Мне нужно вычислить факториалы больших целых чисел внутри a для l oop, которые я хотел бы скомпилировать с помощью numba. Функция factorial в математическом модуле Python кажется быстрой. Как я могу вызвать эту функцию из numba, используя режим no python? К сожалению, эта функция в настоящее время не поддерживается numba https://numba.pydata.org/numba-doc/0.17.0/reference/pysupported.html.

import math
from numba import njit

@njit
def factorial(n):
    return math.factorial(n)

factorial(2)

выдает ошибку TypingError:

TypingError: Failed in nopython mode pipeline (step: nopython frontend) Unknown attribute 'factorial' of type Module(<module 'math' from '/anaconda3/envs/minimalcondaforge/lib/python3.8/lib-dynload/math.cpython-38-darwin.so'>)

Есть ли как вызвать эту функцию? Могу ли я использовать @overload или get_cython_function_address, как описано здесь http://numba.pydata.org/numba-doc/latest/extending/high-level.html? (Мне пока не удалось заставить его работать, я новичок в numba, поэтому, возможно, я просто делаю это неправильно.) Также открыты другие предложения для быстрой функции факториала в numba, но она должна уметь обрабатывать большие целые числа.

1 Ответ

2 голосов
/ 28 мая 2020

Numba не может скомпилировать целые числа произвольной точности Python, поэтому, если вы хотите найти точные факториалы для целых чисел больше 20⁠, что при 2432902008176640000 является максимальным значением, которое может поместиться в 64-битное целое⁠— тогда Numba, к сожалению, не поможет.

Если вам не нужно точное целое число для больших факториалов, вы можете определить свою функцию-факториал как эквивалент math.gamma(n+1), который компилируется под Numba и имеет плавающий -точечный вывод. Но даже это работает только до 170!, которое является наибольшим, которое может поместиться в 64-битное число с плавающей запятой.

Без чисел произвольной точности более крупные факториалы должны быть представлены в виде журнала. Для этого вы можете использовать math.lgamma(n+1), который также компилируется под Numba и может возвращать log(n!) для очень больших n.

...