  This file documents the JACAL symbolic mathematics system.

  Copyright (C) 1993, 1994 Aubrey Jaffer

  Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

  Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

  Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the author.

Overview
********

  JACAL is a symbolic mathematics system for the simplification and
manipulation of equations and single and multiple valued algebraic
expressions constructed of numbers, variables, radicals, and algebraic
functions, differential, and holonomic functions.  In addition, vectors
and matrices of the above objects are included.

  This is free software, and you are welcome to redistribute it under
certain conditions; See the file COPYING with this program or type
`(terms)();' to JACAL for details.

  For a list of the features that have changed since the last JACAL
release, see the file `ANNOUNCE'.  For a list of the features that have
changed over time, see the file `ChangeLog'.

  The maintainer can be reached as `jaffer@ai.mit.edu'.  The most
recent information about JACAL can be found on JACAL's "WWW" home page:

            http://www-swiss.ai.mit.edu/~jaffer/JACAL.html

Installation
============

  JACAL uses the Scheme library SLIB as a portable platform.  Once SLIB
has been installed (and is loaded when your Scheme implementation
starts up), there should be no need for further configuration effort.

  SLIB has initialization files for most Scheme implementations.  It is
available from the same locations and vendors as JACAL.  See
Installation (slib).

  If you also need a Scheme implementation, SCM (written in C) is
available from the same locations and vendors as JACAL.

Starting Jacal
==============

  From your Scheme implementation, type (where
`/usr/local/lib/jacal/math.scm' is a pathname sufficient to specify the
file of that name in the JACAL directory):

     (slib:load "/usr/local/lib/jacal/math.scm")
     => ...
     JACAL version 1a5, Copyright 1989-1994 Aubrey Jaffer
     JACAL comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `(terms)' for details.
     ;;; Type (math) to begin.

     (math)
     =>
     type qed; to return to scheme, type help; for help.
     e0 :

  and you are ready to try the commands described in the rest of the
manual.

  Some implementations give the ability to specify files to `load' on
the commmand line.  Assuming SCM is installed on your system (and
assuming the same location of `jacal/math.scm'), the line would be:

     scm -il/usr/local/lib/jacal/math.scm -e"(math)"

  An alias or shell script which contains this line can conveniently
start JACAL for you.

Recovery from Errors
====================

  As JACAL is a complicated program there are bugs which will
occasionally cause the program to stop with some sort of error reported
by the underlying Scheme system.  In interactive implementations (such
as SCM) you can usually continue your session by typing `(math)'.  The
expression which was input to JACAL just before the error will be lost
but you should be able to otherwise continue with your session.

Stoping Jacal
=============

  The command `quit();' will end your JACAL session.

  With non-interactive Scheme implementations the JACAL command
`qed();' or typing the end-of-file character (<C-z> on MSDOS and VMS,
<C-d> on others) will end your JACAL session.

  The command `qed();' will return to the interactive Scheme session.
Typing `(math)' will return to the JACAL session.

  From the interactive Scheme session `(exit)' or possibly an
end-of-file character will terminate the session.

Conventions
===========

  Things that are labeled as Operators can occur in expressions output
by Jacal.  Things that are labeled as Commands act upon their arguments
and do not generally occur in expressions output by Jacal.  Things that
are labeled as flags are `set' to control aspects of the Jacal
environment.

  The examples throughout this text were produced using `SCM'.

  Jacal has several grammers it understands.  The `standard' grammar is
used in this manual.  It is like simple `TeX' grammar and algol family
computer languages.

  Identifier names are case sensitive and can be any number of
characters long.

Algebra
*******

Algebraic Operators
===================

 - Operator: + AUGEND ADDEND
     Addition of scalar quantities or componentwise addition of bunches
     is accomplished by means of the infix operator `+'. For example,

          e2 : a:[[1, 3, 5], [2, 4, 7]];

              [1  3  5]
          e2: [       ]
              [2  4  7]

          e3 : b:[2, 4];

          e3: [2, 4]

          e4 : a + b;

              [3  5  7 ]
          e4: [        ]
              [6  8  11]

          e5 : 3 + 2;

          e5: 5

          e6 : c + b;

          e6: [2 + c, 4 + c]

          e7 : e1 + e5;

                   2   2
          e7: 5 + (8 a + 12 a ) b

 - Operator: - MINUEND SUBTRAHEND
 - Operator: - SUBTRAHEND
     The symbol `-' is used to denote either the binary infix operator
     subtraction or the unary minus.

          e1 : -[1,2,3];

          e1: [-1, -2, -3]

          e2 : 3-7;

          e2: -4

 - Operator: +/- MINUEND SUBTRAHEND
 - Operator: -/+ MINUEND SUBTRAHEND
 - Operator: +/- AUGEND
 - Operator: -/+ AUGEND
     Jacal allows the use of `+/-' and `-/+' as ambiguous signs (unary
     plus-or-minus, unary minus-or-plus) and as ambiguous infix
     operators (binary plus-or-minus, binary minus-or-plus). The value
     `+/-' is also represented by the constant `%sqrt1', while `-/+' is
     represented by `-%sqrt1'.

          e7 : u:+/-3;

          e7: 3 %sqrt1

          e8 : u^2;

          e8: 9

          e9 : +/-(u);

          e9: 3

          e10 : u-/+3;

          e10: b-/+(3 %sqrt1, 3)

 - Operator: * MULTIPLICAND1 MULTIPLICAND2
     Multiplication of scalar expressions such as numbers, polynomials,
     rational functions and algebraic functions is denoted by the infix
     operator `*'.  For example,

          e1 : (2 + 3 * a) * 4 * a * b^2;

                         2   2
          e1: (8 a + 12 a ) b

     One can also use `*' as an infix operator on bunches.  In that
     case, it operates componentwise, in an appropriate sense.  If the
     bunches are square matrices, the operator `*' multiplies
     corresponding entries of the two factors.  It does not perform
     matrix multiplication.  To multiply matrices one instead uses the
     operator `.' (i.e., a period).  More generally, any binary scalar
     operator other than `^' can be used on bunches and acts
     componentwise.

 - Operator: / DIVIDEND DIVISOR
     The symbol for division in Jacal is `/'.  For example, the value
     returned by `6 / 2' is `3'.

          e3 : (x^2 - y^2) / (x - y);

          e3: x + y

 - Operator: ^ EXPRESSION EXPONENT
     The infix operator `^' is used for exponentiation of scalar
     quantitites or for componentwise exponentiation of bunches.  For
     example, `2^5' returns 32.  Unlike the other scalar infix
     operators, one cannot use `^' for component-wise operations on
     bunches.  Furthermore, one should not try to use `^' to raise a
     square matrix to a power.  Instead, one should use `^^'.

          e7 : (1+x)^4;

                           2      3    4
          e7: 1 + 4 x + 6 x  + 4 x  + x

 - Operator: = EXPRESSION1 EXPRESSION2
     In Jacal, the equals sign `=' is *not* used for conditionals and
     it is *not* used for assignments.  To assign one value to another,
     use either `:' or `:='.  The operator `=' merely returns a value
     of the form `0 = EXPRESSION'.  The value returned by `a = b', for
     example is `0 = a - b'.

          e6 : 1=2;

          e6: 0 = -1

Algebraic Commands
==================

 - Command: eliminate [EQN_1 EQN_2 ...] [VAR_1 VAR_2 ...]
     Here EQN_I is an equation for I = 1 ... N and where VAR_J is a
     variable for J = 1 ... M.  `eliminate' returns a list of equations
     obtained by eliminating the variables VAR_1, ..., VAR_M from the
     equations EQN_1, ..., EQN_N.

          e39 : eliminate([x^2+y=0,x^3+y=0],[x]);

                          2
          e39: 0 = - y - y

          e40 : eliminate([x+y+z=3,x^2+y^2+z^2=3,x^3+y^3+z^3=3],[x,y]);

          e40: 0 = 1 - z

 - Command: suchthat VAR EQN
     The equation EQN must contain an occurence of variable VAR.
     `suchthat' returns an expression for all complex values of VAR
     satisfying EQN.

          e0 : a*x+b*y+c;

          e0: c + a x + b y

          e1 : suchthat(x, e0 = 0);

              - c - b y
          e1: ---------
                  a

 - Command: suchthat VAR EXP
     If an expression rather than an equation is given to `suchthat', it
     is as though the equation `EXP=0' was given.

          e2 : suchthat(x, e0);

              - c - b y
          e2: ---------
                  a

 - Operator: | VAR EXP_OR_EQN
     An alternative infix notation is also available for `suchthat'.

     When used in combination with the `{ }' notation for `or', the set
     notation used by some textbooks results.

     If VAR in EQN has multiple roots, a named "field extension" will
     be introduced to represent any one of those roots.  When multiple
     values are returned, the result (in `disp2d' and `standard'
     grammars) is wrapped with `{ }'.

          e3 : x | a*x^2 + b*x + c;

                                         2
          ext3: {:@ | 0 = c + b :@ + a :@ }
          e3: ext3

          e4 : e3 ^ 2;

              - c - b ext3
          e4: ------------
                   a

 - Command: or EXPR_1 ...
 - Command: or EQN_1 ...
     The function `or' takes as inputs one or more equations or values.
     If the inputs are equations, then `or' returns an equation which
     is equivalent to the assertion that at least one of the input
     equations holds. If the inputs to `or' are values instead of two
     equations, then the function `or' returns a multiple value. If the
     inputs to `or' consist of both equations and values, then `or'
     will return the multiple values.

          e1 : or(x=2,y=3);

          e1: 0 = -6 + 3 x + (2 - x) y

          e2 : or(2,3);

                                      2
          e2: {:@ | 0 = -6 + 5 :@ - :@ }

          e3 : e2^2;

                                        2
          e3: {:@ | 0 = -36 + 13 :@ - :@ }

          e4 : or(x=2,17);

          e4: 17

     `{EQN, ... }' can be used as an alternate syntax for `or':

          e5 : {+1, -1};

                               2
          e5: {:@ | 0 = -1 + :@ }

