First of all, version 2 contains many little additions that were thought of during work with FORM 1. Many times only real work will indicate what it is that a program is lacking, or how a program can be made much more efficient or friendlier. In this category we have
x?{a,b,c} makes the program more readable. It is tightly connected with
the following:
x?!{a,b,c} (any x except for
a,b,c). This
has a friend in the pattern:
f(x?!{y?})*f(y?!{x?})
which takes two occurrences of f provided that their arguments are
different. Getting around this type of wildcards is very difficult
in FORM 1. Basically all cases have to be specified separately.
f(x?pos_) matches only if x is a number and the number is positive.
There is a number of these sets.
Next there are internal reorganizations. Functions are treated differently now. Hence they take (usually) less space, and therefore expressions with many functions may take far less disk space. In addition there is a new type of functions, named tensors. They are very economical and the program knows some tensorial properties. In addition there is a compression algorithm (very simple, but fast and in need of very little memory) that makes most expressions about twice as short (with respect to needed disk space). The net result is that the same amount of disk space allows for much bigger expressions. Another improvement is in the field of traces of gamma matrices. Due to some extra options many n-dimensional traces will be much faster, and in many 4-dimensional traces the occurrences of Levi-Civita tensors in the output is nearly eliminated (when there should not be any). This turns out to be very useful. As a consequence the example of tau decay in the manual can be run in its original version. It takes then only a few seconds and gives the short answer that took so much work with FORM 1.
Most visual are the new features. We name most of them:
integer_) with various options.
f(x,y)*replace_(y,z) becomes f(x,z)
and f(x,y)*replace_(x,y,y,x) becomes f(y,x)
etc. This can give very quick renaming.
nargs_ gives for its value the number of arguments it contains.
reverse_ gives a list of arguments in its reverse order.
distrib_ is a very powerful function for combinatorics. It can
distribute lists of arguments over two functions in all different
ways. The applications are numerous, and most of these are very
hard to simulate with FORM 1 (or even impossible). The manual gives
some examples.
integer_: a rounding function.
Function t;
Table t(0:5,x,y?,??);
In this case there are 6 elements with the array-type argument
having a value ranging from 0 to 5 (inclusive). Once an occurrence
of t is found for which the first argument has such a value, the
rest of the pattern is matched. If this is successful the
replacement is made. This hybrid of tables and patterns is very
powerful. A good application is that the tail end of a recursion
(which gives the widest part of the tree and hence cost most
computer time) is put in a table. This makes that the first few
steps are done with the recursion, because these were not in the
table and then when the values in the table are reached the thing
can terminate immediately. This can gain much time.
collect fun;
transforms the contents of the brackets into arguments of the
function fun. This assumes that these brackets do not violate space
requirements following from the limitations on the size of a single
term. So
+ y * ( 1 + x + x^2 )
+ y^2 * ( 1 + x )
would become
+ y * fun(1+x+x^2) + y^2 * fun(1+x)
This can be very handy for compressing an expression and limiting
the number of terms with a given type of patterns, making the
patternmatching afterwards much faster.
4*f(1+a+a^2)*b + 2*f(1-2*a)*bgive after
.sort(polyfun=f); f(6+4*a^2)*b
f(a*b^n?).
form -d MAX=15 -l testruns the program test. The output goes also to the file test.log and the preprocessor variable is defined to be the string "15" as if the first statement is
#define MAX "15"
Many little things:
#message command.
A message field in the statistics. The message is specified in the .sort
instructions. This way one can see in the statistics where the program
is currently.
while/endwhile statement.
#ifdef preprocessor instruction.
Procedures do not have to have arguments. In that case the brackets and/or parentheses can be omitted. This existed already in some 2.0 versions.
The Normalize command is a command to bring function arguments in a
normal form. This form is defined by multiplying the argument by a
rational number x, such that the coefficient of its first term becomes
1. At the same time the coefficient of the term is divided by x. This
operation is convenient in combination with the polyfun option of the
.sort instruction, executed after antibracketting in a variable. The
function contains then polynomials and bringing them to a standard form
can help reducing the complexity of an expression considerably. It is
like a simple tool to allow the user to guide FORM in compressing an
expression that is ment for further numeric processing. Better tools for
this will be developed in FORM 3, as studies are under way. The problem
with lengthy FORTRAN output (or C) happens to be that compilers cannot
optimize subroutines that are too long, or at least they are very
inefficient at it. Hence there will be a need to have FORM give
preoptimized expressions.
The syntax of the Normalize command follows that of the 'argument'
command. Hence
Normalize, f, 2;normalizes the second argument of the function f. Etc.
The syntax of the id statement can be treated a little sloppier:
If the id is omitted, and the statement doesn't make sense otherwise
FORM will try to interprete the statement as an id statement in which
the id has been forgotten. Examples:
x = y; same as: id x = y;
only,x=y; same as: id,only,x=y;
It should be remarked that it has not been proven mathematically that
ambiguities are impossible. The most obvious ones have been guarded
against.
The write statement has the option setup to show what
the current setup parameters are:
write setup;
The id statement has a new option: ifmatch.
The statement
id,ifmatch->4,x=y;
other statements
label 4;
will jump to label 4 if there is a match and after the substitution has
been made. This can be handy when there is a long list of substitutions,
but applying them all at once may make the substitution tree too
complicated. Logically it is equivalent to
if ( match(x) );
id x = y;
else;
other statements
endif;
Such a nesting of if-statements becomes rather impractical when many
statements are involved. Moreover in this setup the matching has to be
done twice, while the ifmatch construction involves only a single
pattern matching.
The number of preprocessor levels is a setup parameter. These levels are
levels of input nesting, like calls from procedures from procedures from
include files. In addition the use of a preprocessor variable also
counts as one level. The relevant parameter is called PreLevels and its
default value has been increased from 10 to 20.
ToTensor and ToVector.
Both commands have two arguments, a tensor and a vector. The order in which
they occur is unimportant.
The command
ToTensor t,v;
is equivalent to
id v = t(?);
repeat id t(?)*t(??) = t(.,..);
This means that objects of the type v(m1)*v(m2)*v(m3) get replaced by
t(m1,m2,m3). (v is a vector and t a tensor).
This replacement occurs also
when v is contracted with other vectors or other tensors. Hence
v.p^10 becomes t(p,p,p,p,p,p,p,p,p,p);
The ToVector command is the opposite. The tensor t(m1,m2,m3)
is replaced by v(m1)*v(m2)*v(m3). The command
ToVector t,v;
is equivalent to
repeat id t(m1?,?) = v(m1)*t(.);
id t = 1;
Hence these two commands are for convenience and some extra speed only.
There is an extra (combinatorics) function by the name dd_[B.
This function is totally symmetric and formally equal to a sum of products of
Kronecker delta's d_. Hence
dd_(m1,m2) = d_(m1,m2)
dd_(m1,m2,m3,m4) = d_(m1,m2)*d_(m3,m4)+d_(m1,m3)*d_(m2,m4)
+d_(m1,m4)*d_(m2,m3)
etc.
This is however not where the benefit of the function comes in. When it
generates its terms it takes symmetries due to identical arguments into account.
Hence the evaluation of
dd_(p,p,p,p)
generates directly only one term with the proper combinatorial coefficient.
In some programs this can give big savings.
There are two extra built-in sets: even_ and odd_.
They can be used as in
id x^n?even_ = y^n;
This will replace only even powers of x.
The if statement has an extra function. One can use now
if ( count(x,1) == multipleof(3) ) then
Multipleof must have a single argument that is a positive integer.