Search code examples
pythonlinuxpari-gp

Calling PARI/GP from Python


I would like to call PARI/GP from Python only to calculate the function nextprime(n) for different ns 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?


Solution

  • 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!