MathSolver User's Manual

This is a brief summary of MathSolver's syntax and capabilities
as of September 11, 2000.
Suggestions are always welcome.
For further clarification, consult
the example programs.

Introduction

MathSolver is interpreted and uses Forth-like syntax.
This means it behaves much like a ``RPN'' calculater:

7 6 + printn

(13)

It handles rational and real numbers:

2 3 / 4 + dup print " = " (1.0) * printn

(14/3) = (4.666667)

More interesting, of course, are symbolic manipulations, like
cubing a polynomial:

(a+2b) dup dup * * printn

(1 a^3 + 6 a^2 b + 12 a b^2 + 8 b^3)

or taking the derivative of a rational expression:

(x^2 + y) (x + y^2) / &x Deriv Printn

( (-1 x^2 + -2 x y^2 + 1 y) / (1 x^2 + 2 x y^2 + 1 y^4) )

Here, the program's output of ``+ -'' where a simple ``- '' would do
is rather slovenly.
I'm still working on the software, but cosmetics have low priority.
(The mentioned problem is eliminated readily by running the standard
tool ``sed "ss+ -s- sg"'' as a postprocess.)

Syntax

A MathSolver program is a list of tokens separated
by white space.
Two types of token (STRING and EXPRESSION)
may have embedded white space (spaces or tabs)
but neither may span multiple lines (have embedded line feeds).
The string ``//'' is a comment delimiter and causes the remainder of
a line to be ignored.
Input is case-insensitive: ``Print'', ``print'', ``PRINT'' or even
``pRiNt'' all specify the same command token.
Some command words have synonyms: ``Printn,'' for example, can be replaced
with just ``?''.
A MathSolver program is terminated by EOF, or with an explicit
``Exit'' token.

In addition to certain pre-defined command words, a token may be

(STRING).
A character string, beginning and ending with ``"''.
Newlines and tab characters may be inserted as in C syntax.

(EXPRESSION).
An algebraic expression, beginning with ``('' and ending with ``)''.

(INTEGER).
An integer, consisting of digits, optionally preceded by `+' or `-'.

(USER WORD).
A user-defined command word, which can be a program variable or
the name of a subprocedure.

(SET WORD).
The character ``:'' followed by a user-defined word. This is used
to set the word's value.

(VARIABLE).
The character ``&'' followed by the name of an algebraic variable.

(PROCEDURE).
The token ``begin'' (or simply ``{'') followed by a list of tokens,
followed by the token ``end'' (or simply ``}'').

At present, nothing can be done with STRINGs except to print them,
so that's what is done: the data stack is not affected.

Input EXPRESSIONs use algebraic notation and are parsed by a separate
routine.
Each EXPRESSION is turned into a single internal node which is pushed onto
the stack.
Some expressions can be printed and handled internally, but must be
input in a roundabout way.
For example, the expression ((3+i)x) is a single term with a
complex coefficient, but must be entered as two terms: ``(3x + ix)''.

An INTEGER, like ``17'', should be equivalent to the EXPRESSION ``(17)''.
Rational numbers can be built from INTEGERS: ``0 5 - 7 /'' is equivalent
to ``(-5/7)''.

A USER WORD can be set to any token and, when invoked, is equivalent to
that token.

An exception is STRING: since these are currently never pushed onto the
stack, they cannot be popped off and assigned to a User Word.
The same effect can be achieved however:

{ "Greetings Galaxy!\n" } dup :sayhello :say

Here we've created a procedure which does nothing but print a greeting.
The above input, however, doesn't print the greeting, but just gives
the procedure a name.
(To illustrate the homogeneity of tokens, and the power of the ``dup''
command, we actually give the procedure two names.)
Later the program input:

sayhello sayhello

will produce the output:

Greetings Galaxy!
Greetings Galaxy!

The SET WORD syntax was illustrated in the preceeding example.
The input ``7 :Cnt'' is equivalent to the C executable
statement ``Cnt = 7;'' and ``Cnt 2 - :Cnt'' is equivalent to ``Cnt -= 2''.
Here, ``Cnt'' is used as program variable, but these are not to be confused
with the algebraic variables used by MathSolver when it takes
derivatives, etc.
(Often it may seem convenient to bind, or conceptually equate, an
algebraic variable with a program variable of the same name, but this
is just a user mnemonic: MathSolver treats the two as of
independent name spaces.)

A user word must be SET (with a ``:'' token) before it can be referenced;
it is the first such SET which adds the word to an internal lookup table.
In some cases this will be counterintuitive: say you define a procedure
which uses a program variable, then set the variable; then invoke the
procedure.
This will fail: you must provide a dummy SET prior to the procedure
definition.

