Although plotting is not even a side purpose of PARI, a number of plotting functions are provided. Moreover, a lot of people suggested ideas or submitted patches for this section of the code. There are three types of graphic functions.

(all the functions starting with
`ploth`

) in which the user has little to do but explain what type of plot
he wants, and whose syntax is similar to the one used in the preceding
section.

(called *rectplot* functions,
sharing the prefix `plot`

), where every drawing primitive (point, line,
box, etc.) is specified by the user. These low-level functions work as
follows. You have at your disposal 16 virtual windows which are filled
independently, and can then be physically ORed on a single window at
user-defined positions. These windows are numbered from 0 to 15, and must be
initialized before being used by the function `plotinit`

, which specifies
the height and width of the virtual window (called a *rectwindow* in the
sequel). At all times, a virtual cursor (initialized at [0,0]) is attached
to the window, and its current value can be obtained using the function
`plotcursor`

.

A number of primitive graphic objects (called *rect* objects) can then
be drawn in these windows, using a default color attached to that window
(which can be changed using the `plotcolor`

function) and only the part
of the object which is inside the window will be drawn, with the exception of
polygons and strings which are drawn entirely. The ones sharing the prefix
`plotr`

draw relatively to the current position of the virtual cursor,
the others use absolute coordinates. Those having the prefix `plotrecth`

put in the rectwindow a large batch of rect objects corresponding to the
output of the related `ploth`

function.

Finally, the actual physical drawing is done using `plotdraw`

. The
rectwindows are preserved so that further drawings using the same windows at
different positions or different windows can be done without extra work. To
erase a window, use `plotkill`

. It is not possible to partially erase a
window: erase it completely, initialize it again, then fill it with the
graphic objects that you want to keep.

In addition to initializing the window, you may use a scaled window to
avoid unnecessary conversions. For this, use `plotscale`

. As long as this
function is not called, the scaling is simply the number of pixels, the
origin being at the upper left and the y-coordinates going downwards.

Plotting functions are platform independent, but a number of graphical
drivers are available for screen output: X11-windows (hence also for GUI's
based on X11 such as Openwindows and Motif), and the Qt and FLTK graphical
libraries. The physical window opened by `plotdraw`

or any of the
`ploth*`

functions is completely separated from `gp`

(technically, a
`fork`

is done, and the non-graphical memory is immediately freed in the
child process), which means you can go on working in the current `gp`

session, without having to kill the window first. This window can be closed,
enlarged or reduced using the standard window manager functions. No zooming
procedure is implemented though (yet).

in the same way that `printtex`

allows you to have a TeX output
corresponding to printed results, the functions starting with `ps`

allow
you to have `PostScript`

output of the plots. This will not be identical
with the screen output, but sufficiently close. Note that you can use
PostScript output even if you do not have the plotting routines enabled. The
PostScript output is written in a file whose name is derived from the
`psfile`

default (`./pari.ps`

if you did not tamper with it). Each
time a new PostScript output is asked for, the PostScript output is appended
to that file. Hence you probably want to remove this file, or change the
value of `psfile`

, in between plots. On the other hand, in this manner,
as many plots as desired can be kept in a single file.

*None of the graphic functions are available
within the PARI library, you must be under gp to use them*. The reason
for that is that you really should not use PARI for heavy-duty graphical work,
there are better specialized alternatives around. This whole set of routines
was only meant as a convenient, but simple-minded, visual aid. If you really
insist on using these in your program (we warned you), the source
(

`plot*.c`

) should be readable enough for you to achieve something.

Crude ASCII plot of the function represented by expression *expr*
from a to b, with *Y* ranging from *Ymin* to *Ymax*. If
*Ymin* (resp. *Ymax*) is not given, the minimum (resp. the maximum)
of the computed values of the expression is used instead.

The library syntax is `void `

.**pariplot**(GEN X, GEN b, GEN expr, GEN Ymin = NULL, GEN Ymax = NULL, long prec)

