Pari/GP Reference Documentation  Contents - Index - Meta commands

Programming in GP


Control statements   Specific functions used in GP programming   addhelp   alias   allocatemem   break   default   error   extern   for   fordiv   forell   forprime   forstep   forsubgroup   forvec   getheap   getrand   getstack   gettime   global   if   input   install   kill   next   print1   print   printp1   printp   printtex   quit   read   readvec   reorder   return   setrand   system   trap   type   until   whatnow   while   write1   write   writebin   writetex  
 
Control statements  

.

A number of control statements are available in GP. They are simpler and have a syntax slightly different from their C counterparts, but are quite powerful enough to write any kind of program. Some of them are specific to GP, since they are made for number theorists. As usual, X will denote any simple variable name, and seq will always denote a sequence of expressions, including the empty sequence.

Caveat: in constructs like

    for (X = a,b, seq)

the variable X is considered local to the loop, leading to possibly unexpected behaviour:

    n = 5;
     for (n = 1, 10,
       if (something_nice(), break);
     );
     \\  at this point 
n is 5 !

If the sequence seq modifies the loop index, then the loop is modified accordingly:

    ? for (n = 1, 10, n += 2; print(n))
     3
     6
     9
     12

break({n = 1})  

interrupts execution of current seq, and immediately exits from the n innermost enclosing loops, within the current function call (or the top level loop). n must be bigger than 1. If n is greater than the number of enclosing loops, all enclosing loops are exited.

for(X = a,b,seq)  

evaluates seq, where the formal variable X goes from a to b. Nothing is done if a > b. a and b must be in R.

fordiv(n,X,seq)  

evaluates seq, where the formal variable X ranges through the divisors of n (see divisors, which is used as a subroutine). It is assumed that factor can handle n, without negative exponents. Instead of n, it is possible to input a factorization matrix, i.e. the output of factor(n).

This routine uses divisors as a subroutine, then loops over the divisors. In particular, if n is an integer, divisors are sorted by increasing size.