Rational Expression
===================

 - Command: num EXPR
     The function `num' takes a rational expression as input and
     returns a numerator of the expression.

          e25 : num((x^2+y^2)/(x^2-y^2));

                  2    2
          e25: - x  - y

          e26 : num(7/4);

          e26: 7

          e27 : num(7/(4/3));

          e27: 21

 - Operator: denom RATIONAL-EXPRESSION
     The Jacal command `denom' is used to obtain the denominator of a
     rational expression.

          e26 : denom(4/5);

          e26: 5

 - Command: listofvars EXPR
     The command `listofvars' takes as input a rational expression and
     returns a list of the variables that occur in that expression.

          e7 : listofvars(x^2+y^3);

          e7: [x, y]

          e8 : listofvars((x^2+y^3)/(2*x^7+y*x+z));

          e8: [z, x, y]

Polynomials
===========

 - Operator: coeff POLY VAR
 - Operator: coeff POLY VAR DEG
 - Operator: coeffs POLY VAR
     The command `coeff' is used to determine the coefficient of a
     certain power of a variable in a given polynomial. Here POLY is a
     polynomial and VAR is a variable. If the optional third argument
     is omitted, then Jacal returns the coefficient of the variable VAR
     in POLY. Otherwise it returns the coefficient of VAR^DEG in POLY.
     The function `coeffs' returns a list of all of the coefficients.
     For example,

          e14 : coeff((x + 2)^4, x, 3);

          e14: 8

          e15 : (x + 2)^4;

                               2      3    4
          e15: 16 + 32 x + 24 x  + 8 x  + x

          e16 : coeff((x + 2)^4, x);

          e16: 32

          e18 : coeffs((x + 2)^4, x);

          e18: [16, 32, 24, 8, 1]

 - Operator: poly COEFFS
     The function `poly' provides an inverse to the function `coeffs',
     allowing one to recover a polynomial from its list of coefficients.

 - Operator: content POLY VAR
     Returns a list of content and primitive part of a polynomial with
     respect to the variable.  The content is the GCD of the
     coefficients of the polynomial in the variable.  The primitive
     part is POLY divided by the content.

          e24 : content(2*x*y+4*x^2*y^2,y);

                               2
          e24: [2 x, y + 2 x y ]

 - Operator: divide DIVIDEND DIVISOR VAR
 - Operator: divide DIVIDEND DIVISOR
     The command `divide' treats DIVIDENT and DIVISOR as polynomials in
     the variable VAR and returns a pair `[QUOTIENT, REMAINDER]' such
     that `DIVIDEND = DIVISOR * QUOTIENT + REMAINDER'. If the third
     argument VAR is omitted Jacal will choose a variable on its own
     with respect to which it will do the division. In particular, of
     DIVIDEND and DIVISOR are both numerical, one can safely omit the
     third argument.

          e5 : divide(x^2+y^2,x-7*y^2,x);

                      2    2       4
          e5: [x + 7 y , y  + 49 y ]

          e6 : divide(-7,3);

          e6: [-2, -1]

          e11 : divide(x^2+y^2+z^2,x+y+z);

                                 2              2
          e11: [- x - y + z, 2 x  + 2 x y + 2 y ]

          e14 : divide(x^2+y^2+z^2,x+y+z,y);

                                 2              2
          e14: [- x + y - z, 2 x  + 2 x z + 2 z ]

          e15 : divide(x^2+y^2+z^2,x+y+z,z);

                                 2              2
          e15: [- x - y + z, 2 x  + 2 x y + 2 y ]

 - Command: mod POLY1 EQN VAR
 - Command: mod POLY1 POLY2 VAR
 - Command: mod POLY1 POLY2
     Returns POLY1 reduced with respect to POLY2 (or EQN) and VAR.  If
     POLY2 is univariate, the third argument is not needed.

 - Command: mod POLY1 N
     Returns POLY1 with all the coefficients taken modulo N.

 - Command: mod POLY1
     Returns POLY1 with all the coefficients taken modulo the current
     modulus.

     If the modulus (N or the current modulus) is negative, then the
     results use symmetric representation.

          e19 : x^4+4 mod 3;

                    4
          e19: 1 + x

          e20 : x^4+4 mod x^2=2;

          e20: 8

          e22 : mod(x^3*a*7+x*8+34, -3);

                          3
          e22: 1 - x + a x

          e23 : mod(5,2);

          e23: 1

          e24 : mod(x^4+4,x^2=2,x);

          e24: 8

 - Command: gcd POLY_1 POLY_2
     The Jacal function `gcd' takes as arguments two polynomials with
     integer coefficients and returns a greatest common divisor of the
     two polynomials. This includes the case where the polynomials are
     integers.

          e1 : gcd(x^4-y^4,x^6+y^6);

               2    2
          e1: x  + y

          e2 : gcd(4,10);

          e2: 2

 - Command: poly_discriminant POLY VAR
     Here POLY is a polynomial and VAR is a variable.  This function
     returns the square of the product of the differences of the roots
     of the polynomial POLY with respect to the variable VAR.

          e7 : poly_discriminant(x^3 - 1, x);

          e7: -27

 - Command: resultant POLY_1 POLY_2 VAR
     The function `resultant' returns the resultant of the polynomials
     POLY_1 and POLY_2 with respect to the variable VAR.

          e2 : resultant(x^2 + a, x^3 + a, x);

               2    3
          e2: a  + a

Factoring
=========

 - Command: factor INT
     The Jacal command `factor' takes as input an integer and returns a
     list of the prime numbers that divide it, each occurring with the
     appropriate multiplicity in the list. If the number is negative,
     the list will begin with -1.

          e45 : factor(120);

          e45: [2, 2, 2, 3, 5]

          e46 : factor(-120);

          e46: [-1, 2, 2, 2, 3, 5]

 - Command: factor POLYRATIO
     Given a univariate ratio of polynomials POLYRATIO, returns a
     matrix of factors and exponents.

          e11 : factor((14*x^4-10/68*x^-5)/(5*x^2+1));

               [           9     ]
               [[-5 + 476 x ]    ]
               [               1 ]
               [     34          ]
               [               -1]
          e11: [         2       ]
               [ [1 + 5 x ]    -1]
               [                 ]
               [     [x]       -5]

          e12 : (14*x^4-10/68*x^-5)/(5*x^2+1);

                          9
                -5 + 476 x
          e12: --------------
                   5        7
               34 x  + 170 x

          e13 : (476*x^9-5)/(34*(5*x^2+1)*x^5);

                          9
                -5 + 476 x
          e13: --------------
                   5        7
               34 x  + 170 x

          e37 : factor(x*y);

          e37: [[x, y]  1]

          e38 : factor((x+a)*(y^4-z));

               [               4        ]
          e38: [[-1, a + x, - y  + z]  1]

          e39 : factor((x+u*a^3)*(y^4-z));

               [      3           4        ]
          e39: [[-1, a  u + x, - y  + z]  1]

          e40 : factor((x+u*a^3)^2*(y^4-z)/((x+1)*(u^2-v^2)));

               [          4                ]
               [      [- y  + z]           ]
               [                         1 ]
               [        3                  ]
          e40: [      [a  u + x]         2 ]
               [                           ]
               [[u + v, - u + v, 1 + x]  -1]

          e43 : factor(200*(-1*x+1+y)*(u-r^6)*(21*x+2-t^4));

               [         6                      4           ]
          e43: [[200, - r  + u, 1 - x + y, 2 - t  + 21 x]  1]

          e28 : factor(2*(a+u)*(-v+b)*(a*x+y)^2);

               [[-2, a + u, - b + v]  1]
          e28: [                       ]
               [     [a x + y]        2]

          e29 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*(11*x+55)));

               [ [2, a + u, - b + v]   1 ]
               [                         ]
          e29: [      [a x + y]        2 ]
               [                         ]
               [[11, 5 + x, - u + v,   -1]
               [                         ]
               [       u + v]            ]

          e1 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*x^4*(11*x+55)));

              [[2, a + u, - b + v]  1 ]
              [                       ]
              [     [a x + y]       2 ]
          e1: [                       ]
              [[11, 5 + x, - u +    -1]
              [                       ]
              [    v, u + v]        -4]
              [                       ]
              [        [x]            ]

          e1 : factor((c^3*u+b*a)*(b*b*a+v*p^2*q^2*c));

              [    2      2  2           3      ]
          e1: [[a b  + c p  q  v, a b + c  u]  1]

          e2 : factor((2*z+y-x)*(y^3-a*x^2)*(b*z^2+y));

              [      2    3         2                   ]
          e1: [[- a x  + y , y + b z , - x + y + 2 z]  1]

          e35 : factor((a*a*b*z+d)*(2*a*b*b*z+c));

               [      2               2      ]
          e35: [[d + a  b z, c + 2 a b  z]  1]

          e38 : factor((a*a*b*z+d)*(2*a*b*b*z+c)*((u+a)*x+1));

               [          2         2                       ]
          e38: [[c + 2 a b  z, d + a  b z, 1 + (a + u) x]  1]

          e7 : factor((c*z+a)*(a*z+b)*(b*z+c));

          e7: [[b + a z, c + b z, a + c z]  1]

          e15 : factor((a*a*b*(x+w)*z+d)*(2*a*b*b*z+c));

               [       2        2                  2      ]
          e15: [[d + (a  b w + a  b x) z, c + 2 a b  z]  1]

          e16 : factor(((x+w)^2*z-u*d)*(-2*a*b*z+c));

               [             [-1]                ]
               [                                1]
          e16: [                          2      ]
               [[- c + 2 a b z, - d u + (w  +   1]
               [                                 ]
               [                 2               ]
               [        2 w x + x ) z]           ]

          e9 : factor((-200*%i*x-c)*(x-d-z^5)/(a*(b^3-(a+u)*z)));

              [                            5     ]
              [[-1, c + 200 %i x, d - x + z ]    ]
              [                                1 ]
          e9: [        3                         ]
              [    [- b  + (a + u) z, a]       -1]

