## Programming in GP: other specific functions

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 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.

#### Strprintf(fmt, {x}*)

Returns a string built from the remaining arguments according to the format fmt. The format consists of ordinary characters (not %), printed unchanged, and conversions specifications. See `printf`.

#### addhelp(sym, str)

Changes the help message for the symbol `sym`. The string str is expanded on the spot and stored as the online help for `sym`. It is recommended to document global variables and user functions in this way, although `gp` will not protest if you don't.

You can attach a help text to an alias, but it will never be shown: aliases are expanded by the `?` help operator and we get the help of the symbol the alias points to. Nothing prevents you from modifying the help of built-in PARI functions. But if you do, we would like to hear why you needed it!

Without `addhelp`, the standard help for user functions consists of its name and definition.

      gp> f(x) = x^2;
      gp> ?f
      f =
        (x)->x^2

Once addhelp is applied to f, the function code is no longer included. It can still be consulted by typing the function name:

      gp> addhelp(f, "Square")
      gp> ?f
      Square

      gp> f
      %2 = (x)->x^2

The library syntax is `void addhelp(const char *sym, const char *str)`.

#### alarm({s = 0}, {code})

If code is omitted, trigger an e_ALARM exception after s seconds, cancelling any previously set alarm; stop a pending alarm if s = 0 or is omitted.

Otherwise, if s is positive, the function evaluates code, aborting after s seconds. The return value is the value of code if it ran to completion before the alarm timeout, and a `t_ERROR` object otherwise.

        ? p = nextprime(10^25); q = nextprime(10^26); N = p*q;
        ? E = alarm(1, factor(N));
        ? type(E)
        %3 = "t_ERROR"
        ? print(E)
        %4 = error("alarm interrupt after 964 ms.")
        ? alarm(10, factor(N));   \\ enough time
        %5 =
        [ 10000000000000000000000013 1]

        [100000000000000000000000067 1]

Here is a more involved example: the function `timefact(N,sec)` below tries to factor N and gives up after sec seconds, returning a partial factorization.

      \\ Time-bounded partial factorization
      default(factor_add_primes,1);
      timefact(N,sec)=
      {
        F = alarm(sec, factor(N));
        if (type(F) == "t_ERROR", factor(N, 2^24), F);
      }

We either return the factorization directly, or replace the `t_ERROR` result by a simple bounded factorization `factor(N, 2^24)`. Note the `factor_add_primes` trick: any prime larger than 224 discovered while attempting the initial factorization is stored and remembered. When the alarm rings, the subsequent bounded factorization finds it right away.

Caveat. It is not possible to set a new alarm within another `alarm` code: the new timer erases the parent one.

The library syntax is `GEN gp_alarm(long s, GEN code = NULL)`.

#### alias(newsym, sym)

Defines the symbol newsym as an alias for the symbol sym:

      ? alias("det", "matdet");
      ? det([1,2;3,4])
      %1 = -2