To avoid storing all divisors, possibly using a lot of memory, the following (much slower) routine loops over the divisors using essentially constant space:

    FORDIV(N)=
     { local(P, E);
    
       P = factor(N); E = P[,2]; P = P[,1]; 
       forvec( v = vector(#E, i, [0,E[i]]),
         X = factorback(P, v)
         \\ ...
       );
     }
     ? for(i=1,10^5, FORDIV(i))
     time = 3,445 ms.
     ? for(i=1,10^5, fordiv(i, d, ))
     time = 490 ms.

forell(E,a,b,seq)  

evaluates seq, where the formal variable E ranges through all elliptic curves of conductors from a to b. Th elldata database must be installed and contain data for the specified conductors.

forprime(X = a,b,seq)  

evaluates seq, where the formal variable X ranges over the prime numbers between a to b (including a and b if they are prime). More precisely, the value of X is incremented to the smallest prime strictly larger than X at the end of each iteration. Nothing is done if a > b. Note that a and b must be in R.

? { forprime(p = 2, 12,
       print(p);
       if (p == 3, p = 6);
     )
   }
 2
 3
 7
 11

forstep(X = a,b,s,seq)  

evaluates seq, where the formal variable X goes from a to b, in increments of s. Nothing is done if s > 0 and a > b or if s < 0 and a < b. s must be in R^* or a vector of steps [s_1,...,s_n]. In the latter case, the successive steps are used in the order they appear in s.

? forstep(x=5, 20, [2,4], print(x))
 5
 7
 11
 13
 17
 19

forsubgroup(H = G,{B},seq)  

evaluates seq for each subgroup H of the abelian group G (given in SNF form or as a vector of elementary divisors), whose index is bounded by B. The subgroups are not ordered in any obvious way, unless G is a p-group in which case Birkhoff's algorithm produces them by decreasing index. A subgroup is given as a matrix whose columns give its generators on the implicit generators of G. For example, the following prints all subgroups of index less than 2 in G = Z/2Z g_1 x Z/2Z g_2:

? G = [2,2]; forsubgroup(H=G, 2, print(H))
 [1; 1]
 [1; 2]
 [2; 1]
 [1, 0; 1, 1]

The last one, for instance is generated by (g_1, g_1 + g_2). This routine is intended to treat huge groups, when subgrouplist is not an option due to the sheer size of the output.

For maximal speed the subgroups have been left as produced by the algorithm. To print them in canonical form (as left divisors of G in HNF form), one can for instance use

? G = matdiagonal([2,2]); forsubgroup(H=G, 2, print(mathnf(concat(G,H))))
 [2, 1; 0, 1]
 [1, 0; 0, 2]
 [2, 0; 0, 1]
 [1, 0; 0, 1]

Note that in this last representation, the index [G:H] is given by the determinant. See galoissubcyclo and galoisfixedfield for nfsubfields applications to Galois theory.

Warning: the present implementation cannot treat a group G, if one of its p-Sylow subgroups has a cyclic factor with more than 2^{31}, resp.2^{63} elements on a 32-bit, resp.64-bit architecture.

forvec(X = v,seq,{flag = 0})  

Let v be an n-component vector (where n is arbitrary) of two-component vectors [a_i,b_i] for 1 <= i <= n. This routine evaluates seq, where the formal variables X[1],..., X[n] go from a_1 to b_1,..., from a_n to b_n, i.e.X goes from [a_1,...,a_n] to [b_1,...,b_n] with respect to the lexicographic ordering. (The formal variable with the highest index moves the fastest.) If flag = 1, generate only nondecreasing vectors X, and if flag = 2, generate only strictly increasing vectors X.

if(a,{seq1},{seq2})  

evaluates the expression sequence seq1 if a is non-zero, otherwise the expression seq2. Of course, seq1 or seq2 may be empty:

if (a,seq) evaluates seq if a is not equal to zero (you don't have to write the second comma), and does nothing otherwise,

if (a,,seq) evaluates seq if a is equal to zero, and does nothing otherwise. You could get the same result using the ! ( not) operator: if (!a,seq).

Note that the boolean operators && and || are evaluated according to operator precedence as explained in Section [Label: se:operators], but that, contrary to other operators, the evaluation of the arguments is stopped as soon as the final truth value has been determined. For instance

    if (reallydoit && longcomplicatedfunction(), ...)%

is a perfectly safe statement.

Recall that functions such as break and next operate on loops (such as forxxx, while, until). The if statement is not a loop (obviously!).

next({n = 1})  

interrupts execution of current seq, resume the next iteration of the innermost enclosing loop, within the current function call (or top level loop). If n is specified, resume at the n-th enclosing loop. If n is bigger than the number of enclosing loops, all enclosing loops are exited.

return({x = 0})  

returns from current subroutine, with result x. If x is omitted, return the (void) value (return no result, like print).

until(a,seq)  

evaluates seq until a is not equal to 0 (i.e.until a is true). If a is initially not equal to 0, seq is evaluated once (more generally, the condition on a is tested after execution of the seq, not before as in while).

while(a,seq)  

while a is non-zero, evaluates the expression sequence seq. The test is made before evaluating the seq, hence in particular if a is initially equal to zero the seq will not be evaluated at all.

Specific functions used in GP programming  

.

In addition to the general PARI functions, it is necessary to have some functions which will be of use specifically for gp, though a few of these can be accessed under library mode. Before we start describing these, we recall the difference between strings and keywords (see Section [Label: se:strings]): the latter don't get expanded at all, and you can type them without any enclosing quotes. The former are dynamic objects, where everything outside quotes gets immediately expanded.

addhelp(S,str)  

changes the help message for the symbol S. The string str is expanded on the spot and stored as the online help for S. If S is a function you have defined, its definition will still be printed before the message str. It is recommended that you document global variables and user functions in this way. Of course gp will not protest if you skip this.

Nothing prevents you from modifying the help of built-in PARI functions. (But if you do, we would like to hear why you needed to do it!)

alias(newkey,key)  

defines the keyword newkey as an alias for keyword key. key must correspond to an existing function name. This is different from the general user macros in that alias expansion takes place immediately upon execution, without having to look up any function code, and is thus much faster. A sample alias file misc/gpalias is provided with the standard distribution. Alias commands are meant to be read upon startup from the .gprc file, to cope with function names you are dissatisfied with, and should be useless in interactive usage.

allocatemem({x = 0})  

this is a very special operation which allows the user to change the stack size after initialization. x must be a non-negative integer. If x != 0, a new stack of size 16*ceil{x/16} bytes is allocated, all the PARI data on the old stack is moved to the new one, and the old stack is discarded. If x = 0, the size of the new stack is twice the size of the old one.

Although it is a function, allocatemem cannot be used in loop-like constructs, or as part of a larger expression, e.g 2 + allocatemem(). Such an attempt will raise an error. The technical reason is that this routine usually moves the stack, so objects from the current expression may not be correct anymore, e.g. loop indexes.

The library syntax is allocatemoremem(x), where x is an unsigned long, and the return type is void. gp uses a variant which makes sure it was not called within a loop.

default({key},{val})  

returns the default corresponding to keyword key. If val is present, sets the default to val first (which is subject to string expansion first). Typing default() (or \d) yields the complete default list as well as their current values. See Section [Label: se:defaults] for a list of available defaults, and Section [Label: se:meta] for some shortcut alternatives. Note that the shortcut are meant for interactive use and usually display more information than default.

The library syntax is gp_default(key, val), where key and val are char *.

error({str}*)  

outputs its argument list (each of them interpreted as a string), then interrupts the running gp program, returning to the input prompt. For instance

error("n = ", n, " is not squarefree !")

extern(str)  

the string str is the name of an external command (i.e.one you would type from your UNIX shell prompt). This command is immediately run and its input fed into gp, just as if read from a file.

The library syntax is extern0(str), where str is a char *.

getheap()  

returns a two-component row vector giving the number of objects on the heap and the amount of memory they occupy in long words. Useful mainly for debugging purposes.

The library syntax is getheap().

getrand()  

returns the current value of the random number seed. Useful mainly for debugging purposes.

The library syntax is getrand(), returns a C long.

getstack()  

returns the current value of top- avma, i.e.the number of bytes used up to now on the stack. Should be equal to 0 in between commands. Useful mainly for debugging purposes.

The library syntax is getstack(), returns a C long.

gettime()  

returns the time (in milliseconds) elapsed since either the last call to gettime, or to the beginning of the containing GP instruction (if inside gp), whichever came last.

The library syntax is gettime(), returns a C long.

global(list of variables)  

declares the corresponding variables to be global. From now on, you will be forbidden to use them as formal parameters for function definitions or as loop indexes. This is especially useful when patching together various scripts, possibly written with different naming conventions. For instance the following situation is dangerous:

p = 3   \\ fix characteristic

 ...  forprime(p = 2, N, ...)  f(p) = ...

since within the loop or within the function's body (even worse: in the subroutines called in that scope), the true global value of p will be hidden. If the statement global(p = 3) appears at the beginning of the script, then both expressions will trigger syntax errors.

Calling global without arguments prints the list of global variables in use. In particular, eval(global) will output the values of all global variables.

input()  

reads a string, interpreted as a GP expression, from the input file, usually standard input (i.e.the keyboard). If a sequence of expressions is given, the result is the result of the last expression of the sequence. When using this instruction, it is useful to prompt for the string by using the print1 function. Note that in the present version 2.19 of pari.el, when using gp under GNU Emacs (see Section [Label: se:emacs]) one must prompt for the string, with a string which ends with the same prompt as any of the previous ones (a "? " will do for instance).

install(name,code,{gpname},{lib})  

loads from dynamic library lib the function name. Assigns to it the name gpname in this gp session, with argument code code (see the Libpari Manual for an explanation of those). If lib is omitted, uses libpari.so. If gpname is omitted, uses name.

This function is useful for adding custom functions to the gp interpreter, or picking useful functions from unrelated libraries. For instance, it makes the function system obsolete:

? install(system, vs, sys, "libc.so")
 ? sys("ls gp*")
 gp.c            gp.h            gp_rl.c

But it also gives you access to all (non static) functions defined in the PARI library. For instance, the function GEN addii(GEN x, GEN y) adds two PARI integers, and is not directly accessible under gp (it's eventually called by the + operator of course):

? install("addii", "GG")
 ? addii(1, 2)
 %1 = 3

Re-installing a function will print a Warning, and update the prototype code if needed, but will reload a symbol from the library, even it the latter has been recompiled.

Caution: This function may not work on all systems, especially when gp has been compiled statically. In that case, the first use of an installed function will provoke a Segmentation Fault, i.e.a major internal blunder (this should never happen with a dynamically linked executable). Hence, if you intend to use this function, please check first on some harmless example such as the ones above that it works properly on your machine.

kill(s)  

kills the present value of the variable, alias or user-defined function s. The corresponding identifier can now be used to name any GP object (variable or function). This is the only way to replace a variable by a function having the same name (or the other way round), as in the following example:

? f = 1
 %1 = 1
 ? f(x) = 0
   ***   unused characters: f(x)=0
                             ^----
 ? kill(f)
 ? f(x) = 0
 ? f()
 %2 = 0

When you kill a variable, all objects that used it become invalid. You can still display them, even though the killed variable will be printed in a funny way. For example:

? a^2 + 1
 %1 = a^2 + 1
 ? kill(a)
 ? %1
 %2 = #<1>^2 + 1

If you simply want to restore a variable to its "undefined" value (monomial of degree one), use the quote operator: a = 'a. Predefined symbols ( x and GP function names) cannot be killed.

print({str}*)  

outputs its (string) arguments in raw format, ending with a newline.

print1({str}*)  

outputs its (string) arguments in raw format, without ending with a newline (note that you can still embed newlines within your strings, using the \n notation!).

printp({str}*)  

outputs its (string) arguments in prettyprint (beautified) format, ending with a newline.

printp1({str}*)  

outputs its (string) arguments in prettyprint (beautified) format, without ending with a newline.

printtex({str}*)  

outputs its (string) arguments in TeX format. This output can then be used in a TeX manuscript. The printing is done on the standard output. If you want to print it to a file you should use writetex (see there).

Another possibility is to enable the log default (seeSection [Label: se:defaults]). You could for instance do:

default(logfile, "new.tex");
 default(log, 1);
 printtex(result);

quit()  

exits gp.

read({filename})  

reads in the file filename (subject to string expansion). If filename is omitted, re-reads the last file that was fed into gp. The return value is the result of the last expression evaluated.

If a GP binary file is read using this command (see Section [Label: se:writebin]), the file is loaded and the last object in the file is returned.

readvec({str})  

reads in the file filename (subject to string expansion). If filename is omitted, re-reads the last file that was fed into gp. The return value is a vector whose components are the evaluation of all sequences of instructions contained in the file. For instance, if file contains

  1
   2
   3

then we will get:

  ? \r a
   %1 = 1
   %2 = 2
   %3 = 3
   ? read(a)
   %4 = 3
   ? readvec(a)
   %5 = [1, 2, 3]

In general a sequence is just a single line, but as usual braces and \\ may be used to enter multiline sequences.

reorder({x = []})  

x must be a vector. If x is the empty vector, this gives the vector whose components are the existing variables in increasing order (i.e.in decreasing importance). Killed variables (see kill) will be shown as 0. If x is non-empty, it must be a permutation of variable names, and this permutation gives a new order of importance of the variables, for output only. For example, if the existing order is [x,y,z], then after reorder([z,x]) the order of importance of the variables, with respect to output, will be [z,y,x]. The internal representation is unaffected.

setrand(n)  

reseeds the random number generator to the value n. The initial seed is n = 1.

The library syntax is setrand(n), where n is a long. Returns n.

system(str)  

str is a string representing a system command. This command is executed, its output written to the standard output (this won't get into your logfile), and control returns to the PARI system. This simply calls the C system command.

trap({e}, {rec}, {seq})  

tries to evaluate seq, trapping error e, that is effectively preventing it from aborting computations in the usual way; the recovery sequence rec is executed if the error occurs and the evaluation of rec becomes the result of the command. If e is omitted, all exceptions are trapped. Note in particular that hitting ^C (Control-C) raises an exception. See Section [Label: se:errorrec] for an introduction to error recovery under gp.

? \\ trap division by 0

 ? inv(x) = trap (gdiver, INFINITY, 1/x)  ? inv(2)  %1 = 1/2  ? inv(0)  %2 = INFINITY

If seq is omitted, defines rec as a default action when catching exception e, provided no other trap as above intercepts it first. The error message is printed, as well as the result of the evaluation of rec, and control is given back to the gp prompt. In particular, current computation is then lost.

The following error handler prints the list of all user variables, then stores in a file their name and their values:

? { trap( ,
       print(reorder);
       writebin("crash")) }

If no recovery code is given (rec is omitted) a break loop will be started (see Section [Label: se:breakloop]). In particular

? trap()

by itself installs a default error handler, that will start a break loop whenever an exception is raised.

If rec is the empty string "" the default handler (for that error if e is present) is disabled.

Note: The interface is currently not adequate for trapping individual exceptions. In the current version 2.3.1, the following keywords are recognized, but the name list will be expanded and changed in the future (all library mode errors can be trapped: it's a matter of defining the keywords to gp, and there are currently far too many useless ones):

accurer: accuracy problem

archer: not available on this architecture or operating system

errpile: the PARI stack overflows

gdiver: division by 0

invmoder: impossible inverse modulo

siginter: SIGINT received (usually from Control-C)

talker: miscellaneous error

typeer: wrong type

user: user error (from the error function)

type(x)  

this is useful only under gp. Returns the internal type name of the PARI object x as a string. Check out existing type names with the metacommand \t. For example type(1) will return " t_INT".

The library syntax is type0(x), though the macro typ is usually simpler to use since it return an integer that can easily be matched with the symbols t_*. The name type was avoided due to the fact that type is a reserved identifier for some C(++) compilers.

whatnow(key)  

if keyword key is the name of a function that was present in GP version 1.39.15 or lower, outputs the new function name and syntax, if it changed at all (387 out of 560 did).

write(filename,{str}*)  

writes (appends) to filename the remaining arguments, and appends a newline (same output as print).

write1(filename,{str}*)  

writes (appends) to filename the remaining arguments without a trailing newline (same output as print1).

writebin(filename,{x})  

writes (appends) to filename the object x in binary format. This format is not human readable, but contains the exact internal structure of x, and is much faster to save/load than a string expression, as would be produced by write. The binary file format includes a magic number, so that such a file can be recognized and correctly input by the regular read or \r function. If saved objects refer to (polynomial) variables that are not defined in the new session, they will be displayed in a funny way (see Section [Label: se:kill]).

If x is omitted, saves all user variables from the session, together with their names. Reading such a "named object" back in a gp session will set the corresponding user variable to the saved value. E.g after

x = 1; writebin("log")

reading log into a clean session will set x to 1. The relative variables priorities (see Section [Label: se:priority]) of new variables set in this way remain the same (preset variables retain their former priority, but are set to the new value). In particular, reading such a session log into a clean session will restore all variables exactly as they were in the original one.

User functions, installed functions and history objects can not be saved via this function. Just as a regular input file, a binary file can be compressed using gzip, provided the file name has the standard .gz extension.

In the present implementation, the binary files are architecture dependent and compatibility with future versions of gp is not guaranteed. Hence binary files should not be used for long term storage (also, they are larger and harder to compress than text files).

writetex(filename,{str}*)  

as write, in TeX format.