PARI is a compact, very mature, highly optimized C program whose primary focus is number theory. There are two very distinct interfaces that you can use in Sage:
gp
- the ``Go PARI'' interpreter, and
pari
- the PARI C library.
sage: gp('znprimroot(10007)') Mod(5, 10007) sage: pari('znprimroot(10007)') Mod(5, 10007)
'znprimroot(10007)'
is sent to it, evaluated by GP, and the result is assigned
to a variable in GP (which takes up space in the child GP
processes memory that won't be freed). Then the value of that variable is displayed.
In the second case, no separate program is started,
and the string 'znprimroot(10007)'
is evaluated by
a certain PARI C library function. The result is stored
in a piece of memory on the Python heap, which is freed
when the variable is no longer referenced. The
objects have different types:
sage: type(gp('znprimroot(10007)')) <class 'sage.interfaces.gp.GpElement'> sage: type(pari('znprimroot(10007)')) <type 'sage.libs.pari.gen.gen'>
Note: If the GP interface runs out of memory evaluating a given input line, it will silently and automatically double the stack size and retry that input line. Thus your computation won't crash if you didn't correctly anticipate the amount of memory that would be needed. This is a nice trick the usual GP interpreter doesn't seem to provide. Regarding the PARI C library interface, it immediately copies each created object off of the PARI stack, hence the stack never grows. However, each object must not exceed 100MB in size, or the stack will overflow when the object is being created. This extra copying does impose a slight performance penalty.
In summary, Sage uses the PARI C library to provide functionality similar to that provided by the GP/PARI interpreter, except with different sophisticated memory management and the Python programming language.
First we create a PARI list from a Python list.
sage: v = pari([1,2,3,4,5]) sage: v [1, 2, 3, 4, 5] sage: type(v) <type 'sage.libs.pari.gen.gen'>
Every PARI object is of type py_pari.gen
. The PARI type of the
underlying object can be obtained using the type
member
function.
sage: v.type() 't_VEC'
In PARI, to create an elliptic curve we enter
ellinit([1,2,3,4,5])
.
Sage is similar, except that ellinit
is a method that can be called on any PARI object,
e.g., our t_VEC v
.
sage: e = v.ellinit() sage: e.type() 't_VEC' sage: pari(e)[:13] [1, 2, 3, 4, 5, 9, 11, 29, 35, -183, -3429, -10351, 6128487/10351]
Now that we have an elliptic curve object, we can compute some things about it.
sage: e.elltors() [1, [], []] sage: e.ellglobalred() [10351, [1, -1, 0, -1], 1] sage: f = e.ellchangecurve([1,-1,0,-1]) sage: f[:5] [1, -1, 0, 4, 3]
See About this document... for information on suggesting changes.