You are not restricted to ordinary functions, as in the above example: to alias (from/to) member functions, prefix them with ``_.`'; to alias operators, use their internal name, obtained by writing `_` in lieu of the operators argument: for instance, `_!` and `!_` are the internal names of the factorial and the logical negation, respectively.

      ? alias("mod", "_.mod");
      ? alias("add", "_+_");
      ? alias("_.sin", "sin");
      ? mod(Mod(x,x^4+1))
      %2 = x^4 + 1
      ? add(4,6)
      %3 = 10
      ? Pi.sin
      %4 = 0.E-37

Alias expansion is performed directly by the internal GP compiler. Note that since alias is performed at compilation-time, it does not require any run-time processing, however it only affects GP code compiled after the alias command is evaluated. A slower but more flexible alternative is to use variables. Compare

      ? fun = sin;
      ? g(a,b) = intnum(t=a,b,fun(t));
      ? g(0, Pi)
      %3 = 2.0000000000000000000000000000000000000
      ? fun = cos;
      ? g(0, Pi)
      %5 = 1.8830410776607851098 E-39

with

      ? alias(fun, sin);
      ? g(a,b) = intnum(t=a,b,fun(t));
      ? g(0,Pi)
      %2 = 2.0000000000000000000000000000000000000
      ? alias(fun, cos);  \\ Oops. Does not affect *previous* definition!
      ? g(0,Pi)
      %3 = 2.0000000000000000000000000000000000000
      ? g(a,b) = intnum(t=a,b,fun(t)); \\ Redefine, taking new alias into account
      ? g(0,Pi)
      %5 = 1.8830410776607851098 E-39

A sample alias file `misc/gpalias` is provided with the standard distribution.

The library syntax is `void alias0(const char *newsym, const char *sym)`.

#### allocatemem({s = 0})

This special operation changes the stack size after initialization. x must be a non-negative integer. If x > 0, a new stack of at least x bytes is allocated. We may allocate more than x bytes if x is way too small, or for alignment reasons: the current formula is max(16*ceil{x/16}, 500032) bytes.

If x = 0, the size of the new stack is twice the size of the old one.

This command is much more useful if `parisizemax` is non-zero, and we describe this case first. With `parisizemax` enabled, there are three sizes of interest:

* a virtual stack size, `parisizemax`, which is an absolute upper limit for the stack size; this is set by `default(parisizemax, ...)`.

* the desired typical stack size, `parisize`, that will grow as needed, up to `parisizemax`; this is set by `default(parisize, ...)`.

* the current stack size, which is less that `parisizemax`, typically equal to `parisize` but possibly larger and increasing dynamically as needed; `allocatemem` allows to change that one explicitly.

The `allocatemem` command forces stack usage to increase temporarily (up to `parisizemax` of course); for instance if you notice using `\gm2` that we seem to collect garbage a lot, e.g.

      ? \gm2
        debugmem = 2
      ? default(parisize,"32M")
       ***   Warning: new stack size = 32000000 (30.518 Mbytes).
      ? bnfinit('x^2+10^30-1)
       *** bnfinit: collecting garbage in hnffinal, i = 1.
       *** bnfinit: collecting garbage in hnffinal, i = 2.
       *** bnfinit: collecting garbage in hnffinal, i = 3.

and so on for hundred of lines. Then, provided the `breakloop` default is set, you can interrupt the computation, type `allocatemem(100*10^6)` at the break loop prompt, then let the computation go on by typing `<Enter>` . Back at the `gp` prompt, the desired stack size of `parisize` is restored. Note that changing either `parisize` or `parisizemax` at the break loop prompt would interrupt the computation, contrary to the above.

In most cases, `parisize` will increase automatically (up to `parisizemax`) and there is no need to perform the above maneuvers. But that the garbage collector is sufficiently efficient that a given computation can still run without increasing the stack size, albeit very slowly due to the frequent garbage collections.

Deprecated: when `parisizemax.` is unset This is currently still the default behavior in order not to break backward compatibility. The rest of this section documents the behavior of `allocatemem` in that (deprecated) situation: it becomes a synonym for `default(parisize,...)`. In that case, there is no notion of a virtual stack, and the stack size is always equal to `parisize`. If more memory is needed, the PARI stack overflows, aborting the computation.

Thus, increasing `parisize` via `allocatemem` or `default(parisize,...)` before a big computation is important. Unfortunately, either must be typed at the `gp` prompt in interactive usage, or left by itself at the start of batch files. They cannot be used meaningfully in loop-like constructs, or as part of a larger expression sequence, e.g

         allocatemem(); x = 1;   \\  This will not set x!

In fact, all loops are immediately exited, user functions terminated, and the rest of the sequence following `allocatemem()` is silently discarded, as well as all pending sequences of instructions. We just go on reading the next instruction sequence from the file we are in (or from the user). In particular, we have the following possibly unexpected behavior: in

         read("file.gp"); x = 1

were `file.gp` contains an `allocatemem` statement, the `x = 1` is never executed, since all pending instructions in the current sequence are discarded.

The reason for these unfortunate side-effects is that, with `parisizemax` disabled, increasing the stack size physically moves the stack, so temporary objects created during the current expression evaluation are not correct anymore. (In particular byte-compiled expressions, which are allocated on the stack.) To avoid accessing obsolete pointers to the old stack, this routine ends by a `longjmp`.

The library syntax is `void gp_allocatemem(GEN s = NULL)`.

#### apply(f, A)

Apply the `t_CLOSURE` `f` to the entries of `A`. If `A` is a scalar, return `f(A)`. If `A` is a polynomial or power series, apply `f` on all coefficients. If `A` is a vector or list, return the elements f(x) where x runs through `A`. If `A` is a matrix, return the matrix whose entries are the f(`A[i,j]`).

      ? apply(x->x^2, [1,2,3,4])
      %1 = [1, 4, 9, 16]
      ? apply(x->x^2, [1,2;3,4])
      %2 =
      [1 4]

      [9 16]
      ? apply(x->x^2, 4*x^2 + 3*x+ 2)
      %3 = 16*x^2 + 9*x + 4

Note that many functions already act componentwise on vectors or matrices, but they almost never act on lists; in this case, `apply` is a good solution:

      ? L = List([Mod(1,3), Mod(2,4)]);
      ? lift(L)
        ***   at top-level: lift(L)
        ***                 ^ —  — -
        *** lift: incorrect type in lift.
      ? apply(lift, L);
      %2 = List([1, 2])

Remark. For v a `t_VEC`, `t_COL`, `t_LIST` or `t_MAT`, the alternative set-notations

      [g(x) | x <- v, f(x)]
      [x | x <- v, f(x)]
      [g(x) | x <- v]

are available as shortcuts for

      apply(g, select(f, Vec(v)))
      select(f, Vec(v))
      apply(g, Vec(v))

respectively:

      ? L = List([Mod(1,3), Mod(2,4)]);
      ? [ lift(x) | x<-L ]
      %2 = [1, 2]

The library syntax is `genapply(void *E, GEN (*fun)(void*,GEN), GEN a)`.

#### call(f, A)

A = [a1,..., an] being a vector and f being a function, returns the evaluation of f(a1,...,an). f can also be the name of a built-in GP function. If # A = 1, `call`(f,A) = `apply`(f,A)[1]. If f is variadic, the variadic arguments must grouped in a vector in the last component of A.

This function is useful

* when writing a variadic function, to call another one:

      fprintf(file,format,args[..]) = write(file,call(Strprintf,[format,args]))

* when dealing with function arguments with unspecified arity

The function below implements a global memoization interface:

      memo=Map();
      memoize(f,A[..])=
      {
        my(res);
        if(!mapisdefined(memo, [f,A], &res),
          res = call(f,A);
          mapput(memo,[f,A],res));
       res;
      }

for example:

      ? memoize(factor,2^128+1)
      %3 = [59649589127497217,1;5704689200685129054721,1]
      ? ##
        ***   last result computed in 76 ms.
      ? memoize(factor,2^128+1)
      %4 = [59649589127497217,1;5704689200685129054721,1]
      ? ##
        ***   last result computed in 0 ms.
      ? memoize(ffinit,3,3)
      %5 = Mod(1,3)*x^3+Mod(1,3)*x^2+Mod(1,3)*x+Mod(2,3)
      ? fibo(n)=if(n==0,0,n==1,1,memoize(fibo,n-2)+memoize(fibo,n-1));
      ? fibo(100)
      %7 = 354224848179261915075

* to call operators through their internal names without using `alias`

      matnbelts(M) = call("_*_",matsize(M))

The library syntax is `GEN call0(GEN f, GEN A)`.

#### 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 se:defaults for an introduction to GP defaults, Section se:gp_defaults for a list of available defaults, and Section se:meta for some shortcut alternatives. Note that the shortcuts are meant for interactive use and usually display more information than `default`.

The library syntax is `GEN default0(const char *key = NULL, const char *val = NULL)`.

#### errname(E)

Returns the type of the error message `E` as a string.

The library syntax is `GEN errname(GEN E)`.

#### 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 output fed into `gp`, just as if read from a file.

The library syntax is `GEN gpextern(const char *str)`.

#### externstr(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 output is returned as a vector of GP strings, one component per output line.

The library syntax is `GEN externstr(const char *str)`.

#### fileclose(n)

Close the file descriptor n, created via `fileopen` or `fileextern`. Finitely many files can be opened at a given time, closing them recycles file descriptors and avoids running out of them:

      ? n = 0; while(n++, fileopen("/tmp/test", "w"))
       ***   at top-level: n=0;while(n++,fileopen("/tmp/test","w"))
       ***                               ^ —  —  —  —  —  —  —  — --
       *** fileopen: error opening requested file: `/tmp/test'.
       ***   Break loop: type 'break' to go back to GP prompt
      break> n
      65533

