问题
I would like to call PARI/GP from Python only to calculate the function nextprime(n)
for different n
s that I define. Unfortunately I can't get pari-python to install so I thought I would just call it using a command line via os.system
in Python. I can't see in the man page how to do get PARI/GP to run in non-interactive mode, however. Is there a way to achieve this?
回答1:
You can pipe input into gp's stdin like so, using the -q
flag to quash verbosity:
senderle:~ $ echo "print(isprime(5))" | gp -q
1
However, it's not much harder to create a simple python extension that allows you to pass strings to pari's internal parser and get results back (as strings). Here's a bare-bones version that I wrote some time ago so that I could call pari's implementation of the APRT test from python. You could extend this further to do appropriate conversions and so on.
//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);
}
And the setup file:
#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])
Then just type python setup.py build
to build the extension. You can then call it like this:
>>> pariparse.run('nextprime(5280)')
'5281'
I tested this just now and it compiled for me with the latest version of pari available via homebrew (on OS X). YMMV!
回答2:
You might want to try using the Sage math tool. Sage uses Python to glue together all sorts of math libraries, including PARI. Some of the math libraries are nicely integrated, others use hacks (passing strings in to the library and then parsing out the string results) but in all cases someone else did the integration work for you and you can just use it.
You can set up your own Sage system, or you can get a free account and try Sage on the University of Washington servers.
回答3:
I don't think it is a good idea to call os.system
except for a quick and dirty workaround when you have a reliable C library behind it. It is very easy to call C functions from Python; here are two functions for calling nextprime. One is using long
integers (despite the name, it will mean here that you are using small integer numbers); the other is using the string
type (for longer integers).
First check that you have the libpari
installed. The solution below is for Linux and assumes that your library is called libpari.so
. Under Windows it will probably be called with a .dll
suffix instead. You may have to type the whole path of the DLL file if it isn't found at first attempt:
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) )
来源:https://stackoverflow.com/questions/14943507/calling-pari-gp-from-python