The rest of this section documents commands from the factoring package.
To use this package, execute the following command from the JACAL
prompt:

  `require("ff");'

Several of these commands return a matrix.  The first column contains
the factors and the second column contains the corresponding exponent.

 - Command: sff POLY
     Given a primitive univariate polynomial POLY, calculate the square
     free factorisation of POLY. A "primitive" polynomial is one with
     no factors (other than units) common to all its coefficients.

 - Command: ffsff POLY P
 - Command: ffsff POLY P M
     Given a monic polynomial POLY, a prime P, and a positive integer
     M, calculate the square free factorisation of POLY in GF(p^m)[x].
     If M is not supplied, `1' is assumed.

          e0 : ffsff(x^5+x^3+1, 53);

              [                2    3   ]
              [16 - 22 x + 26 x  + x   1]
          e0: [                         ]
              [       -13 + x          2]

 - Command: berl POLY N
     Given a square-free univariate polynomial POLY and an integer
     power of a prime, Q, returns (as a bunch) the irreducible factors
     of POLY.

          e2 : berl(x^5+x^3+2, 53);

                                  2               2
          e2: [1 + x, 5 - 26 x + x , 11 + 25 x + x ]

 - Command: parfrac POLYRATIO
     Returns the partial fraction expansion of a rational univariate
     polynomial POLYRATIO.  The denominator of POLYRATIO must be square
     free.  This code is still being developed.