This is a limitation of the operating system and does not depend on PARI: if you open too many files in `gp` without closing them, the operating system will also prevent unrelated applications from opening files. Independently, your operating system (e.g. Windows) may prevent other applications from accessing or deleting your file while it is opened by `gp`. Quitting `gp` implicitly calls this function on all opened file descriptors.

On files opened for writing, this function also forces a write of all buffered data to the file system and completes all pending write operations. This function is implicitly called for all open file descriptors when exiting `gp` but it is cleaner and safer to call it explicitly, for instance in case of a `gp` crash or general system failure, which could cause data loss.

      ? n = fileopen("./here");
      ? while(l = fileread(n), print(l));
      ? fileclose(n);

      ? n = fileopen("./there", "w");
      ? for (i = 1, 100, filewrite(n, i^2+1))
      ? fileclose(n)

Until a `fileclose`, there is no guarantee that the file on disk contains all the expected data from previous `filewrite`s. (And even then the operating system may delay the actual write to hardware.)

Closing a file twice raises an exception:

      ? n = fileopen("/tmp/test");
      ? fileclose(n)
      ? fileclose(n)
       ***   at top-level: fileclose(n)
       ***                 ^ —  —  —  —
       *** fileclose: invalid file descriptor 0

The library syntax is `void gp_fileclose(long n)`.

#### fileextern(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 the function returns a file descriptor attached to the command output as if it were read from a file.

      ? n = fileextern("ls -l");
      ? while(l = filereadstr(n), print(l))
      ? fileclose(n)

If the `secure` default is set, this function will raise en exception.

The library syntax is `long gp_fileextern(const char *str)`.

#### fileflush({n})

Flushes the file descriptor n, created via `fileopen` or `fileextern`. On files opened for writing, this function forces a write of all buffered data to the file system and completes all pending write operations. This function is implicitly called by `fileclose` but you may want to call it explicitly at synchronization points, for instance after writing a large result to file and before printing diagnostics on screen. (In order to be sure that the file contains the expected content on inspection.)

If n is omitted, flush all descriptors to output streams.

      ? n = fileopen("./here", "w");
      ? for (i = 1, 10^5,      \
          filewrite(n, i^2+1); \
          if (i % 10000 == 0, fileflush(n)))

Until a `fileflush` or `fileclose`, there is no guarantee that the file contains all the expected data from previous `filewrite`s.

The library syntax is `void gp_fileflush0(GEN n = NULL)`. But the direct and more specific variant `void gp_fileflush(long n)` is also available.

#### fileopen(path, mode)

Open the file pointed to by 'path' and return a file descriptor which can be used with other file functions.

The mode can be

* `"r"` (default): open for reading; allow `fileread` and `filereadstr`.

* `"w"`: open for writing, discarding existing content; allow `filewrite`, `filewrite1`.

* `"a"`: open for writing, appending to existing content; same operations allowed as `"w"`.

Eventually, the file should be closed and the descriptor recycled using `fileclose`.

      ? n = fileopen("./here");  \\ "r" by default
      ? while (l = filereadstr(n), print(l))  \\ print successive lines
      ? fileclose(n) \\ done

In read mode, raise an exception if the file does not exist or the user does not have read permission. In write mode, raise an exception if the file cannot be written to. Trying to read or write to a file that was not opend with the right mode raises an exception.

      ? n = fileopen("./read", "r");
      ? filewrite(n, "test")      \\ not open for writing
       ***   at top-level: filewrite(n,"test")
       ***                 ^ —  —  —  —  —  — -
       *** filewrite: invalid file descriptor 0

The library syntax is `long gp_fileopen(const char *path, const char *mode)`.

#### fileread(n)

Read a logical line from the file attached to the descriptor n, opened for reading with `fileopen`. Return 0 at end of file.

A logical line is a full command as it is prepared by gp's preprocessor (skipping blanks and comments or assembling multiline commands between braces) before being fed to the interpreter. The function `filereadstr` would read a raw line exactly as input, up to the next carriage return `\n`.

Compare raw lines

      ? n = fileopen("examples/bench.gp");
      ? while(l = filereadstr(n), print(l));
      {
        u=v=p=q=1;
        for (k=1, 2000,
          [u,v] = [v,u+v];
          p *= v; q = lcm(q,v);
          if (k%50 == 0,
            print(k, " ", log(p)/log(q))
          )
        )
      }

