从Python调用PARI / GP

时间:2013-02-18 19:03:07

标签: python linux pari-gp

我想从Python调用PARI/GP来计算我定义的不同nextprime(n)的函数n。不幸的是我无法安装pari-python所以我想我会在Python中通过os.system使用命令行来调用它。但是,我在手册页中看不到如何让PARI / GP以非交互模式运行。有没有办法实现这个目标?

3 个答案:

答案 0 :(得分:5)

你可以像这样使用-q标志来管道输入到gp的stdin中来解决冗长问题:

senderle:~ $ echo "print(isprime(5))" | gp -q
1

然而,创建一个简单的python扩展并不是很难,它允许你将字符串传递给pari的内部解析器并获得结果(作为字符串)。这是我前段时间写的一个简单的版本,以便我可以从python中调用pari的APRT test实现。您可以进一步扩展它以进行适当的转换,依此类推。

//pariparse.c

#include<Python.h>
#include<pari/pari.h>

static PyObject * pariparse_run(PyObject *self, PyObject *args) {
    pari_init(40000000, 2);
    const char *pari_code;
    char *outstr;

    if (!PyArg_ParseTuple(args, "s", &pari_code)) { return NULL; }
    outstr = GENtostr(gp_read_str(pari_code));
    pari_close();
    return Py_BuildValue("s", outstr);
}

static PyMethodDef PariparseMethods[] = {
    {"run", pariparse_run, METH_VARARGS, "Run a pari command."},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initpariparse(void) {
    (void) Py_InitModule("pariparse", PariparseMethods);
}

设置文件:

#setup.py

from distutils.core import setup, Extension

module1 = Extension('pariparse',
                    include_dirs = ['/usr/include', '/usr/local/include'],
                    libraries = ['pari'],
                    library_dirs = ['/usr/lib', '/usr/local/lib'],
                    sources = ['pariparse.c'])

setup (name = 'pariparse',
       version = '0.01a',
       description = 'A super tiny python-pari interface',
       ext_modules = [module1])

然后只需输入python setup.py build即可构建扩展程序。然后你可以这样称呼它:

>>> pariparse.run('nextprime(5280)')
'5281'

我刚刚对此进行了测试,并通过自制程序(在OS X上)为我编译了最新版本的pari。 YMMV!

答案 1 :(得分:2)

您可能想尝试使用Sage数学工具。 Sage使用Python将各种数学库粘合在一起,包括PARI。一些数学库很好地集成,其他的使用hacks(将字符串传递给库然后解析出字符串结果)但是在所有情况下,其他人为你做了集成工作,你可以使用它。

您可以设置自己的Sage系统,也可以获得免费帐户并在华盛顿大学服务器上试用Sage。

答案 2 :(得分:1)

我认为调用os.system不是一个好主意,除非你后面有一个可靠的C库,这是一个快速而肮脏的解决方法。从Python调用C函数非常容易;这里有两个用于调用nextprime的函数。一个是使用long整数(尽管名称,这意味着你使用的是小整数);另一种是使用string类型(对于更长的整数)。

首先检查您是否安装了libpari。下面的解决方案适用于Linux,并假设您的库名为libpari.so。在Windows下,可能会使用.dll后缀调用它。如果在第一次尝试时找不到DLL文件,则可能必须键入该文件的完整路径:

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)
pari.strtoGENstr.restype = ctypes.POINTER(ctypes.c_long)
pari.geval.restype = ctypes.POINTER(ctypes.c_long)
pari.itostr.restype = ctypes.c_char_p

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

def nextprime(v):
  g = pari.nextprime(pari.stoi(ctypes.c_long(v)))
  return pari.itos(g)

def nextprime2(v):
  g = pari.nextprime(pari.geval(pari.strtoGENstr(str(v))))
  return int(pari.itostr(g))

print( nextprime(456) )
print( nextprime2(456) )