Algebraic VARIABLES in MathSolver take names like ``a'', ``x'',
``x_3'', or ``y_17''.
There are 500 possible such variables: 25 letters (`a' - `z')
and 20 subscripts (`_0' - `_19').
The letters are case-insensitive, and `c' is a synonym of `c_0' and so on.
The letter `i' is reserved: it is not a variable, but rather the
constant square root of -1.

An expression may consist of just a variable, eg. ``(x_4)'' but when a
MathSolver command requires specifically a variable, it must
be input not as an expression, but specially, eg. ``&x_4''.
For example, the following replaces ``b'' with ``c + 2'' in an expression,
followed by the substitution ``c + 2i'':

(Note that, at present, MathSolver forces complex numbers into
floating-point: I've been too lazy to add rational number support there.)

Finally, PROCEDUREs may be the most confusing part of MathSolver
syntax.
They can be given names:

{ whatever ... "Greetings Galaxy!\n" } :sayhello

executed if an expression is constant and positive:

{ whatever ... "Greetings Galaxy!\n" } Progvar If

or executed repeatedly as long as a popped expression
is constant and positive:

{ whatever ... "Greetings Galaxy!\n" Progvar } Untilneg

Since the name of a procedure is executed rather than pushed onto the stack,
it cannot be used with ``If'' or ``Untilneg'' unless encapsulated in
another procedure, eg. as:

{ whatever } :Foo { Foo Progname } Untilneg

The usage of ``If'' and ``Untilneg'' is very clumsy, and I'd
be happy to hear suggestions for improvement.

Do not confuse algebraic variables with user words (``program variables'').
At present there is no way to bind an algebraic variable to a value,
but any instance can be set with the ``Substit'' command.

In the following ``constant'' refers to an expression with no
algebraic variable.

List of Commands

{ ... } :--
A procedure token is built and pushed onto the stack.

anytoken :any_username :--
The token is popped and retained in a separate named memory.

any_username :--
The named memory is accessed.
If it contains a procedure token, that procedure is executed.
Any other token is simply pushed onto the stack.

Pop :--
Remove and ignore the token at the top of the stack.

Dup :--
Replicate the top token and push it onto the stack.

Print :--
Remove the top token and print it on stdout.

Printn :--
Same as ``Print'' but append a line-feed.

Add (or ``+''); Subtract (or ``-''); Times (or ``*''); Quotient (or ``/'') :--
Remove the two top tokens from the stack; perform the indicated
(symbolic) arithmetic,
and push the result onto the stack.
If both inputs are polynomials, the result of Add, Subtract or Times
is also a polynomial, but the result of Quotient will be a rational
expression.
You can take the derivative of a rational expression, but not the integral.

expr Exp :--
The expression, which must be a constant, is replaced with its natural
antilogarithm.

expr1 expr2 variable Substit :--
Pop the three top elements of the stack, pushing the result of substituting
expr2 for variable in expr1.

expression variable Deriv :--
Variable is popped and expression is replaced with its derivative
with respect to that variable.

expression variable Integral :--
Variable is popped and expression is replaced with its integral
with respect to that variable.

expression lbnd ubnd variable DefIntegral :--
Variable, ubnd and lbnd are popped and expression is replaced
with its definite integral between lbnd and ubnd.

expr1 expr2 expr3 Condi :--
Pop the three top elements from the stack, pushing a spline-like
expression, with meaning similar to the C syntax ``expr1 > 0 ? expr2 : expr3''.
Such an expression can be printed with Print, but cannot be input
using the normal ``(...)'' MathSolver syntax.

1 BBVheuristic :--
Taking a multiple definite integral of a ``Condi'' spline can get
complicated, and MathSolver isn't very smart.
In some problems, including Example 4 of the sample program input,
the problem particulars mean that, as a complicated integral is
expanded, whenever the lower bound is variable the upper bound is
constant.
When ``1 BBVheuristic'' is specified, MathSolver knows that
any integral with Both Bounds Variable (``BBV'') can be ignored.
The correct answer would be obtained without specifying this heuristic,
but much more slowly.
(I know how to fix this, at least for Example 4, but it is cumbersome
to program.)

0 BBVheuristic :--
Disable that special heuristic.
(This is the default.)

integer Maxvar :--
Specify the number of recognized algebraic variables.
If the value is set to 8, for example, the variables `a' - `h'
are admissable.
If the value is 33, then `a' - `z' are admissable (except `i'), along
with `a_1' - `h_1'.
`a_0' is a synonym for `a' and so on.
The advantage of smaller Maxvar is speed and memory savings.

1 Varnamemode :--
This changes the ordering of algebraic variables from `a', `b', ...
where `a_1' is the 26'th variable to `a', `a_1',` a_2', ..., `a_19', `b', ...
The relevance of the ordering is as to which variable names are admissable
when Maxvar has less than its maximum setting of 500.

expr1 expr2 Equal :--
The equation ``expr1 = expr2'' is entered into a system of equations
for subsequent solution.

expr Zero :--
This is equivalent to ``expr 0 Equal''.

Linprint :--
Print said system.

Linsolve :--
Simplify the equations previously entered with ``Equal''.
This is useless except insofar as a subsequent `Linprint' is issued.
The equations need not be linear equations; on the other hand we don't
undertake to simplify them maximally.
Running Linsolve two or more times may simplify the system further.
We'll call this a feature instead of a bug.

Linclear :--
Destroy the equation system accesed by
`Equal,' `Zero,' `Linsolve,' `Linprint' either to save memory or to allow the
specification of a new system of equations.

a b Bincoeff :--
Replace a and b, which must be constant integers, with the number
of ways to choose b items from a set of size a.

integer Permsize :--
Set the size of permutation vectors.

integer ... integer Permu :--
``Permsize'' number of integers are popped and placed into a
special permutation token which is pushed on to the stack.
The integers should contain one instance each of 0, 1, ..., Permsize-1.

permutation Pbasis :--
At present this, and Print or Printn, are the only operations
supported on permutations.
Pbasis enters the permutation into a basis array to define a permutation group.

Cycix :--
Compute the cyclic index polynomial of the group defined by the basis
array, and push it onto the stack as a MathSolver expression.

Pbclear :--
Clear the basis array, to allow inputting a new basis.

{ whatever } expr If :--
Execute whatever if expr is constant and non-negative,
popping both from the stack.

{ whatever } Untilneg :--
Execute whatever and pop an expression from the stack when it
concludes.
Repeat this process until that expression is non-constant or negative.