and logical lines

      ? n = fileopen("examples/bench.gp");
      ? while(l = fileread(n), print(l));
      u=v=p=q=1;for(k=1,2000,[u,v]=[v,u+v];p*=v;q=lcm(q,v);[...]

The library syntax is `GEN gp_fileread(long n)`.

#### filereadstr(n)

Read a raw line from the file attached to the descriptor n, opened for reading with `fileopen`, discarding the terminating newline. In other words the line is read exactly as input, up to the next carriage return `\n`. By comparison, `fileread` would read a logical line, as assembled by gp's preprocessor (skipping blanks and comments for instance).

The library syntax is `GEN gp_filereadstr(long n)`.

#### filewrite(n, s)

Write the string s to the file attached to descriptor n, ending with a newline. The file must have been opened with `fileopen` in `"w"` or `"a"` mode. There is no guarantee that s is completely written to disk until `fileclose(n)` is executed, which is automatic when quitting `gp`.

If the newline is not desired, use `filewrite1`.

Variant. The high-level function `write` is expensive when many consecutive writes are expected because it cannot use buffering. The low-level interface `fileopen` / `filewrite` / `fileclose` is more efficient:

      ? f = "/tmp/bigfile";
      ? for (i = 1, 10^5, write(f, i^2+1))
      time = 240 ms.

      ? v = vector(10^5, i, i^2+1);
      time = 10 ms. \\ computing the values is fast
      ? write("/tmp/bigfile2",v)
      time = 12 ms. \\ writing them in one operation is fast

      ? n = fileopen("/tmp/bigfile", "w");
      ? for (i = 1, 10^5, filewrite(n, i^2+1))
      time = 24 ms.  \\ low-level write is ten times faster
      ? fileclose(n);

In the final example, the file needs not be in a consistent state until the ending `fileclose` is evaluated, e.g. some lines might be half-written or not present at all even though the corresponding `filewrite` was executed already. Both a single high-level `write` and a succession of low-level `filewrite`s achieve the same efficiency, but the latter is often more natural. In fact, concatenating naively the entries to be written is quadratic in the number of entries, hence much more expensive than the original write operations:

      ? v = []; for (i = 1, 10^5, v = concat(v,i))
      time = 1min, 41,456 ms.

The library syntax is `void gp_filewrite(long n, const char *s)`.

#### filewrite1(n, s)

Write the string s to the file attached to descriptor n. The file must have been opened with `fileopen` in `"w"` or `"a"` mode.

If you want to append a newline at the end of s, you can use `Str(s,"\n")` or `filewrite`.

The library syntax is `void gp_filewrite1(long n, const char *s)`.

#### fold(f, A)

Apply the `t_CLOSURE` `f` of arity 2 to the entries of `A`, in order to return `f(...f(f(A[1],A[2]),A[3])...,A[#A])`.

      ? fold((x,y)->x*y, [1,2,3,4])
      %1 = 24
      ? fold((x,y)->[x,y], [1,2,3,4])
      %2 = [[[1, 2], 3], 4]
      ? fold((x,f)->f(x), [2,sqr,sqr,sqr])
      %3 = 256
      ? fold((x,y)->(x+y)/(1-x*y),[1..5])
      %4 = -9/19
      ? bestappr(tan(sum(i=1,5,atan(i))))
      %5 = -9/19

The library syntax is `GEN fold0(GEN f, GEN A)`. Also available is `GEN genfold(void *E, GEN (*fun)(void*,GEN, GEN), GEN A)`.

#### getabstime()

Returns the CPU time (in milliseconds) elapsed since `gp` startup. This provides a reentrant version of `gettime`:

      my (t = getabstime());
      ...
      print("Time: ", getabstime() - t);

For a version giving wall-clock time, see `getwalltime`.

The library syntax is `long getabstime()`.

#### getenv(s)

Return the value of the environment variable `s` if it is defined, otherwise return 0.

The library syntax is `GEN gp_getenv(const char *s)`.

#### 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 `GEN getheap()`.

#### getrand()

Returns the current value of the seed used by the pseudo-random number generator `random`. Useful mainly for debugging purposes, to reproduce a specific chain of computations. The returned value is technical (reproduces an internal state array), and can only be used as an argument to `setrand`.

The library syntax is `GEN getrand()`.

#### getstack()

Returns the current value of `top`-`avma`, i.e. the number of bytes used up to now on the stack. Useful mainly for debugging purposes.

The library syntax is `long getstack()`.

#### gettime()

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

For a reentrant version, see `getabstime`.

For a version giving wall-clock time, see `getwalltime`.

The library syntax is `long gettime()`.

#### getwalltime()

Returns the time (in milliseconds) elapsed since 00:00:00 UTC Thursday 1, January 1970 (the Unix epoch).

      my (t = getwalltime());
      ...
      print("Time: ", getwalltime() - t);

The library syntax is `GEN getwalltime()`.

#### global(list of variables)

Obsolete. Scheduled for deletion.

#### inline(x, ..., z)

(Experimental) declare x,..., z as inline variables. Such variables behave like lexically scoped variable (see my()) but with unlimited scope. It is however possible to exit the scope by using `uninline()`. When used in a GP script, it is recommended to call `uninline()` before the script's end to avoid inline variables leaking outside the script.

#### 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 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).

The library syntax is `GEN gp_input()`.

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

Loads from dynamic library lib the function name. Assigns to it the name gpname in this `gp` session, with prototype code (see below). If gpname is omitted, uses name. If lib is omitted, all symbols known to `gp` are available: this includes the whole of `libpari.so` and possibly others (such as `libc.so`).

Most importantly, `install` 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 is eventually called by the `+` operator of course):

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

It also allows to add external functions to the `gp` interpreter. For instance, it makes the function `system` obsolete:

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

This works because `system` is part of `libc.so`, which is linked to `gp`. It is also possible to compile a shared library yourself and provide it to gp in this way: use `gp2c`, or do it manually (see the `modules_build` variable in `pari.cfg` for hints).

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

Prototype. We only give a simplified description here, covering most functions, but there are many more possibilities. The full documentation is available in `libpari.dvi`, see

        ??prototype

* First character `i`, `l`, `v` : return type int / long / void. (Default: `GEN`)

* One letter for each mandatory argument, in the same order as they appear in the argument list: `G` (`GEN`), `&` (`GEN*`), `L` (`long`), `s` (`char *`), `n` (variable).

* `p` to supply `realprecision` (usually `long prec` in the argument list), `P` to supply `seriesprecision` (usually `long precdl`).

We also have special constructs for optional arguments and default values:

* `DG` (optional `GEN`, `NULL` if omitted),

* `D&` (optional `GEN*`, `NULL` if omitted),

* `Dn` (optional variable, -1 if omitted),

For instance the prototype corresponding to

        long issquareall(GEN x, GEN *n = NULL)

is `lGD&`.

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 (this should never happen with a dynamically linked executable). If you intend to use this function, please check first on some harmless example such as the one above that it works properly on your machine.

The library syntax is `void gpinstall(const char *name, const char *code, const char *gpname, const char *lib)`.

#### kill(sym)

Restores the symbol `sym` to its "undefined" status, and deletes any help messages attached to `sym` using `addhelp`. Variable names remain known to the interpreter and keep their former priority: you cannot make a variable "less important" by killing it!

      ? z = y = 1; y
      %1 = 1
      ? kill(y)
      ? y            \\ restored to ``undefined'' status
      %2 = y
      ? variable()
      %3 = [x, y, z] \\ but the variable name y is still known, with y > z !

For the same reason, killing a user function (which is an ordinary variable holding a `t_CLOSURE`) does not remove its name from the list of variable names.

If the symbol is attached to a variable — user functions being an important special case — , one may use the quote operator `a = 'a` to reset variables to their starting values. However, this will not delete a help message attached to `a`, and is also slightly slower than `kill(a)`.

      ? x = 1; addhelp(x, "foo"); x
      %1 = 1
      ? x = 'x; x   \\ same as 'kill', except we don't delete help.
      %2 = x
      ? ?x
      foo

On the other hand, `kill` is the only way to remove aliases and installed functions.

      ? alias(fun, sin);
      ? kill(fun);

      ? install(addii, GG);
      ? kill(addii);

The library syntax is `void kill0(const char *sym)`.

#### listcreate({n})

This function is obsolete, use `List`.

Creates an empty list. This routine used to have a mandatory argument, which is now ignored (for backward compatibility).

#### listinsert(L, x, n)

