The :POINTWISE-EVAL message is complex enough to deserve a complete subsection to itself. This message evaluates simple lisp arithmetic expressions, but operates on complete arrays rather than individual floats or integers. The main purpose of this is to speed such computations by pushing the inner loops from lisp down into C, thus making it practical to use such computations in interactive graphics -- for example, making a flag wave by adding a sinusoidal offset to every point in a flag thing before drawing it each frame.
(send GRL :pointwise-eval '(setq :X (+ :X 1)))
The above will add 1 to every element of the array named :X contained in graphic-relation GRL.
NOTE that although :POINTWISE-EVAL expressions use syntax very similar to standard lisp arithmetic expressions, they are executed by a completely separate interpreter! You may not embed arbitrary xlisp expressions within the :POINTWISE-EVAL expression. You may only use operators implemented by the :POINTWISE-EVAL interpreter, as documented in this subsection. The one minor (but useful) exception is that the values of lisp variables may be referred to:
(setq one 1) (send GRL :pointwise-eval '(setq :X (+ :X one)))
The above is equivalent to the first example.
The :POINTWISE-EVAL message will by default act upon all elements of the named arrays, except that FILL-POINTERs are respected when present. Conditionals may be used to restrict the :POINTWISE-EVAL expression to a subset of the array elements.
The :POINTWISE-EVAL message supports conditionals but not looping constructs. This is partly because conditionals are much more useful than looping constructs in this context ... and partly because they are much easier to implement in this context!
One notable difference between :POINTWISE-EVAL and xlisp expressions is that :POINTWISE-EVAL uses 0 and 1 for the logical values NIL and T respectively. In the tradition of C, 0 is considered FALSE in the context of conditional expressions, and all other values are considered TRUE. This fits much more naturally into the arithmetic orientation of the :POINTWISE-EVAL sublanguage than NIL and T would.
Internally, the interpreter supports four data types: bits, 32-bit integers, floats, and vectors of three floats (useful for x-y-z points, for normals, and for r-g-b color triples). Vectors are de/constructed by the LIST, FIRST, SECOND and THIRD operators.
The :POINTWISE-EVAL interpreter actually processes the expressions in chunks of a couple hundred array entries at a time. This is large enough to amortize expression overhead over reasonably long loop runs, yet small enough to keep temporary (stack) storage usage down to reasonable amounts.
It is not terribly difficult to add new operators to the interpreter, and they will likely accumulate at a steady pace ...
:POINTWISE-EVAL expressions may be nested arbitrarily, much as one expects in lisp: the <expression>s in the following syntax summaries may be replaced by any array name (such as :POINT-X), constant (such as 1.0) or nested subexpression (including conditionals). The pointwise operators can be applied to any mixture of arrays and constants; the following are all valid expressions:
(* :POINT-X :POINT-X) (/ 3.1416 2) (+ :POINT-X 1) (+ :point-x (if (> :point-y :point-z) :point-y :point-z))