Let (x1,y1) be the current position of the virtual cursor. Draw in the
rectwindow w the outline of the rectangle which is such that the points
(x1,y1) and (x2,y2) are opposite corners. Only the part of the rectangle
which is in w is drawn. The virtual cursor does *not* move.

`clips' the content of rectwindow w, i.e remove all parts of the
drawing that would not be visible on the screen. Together with
`plotcopy`

this function enables you to draw on a scratchpad before
committing the part you're interested in to the final picture.

Set default color to c in rectwindow w.
This is only implemented for the X-windows, fltk and Qt graphing engines.
Possible values for c are given by the `graphcolormap`

default,
factory setting are

1 = black, 2 = blue, 3 = violetred, 4 = red, 5 = green, 6 = grey, 7 = gainsborough.

but this can be considerably extended.

Copy the contents of rectwindow *sourcew* to rectwindow *destw*
with offset (dx,dy). If flag's bit 1 is set, dx and dy express fractions of
the size of the current output device, otherwise dx and dy are in pixels. dx
and dy are relative positions of northwest corners if other bits of flag
vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners

Give as a 2-component vector the current (scaled) position of the virtual cursor corresponding to the rectwindow w.

Physically draw the rectwindows given in list
which must be a vector whose number of components is divisible by 3. If
list = [w1,x1,y1,w2,x2,y2,...], the windows w1, w2, etc. are
physically placed with their upper left corner at physical position
(x1,y1), (x2,y2),...respectively, and are then drawn together.
Overlapping regions will thus be drawn twice, and the windows are considered
transparent. Then display the whole drawing in a special window on your
screen. If *flag* != 0, x1, y1 etc. express fractions of the size of the
current output device

High precision plot of the function y = f(x) represented by the expression
*expr*, x going from a to b. This opens a specific window (which is
killed whenever you click on it), and returns a four-component vector giving
the coordinates of the bounding box in the form
[*xmin*,*xmax*,*ymin*,*ymax*].

**Important note.** `ploth`

may evaluate `expr`

thousands of
times; given the relatively low resolution of plotting devices, few
significant digits of the result will be meaningful. Hence you should keep
the current precision to a minimum (e.g. 9) before calling this function.

n specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values (1000 for general plot, 1500 for parametric plot, and 8 for recursive plot).

If no *flag* is given, *expr* is either a scalar expression f(X), in which
case the plane curve y = f(X) will be drawn, or a vector
[f_1(X),...,f_k(X)], and then all the curves y = f_i(X) will be drawn in
the same window.

The binary digits of *flag* mean:

***** 1 = `Parametric`

: *parametric plot*. Here *expr* must
be a vector with an even number of components. Successive pairs are then
understood as the parametric coordinates of a plane curve. Each of these are
then drawn.

For instance:

ploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") ploth(X=0,2*Pi,[sin(X),cos(X)]) ploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric")

draw successively a circle, two entwined sinusoidal curves and a circle cut by the line y = x.

***** 2 = `Recursive`

: *recursive plot*. If this flag is set,
only *one* curve can be drawn at a time, i.e. *expr* must be either a
two-component vector (for a single parametric curve, and the parametric flag
*has* to be set), or a scalar function. The idea is to choose pairs of
successive reference points, and if their middle point is not too far away
from the segment joining them, draw this as a local approximation to the
curve. Otherwise, add the middle point to the reference points. This is
fast, and usually more precise than usual plot. Compare the results of

ploth(X=-1,1, sin(1/X), "Recursive") ploth(X=-1,1, sin(1/X))

for instance. But beware that if you are extremely unlucky, or choose too few
reference points, you may draw some nice polygon bearing little resemblance
to the original curve. For instance you should *never* plot recursively
an odd function in a symmetric interval around 0. Try

ploth(x = -20, 20, sin(x), "Recursive")

to see why. Hence, it's usually a good idea to try and plot the same curve with slightly different parameters.

The other values toggle various display options:

***** 4 = `no_Rescale`

: do not rescale plot according to the
computed extrema. This is used in conjunction with `plotscale`

when
graphing multiple functions on a rectwindow (as a `plotrecth`

call):

s = plothsizes(); plotinit(0, s[2]-1, s[2]-1); plotscale(0, -1,1, -1,1); plotrecth(0, t=0,2*Pi, [cos(t),sin(t)], "Parametric|no_Rescale") plotdraw([0, -1,1]);

This way we get a proper circle instead of the distorted ellipse produced by

ploth(t=0,2*Pi, [cos(t),sin(t)], "Parametric")

***** 8 = `no_X_axis`

: do not print the x-axis.

***** 16 = `no_Y_axis`

: do not print the y-axis.

***** 32 = `no_Frame`

: do not print frame.

***** 64 = `no_Lines`

: only plot reference points, do not join them.

***** 128 = `Points_too`

: plot both lines and points.

***** 256 = `Splines`

: use splines to interpolate the points.

***** 512 = `no_X_ticks`

: plot no x-ticks.

***** 1024 = `no_Y_ticks`

: plot no y-ticks.

***** 2048 = `Same_ticks`

: plot all ticks with the same length.

***** 4096 = `Complex`

: is a parametric plot but where each member of
`expr`

is considered a complex number encoding the two coordinates of a
point. For instance:

ploth(X=0,2*Pi,exp(I*X), "Complex") ploth(X=0,2*Pi,[(1+I)*X,exp(I*X)], "Complex")

will draw respectively a circle and a circle cut by the line y = x.

Given *listx* and *listy* two vectors of equal length, plots (in
high precision) the points whose (x,y)-coordinates are given in
*listx* and *listy*. Automatic positioning and scaling is done, but
with the same scaling factor on x and y. If *flag* is 1, join points,
other non-0 flags toggle display options and should be combinations of bits
2^k, k ≥ 3 as in `ploth`

.

Return data corresponding to the output window
in the form of a 6-component vector: window width and height, sizes for ticks
in horizontal and vertical directions (this is intended for the `gnuplot`

interface and is currently not significant), width and height of characters.

If *flag* = 0, sizes of ticks and characters are in
pixels, otherwise are fractions of the screen size

Initialize the rectwindow w,
destroying any rect objects you may have already drawn in w. The virtual
cursor is set to (0,0). The rectwindow size is set to width x and height
y; omitting either x or y means we use the full size of the device
in that direction.
If *flag* = 0, x and y represent pixel units. Otherwise, x and y
are understood as fractions of the size of the current output device (hence
must be between 0 and 1) and internally converted to pixels.

The plotting device imposes an upper bound for x and y, for instance the
number of pixels for screen output. These bounds are available through the
`plothsizes`

function. The following sequence initializes in a portable
way (i.e independent of the output device) a window of maximal size, accessed
through coordinates in the [0,1000] x [0,1000] range:

s = plothsizes(); plotinit(0, s[1]-1, s[2]-1); plotscale(0, 0,1000, 0,1000);

Erase rectwindow w and free the corresponding memory. Note that if you
want to use the rectwindow w again, you have to use `plotinit`

first
to specify the new size. So it's better in this case to use `plotinit`

directly as this throws away any previous work in the given rectwindow.

Draw on the rectwindow w
the polygon such that the (x,y)-coordinates of the vertices are in the
vectors of equal length X and Y. For simplicity, the whole
polygon is drawn, not only the part of the polygon which is inside the
rectwindow. If *flag* is non-zero, close the polygon. In any case, the
virtual cursor does not move.

X and Y are allowed to be scalars (in this case, both have to).
There, a single segment will be drawn, between the virtual cursor current
position and the point (X,Y). And only the part thereof which
actually lies within the boundary of w. Then *move* the virtual cursor
to (X,Y), even if it is outside the window. If you want to draw a
line from (x1,y1) to (x2,y2) where (x1,y1) is not necessarily the
position of the virtual cursor, use `plotmove(w,x1,y1)`

before using this
function.

This function is obsolete and currently a no-op.

Change the type of lines subsequently plotted in rectwindow w.
*type* -2 corresponds to frames, -1 to axes, larger values may
correspond to something else. w = -1 changes highlevel plotting.

Move the virtual cursor of the rectwindow w to position (x,y).

Draw on the rectwindow w the
points whose (x,y)-coordinates are in the vectors of equal length X and
Y and which are inside w. The virtual cursor does *not* move. This
is basically the same function as `plothraw`

, but either with no scaling
factor or with a scale chosen using the function `plotscale`

.

As was the case with the `plotlines`

function, X and Y are allowed to
be (simultaneously) scalar. In this case, draw the single point (X,Y) on
the rectwindow w (if it is actually inside w), and in any case
*move* the virtual cursor to position (x,y).

This function is obsolete. It is currently a no-op.

Changes the "size" of following points in rectwindow w. If w = -1, change it in all rectwindows.

This function is obsolete and currently a no-op.

change the type of points subsequently plotted in rectwindow w.
*type* = -1 corresponds to a dot, larger values may correspond to
something else. w = -1 changes highlevel plotting.

Draw in the rectwindow w the outline of the rectangle which is such
that the points (x1,y1) and (x1+dx,y1+dy) are opposite corners, where
(x1,y1) is the current position of the cursor. Only the part of the
rectangle which is in w is drawn. The virtual cursor does *not* move.

Writes to rectwindow w the curve output of
`ploth`

(w,X = a,b,*expr*,*flag*,n). Returns a vector for the bounding box.

Plot graph(s) for
*data* in rectwindow w. *flag* has the same significance here as in
`ploth`

, though recursive plot is no more significant.

*data* is a vector of vectors, each corresponding to a list a coordinates.
If parametric plot is set, there must be an even number of vectors, each
successive pair corresponding to a curve. Otherwise, the first one contains
the x coordinates, and the other ones contain the y-coordinates
of curves to plot.

Draw in the rectwindow w the part of the segment (x1,y1)-(x1+dx,y1+dy) which is inside w, where (x1,y1) is the current position of the virtual cursor, and move the virtual cursor to (x1+dx,y1+dy) (even if it is outside the window).

Move the virtual cursor of the rectwindow w to position (x1+dx,y1+dy), where (x1,y1) is the initial position of the cursor (i.e. to position (dx,dy) relative to the initial cursor).

Draw the point (x1+dx,y1+dy) on the rectwindow w (if it is inside w), where (x1,y1) is the current position of the cursor, and in any case move the virtual cursor to position (x1+dx,y1+dy).

Scale the local coordinates of the rectwindow w so that x goes from
x1 to x2 and y goes from y1 to y2 (x2 < x1 and y2 < y1 being
allowed). Initially, after the initialization of the rectwindow w using
the function `plotinit`

, the default scaling is the graphic pixel count,
and in particular the y axis is oriented downwards since the origin is at
the upper left. The function `plotscale`

allows to change all these
defaults and should be used whenever functions are graphed.

Draw on the rectwindow w the String x (see Section se:strings), at the current position of the cursor.

*flag* is used for justification: bits 1 and 2 regulate horizontal alignment:
left if 0, right if 2, center if 1. Bits 4 and 8 regulate vertical
alignment: bottom if 0, top if 8, v-center if 4. Can insert additional small
gap between point and string: horizontal if bit 16 is set, vertical if bit
32 is set (see the tutorial for an example).

Same as `plotdraw`

, except that the output is a PostScript program
appended to the `psfile`

, and flag != 0 scales the plot from size of the
current output device to the standard PostScript plotting size

Same as `ploth`

, except that the output is a PostScript program
appended to the `psfile`

.

Same as `plothraw`

, except that the output is a PostScript program
appended to the `psfile`

.