Отправка полинома в PARI / GP из Python (ctypes) - PullRequest
1 голос
/ 23 марта 2020

Я хотел бы вызвать nfroots({nf}; x) функцию PARI / GP с Python. (см. Функцию № 3.13.135.на странице 371 по этой ссылке:) , но проблема в том, что я не смог отправить алгебраическое выражение c или полином, который нужно отправить, для Например, x^2-7x+12, вот очень простой пример того, что gp может сделать с полиномом четверти c:

> V = readvec("coeff.txt");
> print(V)
[1,-7,12]
> P = Pol(V);  # I get following error when I use Pol in my code:    func=self._FuncPtr((name_or_ordinal, self)) AttributeError: function 'pol' not found 
> print(P)
x^2 -7*x +12
> print(nfroots(,P))
>4, 3

Из ответа Стефан Шлехт (нажмите здесь) , мне удается написать -

from ctypes import *
pari = cdll.LoadLibrary("C:\\Program Files\\Pari64-2-11-3\\libpari.dll")

pari.stoi.restype = POINTER(c_long)
pari.cgetg.restype = POINTER(POINTER(c_long))

pari.nfroots.restype = POINTER(POINTER(c_long))


pari.pari_init(2 ** 19, 0)

def t_vec(numbers):
    l = len(numbers) + 1
    p1 = pari.cgetg(c_long(l), c_long(10)) #t_POL    =  10,
    for i in range(1, l):
        p1[i] = pari.stoi(c_long(numbers[i - 1]))
    return p1

def main():    
    h = "x^2-7x+12"
    res = pari.nfroots(t_vec(h))  
for i in range(1, len(res)):
         print(pari.itos(res[i]))
if __name__ == '__main__':
    main()

Обратите внимание, что существует специфический c процесс создания объектов PARI (см. Ответ Stephan Schlecht ), я изменил значение для t_POL = 10, но код не работает. Как выполнить приведенный выше код PARI / GP с python?

1 Ответ

3 голосов
/ 23 марта 2020

Одним из решений может быть:

  • использовать gtopoly, тип возврата - POINTER(c_long)
  • тип возврата nfroots - POINTER(POINTER(c_long))
  • вывод результата с .pari_printf

Код

from ctypes import *

pari = cdll.LoadLibrary("libpari.so")

pari.stoi.restype = POINTER(c_long)
pari.cgetg.restype = POINTER(POINTER(c_long))
pari.gtopoly.restype = POINTER(c_long)
pari.nfroots.restype = POINTER(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():
    V = (1, -7, 12)
    P = pari.gtopoly(t_vec(V), c_long(-1))
    res = pari.nfroots(None, P)
    pari.pari_printf(bytes("%Ps\n", "utf8"), res)


if __name__ == '__main__':
    main()

Тест

Если вы запустите программу, вы получите нужный вывод в консоли отладки:

[3, 4]

Преобразования

С помощью glength можно определить длину вектора, см. https://pari.math.u-bordeaux.fr/dochtml/html/Conversions_and_similar_elementary_functions_or_commands.html#length

С itos можно вернуть long, если параметр имеет тип t_INT, см. Раздел 4.4.6 https://pari.math.u-bordeaux.fr/pub/pari/manuals/2.7.6/libpari.pdf.

В коде это будет выглядеть так:

pari.glength.restype = c_long
pari.itos.restype = c_long
... 
print("elements as long (only if of type t_INT): ")
for i in range(1, pari.glength(res) + 1):
    print(pari.itos(res[i]))

To GENtostr дает строковое представление аргумента. Его можно использовать так:

pari.GENtostr.restype = c_char_p
...
print("elements as generic strings: ")
for i in range(1, pari.glength(res) + 1):
    print(pari.GENtostr(res[i]).decode("utf-8"))

Есть еще много вариантов конвертации, см. Две ссылки выше.

...