从Python调用PARI/GP
我想在Python中调用PARI/GP,只为了计算不同的数字n
的下一个质数,也就是用nextprime(n)
这个函数。可惜的是,我无法成功安装pari-python,所以我想通过Python里的os.system
命令行来调用它。不过,我在手册上找不到如何让PARI/GP在非交互模式下运行的方法。请问有没有什么办法可以做到这一点?
3 个回答
我觉得调用 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) )
你可以试试使用Sage这个数学工具。Sage是用Python编写的,它把各种数学库连接在一起,包括PARI。某些数学库的整合做得很好,而有些则是用一些小技巧(比如把字符串传给库,然后再解析字符串结果)来实现的,但总的来说,别人已经帮你做好了整合工作,你只需要直接使用就可以了。
你可以自己搭建一个Sage系统,或者你也可以注册一个免费的账户,在华盛顿大学的服务器上试试Sage。
你可以通过管道将输入传递给gp的标准输入,使用-q
选项可以减少输出的信息量:
senderle:~ $ echo "print(isprime(5))" | gp -q
1
不过,创建一个简单的Python扩展来让你可以把字符串传递给pari的内部解析器,并获取结果(作为字符串)其实也不难。我之前写过一个简单的版本,这样我就可以从Python调用pari的APRT测试。你可以进一步扩展这个功能,进行适当的转换等等。
//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'
我刚刚测试过,使用最新版本的pari通过homebrew在OS X上编译成功了。你的情况可能会有所不同!