Desk calculator for Clifford algebra in arbitrarily many
Euclidean dimensions.  (No Minkowski space yet; sorry.)

Usage:  ./cliffer [options]

Command-line options include
  -h      print this message (and exit immediately).
  -v      increase verbosity.
  -i fn   take input from file 'fn'.
  -pre fn take preliminary input from file 'fn'.
  --      take input from STDIN

If no input files are specified with -i or --, the default is an
implicit '--'.  Note that -i and -pre can be used multiple times.
All -pre files are processed before any -i files.

      Advanced usage: If you want to make an input file into a
      self-executing script, you can use "#! /path/to/cliffer -i" as
      the first line.  Similarly, if you want to do some
      initialization and then read from standard input, you can use
      "#! /path/to/cliffer -pre" as the first line.

Ordinary usage example:
  # compound rotation:  two 90 degree rotations
  # makes a 120 degree rotation about the 1,1,1 diagonal:
  echo -e "1 0 0 90° vrml 0 0 1 90° vrml mul @v" | cliffer
Result:
          0.57735 0.57735 0.57735 2.09440 = 120.0000°

Explanation:
  *) Push a rotation operator onto the stack, by
  giving four numbers in VRML format
     X Y Z theta
  followed by the "vrml" keyword.
  *) Push another rotation operator onto the stack,
  in the same way.
  *) Multiply them together using the "mul" keyword.
  *) Pop the result and print it in VRML format using
    the "@v" keyword

On input, we expect all angles to be in radians.  You can convert
  from degrees to radians using the "deg" operator, which can be
  abbreviated to "°" (the degree symbol).  Hint: Alt-0 on some
  keyboards.
  As a special case, on input, a number with suffix "d" (with no
  spaces between the number and the "d") is converted from degrees to
  radians.
    echo "90° sin @" | cliffer
    echo "90 ° sin @" | cliffer
    echo "90d sin @" | cliffer
  are each equivalent to
    echo "pi 2 div sin @" | cliffer

Input words can be spread across as many lines (or as few) as you
  wish.  If input is from an interactive terminal, any error causes
  the rest of the current line to be thrown away, but the program does
  not exit.  In the non-interactive case, any error causes the program
  to exit.

On input, a comma or tab is equivalent to a space.  Multiple spaces
are equivalent to a single space.

Note on VRML format:  X Y Z theta
  [X Y Z] is a vector specifying the axis of rotation,
  and theta specifies the amount of rotation around that axis.
  VRML requires [X Y Z] to be normalized as a unit vector,
  but we are more tolerant;  we will normalize it for you.
  VRML requires theta to be measured in radians.

Also note that on input, the VRML operator accepts either four
  numbers, or one 3-component vector plus one scalar, as in the
  following example.

Same as previous example, with more output:
  echo -e "[1 0 0] 90° vrml dup @v dup @m
           [0 0 1] -90° vrml rev mul dup @v @m" | cliffer
Result:
        1.00000 0.00000 0.00000 1.57080 =  90.0000°
           [  1.00000  0.00000  0.00000 ]
           [  0.00000  0.00000 -1.00000 ]
           [  0.00000  1.00000  0.00000 ]
        0.57735 0.57735 0.57735 2.09440 = 120.0000°
           [  0.00000  0.00000  1.00000 ]
           [  1.00000  0.00000  0.00000 ]
           [  0.00000  1.00000  0.00000 ]

Even fancier:  Multiply two vectors to create a bivector,
then use that to crank a vector:
  echo -e "[ 1 0 0 ] [ 1 1 0 ] mul normalize [ 0 1 0 ] crank @" \
   | ./cliffer
Result:
    [-1, 0, 0]

Another example:  Calculate the angle between two vectors:
  echo -e "[ -1 0 0 ] [ 1 1 0 ] mul normalize rangle @a" | ./cliffer
Result:
    2.35619 = 135.0000°

Example: Powers: Exponentiate a quaternion.  Find rotor that rotates
only half as much:
   echo -e "[ 1 0 0 ] [ 0 1 0 ] mul 2 mul dup rangle @a " \
        " .5 pow dup rangle @a @" | ./cliffer
Result:
    1.57080 =  90.0000°
    0.78540 =  45.0000°
    1 + [0, 0, 1]§

Example:  Take the 4th root using pow, then take the fourth
power using direct multiplication of quaternions:
  echo "[ 1 0 0 ] [ 0 1 0 ] mul dup @v
  .25 pow dup @v dup mul dup mul @v" | ./cliffer
Result
    0.00000 0.00000 1.00000 3.14159 = 180.0000°
    0.00000 0.00000 1.00000 0.78540 =  45.0000°
    0.00000 0.00000 1.00000 3.14159 = 180.0000°

More systematic testing:
   ./cliffer.test1

The following operators have been implemented:
help    help message
listops list all operators
=== Unary operators
pop     remove top item from stack
neg     negate: multiply by -1
deg     convert number from radians to degrees
dup     duplicate top item on stack
gorm    gorm i.e. scalar part of V~ V
norm    norm i.e. sqrt(gorm}
normalize divide top item by its norm
rev     clifford '~' operator, reverse basis vectors
hodge   hodge dual aka unary '§' operator; alt-' on some keyboards
gradesel given C and s, find the grade-s part of C
rangle  calculate rotor angle
=== Binary operators
exch    exchange top two items on stack
codot   multiply corresponding components, then sum
add     add top two items on stack
sub     sub top two items on stack
mul     multiply top two items on stack (in subspace if possible)
cmul    promote A and B to clifs, then multiply them
div     divide clif A by scalar B
dot     promote A and B to clifs, then take dot product
wedge   promote A and B to clifs, then take wedge product
cross   the hodge of the wedge (familiar as cross product in 3D)
crank   calculate R~ V R
pow     calculate Nth power of scalar or quat
sqrt    calculate square root of power of scalar or quat
=== Constructors
[       mark the beginning of a vector
]       construct vector by popping to mark
unpack  unpack a vector, quat, or clif; push its contents (normal order)
dimset  project object onto N-dimensional Clifford algebra
unbave  top unit basis vector in N dimensions
ups     unit pseudo-scalar in N dimensions
pi      push pi onto the stack
vrml    construct a quaternion from VRML representation x,y,z,theta
clif    take a vector in D=2**n, construct a clif in D=n
	Note:  You can do the opposite via '[ exch unpack ]'
=== Printout operators
setbasis set basis mode, 0=abcdef 1=xyzabc
dump    show everything on stack, leave it unchanged
@       compactly show item of any type, D=3 (then remove it)
@m      show quaternion, formatted as a rotation matrix (then remove it)
@v      show quaternion, formatted in VRML style (then remove it)
@a      show angle, formatted in radian and degrees (then remove it)
@x      print clif of any grade, row by row
=== Math library functions:
       sin    cos    tan    sec    csc    cot    
       sinh   cosh   tanh   asin   acos   atan   
       asinh  acosh  atanh  ln     log2   log10  
       exp    atan2  