Inserts the object x at position n in L (which must be of type `t_LIST`). This has complexity O(#L - n + 1): all the remaining elements of list (from position n+1 onwards) are shifted to the right.

The library syntax is `GEN listinsert(GEN L, GEN x, long n)`.

#### listkill(L)

Obsolete, retained for backward compatibility. Just use `L = List()` instead of `listkill(L)`. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns.

The library syntax is `void listkill(GEN L)`.

#### listpop(list, {n})

Removes the n-th element of the list list (which must be of type `t_LIST`). If n is omitted, or greater than the list current length, removes the last element. If the list is already empty, do nothing. This runs in time O(#L - n + 1).

The library syntax is `void listpop0(GEN list, long n)`.

#### listput(list, x, {n})

Sets the n-th element of the list list (which must be of type `t_LIST`) equal to x. If n is omitted, or greater than the list length, appends x. The function returns the inserted element.

      ? L = List();
      ? listput(L, 1)
      %2 = 1
      ? listput(L, 2)
      %3 = 2
      ? L
      %4 = List([1, 2])

You may put an element into an occupied cell (not changing the list length), but it is easier to use the standard `list[n] = x` construct.

      ? listput(L, 3, 1) \\ insert at position 1
      %5 = 3
      ? L
      %6 = List([3, 2])
      ? L[2] = 4 \\ simpler
      %7 = List([3, 4])
      ? L[10] = 1  \\ can't insert beyond the end of the list
       ***   at top-level: L[10]=1
       ***                  ^ —  —
       ***   non-existent component: index > 2
      ? listput(L, 1, 10) \\ but listput can
      %8 = 1
      ? L
      %9 = List([3, 2, 1])

This function runs in time O(#L) in the worst case (when the list must be reallocated), but in time O(1) on average: any number of successive `listput`s run in time O(#L), where #L denotes the list final length.

The library syntax is `GEN listput0(GEN list, GEN x, long n)`.

#### listsort(L, {flag = 0})

Sorts the `t_LIST` list in place, with respect to the (somewhat arbitrary) universal comparison function `cmp`. In particular, the ordering is the same as for sets and `setsearch` can be used on a sorted list.

      ? L = List([1,2,4,1,3,-1]); listsort(L); L
      %1 = List([-1, 1, 1, 2, 3, 4])
      ? setsearch(L, 4)
      %2 = 6
      ? setsearch(L, -2)
      %3 = 0

This is faster than the `vecsort` command since the list is sorted in place: no copy is made. No value returned.

If flag is non-zero, suppresses all repeated coefficients.

The library syntax is `void listsort(GEN L, long flag)`.

#### localbitprec(p)

Set the real precision to p bits in the dynamic scope. All computations are performed as if `realbitprecision` was p: transcendental constants (e.g. `Pi`) and conversions from exact to floating point inexact data use p bits, as well as iterative routines implicitly using a floating point accuracy as a termination criterion (e.g. `solve` or `intnum`). But `realbitprecision` itself is unaffected and is "unmasked" when we exit the dynamic (not lexical) scope. In effect, this is similar to

      my(bit = default(realbitprecision));
      default(realbitprecision,p);
      ...
      default(realbitprecision, bit);

but is both less cumbersome, cleaner (no need to manipulate a global variable, which in fact never changes and is only temporarily masked) and more robust: if the above computation is interrupted or an exception occurs, `realbitprecision` will not be restored as intended.

Such `localbitprec` statements can be nested, the innermost one taking precedence as expected. Beware that `localbitprec` follows the semantic of `local`, not `my`: a subroutine called from `localbitprec` scope uses the local accuracy:

      ? f()=bitprecision(1.0);
      ? f()
      %2 = 128
      ? localbitprec(1000); f()
      %3 = 1024

Note that the bit precision of data (`1.0` in the above example) increases by steps of 64 (32 on a 32-bit machine) so we get 1024 instead of the expected 1000; `localbitprec` bounds the relative error exactly as specified in functions that support that granularity (e.g. `lfun`), and rounded to the next multiple of 64 (resp. 32) everywhere else.

Warning. Changing `realbitprecision` or `realprecision` in programs is deprecated in favor of `localbitprec` and `localprec`. Think about the `realprecision` and `realbitprecision` defaults as interactive commands for the `gp` interpreter, best left out of GP programs. Indeed, the above rules imply that mixing both constructs yields surprising results:

      ? \p38
      ? localprec(19); default(realprecision,1000);  Pi
      %1 = 3.141592653589793239
      ? \p
        realprecision = 1001 significant digits (1000 digits displayed)

Indeed, `realprecision` itself is ignored within `localprec` scope, so `Pi` is computed to a low accuracy. And when we leave the `localprec` scope, `realprecision` only regains precedence, it is not "restored" to the original value.

#### localprec(p)

Set the real precision to p in the dynamic scope. All computations are performed as if `realprecision` was p: transcendental constants (e.g. `Pi`) and conversions from exact to floating point inexact data use p decimal digits, as well as iterative routines implicitly using a floating point accuracy as a termination criterion (e.g. `solve` or `intnum`). But `realprecision` itself is unaffected and is "unmasked" when we exit the dynamic (not lexical) scope. In effect, this is similar to

      my(prec = default(realprecision));
      default(realprecision,p);
      ...
      default(realprecision, prec);

but is both less cumbersome, cleaner (no need to manipulate a global variable, which in fact never changes and is only temporarily masked) and more robust: if the above computation is interrupted or an exception occurs, `realprecision` will not be restored as intended.

Such `localprec` statements can be nested, the innermost one taking precedence as expected. Beware that `localprec` follows the semantic of `local`, not `my`: a subroutine called from `localprec` scope uses the local accuracy:

      ? f()=precision(1.);
      ? f()
      %2 = 38
      ? localprec(19); f()
      %3 = 19

Warning. Changing `realprecision` itself in programs is now deprecated in favor of `localprec`. Think about the `realprecision` default as an interactive command for the `gp` interpreter, best left out of GP programs. Indeed, the above rules imply that mixing both constructs yields surprising results:

      ? \p38
      ? localprec(19); default(realprecision,100);  Pi
      %1 = 3.141592653589793239
      ? \p
          realprecision = 115 significant digits (100 digits displayed)

Indeed, `realprecision` itself is ignored within `localprec` scope, so `Pi` is computed to a low accuracy. And when we leave `localprec` scope, `realprecision` only regains precedence, it is not "restored" to the original value.

#### mapdelete(M, x)

Removes x from the domain of the map M.

      ? M = Map(["a",1; "b",3; "c",7]);
      ? mapdelete(M,"b");
      ? Mat(M)
      ["a" 1]

      ["c" 7]

The library syntax is `void mapdelete(GEN M, GEN x)`.

#### mapget(M, x)

Returns the image of x by the map M.

      ? M=Map(["a",23;"b",43]);
      ? mapget(M,"a")
      %2 = 23
      ? mapget(M,"b")
      %3 = 43

Raises an exception when the key x is not present in M.

      ? mapget(M,"c")
        ***   at top-level: mapget(M,"c")
        ***                 ^ —  —  —  — -
        *** mapget: non-existent component in mapget: index not in map

The library syntax is `GEN mapget(GEN M, GEN x)`.

#### mapisdefined(M, x, {&z})

Returns true (1) if `x` has an image by the map M, false (0) otherwise. If `z` is present, set `z` to the image of x, if it exists.

      ? M1 = Map([1, 10; 2, 20]);
      ? mapisdefined(M1,3)
      %1 = 0
      ? mapisdefined(M1, 1, &z)
      %2 = 1
      ? z
      %3 = 10

      ? M2 = Map(); N = 19;
      ? for (a=0, N-1, mapput(M2, a^3%N, a));
      ? {for (a=0, N-1,
           if (mapisdefined(M2, a, &b),
             printf("%d is the cube of %d mod %d\n",a,b,N)));}
      0 is the cube of 0 mod 19
      1 is the cube of 11 mod 19
      7 is the cube of 9 mod 19
      8 is the cube of 14 mod 19
      11 is the cube of 17 mod 19
      12 is the cube of 15 mod 19
      18 is the cube of 18 mod 19

The library syntax is `GEN mapisdefined(GEN M, GEN x, GEN *z = NULL)`.

#### mapput(M, x, y)

Associates x to y in the map M. The value y can be retrieved with `mapget`.

      ? M = Map();
      ? mapput(M, "foo", 23);
      ? mapput(M, 7718, "bill");
      ? mapget(M, "foo")
      %4 = 23
      ? mapget(M, 7718)
      %5 = "bill"
      ? Vec(M)  \\ keys
      %6 = [7718, "foo"]
      ? Mat(M)
      %7 =
      [ 7718 "bill"]

      ["foo"     23]

The library syntax is `void mapput(GEN M, GEN x, GEN y)`.

#### print({str}*)

Outputs its arguments in raw format ending with a newline. The arguments are converted to strings following the rules in Section se:strings.

      ? m = matid(2);
      ? print(m)  \\ raw format
      [1, 0; 0, 1]
      ? printp(m) \\ prettymatrix format

      [1 0]

      [0 1]

#### print1({str}*)

Outputs its arguments in raw format, without ending with a newline. Note that you can still embed newlines within your strings, using the `\n` notation ! The arguments are converted to strings following the rules in Section se:strings.

#### printf(fmt, {x}*)

This function is based on the C library command of the same name. It prints its arguments according to the format fmt, which specifies how subsequent arguments are converted for output. The format is a character string composed of zero or more directives:

* ordinary characters (not `%`), printed unchanged,

* conversions specifications (`%` followed by some characters) which fetch one argument from the list and prints it according to the specification.

More precisely, a conversion specification consists in a `%`, one or more optional flags (among `#`, `0`, `-`, `+`, ` '), an optional decimal digit string specifying a minimal field width, an optional precision in the form of a period (``.`') followed by a decimal digit string, and the conversion specifier (among `d`,`i`, `o`, `u`, `x`,`X`, `p`, `e`,`E`, `f`, `g`,`G`, `s`).

The flag characters. The character `%` is followed by zero or more of the following flags:

* `#`: the value is converted to an "alternate form". For `o` conversion (octal), a `0` is prefixed to the string. For `x` and `X` conversions (hexa), respectively `0x` and `0X` are prepended. For other conversions, the flag is ignored.

* `0`: the value should be zero padded. For `d`, `i`, `o`, `u`, `x`, `X` `e`, `E`, `f`, `F`, `g`, and `G` conversions, the value is padded on the left with zeros rather than blanks. (If the `0` and `-` flags both appear, the `0` flag is ignored.)

* `-`: the value is left adjusted on the field boundary. (The default is right justification.) The value is padded on the right with blanks, rather than on the left with blanks or zeros. A `-` overrides a `0` if both are given.

* `` '` (a space): a blank is left before a positive number produced by a signed conversion.

* `+`: a sign (+ or -) is placed before a number produced by a signed conversion. A `+` overrides a space if both are used.

The field width. An optional decimal digit string (whose first digit is non-zero) specifying a minimum field width. If the value has fewer characters than the field width, it is padded with spaces on the left (or right, if the left-adjustment flag has been given). In no case does a small field width cause truncation of a field; if the value is wider than the field width, the field is expanded to contain the conversion result. Instead of a decimal digit string, one may write `*` to specify that the field width is given in the next argument.

The precision. An optional precision in the form of a period (``.`') followed by a decimal digit string. This gives the number of digits to appear after the radix character for `e`, `E`, `f`, and `F` conversions, the maximum number of significant digits for `g` and `G` conversions, and the maximum number of characters to be printed from an `s` conversion. Instead of a decimal digit string, one may write `*` to specify that the field width is given in the next argument.

The length modifier. This is ignored under `gp`, but necessary for `libpari` programming. Description given here for completeness:

* `l`: argument is a `long` integer.

* `P`: argument is a `GEN`.

The conversion specifier. A character that specifies the type of conversion to be applied.

* `d`, `i`: a signed integer.

* `o`, `u`, `x`, `X`: an unsigned integer, converted to unsigned octal (`o`), decimal (`u`) or hexadecimal (`x` or `X`) notation. The letters `abcdef` are used for `x` conversions; the letters `ABCDEF` are used for `X` conversions.

* `e`, `E`: the (real) argument is converted in the style `[ -]d.ddd e[ -]dd`, where there is one digit before the decimal point, and the number of digits after it is equal to the precision; if the precision is missing, use the current `realprecision` for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. An `E` conversion uses the letter `E` rather than `e` to introduce the exponent.

* `f`, `F`: the (real) argument is converted in the style `[ -]ddd.ddd`, where the number of digits after the decimal point is equal to the precision; if the precision is missing, use the current `realprecision` for the total number of printed digits. If the precision is explicitly 0, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.

* `g`, `G`: the (real) argument is converted in style `e` or `f` (or `E` or `F` for `G` conversions) `[ -]ddd.ddd`, where the total number of digits printed is equal to the precision; if the precision is missing, use the current `realprecision`. If the precision is explicitly 0, it is treated as 1. Style `e` is used when the decimal exponent is < -4, to print `0.`, or when the integer part cannot be decided given the known significant digits, and the `f` format otherwise.

* `c`: the integer argument is converted to an unsigned char, and the resulting character is written.

* `s`: convert to a character string. If a precision is given, no more than the specified number of characters are written.

* `p`: print the address of the argument in hexadecimal (as if by `%#x`).

* `%`: a `%` is written. No argument is converted. The complete conversion specification is `%%`.

Examples:

      ? printf("floor: %d, field width 3: %3d, with sign: %+3d\n", Pi, 1, 2);
      floor: 3, field width 3:   1, with sign:  +2

      ? printf("%.5g %.5g %.5g\n",123,123/456,123456789);
      123.00 0.26974 1.2346 e8

      ? printf("%-2.5s:%2.5s:%2.5s\n", "P", "PARI", "PARIGP");
      P :PARI:PARIG

      \\ min field width and precision given by arguments
      ? x = 23; y=-1/x; printf("x=%+06.2f y=%+0*.*f\n", x, 6, 2, y);
      x=+23.00 y=-00.04

      \\ minimum fields width 5, pad left with zeroes
      ? for (i = 2, 5, printf("%05d\n", 10^i))
      00100
      01000
      10000
      100000  \\  don't truncate fields whose length is larger than the minimum width
      ? printf("%.2f  |%06.2f|", Pi,Pi)
      3.14  |  3.14|

All numerical conversions apply recursively to the entries of vectors and matrices:

      ? printf("%4d", [1,2,3]);
      [   1,   2,   3]
      ? printf("%5.2f", mathilbert(3));
      [ 1.00  0.50  0.33]

      [ 0.50  0.33  0.25]

      [ 0.33  0.25  0.20]

Technical note. Our implementation of `printf` deviates from the C89 and C99 standards in a few places:

* whenever a precision is missing, the current `realprecision` is used to determine the number of printed digits (C89: use 6 decimals after the radix character).

* in conversion style `e`, we do not impose that the exponent has at least two digits; we never write a `+` sign in the exponent; 0 is printed in a special way, always as `0.Eexp`.

* in conversion style `f`, we switch to style `e` if the exponent is greater or equal to the precision.

* in conversion `g` and `G`, we do not remove trailing zeros from the fractional part of the result; nor a trailing decimal point; 0 is printed in a special way, always as `0.Eexp`.

#### printp({str}*)

Outputs its arguments in prettymatrix format, ending with a newline. The arguments are converted to strings following the rules in Section se:strings.

      ? m = matid(2);
      ? print(m)  \\ raw format
      [1, 0; 0, 1]
      ? printp(m) \\ prettymatrix format

      [1 0]

      [0 1]

#### printsep(sep, {str}*)

Outputs its arguments in raw format, ending with a newline. The arguments are converted to strings following the rules in Section se:strings. Successive entries are separated by sep:

      ? printsep(":", 1,2,3,4)
      1:2:3:4

#### printsep1(sep, {str}*)

Outputs its arguments in raw format, without ending with a newline. The arguments are converted to strings following the rules in Section se:strings. Successive entries are separated by sep:

      ? printsep1(":", 1,2,3,4);print("|")
      1:2:3:4|

#### printtex({str}*)

Outputs its arguments in TeX format. This output can then be used in a TeX manuscript. The arguments are converted to strings following the rules in Section se:strings. 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 (see Section se:defaults). You could for instance do:

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

#### quit({status = 0})

Exits `gp` and return to the system with exit status `status`, a small integer. A non-zero exit status normally indicates abnormal termination. (Note: the system actually sees only `status` mod 256, see your man pages for `exit(3)` or `wait(2)`).

#### 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 se:writebin), the file is loaded and the last object in the file is returned.

In case the file you read in contains an `allocatemem` statement (to be generally avoided), you should leave `read` instructions by themselves, and not part of larger instruction sequences.

Variants. `readvec` allows to read a whole file at once; `fileopen` followed by either `fileread` (evaluated lines) or `filereadstr` (lines as non-evaluated strings) allows to read a file one line at a time.

The library syntax is `GEN gp_read_file(const char *filename)`.

#### readstr({filename})

Reads in the file filename and return a vector of GP strings, each component containing one line from the file. If filename is omitted, re-reads the last file that was fed into `gp`.

The library syntax is `GEN readstr(const char *filename)`.

#### readvec({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 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.

The library syntax is `GEN gp_readvec_file(const char *filename)`. The underlying library function `GEN gp_readvec_stream(FILE *f)` is usually more flexible.

#### select(f, A, {flag = 0})

We first describe the default behavior, when flag is 0 or omitted. Given a vector or list `A` and a `t_CLOSURE` `f`, `select` returns the elements x of `A` such that f(x) is non-zero. In other words, `f` is seen as a selection function returning a boolean value.

      ? select(x->isprime(x), vector(50,i,i^2+1))
      %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]
      ? select(x->(x<100), %)
      %2 = [2, 5, 17, 37]

returns the primes of the form i^2+1 for some i ≤ 50, then the elements less than 100 in the preceding result. The `select` function also applies to a matrix `A`, seen as a vector of columns, i.e. it selects columns instead of entries, and returns the matrix whose columns are the selected ones.

Remark. For v a `t_VEC`, `t_COL`, `t_LIST` or `t_MAT`, the alternative set-notations

      [g(x) | x <- v, f(x)]
      [x | x <- v, f(x)]
      [g(x) | x <- v]

are available as shortcuts for

      apply(g, select(f, Vec(v)))
      select(f, Vec(v))
      apply(g, Vec(v))

respectively:

      ? [ x | x <- vector(50,i,i^2+1), isprime(x) ]
      %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]

If flag = 1, this function returns instead the indices of the selected elements, and not the elements themselves (indirect selection):

      ? V = vector(50,i,i^2+1);
      ? select(x->isprime(x), V, 1)
      %2 = Vecsmall([1, 2, 4, 6, 10, 14, 16, 20, 24, 26, 36, 40])
      ? vecextract(V, %)
      %3 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]

The following function lists the elements in (ℤ/Nℤ)*:

      ? invertibles(N) = select(x->gcd(x,N) == 1, [1..N])

Finally

      ? select(x->x, M)

selects the non-0 entries in `M`. If the latter is a `t_MAT`, we extract the matrix of non-0 columns. Note that removing entries instead of selecting them just involves replacing the selection function `f` with its negation:

      ? select(x->!isprime(x), vector(50,i,i^2+1))

The library syntax is `genselect(void *E, long (*fun)(void*,GEN), GEN a)`. Also available is `GEN genindexselect(void *E, long (*fun)(void*, GEN), GEN a)`, corresponding to flag = 1.

#### self()

Return the calling function or closure as a `t_CLOSURE` object. This is useful for defining anonymous recursive functions.

      ? (n->if(n==0,1,n*self()(n-1)))(5)
      %1 = 120

The library syntax is `GEN pari_self()`.

#### setrand(n)

Reseeds the random number generator using the seed n. No value is returned. The seed is a small positive integer 0 < n < 264 used to generate deterministically a suitable state array. All gp session start by an implicit `setrand(1)`, so resetting the seed to this value allows to replay all computations since the session start. Alternatively, running a randomized computation starting by `setrand`(n) twice with the same n will generate the exact same output.

In the other direction, including a call to `setrand(getwalltime())` from your gprc will cause GP to produce different streams of random numbers in each session. (Unix users may want to use `/dev/urandom` instead of `getwalltime`.)

For debugging purposes, one can also record a particular random state using `getrand` (the value is encoded as a huge integer) and feed it to `setrand`:

      ? state = getrand(); \\ record seed
      ...
      ? setrand(state); \\ we can now replay the exact same computations

The library syntax is `void setrand(GEN 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.

The library syntax is `void gpsystem(const char *str)`.

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

This function is obsolete, use `iferr`, which has a nicer and much more powerful interface. For compatibility's sake we now describe the obsolete function `trap`.

This function tries to evaluate seq, trapping runtime 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. See Section se:errorrec for an introduction to error recovery under `gp`.

      ? \\  trap division by 0
      ? inv(x) = trap (e_INV, INFINITY, 1/x)
      ? inv(2)
      %1 = 1/2
      ? inv(0)
      %2 = INFINITY

Note that seq is effectively evaluated up to the point that produced the error, and the recovery sequence is evaluated starting from that same context, it does not "undo" whatever happened in the other branch (restore the evaluation context):

      ? x = 1; trap (, /* recover: */ x, /* try: */ x = 0; 1/x)
      %1 = 0

Note. The interface is currently not adequate for trapping individual exceptions. In the current version 2.12.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`):

`e_ALARM`: alarm time-out

`e_ARCH`: not available on this architecture or operating system

`e_STACK`: the PARI stack overflows

`e_INV`: impossible inverse

`e_IMPL`: not yet implemented

`e_OVERFLOW`: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle).

