OVERVIEW

The underlying language understood by PROGRAM_COMPILER has a C-like syntax, with
the same rules for names of functions, variables, and numbers.  Examples of
valid programs (assuming x,y,t are scalar inputs, u,v are 3d vector inputs, m is
a 3x3 matrix input, and r is a scalar output) are:

r = x * y + t;

r=exp(cos(x*x))-8.2e-3*y^3

a = x*y; b=x+y; r=a^b;

r=dot(m*v); r+=min(x,y);

n=outer(u,v); w=cross((m-n)*m*u-v,trans(m)*u); r=norm(w)*u[0];

r=x; if(y>2){r-=1;} else{r=2;}

VARIABLES

All variables are scalars, vectors, or matrices.  Vectors and matrices have
fixed size.  The types of inputs and outputs are determined before parsing from
calls to Add_Input and Add_Output.  Inputs should be initialized before
executing the program.  Outputs are automatically initialized to zero before
program execution; it is perfectly valid not to set all of the output variables.
New variables (such as a,b,n,w in the above examples) are created with unknown
type when they are first encountered during parsing.  The only thing that may be
done with a variable with unknown type is to assign to it using the = operator,
from which its type is set to match the right hand side.  After this, the
variable has fixed type and can be used as any other variable.  The variable pi
is created automatically.

All variables are global, so "r=3; if(x>0){a=4;}else{a=5;} r=a;" is valid.
Types may not be changed.  Thus, "a=vec(1,2);a=3;" and
"if(x>0){k=3;}else{k=vec(1,2);}" are both invalid.  Note that in the second
example, k is deduced as scalar in the first if branch, and then in the second
if branch the scalar variable k is assigned a vector, which is not allowed.

OPERATORS

The available operators is different from those of C.  Supported combinations
are indicated with M=matrix, V=vector, S=scalar. Supported operators are

a=b a+=b a.+=b a-=b a.-=b a*=b a.*=b a/=b a./=b a%=b a.%=b a^=b a.^=b
+a -a a+b a.+b a-b a.-b a*b a.*b a/b a./b a%b a.%b a^b a.^b
a<b a>b a<=b a>=b a==b a!=b !a a&&b a||b a?b:c

With the exception of *, /, *=, /=, and ?:, all of these are componentwise.  Dot
versions such as .* are always componentwise (rather like matlab).  Note that
x^2 is x*x, and x%2 is modulus.  For binary assignment ops, the combinations
S@=S, V@=S, V@=V, M@=S, M@=M are valid, where the sizes of matrices and vectors
must match.  For other the other binary ops, S@S, V@S, S@V, V@V, M@S, S@M, M@M
are supported.  Note that M+S adds the scalar to all entries of the matrix; this
is different from how the PhysBAM operator behaves.

Exceptions to the above are *, /, *=, and /= operators.  *=, /=, and / only
support scalars on the right hand side.  M*M and M*V perform matrix/matrix and
matrix/vector multiply in the usual mathematical sense, and the sizes of the
inputs must be compatible.

The ?: operator supports the combinations S?S:S, S?V:V, S?M:M.  The matrices and
vectors must have the same size.  As in C++, the ?: operator is lazy.  The last
two arguments (and any side-effects) are only executed if needed.  Unlike C++,
the && and || operators are not lazy.

In addition, there are function calls with the usual syntax:
"cos(x)+atan2(x,y)".  Vectors and matrices support indexing "u[1]+m[2,1]".

Note that all operators on matrices and vectors happen strictly at parse time.
Indices must be numbers.  "u[1]" as allowed, but "u[1+1]" and "a=1; u[a]" are
not.  The functions "zeros(2)" and "ones(2)" can be used to create vectors, and
"zeros(2,3)", "ones(2,3)", and "id(3)" can be used to create matrices.  The
inputs must be numbers, which indicate the fixed size of the results.
"ones(1+1)" and "a=3;id(a)" are not allowed.  There are no "complicated" matrix
or vector operations.  Thus, "exp(M)", "inv(M)", and "M^3" are all
componentwise.

FUNCTIONS

User-defined functions are not supported, but there are a number of built-in
ones.

1. Unary functions.  Operate componentwise on matrices and vectors.

inv, sqrt, exp, ln, sin, cos, asin, acos, atan, floor, ceil, rint, abs, tan,
cot, sec, csc, acot, asec, acsc

2. Binary functions.  Operate componentwise on matrices and vectors.

atan2, mod, pow, min, max

3. Matrix/vector construction

id(#)      identity matrix
zeros(#)   zero vector
zeros(#,#) zero matrix
ones(#)    all-ones vector
ones(#,#)  all-ones matrix
vec(...)   stacks scalars and vectors into a vector; any number of arguments.

4. Matrix/vector operations

norm(S)    Equivalent to abs.
norm(S)    Equivalent to x*x.

norm(V)    Vector magnitude
norm2(V)   Vector magnitude squared
dot(V,V)   Dot product
cross(V,V) Cross product (supports the same size combinations as PhysBAM)
outer(V,V) Outer product; input vectors may have different sizes.

trans(M)   matrix transpose
tr(M)      matrix trace
norm(M)    Frobenius norm
norm2(M)   Frobenius norm squared

ADDITIONAL NOTES ON MATRICES AND VECTORS

Vectors can be constructed with the syntax "vec(1,2,5)" and matrices and be
constructed using Matlab syntax "[1,2,3;2,3,4]" but where the commas are
required.  "[1 2;3 4]" is not allowed.  "vec(1,2,5)" is a 3-vector, "[1,2,5]" is
a 1x3 matrix, and "[1;2;5]" is a 3x1 matrix.  These are distinct types, and so
"dot([1;2;5],[1;2;5])" is not allowed.

The construct "M+s*I" would be implemented as "M+s*id(3)" in a similar way to
how this would be done in Matlab.  There is no specific routine for getting a
column or row from a matrix, but this can be accomplished with "M*vec(0,1,0)"
and "trans(M)*vec(0,1,0)".


