Python кортежи или C -массивы нельзя использовать напрямую, поскольку PARI использует векторы PARI / GP, определяющие c векторов, где тип / длина кодируются в первом элементе.
В разделе 4.4 .1 Creation of PARI objects
там написано:
Функция basi c, которая создает объект PARI, - это GEN cgetg (long l, long t) l, который определяет количество длинных слов, которые должны быть выделены объекту. и t - тип объекта в символьной форме c (список приведен в разделе 4.5). Точный эффект этой функции заключается в следующем: она сначала создает в стеке PARI фрагмент памяти длинных слов длины размера и сохраняет адрес фрагмента, который будет возвращен в конце. Если стек израсходован, выводится сообщение о том, что «переполнение стека PARI» и возникает ошибка. В противном случае он устанавливает тип и длину объекта PARI. По сути, оно заполняет свое первое кодовое слово (z [0]).
см. https://pari.math.u-bordeaux.fr/pub/pari/manuals/2.7.6/libpari.pdf
В примерах в этом документе вы можете видеть, что чтобы создать вектор с двумя элементами, он вызывается с размером l = 3 , чтобы получить подходящий вектор. Первый элемент вектора фактических чисел начинается не с индекса 0, а с индекса 1 (см. Раздел 4.5.15 в этом документе PDF).
С
git clone http://pari.math.u-bordeaux.fr/git/pari.git
исходного кода для PARI можно получить.
Там вы можете увидеть различные типы в конце в src / headers / parigen.h. Это перечисление, и нам нужен тип t_VE C. Соответствующее целое число равно 17.
Теперь мы можем определить небольшую функцию, которая преобразует тупель в вектор GP, как это:
def t_vec(numbers):
l = len(numbers) + 1
p1 = pari.cgetg(c_long(l), c_long(t_VEC))
for i in range(1, l):
p1[i] = pari.stoi(c_long(numbers[i - 1]))
return p1
Затем мы можем вызвать ellinit
так:
h = (0, 0, 0, 4, 6)
res = pari.ellinit(t_vec(h), pari.stoi(c_long(1)), precision)
Чтобы протестировать его с параметрами [0, 0, 0, 4, 6], вы можете вызвать GP из командной строки:
? ellinit([0, 0, 0, 4, 6], 1)
%1 = [0, 0, 0, 4, 6, 0, 8, 24, -16, -192, -5184, -19648, 110592/307, Vecsmall([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, 0]]
Маленький, сам * Содержащаяся Python программа примера на странице 441 цитируемого документа PDF может выглядеть следующим образом:
from ctypes import *
pari = cdll.LoadLibrary("libpari.so")
pari.stoi.restype = POINTER(c_long)
pari.cgetg.restype = POINTER(POINTER(c_long))
pari.ellinit.restype = POINTER(POINTER(c_long))
pari.ellisdivisible.restype = c_long
pari.nfinit0.restype = POINTER(c_long)
pari.polcyclo_eval.restype = POINTER(c_long)
pari.fetch_user_var.restype = c_long
pari.pol_x.restype = POINTER(c_long)
(t_VEC, t_COL, t_MAT) = (17, 18, 19) # incomplete
precision = c_long(38)
pari.pari_init(2 ** 19, 0)
def t_vec(numbers):
l = len(numbers) + 1
p1 = pari.cgetg(c_long(l), c_long(t_VEC))
for i in range(1, l):
p1[i] = pari.stoi(c_long(numbers[i - 1]))
return p1
def main():
t = pari.pol_x(pari.fetch_user_var(bytes("t", "utf8")))
Q = pari.pol_x(pari.fetch_user_var(bytes("Q", "utf8")))
K = pari.nfinit0(pari.polcyclo_eval(11, t), c_long(0), precision)
h = (0, -1, 1, 0, 0)
res = pari.ellinit(t_vec(h), K, precision)
P = (0, 0)
y = pari.ellisdivisible(res, t_vec(P), pari.stoi(c_long(5)), byref(Q))
pari.pari_printf(bytes("Q: %Ps\n", "utf8"), Q)
print("ellisdivisible =", y)
if __name__ == '__main__':
main()
Test
Теперь мы можем вызвать * Программа 1054 * и, и сравните с ней с выводом интерактивной программы GP, фактически дает тот же результат:
Q: [Mod(-t^7 - t^6 - t^5 - t^4 + 1, t^10 + t^9 + t^8 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2 + t + 1), Mod(-t^9 - 2*t^8 - 2*t^7 - 3*t^6 - 3*t^5 - 2*t^4 - 2*t^3 - t^2 - 1, t^10 + t^9 + t^8 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)]
ellisdivisible = 1