我想从 Python 调用PARI/GP只是为了计算我定义nextprime(n)
的不同s 的函数。n
不幸的是,我无法安装pari-pythonos.system
,所以我想我会在 Python 中使用命令行调用它。但是,我在手册页中看不到如何让 PARI/GP 在非交互模式下运行。有没有办法做到这一点?
3 回答
您可以像这样通过管道将输入输入 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'
我刚刚对此进行了测试,它使用通过自制软件(在 OS X 上)提供的最新版本的 pari 为我编译。YMMV!
您可能想尝试使用Sage数学工具。Sage 使用 Python 将各种数学库(包括 PARI)粘合在一起。一些数学库很好地集成,另一些则使用 hacks(将字符串传递到库,然后解析字符串结果),但在所有情况下,其他人为您完成了集成工作,您可以使用它。
您可以设置自己的 Sage 系统,也可以获取免费帐户并在华盛顿大学的服务器上试用 Sage。
我认为调用它不是一个好主意,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) )