`e_SYNTAX`: syntax error

`e_MISC`: miscellaneous error

`e_TYPE`: wrong type

`e_USER`: user error (from the `error` function)

The library syntax is `GEN trap0(const char *e = NULL, GEN rec = NULL, GEN seq = NULL)`.

#### 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 `GEN type0(GEN x)`. The macro `typ` is usually simpler to use since it returns a `long` that can easily be matched with the symbols `t_*`. The name `type` was avoided since it is a reserved identifier for some compilers.

#### uninline()

(Experimental) Exit the scope of all current `inline` variables.

#### version()

Returns the current version number as a `t_VEC` with three integer components (major version number, minor version number and patchlevel); if your sources were obtained through our version control system, this will be followed by further more precise arguments, including e.g. a `git` commit hash.

This function is present in all versions of PARI following releases 2.3.4 (stable) and 2.4.3 (testing).

Unless you are working with multiple development versions, you probably only care about the 3 first numeric components. In any case, the `lex` function offers a clever way to check against a particular version number, since it will compare each successive vector entry, numerically or as strings, and will not mind if the vectors it compares have different lengths:

         if (lex(version(), [2,3,5]) >= 0,
           \\ code to be executed if we are running 2.3.5 or more recent.
         ,
           \\ compatibility code
         );

