1

Python からPARI/GPを呼び出したいと思います。ellisdivisible(E; P; n;{&Q})PARI の関数 を使用する必要があります(このリンクの 441 ページの関数番号 3.15.35 を参照してください:)ため、2 つのベクトルまたは配列 (E = などellinit([0,-1,1,0,0], K);P = [0,0];) を渡す必要があります。

Python (Thomas Baruchel 提供)から単一の引数/変数の PARI 関数 (C) を呼び出すには、以下のようなものがあります -

import ctypes

# load the library
pari=ctypes.cdll.LoadLibrary("libpari.so")

# set the right return type of the functions
pari.stoi.restype = ctypes.POINTER(ctypes.c_long)
pari.nextprime.restype = ctypes.POINTER(ctypes.c_long)

# initialize the library 
pari.pari_init(2**19,0)

def nextprime(v):
  g = pari.nextprime(pari.stoi(ctypes.c_long(v))) # nextprime(argument) is a PARI function
  return pari.itos(g)



print( nextprime(456) )

たとえば、私が試した -

h=(0,0,0, 4,6)
pari.stoi.restype = ctypes.POINTER(ctypes.c_long*5)
pari.ellinit.restype = ctypes.POINTER(ctypes.c_long)
def ellinit(v):
  g = pari.ellinit(pari.stoi(ctypes.c_long(v)*5))
  return pari.itos(g)


print(ellinit(h))

以下のエラーが発生しました-

   File "C:\Users\miron\Desktop\trash5\x\f.py", line 68, in <module>
    print( ellinit(h) )
  File "C:\Users\miron\Desktop\trash5\x\f.py", line 62, in ellinit
    g = pari.ellinit(pari.stoi(ctypes.c_long(v)*5))
TypeError: an integer is required (got type tuple)

タプル/配列/ベクトルを渡すにはどうすればよいですか? ありがとう。

編集: 取得に失敗しましたellisdivisible(E; P; n;{&Q})-

from ctypes import *

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

pari.stoi.restype = POINTER(c_long)
pari.cgetg.restype = POINTER(POINTER(c_long))
pari.ellinit.restype = POINTER(POINTER(c_long))
#-------------------------CHANGE 1
pari.ellisdivisible.restype = c_long
Q = pari.stoi(c_long(0))
#-------------------------
(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():
    h = (0, 0, 0, 0, 1)
    P=(0,0)
    res = pari.ellinit(t_vec(h), pari.stoi(c_long(1)), precision)
#---------------CHANGE 2
   # res = pari.ellinit(t_vec(h), pari.stoi(c_long(1)), precision).disc
    y = pari.ellisdivisible(res, t_vec(P), pari.stoi(c_long(5)), byref(Q))
    print(pari.itos(y))
#---------------
    for i in range(1, 13):
        print(pari.itos(res[i]))

if __name__ == '__main__':
    main()

エラーは -

Traceback (most recent call last):
  File "C:\Users\miron\Desktop\trash5\x\ex - Copy (2).py", line 34, in <module>
    main()
  File "C:\Users\miron\Desktop\trash5\x\ex - Copy (2).py", line 28, in main
    print(pari.itos(y))
OSError: exception: access violation reading 0x0000000000000009
4

1 に答える 1

4

PARI は型/長さが最初の要素でエンコードされている PARI/GP 固有のベクトルを使用しているため、Python のタプルまたは C 配列を直接使用することはできません。

セクション 4.4.1Creation of PARI objectsには次のように書かれています。

PARI オブジェクトを作成する基本的な関数は GEN cgetg(long l, long t) です。l はオブジェクトに割り当てられるロングワードの数を指定し、t はオブジェクトの型をシンボリック形式で表します (リストについてはセクション 4.5 を参照)。これらの)。この関数の正確な効果は次のとおりです。最初に PARI スタック上に長さロングワードのサイズのメモリのチャンクを作成し、最後に返すチャンクのアドレスを保存します。スタックが使い果たされた場合、「PARI スタックがオーバーフローしました」というメッセージが表示され、エラーが発生します。それ以外の場合は、PARI オブジェクトの型と長さを設定します。実際には、最初のコードワード (z[0]) を埋めます。

https://pari.math.u-bordeaux.fr/pub/pari/manuals/2.7.6/libpari.pdfを参照してください。

このドキュメントの例では、2 つの要素を持つベクトルを作成するために、適切なベクトルを取得するためにサイズl=3で呼び出されることがわかります。実際の数値ベクトルの最初の要素は、インデックス 0 ではなく、インデックス 1 で始まります (この PDF ドキュメントのセクション 4.5.15 を参照してください)。

git clone http://pari.math.u-bordeaux.fr/git/pari.git   

PARI のソース コードを取得できます。

src/headers/parigen.h の最後にさまざまなタイプが表示されます。これは列挙型で、必要な型は t_VEC です。対応する整数は 17 です。

したがって、次のように tupel を 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]]

引用された PDF ドキュメントの 441 ページにある例の小さな自己完結型 Python プログラムは、次のようになります。

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()

テスト

これで Python プログラムを呼び出すことができ、対話型 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
于 2020-03-22T17:34:21.310 に答える