Programming Gri

1: Introduction
2: Simple example
3: Fancy example
4: Running Gri
5: Programming Gri
6: General Issues
7: X-Y Plots
8: Contour Plots
9: Image Plots
10: Examples
11: Handling Data
12: Gri Commands
13: Gri Extras
14: Evolution of Gri
15: Installing Gri
16: Gri Bugs
17: System Tools
18: Acknowledgments
19: License
20: Newsgroup

21: Concept Index

5.8: Built-in rpn Calculator

Gri can do simple mathematics on numbers. The syntax is reverse-polish notation (`rpn'), which is used in some calculators. Most users can learn rpn in a few minutes, so don't worry if you don't know RPN yet.

syntax rpn expressions can be used anywhere Gri expects a number. RPN expressions start with a opening curly brace (`{') which is immediately followed by the word `rpn'. rpn expressions end with a closing curly brace (`}'). Instead of `set x size 10' you could write `set x size {rpn 20 2 /}', where the expression `{rpn 20 2 /}' tells Gri to insert the number 20 onto a stack, then insert the number 2 above it on the stack, and then divide the top two items on the stack. The following are equivalent:
set x size {rpn 20 2 /}           # 10 = 20/2
set x size {rpn 30 2 / 5 -}       # 10 = (30/2-5)
set x size {rpn pi 3.1415 / 10 *} # 10 = 10*pi/pi

RPN operations can be divided roughly into the following groups.

5.8.1: Stack Operators

Stack operators manipulate or display the stack. `pop' removes the top item from the stack, `dup' duplicates the top item on the stack, `exch' reorders the top two items on the stack, `pstack' prints the items on the stack (without changing the stack), `roll_right' rolls the items to the right and `roll_left' rolls the items to the left, e.g.
# following yields [4 1 2 3] on the stack
{rpn 1 2 3 4 roll_right pstack}

5.8.2: Rpn function Operators

`rpnfunction' operators are user-defined operators. The parser replaces any such operator with the user-defined rpn expression. The `rpnfunction' operators are both general and powerful. An `rpnfunction' may be composed of any legal primitive rpn constructs or even other legal `rpnfunction' constructs. For details, see Rpnfunction.

5.8.3: rpn constants

Gri knows the values `pi' = 3.141..., `e' = 2.718.... These are defined near the end of the startup file `gri.cmd' as `rpnfunction' commands see Rpnfunction. To add more builtin constants, follow the same `rpnfunction' procedure.

5.8.4: Testing for Existence of Files, Variables, and Synonym

The `defined' operator checks whether synonyms or variables are defined, e.g.
.var_exists. = {rpn ".var." defined}
.syn_exists. = {rpn "\\syn" defined}
Note the double-backslash used in the synonym case, which is required to prevent Gri from substituting the synonym value into the string.

To test for the existence of files, use the operating system, e.g., testing for existence of unix file called `A':
.file_exists. = {rpn \
    "test -r A && echo 1 || echo 0" system
    "1" ==}
Another way to do this is
\file_exists = "\$(test -r A && echo 1 || echo 0)"

5.8.5: Binary Operators

Binary operators act on the top two items on the stack. With most binary operators, the result is to replace these two items with a single new item. For example, `{rpn 1 2 /}' yields 0.5.

Some binary operators replace the top two items with two new items. Examples are the pairwise conversion operators `xyusertocm' and `xycmtouser'.

List of binary operators: `+', `-', `*', `/', `<' (e.g., `1 2 <' yields 0 since 2 is not less than 1), `<=', `>', (e.g., `0 10 >' yields 1 since 10 is greater than 0), `>=', `==', `&', `|', `power' (e.g., `2 3 power' yields 8), `exch' (exchange two items on top of stack), `strcat' (add top string to end of string before it, then delete top string), `=' (assign string value to synonym or numerical value to variable; see example below), `sup' picks the larger of two values on stack, `inf' picks the smaller of two values on the stack, `remainder' yields the remainder from division of two values on the stack, using the C-language subroutine `fmod', which is similar to `mod' in fortran. See the manuals on these functions, and the examples below, for details on sign of the result compared to the two input numbers.

Notes:

  • String comparison operators are done with the operators `==' and `!=', as in the example below (see About Synonyms.).
    if {rpn "\item" "S" ==}
        show "The item is 'S'"
    end if
    

  • Assignment to variables and synonyms:
    # Variable assignment.  Note that the '=' operator
    # removes the last two items from the stack, so
    # this whole line translates to a blank line,
    # which gri then ignores.
    {rpn 2 pi * ".two_pi." =}
    

    # String assignment; note double quote needed, # so Gri won't try to substitute for an # existing synonym. {rpn "Hi there" "\\politeness" =}