Caculus
*******

Differential Operator
=====================

 - Operator: differential EXPR
 - Operator: ' EXPR
     The Jacal command `differential' computes the derivative of the
     expression EXPR with respect to a generic derivation. It is
     generic in the sense that nothing is assumed about its effect on
     the individual variables. The derivation is denoted by a right
     quote.

          e6 : differential(x^2+y^3);

                          2
          e6: 2 x x' + 3 y  y'

          e7 : (x^2+y^3)';

                          2
          e7: 2 x x' + 3 y  y'

Derivative Commands
===================

 - Command: diff EXPR VAR1 ...
     The Jacal command `diff' computes the derivative of the expression
     EXPR with respect to VAR1, ....

          e6 : diff(x^2+y^3,y);

                 2
          e6: 3 y

 - Command: partial EXPR VAR1 ...
     The Jacal command `partial' computes the partial derivative of the
     expression EXPR with respect to VAR1, ....

          e6 : partial(x^2+@1^3,1);

                  2
          e6: 3 @1

 - Command: PolyDiff POLY VAR1 ...
     The Jacal command `PolyDiff' computes the derivative of the
     expression POLY with respect to VAR1, ....  It is faster than
     `diff' but POLY must be a polynomial.

Matrices and Tensors
********************

  In JACAL, a matrix is just a `bunch' of equal length `bunch's, and
this is the structure that the matrix operations currently supported by
JACAL (ncmult(), ^^, transpose(), etc.) expect.