On a number of different machines, `version()` could return either of

       %1 = [2, 3, 4]    \\ released version, stable branch
       %1 = [2, 4, 3]    \\ released version, testing branch
       %1 = [2, 6, 1, 15174, ""505ab9b"] \\ development

In particular, if you are only working with released versions, the first line of the gp introductory message can be emulated by

         [M,m,p] = version();
         printf("GP/PARI CALCULATOR Version %s.%s.%s", M,m,p);

If you are working with many development versions of PARI/GP, the 4th and/or 5th components can be profitably included in the name of your logfiles, for instance.

Technical note. For development versions obtained via `git`, the 4th and 5th components are liable to change eventually, but we document their current meaning for completeness. The 4th component counts the number of reachable commits in the branch (analogous to `svn`'s revision number), and the 5th is the `git` commit hash. In particular, `lex` comparison still orders correctly development versions with respect to each others or to released versions (provided we stay within a given branch, e.g. `master`)!

The library syntax is `GEN pari_version()`.

#### warning({str}*)

Outputs the message "user warning" and the argument list (each of them interpreted as a string). If colors are enabled, this warning will be in a different color, making it easy to distinguish.

      warning(n, " is very large, this might take a while.")

#### whatnow(key)

If keyword key is the name of a function that was present in GP version 1.39.15, outputs the new function name and syntax, if it changed at all. Functions that where introduced since then, then modified are also recognized.

      ? whatnow("mu")
      New syntax: mu(n) ===> moebius(n)

      moebius(x): Moebius function of x.

      ? whatnow("sin")
      This function did not change

When a function was removed and the underlying functionality is not available under a compatible interface, no equivalent is mentioned:

      ? whatnow("buchfu")
      This function no longer exists

(The closest equivalent would be to set `K = bnfinit(T)` then access `K.fu`.)

#### write(filename, {str}*)

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

Variant. The high-level function `write` is expensive when many consecutive writes are expected because it cannot use buffering. The low-level interface `fileopen` / `filewrite` / `fileclose` is more efficient.

#### 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 as `tn` for some integer n (the attached variable number). Installed functions and history objects can not be saved via this function.

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 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.

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).

The library syntax is `void gpwritebin(const char *filename, GEN x = NULL)`.

#### writetex(filename, {str}*)

As `write`, in TeX format.