5.8.6: Unary Operators

First, an operation that does not require even a single item on the stack: random number generation. Random numbers are given by `rand'.

Unary operators replace the last item on the stack with another item. For example, the `sin' operator takes the sine of the number on the top of the stack; e.g., `{rpn 45 sin}' yields sin of 45 degrees.

List of unary operators:

`ismissing' (=1 if value is current missing value, 0 otherwise), `abs', `atof' (converts string to number), `!', `acosh', `asinh', `atanh', `acos', `asin', `atan', `sin', `cos', `tan', `cosh', `sinh', `tanh', `sqrt', `system' (replaces string with output when that string is fed to the operating system), `log', `ln', `exp', `exp10', `ceil', `floor', `cmtopt', `pttocm', `xusertocm', `yusertocm', `xcmtouser', `ycmtouser', `width' (e.g., `"hi" width' yields the width of this string in cm), `ascent' (e.g., `"hi" ascent' yields the ascent above the baseline in cm), `descent' (e.g.,m `"hi" descent' yields the descent below the baseline in cm), `pop' (removes top item from stack), `dup' (duplicates top item on stack).

5.8.7: Manipulation of Columns etc

5.8.7.1: Columns

Individual data in the `x', `y', `z', `u', `v' and `weight' columns can be accessed with the `@' operator. The first point has index 0. Examples:
show "first x is " {rpn x 0 @ }
show "last  x is " {rpn x ..num_col_data.. 1 - @ }
show "and here are all the data:"
.i. = 0
while {rpn .i. ..num_col_data.. >}
    show {rpn x .i. @ }
    .i. += 1
end while

The mean value is available from the `mean' operator (e.g., `.xmean. = {rpn x mean }', while the standard deviation is given by `stddev' and the minimal and maximal values are given by `min' and `max'.

The area under the curve y=y(x) is found by `{rpn y x area }', defined by `0.5 * sum ( (y[i] + y[i-1]) * (x[i] - x[i-1]) )' for `i' ranging from 1 to `..num_col_data..'-1.

5.8.7.2: Grid

Grid data can be accessed with e.g. `{rpn grid min } ', `{rpn grid max } ', and `{rpn grid mean } '.

The value of the grid at a given `(.x.,.y.)' coordinate may be found by by e.g. `{rpn grid .x. .y. interpolate}'. The interpolation scheme is the same as that used in converting grids to images.

5.8.8: rpn Examples

Here are some reverse-polish expressions and the corresponding algebraic interpretations:

  • `{rpn 1 2 + 10 / }' = (1+2)/10
  • `{rpn .a. .b. + .c. + .d. / }' = (.a.+.b.+.c.)/.d.
  • `{rpn e 2 / }' = e/2 (Gri knows values of ``e'' and ``pi'')
  • `{rpn 23 sin 100 * 12 cos + }' = cos(12) + 100sin(23)
  • `{rpn 5 2 power }' = 25
  • `{rpn 2 log exp }' = exp(log 2)
  • `{rpn 2 ln exp10 }' = 10^ln2
  • `{rpn 1.7 floor }' = 1 (rounds down to nearest integer. Note that the floor of -1.7 is -2)
  • `{rpn 10.1 2 remainder }' = 0.1 (remainder of 10.1 after division by 2; see C function `remainder(x,y)')
  • `{rpn -10.1 2 remainder }' = -0.1
  • `{rpn -10.1 -2 remainder }' = -0.1
  • `{rpn .num. 10 > }' = 1 if 10 exceeds .num., or 0 otherwise

NOTES:

  • The units of `sin', `cos', etc, are degrees, not radians.
  • The scales of the plot are accessible to `rpn'. For example, with the command
    draw label "hi" at 10 20
    
    you draw the indicated string at the indicated location in user coordinates. To put it 0.15 centimetres to the right of this location and 0.1 centimetres lower, you could do as follows:
    draw label "\label" at \
        {rpn .x. xusertocm 0.15 + xcmtouser} \
        {rpn .y. yusertocm 0.10 - ycmtouser}
    
    (Note that the x and y scales have individual translations from "user" to "cm" coordinates.)
  • Some conversion factors are built into `rpn'; `cmtopt' converts from centimetres to points (by dividing by 28.45; the conversion factor to inches is 72.27) while `pttocm' converts from points to centimetres. For example, here is how to label a data curve with a label placed near the last y-value of the data set:
    draw curve
    .y. = {rpn ..lasty.. yusertocm 0.5 - ycmtouser}
    draw label "Smoothed" at ..lastx.. .y.