Generating Matrices
===================

 - Operator: bunch ELT_1 ELT_2 ...
     `[ELT_1, ELT_2, ...]'

     To collect any number of Jacal objects into a bunch, simply
     enclose them in square brackets. For example, to make the bunch
     whose elements are `1', `2', `4', type `[1, 2, 4]'. One can also
     nest bunches, for example, `[1, [[1, 3], [2, 5]], [1, 4]]'.  Note
     however that the bunch whose only element is `[1, 2, 3]' is `[1 2
     3]'.  It is importance to notice that one has commas and the other
     doesn't.

          e3 : a:bunch(1, 2, 3);

          e3: [1, 2, 3]

          e4 : b:[a];

          e4: [1  2  3]

          e5 : c:[b];

          e5: [[1, 2, 3]]

          e6 : [[[1, 2, 3]]];

          e6: [[1, 2, 3]]

 - Command: ident N
     The command `ident' takes as argument a positive integer N and
     returns an NxN identity matrix. This is sometimes more convenient
     than obtaining this same matrix using the command `scalarmatrix'.

          e6 : ident(4);

              [1  0  0  0]
              [          ]
              [0  1  0  0]
          e6: [          ]
              [0  0  1  0]
              [          ]
              [0  0  0  1]

 - Command: scalarmatrix SIZE ENTRY
     The command `scalarmatrix' takes as inputs a positive integer SIZE
     and an algebraic expression ENTRY and returns an `N * N' diagonal
     matrix whose diagonal entries are all equal to ENTRY, where `N =
     SIZE'.

          e1 : scalarmatrix(3, 6);

              [6  0  0]
              [       ]
          e1: [0  6  0]
              [       ]
              [0  0  6]

 - Command: diagmatrix LIST
     The Jacal command `diagmatrix' takes as input a list of objects and
     returns the diagonal matrix having those objects as diagonal
     entries. In case one wants all of the diagonal entries to be
     equal, it is more convenient to use the command `scalarmatrix'.

          e3 : diagmatrix(12,3,a,s^2);

              [12  0  0  0 ]
              [            ]
              [0   3  0  0 ]
          e3: [            ]
              [0   0  a  0 ]
              [            ]
              [0   0  0   2]
              [          s ]

          e4 : diagmatrix([1,2],2);

              [[1, 2]  0]
          e4: [         ]
              [  0     2]

 - Command: sylvester POLY_1 POLY_2 VAR
     Here, POLY_1 and POLY_2 are polynomials and VAR is a variable.
     The function `sylvester' returns the matrix introduced by
     Sylvester (`A Method of Determining By Mere Inspection the
     Derivatives from Two Equations of Any Degree, Phil.Mag. `16' (1840)
     pp. 132-135, Mathematical Papers, vol. I, pp. 54-57') for
     computing the resultant of the two polynomials POLY_1 and POLY_2
     with respect to the variable VAR. If one wants to compute the
     resultant itself, one can simply use the command `resultant' with
     the same syntax.

          e5 : sylvester(a0 + a1*x + a2*x^2 + a3*x^3, b0 + b1*x + b2*x^2, x);

              [a3  a2  a1  a0  0 ]
              [                  ]
              [0   a3  a2  a1  a0]
              [                  ]
          e5: [b2  b1  b0  0   0 ]
              [                  ]
              [0   b2  b1  b0  0 ]
              [                  ]
              [0   0   b2  b1  b0]

 - Command: genmatrix FUNCTION ROWS COLS
     The function `genmatrix' takes as arguments a function FUNCTION of
     two variables and two positive integers, ROWS and COLS. It returns
     a matrix with the indicated numbers of rows and columns in which
     the $(i,j)$th entry is obtained by evaluating FUNCTION at $(i,j)$.
     The function may be defined in any of the ways available in Jacal,
     i.e previously by an explicit algebraic definition, by an explicit
     lambda expression or by an implicit lambda expression.

          e4 : @1^2+@2^2;

                                 2      2
          e4: lambda([@1, @2], @1  + @2 )

          e5 : genmatrix(e4,3,5);

              [2   5   10  17  26]
              [                  ]
          e5: [5   8   13  20  29]
              [                  ]
              [10  13  18  25  34]

Matrix Parts
============

 - Command: row MATRIX I
     The command `row' returns the Ith row of the matrix MATRIX, where
     `i = INT'.  If INT is larger than the number of rows of MATRIX,
     then Jacal prints an error message.  The corresponding command for
     columns of a matrix is `col'.

          e3 : u:[[1, 2, 3], [1, 5, 3]];

              [1  2  3]
          e3: [       ]
              [1  5  3]

          e4 : row(u, 2);

          e4: [1, 5, 3]

 - Command: col MATRIX INTEGER
     The command `col' is used to extract a column of a matrix. Here,
     MATRIX is a matrix and INTEGER is a positive integer. If that
     integer exceeds the number of columns, an error message such as

          ERROR: list-ref: Wrong type in arg1 ()

     appears. Here is an example of correct use of the command `col':

          e19 : a:[[1,2,4],[2,5,6]];

               [1  2  4]
          e19: [       ]
               [2  5  6]

          e20 : col(a,2);

               [2]
          e20: [ ]
               [5]

 - Command: minor MATRIX ROW COL
     The command `minor' returns the submatrix of MATRIX obtained by
     deleting the Ith row and the Jth column, where I = ROW and J = COL.

          e21 : b:[[1,2,3],[3,1,5],[5,2,7]];

               [1  2  3]
               [       ]
          e21: [3  1  5]
               [       ]
               [5  2  7]

          e22 : minor(b,3,1);

               [2  3]
          e22: [    ]
               [1  5]

 - Command: rapply BUNCH INT_1 INT_2 ...
     The function `rapply' is used to access elements of bunches.  It
     can also access elements nested at lower levels in a bunch.  In
     particular, it can also access matrix elements.  In the above
     syntax, BUNCH is the bunch whose parts one wishes to access, and N,
     INT_1, INT_2, ..., INT_N are positive integers.  It returns the
     INT_N-th element of the INT_{N-1}-th element of ... of the
     INT_2-th element of the INT_1-th element of BUNCH.  One can have
     `n = 0'.  In that case, `rapply' simply returns the bunch.

          e2 : rapply([[1,2,3],[1,4,6],3],2,3);

          e2: 6

          e6 : rapply([a,b],2);

          e6: b

          e7 : rapply([a,b]);

          e7: [a, b]

Matrix commands
===============

 - Command: . MATRIX1 MATRIX2
     Matrix multiplication.

          e1 : a:[[1, 2, 3], [5, 2, 7]];

              [1  2  3]
          e1: [       ]
              [5  2  7]

          e2 : b:[[3, 2], [6, 4]];

              [3  2]
          e2: [    ]
              [6  4]

          e3 : b . a;

              [13  10  23]
          e3: [          ]
              [26  20  46]

 - Command: ^^ MATRIX EXPONENT
     The infix operator `^^' is used for raising a square matrix to an
     integral power.  It can also be used on nonsquare matrices, but the
     results are not documented.

          e8 : a:[[1, 0], [-1, 1]];

              [1   0]
          e8: [     ]
              [-1  1]

          e9 : a^^3;

              [1   0]
          e9: [     ]
              [-3  1]

 - Command: dotproduct VECTOR_1 VECTOR_2
     The Jacal function `dotproduct' returns the dot product of two row
     vectors of the same length. It will also give the dot product of
     two matrices of the same size by computing the sum of the dot
     products of the corresponding rows or, what is the same, the trace
     of one matrix times the transpose of the other one.

          e28 : a:[1,2,3]; b:[3,1,5];

          e28: [1, 2, 3]

          e29 :
          e29: [3, 1, 5]

          e30 : dotproduct(a,b);

          e30: 20

 - Command: crossproduct VECTOR_1 VECTOR_2
     The Jacal command `crossproduct' computes the cross product of two
     vectors.  By definition, the two vectors must each have three
     components.

          e24: [2 x, y + 2 x y ]

          e25 : crossproduct([1,2,3],[4,2,5]);

          e25: [4, 7, -6]

 - Command: determinant MATRIX
     The Jacal command `determinant' computes the determinant of a
     square matrix.  Attempting to take the determinant of a non-square
     matrix will produce an error message.

          e1 : a:[[1,2],[6,7]];

              [1  2]
          e1: [    ]
              [6  7]

          e2 : determinant(a);

          e2: -5

 - Command: transpose MATRIX
     Computes the transpose of `(MATRIX)'.

Tensors
=======

  The `tensors' supported by JACAL are an extension of the matrix
structure (i.e., a bunch of bunches of bunches ...) with the added
stipulation that all `dimensions' of the tensor be the same length
(e.g., 4x4x4).  The number of dimensions (indices) in a tensor is its
rank: A scalar is a tensor of rank 0; a vector is a rank 1 tensor; a
matrix has rank 2; and so on.

  Further, just as matrix binary operations place restrictions on the
matrices involved (e.g., the row/column length requirement for matrix
multiplication), the tensor binary operations require that the
dimensions of each tensor be of the same length.  For example, you
could not multiply a 3x3 tensor and a 4x4x4 tensor.

  JACAL's tensors do not support the construct of contravariant and
covariant indices.  Users must keep track of this information
themselves, and perform the necessary operations with an appropriate
metric so that the "index gymnastics" is performed correctly.

  Before using any of JACAL's tensor operations, execute the following
command from the JACAL prompt:

  	require("tensor");

  This loads the file `tensor.scm' into JACAL, and makes the tensor
operations available for use.

  JACAL currently supports four tensor operations: `tmult', `contract',
`indexshift', and `indexswap'.  Each of these is described in detail
below.

Tensor Multiplication
=====================

 - Command: tmult MATRIX_1 MATRIX_2 INDEX_1 INDEX_2
     `tmult' takes a minimum of two arguments which are the tensors on
     which the multiplication operation is to be performed.

     With no additional arguments, `tmult' will produce the outer
     product of the two input tensors.  The rank of the resulting
     tensor is the sum of the inputs' ranks, and the components of the
     result are formed from the pair-wise products of components of the
     inputs.  For example, for the input tensors `x[a,b]' and `y[c]'
          z:tmult(x,y);=> z[a,b,c] = x[a,b]*y[c]

     With an additional argument, `tmult' will produce the inner product
     of the two tensors on the specified index.  For example, given
     `x[i,j]' and `y[k,l,m]'
          z:tmult(x,y,3);
          =>
          			length
          			-----
          			\
          	     z[a,b,c] =  >   x[a,q] * y[b,c,q]
          			/
          			-----
          			q = 1

     Note that in this case X only has 2 indices.  All of JACAL's tensor
     operations modify index inputs to be between 1 and the rank of the
     tensor.  Thus, in this example, the 3 is modified to 2 in the case
     of X.  As another example, with `x[i,j,k]' and `y[l,m,n]'
          z:tmult(x,y,2);
          =>
          			  length
          			  -----
          			  \
          	     z[a,b,c,d] =  >   x[a,q,b] * y[c,q,d]
          			  /
          			  -----
          			  q = 1

     With four arguments, `tmult' produces an inner product of the two
     tensors on the specified indices.  For example, for `x[i,j]' and
     `y[k,l,m]'
          z:tmult(x,y,1,3);
          =>
          			length
          			-----
          			\
          	     z[a,b,c] =  >   x[q,a] * y[b,c,q]
          			/
          			-----
          			q = 1

     Note that matrix multiplication is the special case of an inner
     product (of two "two dimensional matrices") on the second and
     first indices, respectively: `tmult(x,y,2,1) == ncmult(x,y)'

     Finally, tmult handles the case of a scalar times a tensor, in
     which case each component of the tensor is multiplied by the
     scalar.

Tensor contraction
==================

 - Command: contract MATRIX INDEX1 ...
     The contraction operation produces a tensor of rank two less than
     a given tensor.  It does this by performing a summation over two
     of the indices of the given tensor, as clarified in the examples
     below.

     `contract' takes at least one argument which is the tensor on
     which the contraction operation is to be performed.  One or two
     additional arguments may be provided to specify the indices to be
     used in the summation.  If no additional arguments are provided,
     the summation is performed over the first and second indices.
     With one additional argument, the summation is over the specified
     index and the one following it (e.g., if 3 is specified, the third
     and fourth indices are used).  With two additional arguments, the
     summation is performed over the indices specified.  The actual
     indices used will be constrained to be between 1 and the rank of
     the tensor.

     Examples:

     1) For a square matrix (tensor of rank 2), `contract' returns a
     scalar that is the sum of the diagonal elements of the matrix.

     2) Given `x[i,j,k,l]', the command
          y:contract(x,2,4);
     produces:
          			length
          			-----
          			\
          	       y[a,b] =  >   x[a,q,b,q]
          			/
          			-----
          			q = 1

     Special cases:  If `contract' is given a scalar (rank 0 tensor) as
     input, it just returns the scalar.  For a vector (tensor of rank
     1), `contract' returns a scalar that is the sum of the elements of
     the vector.

Shifting of Tensor Indices
==========================

 - Command: indexshift MATRIX INDEX1 ...
     `indexshift' rearranges the indices of a tensor.  It is one of two
     generalizations of the matrix transpose operation (cf.
     `indexswap').

     `indexshift' takes at least one argument which is the tensor on
     which the index shifting is to be performed.  One or two
     additional arguments may be provided to specify the index and the
     position to which it is to be shifted.  If no additional arguments
     are provided, the first index of the tensor is shifted to the
     second position (equivalent the matrix transpose operation).  If
     one additional argument is provided, it specifies the index to be
     shifted, and that index will be shifted "to the right" one position
     (e.g., if 3 is specified, the third index will be shifted to the
     forth position).  If two additional arguments are provided, the
     first specifies the index and the second specifies the position to
     which it is to be shifted.  The actual index shifted and its
     shifted position will be constrained to be between 1 and the rank
     of the tensor.

     For example, given `x[a,b,c,d]', the command
     `y:indexshift(x,1,3);' produces a tensor Y such that `y[a,b,c,d]
     == x[b,c,a,d]'.  In this example, the element that was in position
     `[a,b,c,d]' in X will be in position `[b,c,a,d]' in Y.

     Special cases:  If `indexshift' is given a scalar (rank 0 tensor)
     as input, it just returns the scalar.  For a vector (tensor of
     rank 1), `indexshift' transposes the 1-by-n matrix (row vector) to
     an n-by-1 matrix (column vector).

Swapping of Tensor Indices
==========================

 - Command: indexswap TENSOR ...
     `indexswap' rearranges the indices of a tensor.  It is one of two
     generalizations of the matrix transpose operation (cf.
     `indexshift').

     `indexswap' takes at least one argument which is the tensor on
     which index swapping is to be performed.  One or two additional
     arguments may be provided to specify the indices to be swapped.
     If no additional arguments are provided, the first and second
     indices of the tensor are swapped (equivalent the matrix transpose
     operation).   With one additional argument, the specified index is
     swapped with the one following it (e.g., if 2 is specified, the
     second and third indices will be swapped).  If two additional
     arguments are provided, they specify the indices to be swapped.
     The actual indices used will be constrained to be between 1 and
     the rank of the tensor.

     For example, given x[a,b,c,d], the command `y:indexswap(x,2,4);'
     produces a tensor Y such that y[a,b,c,d] = x[a,d,c,b].  In this
     example, the element that was in position [a,b,c,d] in X will be
     in position [a,d,c,b] in Y.

     Special cases:  If `indexswap' is given a scalar (rank 0 tensor)
     as input, it just returns the scalar.  For a vector (tensor of
     rank 1), `indexswap' transposes the 1-by-n matrix (row vector) to
     an n-by-1 matrix (column vector).

Lambda Calculus
***************

Create a lambda expression
==========================

 - Operator: lambda VARLIST EXPRESSION
     Jacal has the ability to work with lambda expressions, via the
     command `lambda'. Furthermore, Jacal always converts user
     definitions of functions by any method into lambda expressions and
     converts the dummy variables of the function definition into
     symbols such as 1, 2, .... Jacal can manipulate lambda expressions
     by manipulating their function parts, as in `e14' below.  Jacal can
     also invert a function using the command `finv'.

          e12 : lambda([x],x^2);

                              2
          e12: lambda([@1], @1 )

          e13 : lambda([x,y,z],x*y*z);

          e13: lambda([@1, @2, @3], @1 @2 @3)

          e14 : e12+e13;

                                      2
          e14: lambda([@1, @2, @3], @1  + @1 @2 @3)

Compute inverse function
========================

 - Command: finv FUNCTION
     `FUNCTION^^-1'

     The command `finv' takes as input a function of one variable and
     returns the inverse of that function. The function may be defined
     in any of the ways permitted in Jacal, i.e. by an explicit
     algebraic definition, by an explicit lambda expression or by an
     implicit lamba expression. If F is the function, then typing
     `f^^-1' has the same effect as typing `finv(F)'.

          e0 : w(t):=t+1;

          w(t): lambda([@1], 1 + @1)

          e0 : finv(w);

          e0: lambda([@1], -1 + @1)

Miscellaneous
*************

 - Command: %
     The symbol `%' represents the last expression obtained by Jacal. It
     can be used in formulas like any other constant or variable or
     expression.

          e21: 5

          e22 : %;

          e22: 5

          e23 : %^2;

          e23: 25

 - Command: batch FILENAME
     The command `batch' is used to read in a file containing programs
     written in Jacal. Here, FILENAME is a string in double quotes. The
     precise way in which one refers to a file is, of course, system
     dependent.

          batch("demo");
     of the file demo in the JACAL directory will give a
     demonstration of JACAL's capabilities.

 - Command: commands
     The command `commands' produces a list of all of the command
     available in Jacal. It is called as s function of no arguments.
     Explicitly:

          e21 : commands();

               u-/+ u+/- transpose transcript differential terms system sylvester
               show set scalarmatrix row resultant rapply quit qed poly_discriminant poly
               or num negate mod minor matrix load listofvars ident genmatrix gcd finv
               factor example eliminate dotproduct divide diff diagmatrix determinant
               describe denom crossproduct content commands col coeffs coeff bunch batch
               b+/- ^^ ^ = / - + * %

 - Command: describe COMMAND
     The command `describe' is the heart of the online help facility of
     Jacal.  Here, COMMAND is a string which is the name of a command
     and `describe' produces a brief description of the command and in
     many cases includes an example of its use. Together with the
     command `commands()', which prints a list of all available Jacal
     commands, and the command `example', which gives an example of the
     use of the command, one can in principle use Jacal without a
     manual after one has learned how to get started.

          e27 : describe(col);
          column.  column of a matrix
          e27 : describe(resultant);
          resultant.  The result of eliminating a variable between 2
          equations (or polynomials).
          27 : describe(+);
          Addition, plus.
          a + b

 - Command: example COMMAND
     Here, COMMAND is a string which is the name of a Jacal command.
     `example' gives an example of the use of the command.  See also
     describe.

          e43 : example(+);
          a + b

          e43: a + b

 - Command: load STRING
     The Jacal command `load' takes as input a string and reads in a
     `Scheme' file whose name is obtained by appending the extension
     `.scm' to the string.  If you want to read in a file of Jacal
     commands, do not use `load'.  Instead use the command `batch'. To
     load in the file `foo.scm',

          e9 : load("foo");

          e9: foo

 - Command: qed
     Exit from Jacal to Scheme.  With interactive Scheme systems (such
     as SCM), It does not return you to the operating system.  Instead
     it suspends Jacal and returns you to the underlying scheme.  You
     can return to the Jacal session where you left off by simply
     typing `(math)'.  If you do not wish to return to Jacal but really
     want to terminate the session and return to the operating system,
     then after typing `qed();', type `(slib:exit)' or use `quit'.

 - Command: quit
     Exit directly from Jacal to the operating system.  You will not be
     able to continue your Jacal session.

          type qed(); to return to scheme
          e1 : qed();
          scheme
          > (math)
          type qed(); to return to scheme
          e2 : quit();
          unix>

 - Command: system COMMAND
     One can issue commands to the operating system without leaving
     Jacal. To do this, one uses the command `system'. For example, in
     a UNIX operating system, the command `system("ls");' will print the
     directory. One way in which the command `system' might be
     especially useful is to edit files containing Jacal scripts without
     leaving Jacal, particularly in non-UNIX machines or on machines
     without GNU emacs.

          e0 : system("echo hi there");
          hi there

          e0: 0

 - Command: terms
     Prints a copy of the GNU General Public License
          e1 : terms();

          GNU GENERAL PUBLIC LICENSE
          **************************
                                  Version 1, February 1989

               Copyright (C) 1989 Free Software Foundation, Inc.
               675 Mass Ave, Cambridge, MA 02139, USA

               Everyone is permitted to copy and distribute verbatim copies
               of this license document, but changing it is not allowed.
                       [ rest deleted for brevity]

 - Command: transcript STRING
     The command `transcript' allows one to record a Jacal session. It
     is called with the syntax `transcript(STRING);', where STRING is
     the name of the file in which one wants to keep the transcript of
     the session. When one wishes to stop recording, one types
     `transcript();'. One is then free to use `transcript' again later
     in the session on another file. One can use it on the same file,
     but the file is overwritten. Presently, the command `transcript'
     does not echo commands to a file.

          e9 : a:[1,2,3];

          e9: [1, 2, 3]

          e10 : transcript("foo");

          e10: foo

          e11 : a;

          e11: [1, 2, 3]

          e12 : transcript();
          e12 : system("cat foo");

          e10: foo

          e11 : a;

          e11: [1, 2, 3]

          e12 : transcript();

          e12: 0

 - Command: set FLAG VALUE
     There are various flags that the Jacal user can control, namely the
     Jacal command line prompt, the priority for printing terms in Jacal
     output, the input grammar and the output grammar.  For a
     discussion of the various grammars please Flags.  The
     command `show' is closely related, allowing one to see what the
     current settings are.

 - Command: show FLAG
     The command `show' enables the Jacal user to examine the current
     setting of various flags as well as to list the flags that can be
     set by the user and to display other information. To change the
     settings of the flags, use the command `set'. To see all the
     information accessible through the `show' command, type `show
     all'. To see the available grammars, type `show grammars'.  To see
     the current input grammar type `show ingrammar'. To see the
     current output grammar, type `show outgrammar'. To see the current
     priority for printing expressions, type `show priority'.
          e1 : show all;

               prompt priority outgrammar ingrammar grammars all
          e1 : show prompt;

          e1: e1

          e3 : show priority;

              :@ (differential :@) @3 @2 @1 %inftsl y x u-/+ u+/-
              transpose transcript differential terms t system sylvester
              showpriority show set scalarmatrix row resultant rapply quit
              qed prompt priority poly_discriminant poly or num negate mod
              minor matrix load listofvars ident genmatrix gcd finv factor
              example eliminate e1 dotproduct divide diff diagmatrix
              determinant describe denom crossproduct content commands col
              coeffs coeff c bunch batch b-/+ b+/- b all a ^^ ^ = / - + *
              % %sqrt1 %i

          e3 : show outgrammar;

          e3: disp2d

          e4 : show ingrammar;

          e4: standard

          e5 : show grammars;

          e5: [disp2d, standard, schemepretty, scheme]

Flags
*****

 - Flag: prompt
     If one changes the prompt, STRING is a string of alphanumeric
     characters without quotes.  After this command is executed,
     subsequent commands will cause new prompts to be obtained from
     STRING by incrementing it.  If the prompt ends in a letter, it
     will be treated as a digit in base 26 and incremented.  If it ends
     in a string of digits, that string will be treated as a number in
     base 10 and incremented.  The remaining characters in the string
     will play no role in this incrementation.

          e1 : set prompt az9Z;
          e1 : a+b;

          az9Z: a + b

          az9AA : a+b;

          az9AA: a + b

          az9AB : set prompt ok99;
          az9AB : a+b;

          ok99: a + b

          ok100 : a+b;

          ok100: a + b

          ok101 :

 - Flag: ingrammar
 - Flag: outgrammar
     The following examples show how one changes the input grammar or
     the output grammar.
          e1 : a:[[[1,2,3]]];

          e1: [[1, 2, 3]]

          e2 : set outgrammar standard;
          e2 : a;

          e2: [[[1, 2, 3]]]

          e3 : set outgrammar scheme;
          e3 : a;

          (define e3 #(#(#(1 2 3))))
          e4 : (1+x)^5;

          (define e4 (+ 1 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5)))
          e6 : set ingrammar scheme;
          e6 : (+ e4 1);

          (define e6 (+ 2 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5)))
          e7 : (set ingrammar disp2d)
          e7 : diagmatrix(3,6);

          (define e7 #(#(3 0) #(0 6)))
          e8 : set outgrammar disp2d;
          e8 : e7;

              [3  0]
          e8: [    ]
              [0  6]

          e9 : set outgrammar standard;
          e9 : e7;

          e9: [[3, 0], [0, 6]]

     Note that in the above examples, it is possible to input and output
     expressions in scheme by setting the ingrammar and/or outgrammar to
     `scheme'.  Doing so result in linear output (as with `standard
     grammar') as opposed to a two dimensional display (as with
     `disp2d').  The analogue of `disp2d' for scheme output is scheme
     pretty-printing.  To have such output, set the output grammar to
     `schemepretty'.

          e4 : set outgrammar schemepretty;
          e4 : (1+x)^5;

          (define e4
            (+ 1
               (* 5 x)
               (* 10 (^ x 2))
               (* 10 (^ x 3))
               (* 5 (^ x 4))
               (^ x 5)))

     Jacal also allows for output to be automatically typeset in TeX.
     This can be quite useful if one wants to use the results of one's
     computations in published articles. Continuing with the example of
     `(1+x)^5' above, we have:

          e5 : set outgrammar tex;
          e5 : e4;

          e5: 1 + 5 x + 10 x^{2} + 10 x^{3} + 5 x^{4} + x^{5}

          e6 : (1+1/x)^3/(1-1/y)^4;

          e6: {\left(1 + 3 x + 3 x^{2} + x^{3}\right) y^{4}}\over{x^{3} - 4 x^{3} y +

                          6 x^{3} y^{2} - 4 x^{3} y^{3} + x^{3} y^{4}}

     That looks much better when formatted by TeX in an article than the
     actual Jacal output in `disp2d' grammar.

 - Flag: priority
     The following examples show how to set the priority of printing
     terms.
          e10 : a;

          e10: [[[1, 2, 3]]]

          e11 : show priority a;

          ;;; not a simple variable:  (((1 2 3) . ()) . ())

          e12 : show priority b;

          e12: 128

          e13 : show priority c;

          e13: 128

          e14 : b+c;

          e14: b + c

          e15 : c+b;

          e15: b + c

          e16 : set priority b 200;
          e16 : b+c;

Function Index
**************

  This is an alphabetical list of all the operators and commands in
JACAL.

Variable Index
**************

  This is an alphabetical list of the built-ins and flags in JACAL.