FORM
version 4.0 beta
Reference manual

11-mar-2010

J.A.M.Vermaseren, J. Kuipers, M.Tentyukov and J.Vollinga


Contents


Running FORM

The proper way to invoke the running of FORM depends on the operating system that is being used. Here we will consider the UNIX operating system and its derivatives. The version for computers with the Windows operating system use Cygwin, which is a UNIX derivative as well and hence it functions similarly. In all cases a proper call of FORM is

     form [options] inputfile
The input file should have a name that ends in the extension .frm. It is however not needed to specify this extension. If this extension is absent, FORM will add it. Example:
     form myformprogram
and FORM will look for the file myformprogram.frm. The options are separated by blanks and start with a minus sign, followed by one or more alphabetic characters. They are:
-c
Error checking only. Notice that this will not work properly if there are conditionals in the preprocessor phase that depend on results obtained at earlier stages of the program.
-d
Next argument/option is the name of a preprocessor variable that will be defined before the run starts. A specific value can be assigned with the syntax -d VARIABLENAME=VALUE. The default value is 1.
-D
Same as -d.
-f
Output goes only to log file.
-F
Output only to log file. Further like -L or -ll.
-h
Wait for some key to be touched before finishing the run. Basically only for some old window based systems.
-I
Next argument/option is the path of a directory for include, procedure and subroutine files.
-l
Make a regular log file.
-ll
Make a log file without intermediate statistics.
-L
Same as -ll.
-M
Put the PID (process identifier) in the name of the temporary files. This makes for longer names, but gives a better guarantee of uniqueness. If a file with the created name exists already it will be overwritten. This option is for when several instances of FORM are started at nearly the same time as can happen from minos or make (with the make -j option).
-p
Next argument/option is the path of a directory for input, include, procedure and subroutine files.
-pipe
Indicates that FORM is started up as the receiving end of a pipe. Action will be taken to set up the proper communication channels.
-q
Quiet option. Only output expressions are printed.
-R
Recover from a crash. See the checkpoint mechanism in [*].
-s
Next argument/option is the path of a directory for a setup file.
-si
Same as -q.
-S
Next argument/option is the name of a setup file.
-t
Next argument/option is the path of a directory for temporary files.
-T
Puts FORM in a mode in which the maximum totalsize is measured and printed at the end of the program. For more information see the "On TotalSize;" statement[*].
-v
Only the version will be printed. The program terminates immediately after it.
-w
This should be followed immediately by a number. The number indicates the number of worker threads for TFORM. All other versions of FORM ignore this parameter. It should be noted that TFORM is a different program. For more information, please consult chapter [*].
-y
Run only the preprocessor and dump its output.

The log file is a file in which all output is collected, even when the output appears on the screen already. This makes it possible to follow the progress of the program and have a record of everything at the same time. The name of the log file is identical to the name of the program without the extension .frm but with the extra extension .log. Example:

     form -t /LocalDisk/mydir -l myformprogram
FORM will run the program in the file myformprogram.frm. Its output will both be written to the screen and into the file myformprogram.log. The temporary files (if any) will be made in the directory /LocalDisk/mydir. This last feature is very useful, because writing temporary files across a network can sometimes slow things down considerably.

The second way to pass parameters to FORM during startup is by means of environment variables, assuming of course that the system supports them. The following variables are supported:

FORMPATH
The directory in which FORM will look for procedures and header files, assuming it cannot find them in the current directory.
FORMTMP
The directory in which FORM will make its temporary files.
FORMSETUP
The full path and name of a setup file.
It should be noted that when a parameter is specified both in the command tail and in the environment the value of the command tail will be used.

The third way to pass parameters at startup is by means of a setup file. One of the first things FORM does is to locate such a startup file. The procedure that is being followed for this is:

If all the above attempts fail, FORM will not use a setup file. For more information about the setup file one should consult the corresponding chapter on page [*].


Variables

The objects of symbolic manipulations are expressions. Expressions are built up from terms and terms are composed of variables. FORM knows several types of variables, each of which has special rules assigned to it. The types of variables are symbols, vectors, indices, functions, sets, and expressions. In addition there are tensors and tables which are special functions, preprocessor variables (see chapter [*]), and there are dollar variables (see chapter [*]). The expressions are used either in the definition of an expression or in the right hand side of an expression or a substitution. When an expression is used in the right hand side of another expression or a substitution, it will be replaced by its contents at the first opportunity. Therefore an expression will never occur as a variable in the output of other expressions and we will ignore their potential presence in the remainder of this chapter. Similarly preprocessor variables and dollar variables will be replaced immediately when they are encountered.

The right hand side of an expression can consist of symbols, vectors, indices, functions and elements of a set. All these objects have to be declared before they can be used. The rules connected to each of these types of variables are described in the sections below.

Names

There are two types of names. Regular names consist of alphabetic and numeric characters with the condition that the first character must be alphabetic. FORM is case sensitive with respect to names. In addition there are formal names. These names start with the character [ and end with a matching character ]. In between there can be any characters that are not intercepted by the preprocessor. This allows the use of variables like [x+a]. Using formal names can improve the readability of programs very much, while at the same time giving the user the benefits of the greater speed. The use of denominators that are composite (like 1/(x+a)) is usually rather costly in time. Often 1/[x+a] is equally readable, while leading to the same results. Note however that the variable [x+a] will have to be declared properly. On the other hand: FORM may not have to know about x and a. These formal names can also be used for the names of expressions, but they are not valid for the names of dollar variables and the names of preprocessor variables.

Some names may contain special characters. All built in objects have for their last character an underscore (_). Dotproducts (the scalar product of two vectors) consist of two vectors separated either by a period or by a dollar sign. The dollar sign is used by FORM, when the output of the program has to be Fortran compatible. The user can replace the dollar sign in the output by an arbitrary character by defining the variable "DotChar" in the setup file. How this is done is explained in chapter [*]. In the input the user may apply either the notation with the period or the notation with the dollar. It is however recommended to use the period because in future versions the notation with the dollar may be dropped. The above conventions avoid the possibility of conflicts with reserved names, allowing the user full freedom when choosing names.

The dollar sign is also used as the first character in the name of dollar variables. The rest of the name should consist of alphanumeric characters of which the first should be alphabetic. The names of preprocessor variables should also consist of alphanumeric characters of which the first should be alphabetic. Also here the ones that are defined by the system have a trailing underscore (_) character.

With respect to the user defined names FORM is case sensitive. This means that the variables a and A are different objects. With respect to system defined objects FORM is case insensitive. Hence both d_ and D_ indicate the same Kronecker delta.

In many languages the use of the underscore (_) character is also permitted in the definition of user defined names. In FORM this is NOT the case. Even though the earlier manuals `forbade' this specifically there was a bug in earlier versions that permitted it to some degree. And because people don't read manuals, there were those who used this character and even made it into a vital part of their naming conventions. This then broke when version 3 was introduced. It should be clear though that the underscore character is reserved for a completely different type of future use and hence nothing can be done about this. Just remember: it is never a good idea to use undocumented features without consulting with the development team first.

The complex conjugate of a complex quantity is indicated by the character # appended to the name of the variable. In the current version of FORM not much is done with it. The latest approach is that it is seen as obsolete. If possible, please avoid using it.

The length of names is not restricted in FORM. There is one exception to this rule: names of expressions cannot be longer than 16 characters. Of course in practise there are physical limits on the size of names, posed by the size of the memory of the computer being used.

Symbols

Symbols are plain objects that behave most like normal variables in hand manipulations. Many hand manipulations concern polynomial formulae of simple algebraic variables. FORM assumes that symbols commute with all other objects and have a power connected to them. This power is limited to an installation dependent maximum and minimum. A power outside this range will lead to an error message. The user may override this built in restriction by one of private design that is more restrictive. Any power that falls outside the user defined range leads to the removal of the term that contains the variable with this power. Such a power restriction can be defined for each symbol separately.

Symbols can also have complex conjugation properties. A symbol can be declared to be real, imaginary or complex. This property is only relevant, when the complex conjugation operator is used. This operator has not been implemented and currently there are no plans to do so.

The syntax of the statement that defines symbols is given by (see also [*]):

     S[ymbols]    name[#{R|I|C}][(min:max)];
Each variable is declared by the presence of its name in a symbol-statement. If the # symbol is appended, it should be followed by either the character C, I or R to indicate whether the variable is complex, imaginary or real. The #R is not really necessary, as the type `real' is the default. It is not relevant whether the C, I, R are in upper or in lower case. A power restriction is indicated with a range between regular parentheses. If one of the two numbers is not present, the default value is taken. This default value is installation dependent, but it is at least -10000 and 10000 respectively. Each symbol-statement can define more than one variable. In that case the variables have to be separated either by comma's or by blanks. Example:
     S    x,y,z,a#c,b#c,c#c,r(-5:5),s(:20),t#i(6:9);
In this statement x, y and z are normal real algebraic variables. The variables a, b and c are complex. This means that for each of these variables two entries are reserved in the property lists: one for the variable and one for its complex conjugate. The variable r has a power restriction: Any power outside the specified range will cause the term containing this power to be eliminated. This is particularly useful in power series expansions. The restrictions on s are such that there is no limitation on the minimum power of s -with the exception of the built in restrictions- but a term with a power of s that is larger than 20 is eliminated. The variable t is imaginary. This means that under complex conjugation it changes sign. Its power restrictions are somewhat uncommon. Any power outside the range 6 to 9 is eliminated. There is however one exception: a term that does not contain t to any power ($t^0$) is not affected.
    s     x(:10),y;
    L     F=y^7;
    id    y=x+x^2;
    print;
    .end

Time =       0.01 sec    Generated terms =          4
                F        Terms in output =          4
                         Bytes used      =         54

   F =
      x^7 + 7*x^8 + 21*x^9 + 35*x^10;
Note that all terms with a power greater than 10 do not even count as generated terms. They are intercepted immediately after the replacement, before any possible additional statements can be carried out.

There are several built in symbols. They are:

i_: it is defined by i_^2 = -1 and this property is used by FORM to simplify terms. It is the only symbol that cannot be used as a dimension or a wildcard.

pi_: a reserved variable which will eventually be used to indicate the variable $\pi$.

coeff_: this variable is automatically replaced by the coefficient of the current term.

num_: this variable is automatically replaced by the numerator of the coefficient of the current term.

den_: this variable is automatically replaced by the denominator of the coefficient of the current term.

extrasymbols_: this symbol represents the number of extra symbols (see [*]).

Vectors

A vector is an object with a single index. This index represents a number that indicates which component of the vector is meant. Vectors have a dimension connected to them which is the dimension of the vector space in which they are defined. In FORM this dimension is by default set to 4. If the user likes to change this default, this can be done with the `Dimension'-statement. The use of this command affects the dimension of all vectors and the default dimension of indices. Its syntax is (see also [*]):

     Dimension number;
or
     Dimension symbol;
The number must be a number that fits inside a FORM word which is an installation dependent size, but it will be at least 32767. The number must be positive or zero. Negative values are illegal. If a symbol is specified, it must have been declared before. Any symbol may be used with the exception of i_.

The declaration of vectors (see [*]) is rather straightforward:

     V[ector] name [,MoreNames];
The names of the vectors may be separated either by comma's or by blanks. Example:
     V    p,q;
     I    mu,nu;
     L    F=p(mu)*q(nu);

Indices

Indices are objects that represent a number that is used as an integer argument for counting purposes. They are used mostly as the arguments of vectors or multidimensional arrays (or tensors). Their main property is that they have a dimension. This dimension indicates what values the index can take. A four-dimensional index can usually take the values 1 to 4. A very important property of an index is found in the convention that it is assumed that an index that is used twice in the same term is summed over. This is called the Einstein summation convention. Hence the term p(mu)$*$q(mu) is equivalent to the scalar product of the vectors p and q (which can also be written as p.q).

There are of course also indices that should not be summed over. Such indices we call zero-dimensional. This is just a convention. To declare indices we use the statement (see also [*]):

     Index name[={number|symbol}]
                   [,othername[={number|symbol}]];
When the equals sign is used, this indicates the specification of a dimension. Indices that are not followed by an equals sign get the dimension that is currently the default dimension (see also [*])). The dimension can be either a number that is zero or positive (zero indicates that the summation convention does not apply for this index) or it can be any symbol with the exception of the symbol i_. The symbol must have been declared before.

The most important use of the dimension of an index is the built in rule that a Kronecker delta with twice the same index is replaced by the dimension of this index, provided this index has a non-zero dimension. Therefore when mu is 4-dimensional, d_(mu, mu) will be replaced by 4 and when nu is n-dimensional, d_(nu,nu) will be replaced by n. If rho is zero dimensional, the expression d_(rho,rho) is left untouched.

In addition to the symbolic indices there is a number of fixed indices with a numeric value. The values of these indices runs from zero to an installation dependent number (usually 127). Users who like a different maximum value should consult chapter [*] about the setup parameters. The numeric indices are all assumed to have dimension zero, hence no summation is applied to them. This means that they can be used for vector components. It is therefore perfectly legal to use:

     V    p,q,r;
     L    F=p(1)*q(1)*r(1)+p(2)*q(2)*r(2);
When two numeric indices occur inside the same Kronecker delta, a value is substituted for this delta. Normally this value is one, when the two indices are identical and zero, when they are different. The value for the diagonal elements can be changed with the `FixIndex'-statement (see also [*]):
     Fi[xIndex] number:value [,number:value];
This command assigns to d_(number,number) the given value. This value must fit inside a single FORM word. This means that this value can at least be in the range -32768 to +32767. For more details on the size of a FORM word one should consult the installation manual.

In the case of summable indices the use of three times the same index in the same term would cause problems. FORM will execute the contraction for the first pair it encounters, after which the third index is left. In the case of four or more indices the pairing for the contractions depends on the order in which the parts of the term are processed. Hence to the user the result may seem to be quasi random. Nothing can be done about this and the user should guard against such ambiguous notation.

There is a special version of the index declarations that is used for traces of gamma matrices in n dimensions. If an index is declared with

    Symbols n,epsilon;
    Index m=n:epsilon;
its dimension will be n and it is assumed that epsilon can be used for $(n-4)$ during the taking of the trace of a string of gamma matrices. It is also possible to use this notation in the dimension-statement. See also chapter [*] on the gamma matrices.

Functions

There are two classes of functions: commuting functions which commute automatically with all other objects, and non-commuting functions which do not necessarily commute with other non-commuting functions. An object is declared to be a commuting function with the `cfunction' command. Of this command the first two characters are mandatory, the others optional. An object is declared to be a non-commuting function with the `function' command. Here only the f is mandatory. The declaration of a function knows one option. This option concerns the complexity properties of the function. It is indicated by a # following the name, after which one of the characters R, I, C specifies whether the function is real, imaginary or complex. The declaration that a function is real is unnecessary as `real' is the default property. Example:

     CF   fa,fb,fc;
     F    ga,gb,gc#c;
In this example the functions fa, fb, fc are commuting and the functions ga, gb and gc are not necessarily commuting. In addition the function gc is complex. More about functions and their conventions is explained in chapter [*].

Within the commutation classes there are several types of special functions. Currently these are tensors and tables. The tables are described in section [*] and in chapter [*].

Tensors are special functions. Their arguments can be indices and vectors only. When an argument is a vector, it is assumed that this vector has been put in this position as the result of an Einstein summation, i.e., there used to be an index in this position, but the index was contracted with the index of the vector. Hence FORM assumes that there is a linearity property with respect to such vectors. Tensors are declared with one of the following statements (see also pages [*], [*],[*]):

    T[ensors] t1;
    CT[ensors] t2;
    NT[ensors] t3;
The type `ntensor' indicates a non-commuting tensor, while the other two types indicate commuting tensors. Note that the 'T' is a commuting tensor, while the 'F' indicates a non-commuting function. In addition to the above declarations one may add the same complexity properties that can be added for functions. This is currently not very useful though as there exists no complex conjugation operator yet. Internally a tensor is a function with special properties. Hence when function properties are discussed, usually these properties refer also to tensors, unless the type of the arguments would not allow the operations or arguments specified.

Sets

A set is a (non-empty) collection of variables that should all be of the same type. This type can be symbols, vectors, indices or functions. A set has a name which can be used to refer to it, and this name may not coincide with any of the other names in the program. A set is declared by giving its name, followed by a colon, after which the elements of the set are listed. The first element determines the type of all the elements of the set. All elements must have been declared as variables before the set-statement. There can be only one set per statement. Example (see also [*]):

     s    xa, xb, xc, xd, ya, x, y;
     i    mu, nu, rho;
     set exxes: xa, xb, xc, xd;
     set yyy: xc, xd, xb, ya;
     set indi:  mu, nu, rho, 1, 2, 3;
     set xandy: xa, ya;
We see here that a single symbol (xa) can belong to more than one set. Also the fixed indices (1, 2 and 3) can be elements of a set of indices and the numbers that can be powers can also be members of a set of symbols (usually -9999 to + 9999). If this can cause confusion, FORM will give a warning and interpret the set as a set of symbols.

In addition to the user defined sets there are some built in sets with a special meaning. These are:

int_
This is a set of symbols. It refers to all integer numbers that fit inside a FORM word.
pos_
This is a set of symbols. They are the positive integers that fit inside a FORM word.
pos0_
A set of symbols. They are all non-negative integers that fit inside a FORM word.
neg_
A set of symbols. They are all negative integers that fit inside a FORM word.
neg0_
A set of symbols. They are all non-positive integers that fit inside a FORM word.
symbol_
The set of all formal symbols. It excludes integers, numbers and whole function arguments.
fixed_
The set of all fixed indices.
index_
The set of all indices.
number_
The set of all rational numbers.
even_
This is a set of symbols. It refers to all even integer numbers that fit inside a FORM word.
odd_
This is a set of symbols. It refers to all odd integer numbers that fit inside a FORM word.

Sets can be used during wildcarding. When x is a symbol, the notation x? indicates `any symbol'. This is sometimes more than we want. In the case that we would like `any symbol that belongs to the set exxes' we would write x?exxes which is an unique notation as usually the question mark cannot be followed by a name. There should be no blank between the question mark and the name of the set. The object x?indi would result in a type mismatch error, if x is a symbol and indi a set of indices.

This use of wildcards belonging to sets can be extended even more: The notation x?exxes?yyy means that x should belong to the set exxes, and its replacement should be the corresponding element of set yyy. At first this notation looks unnecessarily complicated. The statement

     id   x?exxes?yyy = x;
should have the much simpler syntax
     id   exxes = yyy;
This last notation cannot be maintained, when the patterns are more complicated, hence it has been omitted altogether.

When things become really complicated, the sets can be used as kind of an array. They can be used with a fixed array index (running from 1 for the first element). When they have a symbolic argument (must be a symbol), they are either in the right hand side of an id-statement and the symbol must be replaced by a number by means of a wildcard substitution or in the left hand side and the symbol is automatically seen as a wildcard. The set must still follow the question mark of a wildcard. An example will clarify the above:

    s a1,a2,a3,b1,b2,b3,x,n;
    f g1,g2,g3,g;
    set aa:a1,a2,a3;
    set bb:b1,b2,b3;
    set gg:g1,g2,g3;
   
    id  g(x?aa[n]) = gg[n](bb[n]) + bb[2]*n;
The n in the left hand side is automatically a symbol wildcard. x must match an element in aa and n takes its number. In the right hand side gg[n] becomes an array element, when the n is substituted. The same holds for bb[n]. The element bb[2] is immediately replaced by b2, so there is rarely profit by using this, unless the preprocessor had something to do with the construction of this quantity. As should be clear from the above: the array elements are indicated with straight braces.

Another use of sets is in the select option of the id-statement. This is discussed in chapter [*] on pattern matching.

Neither the array properties of the sets nor the select option of the id-statement can be used in conjunction with the built in sets. These sets are not supposed to have a finite number of indices.

Apart from the above sets that were formally declared and used by name there is a second way to use sets. These sets are called implicitly declared sets. They are declared at the position that they are used and their use defines their contents. The elements of the set should be enclosed by a pair of curly brackets and the set is placed at the position where otherwise the name of the set would be used:

    Symbols a1,a2,a3,b1,b2,b3,x,n;
    CFunctions g1,g2,g3,g;
    Local expr =
        g(a1)+g(a2)+g(a3)+g(x);
    id,g(x?{a1,a2,a3}[n]) = {g1,g2,g3}[n]({b1,b2,b3}[n]);
    print;
    .end

   expr =
      g1(b1) + g2(b2) + g3(b3) + g(x);
Such a set exists internally only till the end of the module in which it is used. It can be used at all positions where named sets can be used. Hence they can also be used, when the array properties of sets are considered.

The preprocessor has to be able to distinguish these sets from strings for its calculator (see chapter [*]). Usually this is no problem, because any regular name contains at least one character that is not accepted by this calculator. If the only elements in the set are numeric the comma will tell the preprocessor that it is a set and the calculator should not be used. This leaves the case of a set with a single numeric element. By placing a comma either before or after it the use of the calculator is vetoed. For the interpretation of the set this makes no difference.

When it is possible to demand an object to be inside a set, it should also be possible to demand that an object be outside a set. This is done with the `?!' operator instead of the `?' operator. The extra exclamation mark is like a `not' operator. It can be used only, when its use makes sense. Hence it cannot be used in conjunction with the array properties of sets and together with the select option of the id-statement. So its only use is in patterns of the type

    x?!setname
    x?!{a,b,c}
as is done in
    id  x^n?!{,-1} = x^(n+1)/(n+1);
There is a variation of the second type that is not possible with named sets:
    Symbols a,b,x,y,z;
    CFunction f;
    
    id  f(x?!{a,y?,z?})*f(y?!{b,x?,z?})*f(z?!{x?,y?})
            =  .........
In this complicated pattern the z is easiest: It is not allowed to be equal to the objects that will be substituted for the wildcards x and y. The symbol x cannot be equal to the wildcards y and z, but in addition it should not be equal to a. A similar condition holds for y. One could argue that at least one of these conditions is superfluous from the strictly logical viewpoint. It depends however on the order of the declarations in how FORM runs through the pattern, so it would require some trying to see which `not' specifications are superfluous. If for instance the first function is matched first, there is still no assignment for z. This means that the z? in the set cannot be used yet and hence it places no restrictions on x. Therefore it is the x? in the last function that causes x and z to be different. If on the other hand the last function would be matched first, we need the z? in the set of the first function. From the strict logical viewpoint, FORM could go back over the pattern and still make the appropriate rejections, but this would cost too much extra time. As one can see, it is safer to specify both.

The autodeclare conventions

As we have seen above, all variables that are introduced by the user have to be declared. As such FORM is a strong typing language. This isn't always handy. Hence it is possible to introduce some rules about the automatic declaration of classes of variables. This is done with the AutoDeclare statement (see also [*]). If we use the statements

     AutoDeclare Symbol x,tt;
     AutoDeclare CFunction f,t;
any object encountered by the compiler of which the name starts with the character x will automatically be declared as a symbol. Also objects of which the name starts with the characters tt will be declared as symbols. Objects of which the name starts with the characters f or t, but not with the string tt, and that have not yet been declared will be declared automatically as commuting functions. As one can see, in the case of potential conflicts (like with t and tt) the more restrictive one takes precedence. This is independent of the order of the AutoDeclare statements. One disadvantage of the use of the AutoDeclare statement is that one looses a certain amount of control over the order of declaration of the variables, as now they will be declared in the order in which they occur in the statements. The order of the declaration determines the ordering of the objects in the output.

Name lists

Sometimes it is necessary to see how FORM has interpreted a set of declarations. It can also be that declarations were made in an unlisted include file and that the user wants to know what variables have been defined. The lists of active variables can be printed with the statement

     On names;
This statement sets a flag that causes the listing of all name tables and default properties that are active at the moment that the compiler has finished compiling the current module and all modules after. The printing is just before the algebra processor takes over for the execution of the module - assuming that no error condition exists. If the `On names' is specified in a module that ends with a .global-instruction, the name lists will be printed at the end of each module, as printing the name lists will then be the default option. If one likes to switch this flag off, this can be done with the statement
     Off names;
which prohibits the printing of the name lists in the current module and all modules following.

Dummy indices

Sometimes indices are to be summed over but due to the evaluation procedures some terms contain the index mu and other terms contain the index nu. There is a command to sum over indices in such a way that FORM recognizes that the exact name of the index is irrelevant. This is the `sum'-statement (see also [*]):

   i  mu,nu;
   f  f1,f2;
   L  F=f1(mu)*f2(mu)+f1(nu)*f2(nu);
   sum  mu;
   sum  nu;
   print;
   .end
At first the expression contains two terms. After the summations FORM recognizes the terms as identical. In the output we see the term:
   2*f1(N1_?)*f2(N1_?)
The N1_? are dummy indices. The dimension of these dummy indices is the current default dimension as set with the last dimension-statement. This may look like it is a restriction, but in practice it is possible to declare the default dimension to have one value in one module, take some sums, and do some more operations, and then give the default dimension another value in the next module. It should be realized however that then the dimension of the already existing dummy indices may change with it.

The scheme that is used to renumber the indices in a term is quite involved. It will catch nearly all possibilities, but in order to avoid to try all $n!$ permutations, when there are n pairs of dummy indices, FORM does not try everything. It is possible to come up with examples in which the scheme is not perfect. It is left as a challenge for the reader to find such an example. In the case that the scheme isn't sufficient one can use the Renumber statement (see [*]) to force a complete renumbering. As this involves n! attempts in which n is the number of different dummy indices, this can become time consuming.

These dummy indices can be used to solve a well known problem in the automatic summation of indices. This problem occurs, when summed indices are found inside a subexpression that is raised to a power:

    Index mu,nu;
    CFunctions f,g;
    Vectors p,q;
    Local F = (f(mu)*g(mu))^2;
    sum mu;
    id f(nu?) = p(nu);
    id g(nu?) = q(nu);
    print;
    .end

   F =
      p.p*q.q;
Clearly the answer is not what we had in mind, when we made the program. There is an easy way out:
    Index mu,nu;
    Symbol x;
    CFunctions f,g;
    Vectors p,q;
    Local F = x^2;
    repeat;
        id,once,x = f(mu)*g(mu);
        sum mu;
    endrepeat;
    id f(nu?) = p(nu);
    id g(nu?) = q(nu);
    print;
    .end

   F =
      p.q^2;
This time things went better, because each sum-statement moves an index mu to a new dummy index.

There are some extra problems connected to dummy indices. Assume that we have the expression F which contains

     F = f(N1_?,N2_?)*f(N2_?,N1_?);
and next we have the module
     Indices mu,nu,rho,si;
     Vectors p1,p2,p3,v;
     Tensor g;
     Local G = e_(mu,nu,rho,si)*g(mu,nu,p1,v)*g(rho,si,p2,v);
     sum mu,nu,rho,si;
     Multiply F^3;
     id  v = e_(p1,p2,p3,?);
     print;
     .end

   G =
      f(N1_?,N2_?)*f(N2_?,N1_?)*f(N3_?,N4_?)*f(N4_?,N3_?)*
      f(N5_?,N6_?)*f(N6_?,N5_?)*g(N7_?,N8_?,p1,N9_?)*
      g(N10_?,N11_?,p2,N12_?)*e_(p1,p2,p3,N9_?)*
      e_(p1,p2,p3,N12_?)*e_(N7_?,N8_?,N10_?,N11_?);
Here the situation with the dummy indices becomes rather messy, and all earlier versions of FORM were not prepared for this. Their answer could be:
    G =
      f(N1_?,N2_?)*f(N1_?,N2_?)*f(N1_?,N2_?)*f(N2_?,N1_?)*
      f(N2_?,N1_?)*f(N2_?,N1_?)*g(N1_?,N2_?,p2,N3_?)*
      g(N4_?,N5_?,p1,N6_?)*e_(p1,p2,p3,N3_?)*
      e_(p1,p2,p3,N6_?)*e_(N1_?,N2_?,N4_?,N5_?);
which is clearly not what the program is supposed to give. In the current version we have made the tracing of the dummy indices and the renumbering of them at the proper moment a lot better. It is however not complete as a complete implementation might severely influence the speed of execution at some points. The scheme is complete for the inclusion of local and global expressions. On the other hand it doesn't work for the contents of dollar variables. Neither does it work for dummy indices introduced in user defined code as in
     id  x^n? = (f(N1_?)*g(N1_?))^n;
For the latter case we showed a workaround above. Anyway there is a certain ambiguity here. Just imagine we write
     id  x^n? = f(N1_?)^n*g(N1_?)^n;
Formally it is exactly the same, but what we mean is far from clear. For the dollar variables we considered the contracted dummy indices rare enough that it doesn't merit sacrificing speed. And then there is one more little caveat. Global expressions that were stored with older versions of FORM than version 3.2, but are read with version 3.2 or later would have a problem if the expression were to contain dummy indices. The newer version of the .sav files will contain information about the dummy indices. FORM can still read the old versions but will have to `invent' information by assuming that there are no dummy indices. If there are expressions with such dummy indices the best is to copy the expressions to a new expression and let the copying be followed by a .sort. That should set things straight. A final remark: if an elegant solution is found with which the above cases could be made to work without the penalty in execution time, it will be built in in the future.

Kronecker delta's

The built in object d_ represents the Kronecker delta. Even though this object looks a little bit like a tensor, internally it isn't treated as such. Actually it has its own data type. It must have exactly two arguments and these arguments should be either indices or vectors. A d_ with at least one vector is immediately replaced, either by a vector with an index (if there is one vector and one index) or by a dotproduct (when there are two vectors). If a Kronecker delta contains an index that occurs also at another position in the same term, and if that index is summable, and if the index occurs as the index of a vector, inside a tensor, inside another d_ or as the argument of a function, and the object inside which it occurs is not inside the argument of a function itself (unless the d_ is inside the same argument) then the Einstein summation convention is used and the d_ is eliminated, while the second occurrence of the index is replaced by the other index in the d_ (Are you still with us?). When a Kronecker delta has two identical indices and these indices are summable, the d_ is replaced by the dimension of the index. If they are fixed indices, the d_ is replaced by one, unless this value has been altered with the fixindex-statement. Some examples of Kronecker delta's are given in section [*].

Extra Symbols

Starting with version 4.0 FORMis equipped with a mechanism to replace non-symbol objects by internally generated symbols. These are called the extra symbols. Their numbering starts at maximum number allowed for internal objects and then counts down. Hence their ordering will be opposite to what might otherwise be expected. It is possible to control their representation when they are to be printed in the output. For this there is the ExtraSymbols([*]) statement. The definitions of the extra symbols can be made visible with the %X option in the #write preprocessor instruction.

Extra symbols can be introduced by the user with the ToPolynomial statement ([*]). This statement replaces all objects that are not numbers or symbols to positive powers by extra symbols. This may be needed for some new manipulations and can also be very handy for output that is to be treated by for instance a FORTRAN or C compiler. The FromPolynomial statement replaces the extra symbols again by their original meaning.

    Vector p,q,p1,p2;
    CFunction f;
    CFunction Dot,InvDot;
    Symbol x,x1,x2;
    Set pdot:p,q;
    Off Statistics;
    Local F = x+x^2+1/x+1/x^2+f(x1)+f(x2)*p.q*x+f(x2)/p.q^2;
    id  p1?pdot.p2?pdot = Dot(p1,p2);
    id  1/p1?pdot.p2?pdot = InvDot(p1,p2);
    Print;
    .sort

   F =
      x^-2 + x^-1 + x + x^2 + f(x1) + f(x2)*Dot(p,q)*x + f(x2)*InvDot(p,q)^2;

    ExtraSymbols,array,Y;
    Format DOUBLEFORTRAN;
    ToPolynomial;
    Print;
    .sort

      F =
     & Y(1) + Y(1)**2 + Y(2) + Y(5)**2*Y(3) + x + x*Y(4)*Y(3) + x**2

    #write <sub.f> "      SUBROUTINE sub(Y)"
    #write <sub.f> "*"
    #write <sub.f> "*      Compute the extra symbols. Generated on `DATE_'"
    #write <sub.f> "*"
    #write <sub.f> "      REAL*8 Y(`EXTRASYMBOLS_')"
    #write <sub.f> "      REAL*8 Dot,InvDot"
    #write <sub.f> "      Dot(p1,p2)=p1(1)*p2(1)-p1(2)*p2(2)-p1(3)*p2(3)-p1(4)*p2(4)"
    #write <sub.f> "      InvDot(p1,p2)=1.D0/(Dot(p1,p2))"
    #write <sub.f> "*"
    #write <sub.f> "*        We still have to add definitions here."
    #write <sub.f> "*        And we have to import all the variables."
    #write <sub.f> "*"
    #write <sub.f> "%X"
    #write <sub.f> "*"
    #write <sub.f> "      RETURN"
    #write <sub.f> "      END"
    ExtraSymbols,underscore,Z;
    Format Normal;
    Format 80;
    Print;
    .end

   F =
      Z1_ + Z1_^2 + Z2_ + Z5_^2*Z3_ + x + x*Z4_*Z3_ + x^2;

    FromPolynomial;
    Print;
    .end

   F =
      x^-2 + x^-1 + x + x^2 + f(x1) + f(x2)*Dot(p,q)*x + f(x2)*InvDot(p,q)^2;
In the ExtraSymbols statement we say that we want the extra symbols to be presented as an array with the name Y. The alternative is a set of symbols with names ending in an underscore, but that would not make the FORTRAN compiler very happy. Then we convert the expression to symbols. As one can see, everything got converted to elements of an array Y which are treated as symbols. After we have written the file sub.f (notice that EXTRASYMBOLS_ is a built in symbol indicating the number of extra symbols) we change the representation to the (default) notation with an underscore and the character Z. The contents of the file sub.f are:
      SUBROUTINE sub(Y)
*
*      Compute the extra symbols. Generated on Sat Apr  2 20:40:33 2011
*
      REAL*8 Y(5)
      REAL*8 Dot,InvDot
      Dot(p1,p2)=p1(1)*p2(1)-p1(2)*p2(2)-p1(3)*p2(3)-p1(4)*p2(4)
      InvDot(p1,p2)=1.D0/(Dot(p1,p2))
*
*        We still have to add definitions here.
*        And we have to import all the variables.
*
      Y(1)=x**(-1)
      Y(2)=f(x1)
      Y(3)=f(x2)
      Y(4)=Dot(p,q)
      Y(5)=InvDot(p,q)

*
      RETURN
      END
As one can see, with very little effort this routine can be made into a proper subroutine that computes all elements of the array Y which can then be used for computing the expression F.

Restrictions

There is a restriction on the total number of variables that FORM can handle. For the number of symbols, vectors, indices, functions and sets together the exact number depends on the type of computer. For a computer with a 32-bits processor this number is 32768. This includes the built in objects. Individual types of variables (like symbols) are usually restricted to about 8000. For a computer with a 64-bits processor the maximum has been set arbitrarily at 2000000000. In addition there are restrictions on the total amount of memory needed by FORM to maintain an administration of all these variables. These restrictions are set by the memory allocator of the computer on which FORM is running.

Some common bugs

There is a type of error by the user (including at times the author) that is so common that it deserves mentioning here. Consider the code:

     Symbol x1,x2
     Index m1,m2;
As a statement it is perfectly legal, but it may produce rather funny errors at a later stage when we try to use m1 or m2. Inspection with the `On names;' statement shows that we have the symbols x1,x2,Index,m1,m2. This is most likely not what the user wanted. Closer inspection shows that we forgot the semicolon at the end of the symbol statement. We should have had:
     Symbol x1,x2;
     Index m1,m2;
This is the most common error for which FORM cannot give a direct error message (it is after all a legal statement). Hence when faced with mysterious errors or error messages, one could have a good look by using the `On names' statement. Maybe it shows something, and if not, one has to look for other causes.


The preprocessor

The preprocessor is a program segment that reads and edits the input, after which the processed input is offered to the compiler part of FORM. When a module instruction is encountered by the preprocessor, the compilation is halted and the module is executed. The compiler buffers are cleared and FORM will continue with the next module. The preprocessor acts almost purely on character strings. As such it does not know about the algebraic properties of the objects it processes. Additionally the preprocessor also filters out the commentary.

The commands for the preprocessor are called instructions. Preprocessor instructions start with the character # as the first non-blank character in a line. After this there are several possibilities.

#:
Special syntax for setup parameters at the beginning of the program. See the chapter on the setup parameters.
#$-$, #$+$
Turns the listing of the input off or on.
#name
Preprocessor command. The syntax of the various commands will be discussed below.
#$name
Giving a value to a dollar variable in the preprocessor. See chapter [*] on dollar variables.


The preprocessor variables

In order to help in the edit function the preprocessor is equipped with variables that can be defined or redefined by the user or by other preprocessor actions. Preprocessor variables have regular names that are composed of strings of alphanumeric characters of which the first one must be alphabetic. When they are defined one just uses this name. When they are used the name should be enclosed between a backquote and a quote as if these were some type of brackets. Hence `a2r' is the reference to a regular preprocessor variable. Preprocessor variables contain strings of characters. No interpretation is given to these strings. The backquote/quote pairs can be nested. Hence `a`i'r' will result in the preprocessor variable `i' to be substituted first. If this happens to be the string "2", the result after the first substitution would be `a2r' and then FORM would look for its string value.

The use of the backquotes is different from the earlier versions of FORM. There the preprocessor variables would be enclosed in a pair of quotes and no nesting was possible. FORM still understands this old notation because it does not lead to ambiguities. The user is however strongly advised to use the new notation with the backquotes, because in future versions the old notation may not be recognized any longer.

FORM has a number of built in preprocessor variables. They are:

VERSION_ The current version as the 3 in 3.2.
SUBVERSION_ The sub-version as the 2 in 3.2.
NAMEVERSION_ For special versions that are experimental. Otherwise empty.
NAME_ The name of the program file.
DATE_ The date of the current run.
CMODULE_ The number of the current module.
SHOWINPUT_ If input listing is on: 1, if off: 0.

If FORM cannot find a preprocessor variable, because it has neither been defined by the user, nor is it one of the built in variables, it will look in the systems environment to see whether there is an environment variable by that name. If this is the case its string value will be substituted.


The preprocessor calculator

Sometimes a preprocessor variable should be interpreted as a number and some arithmetic should be done with it. For this FORM is equipped with what is called the preprocessor calculator. When the input reading device encounters a left curly bracket {, it will read till the matching right curly bracket } and then test whether the characters (after substitution of preprocessor variables) can be interpreted as a numerical expression. If it is not a valid numerical expression the whole string, including the curly brackets, will be passed on to the later stages of the program. If it is a numerical expression, it will be evaluated, and the whole string, including the curly brackets, will be replaced by a textual representation of the result. Example:

    Local F`i' = F{`i'-1}+F{`i'-2};
If the preprocessor variable i has the value 11, the calculator makes this into
    Local F11 = F10+F9;
Valid numerical expressions can contain the characters
   0 1 2 3 4 5 6 7 8 9 + - * / % ( ) { } & | ^ !
The use of parentheses is as in regular arithmetic. The curly brackets fulfil the same role, as one can nest these brackets of course. Operators are:
$+$
Regular addition.
$-$
Regular subtraction.
$\ast$
Regular multiplication.
$/$
Regular (integer) division.
$\%$
The remainder after (integer) division as in the language C.
$\&$
And operator. This is a bitwise operator.
$\vert$
Or operator. This is a bitwise or.
$\wedge$
Exponent operator.
$!$
Factorial. This is a postfix operator.
$\wedge\%$
A postfix ${}^2\!\log$. This means that it takes the ${}^2\!\log$ of the object to the left of it.
$\wedge/$
A postfix square root. This means that it takes the square root of the object to the left of it.
Note that all arithmetic is done over the integers and that there is a finite range. On 32 bit systems this range will be $2^{31}-1$ to $-2^{31}$, while on 64 bit systems this will be $2^{63}-1$ to $-2^{63}$. In particular this means that {13^/} becomes 3. The preprocessor calculator is only meant for some simple counting and organization of the program flow. Hence there is no large degree of sophistication. Very important is that the comma character is not a legal character for the preprocessor calculator. This can be used to avoid some problems. Suppose one needs to make a substitution of the type:
    id f(x?!{0}) = 1/x;
in which the value zero should be excluded from the pattern matching (see dynamical sets in chapter [*] on pattern matching). This would not work, because the preprocessor would make this into
    id f(x?!0) = 1/x;
which is illegal syntax. Hence the proper trick is to write
    id f(x?!{,0}) = 1/x;
With the comma the preprocessor will leave this untouched, and hence now the set is passed properly.

Good use of the preprocessor calculator can make life much easier for FORM. For example the following statements

    id  f(`i') = 1/(`i'+1);
    id  f(`i') = 1/{`i'+1};
are quite different in nature. In the first statement the compiler gets an expression with a composite denominator. The compiler never tries to simplify expressions by doing algebra on them. Sometimes this may not be optimal, but there are cases in which it would cause wrong results (in particular when noncommuting and commuting functions are mixed and wildcards are used). Hence the composite denominator has to be worked out during run time for each term separately. The second statement has the preprocessor work out the sum and hence the compiler gets a simple fraction and less time will be needed during running. Note that
    id  f(`i') = {1/(`i'+1)};
would most likely not produce the desired result, because the preprocessor calculator works only over the integers. Hence, unless i is equal to zero or -2, the result would be zero (excluding of course the fatal error when i is equal to -1).


The triple dot operator

The last stage of the actions of the preprocessor involves the triple dot operator. It indicates a repeated pattern as in a1+...+a4 which would expand into a1+a2+a3+a4. This operator is used in two different ways. First the most general way:

    <pattern1>operator1...operator2<pattern2>
in which the less than and greater than signs serve as boundaries for the patterns. The operators can be any pair of the following:
+ +
Repetitions will be separated by plus signs.
- -
Repetitions will be separated by minus signs.
+ -
Repetitions will be separated by alternating signs. First will be plus.
- +
Repetitions will be separated by alternating signs. First will be minus.
$\ast \ast$
Repetitions will be separated by $\ast$.
/ /
Repetitions will be separated by /.
, ,
Repetitions will be separated by comma's.
: :
Repetitions will be separated by single dots.
For such a pair of operators FORM will inspect the patterns and see whether the differences between the two patterns are just numbers. If the differences are numbers and the absolute value of the difference of each matching pair is always the same (a difference of zero is allowed too; it leads to no action for the pair), then FORM will expand the pattern, running from the first to the last in increments of one. For each pair the counter can either run up or run down, depending on whether the number in the first pattern is greater or less than the number in the second pattern. Example:
    Local F = <a1b6(c3)>-...+<a4b3(c6)>;
leads to
    Local F = a1b6(c3)-a2b5(c4)+a3b4(c5)-a4b3(c6);
The second form is a bit simpler. It recognizes that there are special cases that can be written in a more intuitive way. If there is only a single number to be varied, and it is the end of the pattern, and the rest of the patterns consists only of alphanumeric characters of which the first is an alphabetic character, we do not need the less than/greater than combination. This is shown in
    Symbol a1,...,a12;
There is one extra exception. The variables used this way may have a question mark after them to indicate that they are wildcards:
    id  f(a1?,...,a4?) = g(a1,...,a4,a1+...+a4);
This construction did not exist in earlier versions of FORM (version 1 and version 2). There one needed the #do instruction for many of the above constructions, creating code that was very hard to read. The ... operator should improve the readability of the programs very much.


#append

Syntax:

#append $<$filename$>$

See also write ([*]), close ([*]), create ([*]), remove ([*])

Opens the named file for writing. The file will be positioned at the end. The next #write instruction will add to it.


#break

Syntax:

#break

See also switch ([*]), endswitch ([*]), case ([*]), default ([*])

If the lines before were not part of the control flow (i.e. these lines are used for the later stages of the program), this instruction is ignored. If they are part of the control flow, the flow will continue after the matching #endswitch instruction. The #break instruction must of course be inside the range of a #switch/#endswitch construction.


#call

Syntax:

#call procname(var1,...,varn)

See also procedure ([*]), endprocedure ([*])

This instruction calls the procedure with the name procname. The result is that FORM looks for this procedure, first in its procedure buffers (for procedures that were defined in the regular text stream as explained under the #procedure instruction), then it looks for a file by the name procname.prc in the current directory, and if it still has not found the procedure, it looks in the directories indicated by the path variable in either the setup file or at the start of the program (see chapter [*] on the setup file). Next it looks for the -p option in the command that started FORM (see the chapter on running FORM). If this -p option has not been used FORM will see whether there is an environment variable by the name FORMPATH. The directories indicated there will be searched for the file procname.prc. If FORM cannot find the file, there will be an error message and execution will be stopped immediately.

Once the procedure has been located, FORM reads the whole file and then determines whether the number of parameters is identical in the #call instruction and the #procedure instruction. A difference is a fatal error.

The parameter field consists of strings, separated by commas. If a string contains a comma, this comma should be preceded by a backslash character (\). If a string should contain a linefeed, one should `escape' this linefeed by putting a backslash and continue on the next line.

Before version 3 of FORM the syntax was different. The parentheses were curly brackets and the separators the symbol |. This was made to facilitate the use of strings that might contain commas. In practise however, this turned out to be far from handy. In addition the new preprocessor calculator is a bit more active and hence an instruction of the type

    #call test{1}
will now be intercepted by the preprocessor calculator and changed into
    #call test1
Because there are many advantages to the preprocessor calculator treating the parameters of the procedures before they are called (in the older versions it did not do this), the notation has been changed. FORM still understands the old notation, provided that there is no conflict with the preprocessor calculator. Hence
    #call test{1|a}
    #call test{1,a}
    #call test(1|a)
    #call test(1,a)
are all legal and give the same result, but only the last notation will work in future versions of FORM.

Nowadays also the use of the argument field wildcard (see chapter [*] on pattern matching) is allowed as in the regular functions:

    #define a "1"
    #define bc2 "x"
    #define bc3 "y"
    #define b "c`~a'"
    #procedure hop(c,?d);
    #redefine a "3"
    #message This is the call: `c',`?d'
    #endprocedure
    
    #redefine a "2"
    #message This is b: `b'
~~~This is b: c2
    
    #call hop(`b`!b''`!b'`b'`!b'`b',`~a',`b',`a')
~~~This is the call: xc2c3c2c3,3,c3,2
    
    .end
We also see here that the rules about delayed substitution (see also the #define instruction in section [*]) apply. The use of `!b' cancels the delayed substitution that is asked for in the definition of b.

The default extension for procedure files is .prc, but it is possible to change this. There are two different ways: One is with the #procedureExtension instruction in section [*]. The other is via the setup (see the chapter on the setup file, chapter [*]).


#case

Syntax:

#case string

See also switch ([*]), endswitch ([*]), break ([*]), default ([*])

The lines after the #case instruction will be used if either this is the first #case instruction of which the string matches the string in the #switch instruction, or the control flow was already using the lines before this #case instruction and there was no #break instruction (this is called fall-through). The control flow will include lines either until the next matching #break instruction, or until the matching #endswitch instruction.


#close

Syntax:

#close $<$filename$>$

See also write ([*]), append ([*], create ([*], remove ([*])

This instruction closes the file by the given name, if such a file had been opened by the previous #write instruction. Normally FORM closes all such files at the end of execution. Hence the user would not have to worry about this. The use of a subsequent #write instruction with the same file name will remove the old contents and hence start basically a new file. There are times that this is useful.


#commentchar

Syntax:

#commentchar character

The specified character should be a single non-whitespace character. There may be white space (blanks and/or tabs) before or after it. The character will take over the role of the comment character. i.e. any line that starts with this character in column 1 will be considered commentary. This feature was provided because output of some other algebra programs could put the multiplication sign in column 1 in longer expressions.

The default commentary character is $\ast$.


#create

Syntax:

#append $<$filename$>$

See also write ([*]), close ([*]), append ([*]), remove ([*])

Opens the named file for writing. If the file existed already, its previous contents will be lost. The next #write instruction will add to it. In principle this instruction is not needed, because the #write instruction would create the file if it had not been opened yet at the moment of writing.


#default

Syntax:

#default

See also switch ([*]), endswitch ([*]), case ([*]), break ([*])

Control flow continues after this instruction if there is no #case instruction of which the string matches the string in the #switch instruction. Control flow also continues after this instruction, if the lines before were included and there was no #break instruction to stop the control flow (fall-through). Control flow will stop either when a matching #break instruction is reached, or when a matching #endswitch is encountered. In the last case of course control flow will continue after the #endswitch instruction.


#define

Syntax:

#define name "string"

See also redefine ([*]), undefine ([*])

in which name refers to the name of the preprocessor variable to be defined and the contents of the string will form the value of the variable. The double quotes are mandatory delimiters of the string.

The use of the #define instruction creates a new instance of the preprocessor variable with the given name. This means that the old instance remains. If for some reason the later instance becomes undefined (see for instance #undefine), the older instance will be the one that is active. If the old definition is to be overwritten, one should use the #redefine instruction.

As of version 3.2 preprocessor variables can also have arguments as in the C language. Hence

#define var(a,b) "(`~a'+`~b'+`c')"

is allowed. The parameters should be referred to inside a pair of `' as with all preprocessor variables. A special feature is the socalled delayed substitution. With macro's like the above the question is always when a preprocessor variable will be substituted. Take for instance

    #define c "3"
    #define var1(a,b) "(`~a'+`~b'+`c')"
    #define var2(a,b) "(`~a'+`~b'+`~c')"
    #redefine c "4"
    Local F1 = `var1(1,2)';
    Local F2 = `var2(1,2)';
    Print;
    .end

   F1 =
      6;

   F2 =
      7;
The parameter c will be substituted immediately when var1 is defined. In var2 it will be only substituted when var2 is used. It should be clear that a and b should also be used in the delayed fashion because they do not exist yet at the moment of the definition of var1 and var2. Notice also that the whole macro, with its arguments should be placed between the backquote and the quote. Another example can be found with the #call instruction. See section [*]


#do

Syntax:

#do lvar = i1,i2

#do lvar = i1,i2,i3

#do lvar = $\{$string1$\vert$...$\vert$stringn$\}$

#do lvar = $\{$string1,...,stringn$\}$

#do lvar = nameofexpression

See also enddo ([*])

The #do instruction needs a matching #enddo instruction. All code in-between these two instructions will be read as many times as indicated in the parameter field of the #do instruction. The parameter lvar is a preprocessor variable of which the value is determined by the other parameters. Inside the loop it should be referred to by enclosing its name between a backquote/quote pair as is usual for preprocessor variables. The various possible parameter fields have the following meaning:

#do lvar = i1,i2
The parameters i1 and i2 should be integers. The first time in the loop lvar will get the value of i1 (as a string) and each next time its value will be one greater (translated into a string again). The last time in the loop the value of lvar will be the greatest integer that is less or equal to i2. If i2 is less than i1, the loop is skipped completely.
#do lvar = i1,i2,i3
The parameters i1,i2 and i3 should be integers. The first time in the loop lvar will get the value of i1 (as a string) and each next time its value will be incremented by adding i3 (translated into a string again). If i3 is positive, the last value of lvar will be the one for which lvar+i3 is greater than i2. If i2 is less than i1, the loop is skipped completely. If i3 is negative the last value of lvar will be the one for which lvar+i3 is less than i2. If i3 is zero there will be an error.
#do lvar = $\{$string1$\vert$...$\vert$stringn$\}$
The first time in the loop the value of lvar is the string indicated by string1, the next time will be string2 etc till the last time when it will be stringn. This is called a listed loop. The notation with the $\vert$ is an old notation which is still accepted. The new notation uses a comma instead.
#do lvar = $\{$string1,...,stringn$\}$
The first time in the loop the value of lvar is the string indicated by string1, the next time will be string2 etc till the last time when it will be stringn. This is called a listed loop.
#do lvar = expression
The loop variable will take one by one for its value all the terms of the given expression. This is protected against changing the expression inside the loop by making a copy of the expression inside the memory. Hence one should be careful with very big expressions. An expression that is zero gives a loop over zero terms, hence the loop is never executed.
The first two types of #do instructions are called numerical loops. In the parameters of numerical loops the preprocessor calculator is invoked automatically. One should make sure not to use a leading $\{$ for the first numerical parameter in such a loop. This would be interpreted as belonging to a listed loop.

After a loop has been finished, the corresponding preprocessor variable will be undefined. This means that if there is a previous preprocessor variable by the same name, the value of the #do instruction will be used inside the loop, and afterwards the old value will be active again.

It is allowed to overwrite the value of a preprocessor #do instruction variable. This can be very useful to create the equivalent of a repeat loop that contains .sort instructions as in

    #do i = 1,1
        id,once,x = y+2;
        if ( count(x,1) > 0 ) redefine i "0";
        .sort
    #enddo
A few remarks are necessary here. The redefine statement (see section [*]) should be before the last .sort inside the loop, because the #do instruction is part of the preprocessor. Hence the value of i is considered before the module is executed. This means that if the redefine would be after the .sort, two things would go wrong: First the loop would be terminated before the redefine would ever make a chance of being executed. Second the statement would be compiled in the expectation that there is a variable i, but then the loop would be terminated. Afterwards, when the statement is being executed it would refer to a variable that does not exist any longer.

If one wants to make a loop over the externals of the brackets of an expression only, one needs to do some work. Assume we have the expression F and we want to loop over the brackets in x and y:

    L   FF = F;
    Bracket x,y;
    .sort
    CF acc,acc2;
    Skip F;
    Collect acc,acc2;
    id  acc(x?) = 1;
    id  acc2(x?)= 1;
    B   x,y;
    .sort
    Skip F;
    Collect acc;
    id  acc(x?) = 1;
    .sort
    #do i = FF
    L   G = F[`i'];
        .
        .
    #enddo
Notice that we have to do the collect trick twice because the first time the bracket could be too long for one term. The second time that restriction doesn't exist because besides the x and the y there are only integer coefficients.


#else

Syntax:

#else

See also if ([*]), endif ([*]), elseif ([*]), ifdef ([*]), ifndef ([*])

This instruction is used inside a #if/#endif construction. The code that follows it until the #endif instruction will be read if the condition of the #if instruction (and of none of the corresponding #elseif instructions) is not true. If any of these conditions is true, this code is skipped. The reading is stopped after the matching #endif is encountered and continued after this matching #endif instruction.


#elseif

Syntax:

#elseif ( condition )

See also if ([*]), endif ([*]), else ([*])

The syntax of the condition is identical to the syntax for the condition in the #if instruction. The #elseif instruction can occur between an #if and an #endif instruction, before a possible matching #else instruction. The code after this condition till the next #elseif instruction, or till a #else instruction or till a #endif instruction, whatever comes first, will be read if the condition in the #elseif instruction is true and none of the conditions in matching previous #if or #elseif instructions were true. The reading is stopped after the matching #elseif/#else/#endif is encountered and continued after the matching #endif instruction.

Example

    #if ( `i' == 2 )
        some code
    #elseif ( `i' == 3 )
        more code
    #elseif ( `j' >= "x2y" )
        more code
    #else
        more code
    #endif


#enddo

Syntax:

#enddo

See also do ([*])

Used to terminate a preprocessor do loop. See the #do instruction.


#endif

Syntax:

#endif

See also if ([*]), else ([*]), elseif ([*]), ifdef ([*]), ifndef ([*])

Used to terminate a #if, #ifdef or #ifndef construction. Reading will continue after it.


#endprocedure

Syntax:

#endprocedure

See also procedure ([*]), call ([*])

Each procedure must be terminated by an #endprocedure instruction. If the procedure resides in its own file, the #endprocedure will cause the closing of the file. Hence any text that is in the file after the #endprocedure instruction will be ignored.

When control reaches the #endprocedure instruction, all (local) preprocessor variables that were defined inside the procedure and all parameters of the call of the procedure will become undefined.


#endswitch

Syntax:

#endswitch

See also switch ([*]), case ([*]), break ([*]), default ([*])

This instruction marks the end of a #switch construction. After none or one of the cases of the #switch construction has been included in the control flow, reading will continue after the matching #endswitch instruction. Each #switch needs a #endswitch, unless a .end instruction is encountered first.


#exchange

Syntax:

#exchange expr1,expr2

#exchange $var1,$var2

Exchanges the names of two expressions. This means that the contents of the expressions remain where they are. Hence the order in which the expressions are processed remains the same, but the name under which one has to refer to them has been changed.

In the variety with the dollar variables the contents of the variables are exchanged. This is not much work, because dollar variables reside in memory and hence only two pointers to the contents have to be exchanged (and some extra information about the contents).

This instruction can be very useful when sorting expressions or dollar variables by their contents.


#external

Syntax:

#external ["prevar"] systemcommand

Starts the command in the background, connecting to its standard input and output. By default, the #external command has no controlling terminal, the standard error stream is redirected to /dev/null and the command is run in a subshell in a new session and in a new process group (see the preprocessor instruction #setexternalattr).

The optional parameter ``prevar'' is the name of a preprocessor variable placed between double quotes. If it is present, the ``descriptor'' (small positive integer number) of the external command is stored into this variable and can be used for references to this external command (if there is more than one external command running simultaneously).

The external command that is started last becomes the ``current'' (active) external command. All further instructions #fromexternal and #toexternal deal with the current external command.


#fromexternal

Syntax:

#fromexternal[$+-$] ["[$]varname" [maxlength]]

Appends the output of the current external command to the FORM program. The semantics differ depending on the optional arguments. After the external command sends the prompt, FORM will continue with a next line after the line containing the #fromexternal instruction. The prompt string is not appended. The optional $+$ or $-$ sign after the name has influence on the listing of the content. The varieties are:

#fromexternal[$+-$]

The semantics is similar to the #include instruction but folders are not supported.

#fromexternal[$+-$] "[$]varname"

is used to read the text from the running external command into the preprocessor variable varname, or into the dollar variable $varname if the name of the variable starts with the dollar sign ``$''.

#fromexternal[$+-$] "[$]varname" maxlength

is used to read the text from the running external command into the preprocessor (or dollar) variable varname. Only the first maxlength characters are stored.


#if

Syntax:

#if ( condition )

See also endif ([*]), else ([*]), elseif ([*]), ifdef ([*]), ifndef ([*])

The #if instruction should be accompanied by a matching #endif instruction. In addition there can be between the #if and the #endif some #elseif instructions and/or a single #else instruction. The condition is a logical variable that is true if its value is not equal to zero, and false if its value is zero. Hence it is allowed to use

    #if `i'
        statements
    #endif
provided that i has a value which can be interpreted as a number. If there is just a string that cannot be seen as a logical condition or a number it will be interpreted as false. The regular syntax of the simple condition is
    #if `i' == st2x
        statements
    #endif
or
    #if ( `i' == st2x )
        statements
    #endif
in which the compare is a numerical compare if both strings can be seen as numbers, while it will be a string compare if at least one of the two cannot be seen as a numerical object. One can also use more complicated conditions as in
    #if ( ( `i' > 5 ) && ( `j' > `i' ) )
These are referred to as composite conditions. The possible operators are
$>$
Greater than, either in numerical or in lexicographical sense.
$<$
Less than, either in numerical or in lexicographical sense.
$>=$
Greater than or equal to, either in numerical or in lexicographical sense.
$<=$
Less than or equal to, either in numerical or in lexicographical sense.
$==$ or $=$
Equal to.
$!=$
Not equal to.
$\&\&$
Logical and operator to combine conditions.
$\vert\vert$
Logical or operator to combine conditions.

If the condition evaluates to true, the lines after the #if instruction will be read until the first matching #elseif instruction, or a #else instruction or a #endif instruction, whatever comes first. After such an instruction is encountered input reading stops and continues after the matching #endif instruction.

Like with the regular if-statement (see [*]), there are some special functions that allow the asking of questions about objects. These are

termsin()

The argument of termsin is the name of an expression or a $-variable. This function then evaluates into the number of terms in that expression.

maxpowerof()

The argument of maxpowerof is the name of a symbol. This function then evaluates into the maximum power of that symbol as it has been declared. If no maximum power has been set in the declaration of the symbol, the general maximum power for symbols is returned (see [*]).

minpowerof()

The argument of minpowerof is the name of a symbol. This function then evaluates into the minimum power of that symbol as it has been declared. If no minimum power has been set in the declaration of the symbol, the general minimum power for symbols is returned (see [*]).


#ifdef

Syntax:

#ifdef `prevar'

See also if ([*]), endif ([*]), else ([*]), ifndef ([*])

If the named preprocessor variable has been defined the condition is true, else it is false. For the rest the instruction behaves like the #if instruction.


#ifndef

Syntax:

#ifndef `prevar'

See also if ([*]), endif ([*]), else ([*]), ifdef ([*])

If the named preprocessor variable has been defined the condition is false, else it is true. For the rest the instruction behaves like the #if instruction.


#include

Syntax:

#include[$-+$] filename

#include[$-+$] filename # foldname

The named file is searched for and opened. Reading continues from this file until its end. Then the file will be closed and reading continues after the #include instruction. If a foldname is specified, FORM will only read the contents of the first fold it encounters in the given file that has the specified name.

The file is searched for in the current directory, then in the path specified in the path variable in the setup file or at the beginning of the program (see chapter [*] on the setup file). Next it will look in the path specified in the -p option when FORM is started (see the chapter on running FORM). If this option has not been used, FORM will look for the environment variable FORMPATH. If this variable exists it will be interpreted as a path and FORM will search the indicated directories for the given file. If none is found there will be an error message and execution will be halted.

The optional $+$ or $-$ sign after the name has influence on the listing of the contents of the file. A $-$ sign will have the effect of a #$-$ instruction during the reading of the file. A plus sign will have the effect of a #$+$ instruction during the reading of the file.

A fold is defined by a starting line of the format:

    *--#[ name :
and a closing line of the format
    *--#] name :
in which the first character is actually the current commentary character (see the #commentchar instruction). All lines between two such lines are considered to be the contents of the fold. If FORM decides that it needs this fold, it will read these contents and put them in its input stream. More about folds is explained in the manual of the STedi editor which is also provided in the FORM distribution.


#message

Syntax:

#message themessagestring

This instruction places a message in the output that is clearly marked as such. It is printed with an initial three characters in front as in

    Symbols a,b,c;
    #message Simple example;
~~~Simple example;
    Local F = (a+b+c)^10;
    .end

Time =       0.00 sec    Generated terms =         66
                F        Terms in output =         66
                         Bytes used      =       1138
Note that the semicolon is not needed and if present is printed as well. If one needs messages without this clear marking, one should use the #write instruction.


#pipe

Syntax:

#pipe systemcommand

See also system ([*])

This forces a system command to be executed by the operating system. The complete string (excluding initial blanks or tabs) is passed to the operating system. Next FORM will intercept the output of whatever is produced and read that as input. Hence, whenever output is produced FORM will take action, and it will wait when no output is ready. After the command has been finished, FORM will continue with the next line. This instruction has only been implemented on systems that support pipes. This is mainly UNIX and derived systems. Note that this instruction also introduces operating system dependent code. Hence it should be used with great care.


#preout

Syntax:

#preout ON

#preout OFF

Turns listing of the output of the preprocessor to the compiler on or off. Example:

    #PreOut ON
    S   a1,...,a4;
 S,a1,a2,a3,a4
    L   F = (a1+...+a4)^2;
 L,F=(a1+a2+a3+a4)^2
    id  a4 = -a1;
 id,a4=-a1
    .end

Time =       0.00 sec    Generated terms =         10
                F        Terms in output =          3
                         Bytes used      =         52


#printtimes

Syntax:

#printtimes

Prints the current execution time and real time in the same way as done at the end of the program. Helps in monitoring the real time passed in TFORM jobs. Example:

    #Printtimes
  423.59 sec + 5815.88 sec: 6239.47 sec out of 1215.29 sec


#procedure

Syntax:

#procedure name(var1,...,varn)

See also endprocedure ([*]), call ([*])

Name is the name of the procedure. It will be referred to by this name. If the procedure resides in a separate file the name of the file should be name.prc and the #procedure instruction should form the first line of the file. The # should be the first character of the file. The parameter field is optional. If there are no parameters, the procedure should also be called without parameters (see the #call instruction). The parameters (here called var1 to varn) are preprocessor variables and hence they should be referred to between a backquote/quote pair as in `var1' to `varn'. If there exist already variables with such names when the procedure is called, the new definition comes on top of the old one. Hence in the procedure (and procedures called from it, unless the same problems occurs there too, as would be the case with recursions) the new definition is used, and it is released again when control returns from the procedure. After that the old definition will be in effect again.

If the procedure is included in the regular input stream, FORM will read the text of the procedure until the #endprocedure instruction and store it in a special buffer. When the procedure is called, FORM will read the procedure from this buffer, rather than from a file. In systems where file transfer is slow (very busy server with a slow network) this may be faster, especially when many small procedures are called.

One way to make libraries that contain many procedures and maybe more code is to put all procedures into one header (.h) file and include this file at the beginning of the program with a #include instruction. This way one has all procedures load and one knows for sure that it are the proper procedures as it guards against the inadvertently picking up of procedures from other directories. It also makes for fewer files and hence makes for better housekeeping.


#procedureextension

Syntax:

#procedureextension string

See also #call ([*])

The default extension of procedures is .prc in FORM. It is however possible that this clashes with the extensions used by other programs like the Grace system (Yuasa et al, Prog. Theor. Phys. Suppl. 138(2000)18 ). In that case it is possible to change the extension of the procedures in the current program. This is either done via the setup (page [*]) or by the #procedureextension instruction of the preprocessor. The new string replaces the string prc, used by default. For the new string the following restrictions hold:

  1. The first character must be alphabetic
  2. No whitespace characters (blanks and/or tabs) are allowed
For the rest any characters can be used.

The new extension will remain valid either till the next #procedureextension instruction or to the next .clear instruction (page [*]), whatever comes first.


#prompt

Syntax:

#prompt [newprompt]

Sets a new prompt for the current external command (if present) and all further (newly started) external commands.

If newprompt is an empty string, the default prompt (an empty line) will be used.

The prompt is a line consisting of a single prompt string. By default, this is an empty string.


#redefine

Syntax:

#redefine name "string"

See also define ([*]), undefine ([*])

in which name refers to the name of the preprocessor variable to be redefined. The contents of the string will be its new value. If no variable of the given name exists yet, the instruction will be equivalent to the #define instruction.


#remove

Syntax:

#remove $<$filename$>$

See also write ([*]), append ([*]), create ([*]), close ([*])

Deletes the named file from the system. Under UNIX this would be equivalent to the instruction

    #system rm filename
and under MS-DOS oriented systems like Windows it would be equivalent to
    #system del filename
The difference with the #system instruction is that the #remove instruction does not depend on the particular syntax of the operating system. Hence the #remove instruction can always be used.


#rmexternal

Syntax:

#rmexternal [n]

Terminates an external command. The integer number n must be either the descriptor of a running external command, or 0.

If n is 0, then all external programs will be terminated.

If n is not specified, the current external command will be terminated.

The action of this instruction depends on the attributes of the external channel (see the #setexternalattr (section [*]) instruction). By default, the instruction closes the commands' IO channels, sends a KILL signal to every process in its process group and waits for the external command to be finished.


#setexternal

Syntax:

#setexternal n

Sets the ``current'' external command. The instructions #toexternal and #fromexternal deal with the current external command. The integer number n must be the descriptor of a running external command.


#setexternalattr

Syntax:

#setexternalattr list_of_attributes

sets attributes for newly started external commands. Already running external commands are not affected. The list of attributes is a comma separated list of pairs attribute=value, e.g.:

   #setexternalattr shell=noshell,kill=9,killall=false
Possible attributes are:
kill
specifies the signal to be sent to the external command either before the termination of the FORM program or by the preprocessor instruction #rmexternal. By default this is 9 ( SIGKILL). Number 0 means that no signal will be sent.
killall
Indicates whether the kill signal will be sent to the whole group or only to the initial process. Possible values are ``true'' and ``false''. By default, the kill signal will be sent to the whole group.
daemon
Indicates whether the command should be ``daemonized'', i.e. the initial process will be passed to the init process and will belong to the new process group in the new session. Possible values are ``true'' and ``false''. By default, ``true''.
shell
specifies which shell is used to run a command. (Starting an external command in a subshell permits to start not only executable files but also scripts and pipelined jobs. The disadvantage is that there is no way to detect failure upon startup since usually the shell is started successfully.) By default this is ``/bin/sh -c''. If set shell=noshell, the command will be stared by the instruction #external directly but not in a subshell, so the command should be a name of the executable file rather than a system command. The instruction #external will duplicate the actions of the shell in searching for an executable file if the specified file name does not contain a slash (/) character. The search path is the path specified in the environment by the PATH variable. If this variable isn't specified, the default path ``:/bin:/usr/bin'' is used.
stderr
specifies a file to redirect the standard error stream to. By default it is ``/dev/null''. If set stderr=terminal, no redirection occurs.
Only attributes that are explicitly mentioned are changed, all others remain unchanged. Note, changing attributes should be done with care. For example,
   #setexternalattr daemon=false
starts a command in the subshell within the current process group with default attributes kill=9 and killall=true. The instruction #rmexternal sends the KILL signal to the wholegroup, which means that also FORM itself will be killed.


#show

Syntax:

#show [preprocessorvariablename[s]]

If no names are present, the contents of all preprocessor variables will be printed to the regular output. If one or more preprocessor variables are specified (separated by comma's), only their contents will be printed. The preprocessor variables should be represented by their name only. No enclosing backquote/quote should be used, because that would force a substitution of the preprocessor variable before the instruction gets to see the name. Example:

    #define MAX "3"
    Symbols a1,...,a`MAX';
    L F = (a1+...+a`MAX')^2;
    #show
#The preprocessor variables:
0: VERSION_ = "3"
1: SUBVERSION_ = "2"
2: NAMEVERSION_ = ""
3: DATE_ = "Wed Feb 28 08:43:20 2007"
4: NAME_ = "testpre.frm"
5: CMODULE_ = "1"
6: MAX = "3"
    .end

Time =       0.00 sec    Generated terms =          6
                F        Terms in output =          6
                         Bytes used      =        102
We see that the variable MAX has indeed the value 3. There are six additional variables which have been defined by FORM itself. Hence the trailing underscore which cannot be used in user defined names. The current version of FORM is shown in the variable VERSION_ and the name of the current program is given in the variable NAME_. For more about the system defined preprocessor variables see [*].

There is another preprocessor variable that does not show in the listings. Its name is SHOWINPUT_. This variable has the value one if the listing of the input is on and the value zero if the listing of the input is off.


#switch

Syntax:

#switch string

See also endswitch ([*]), case ([*]), break ([*]), default ([*])

the string could for instance be a preprocessor variable as in

    #switch `i'
The #switch instruction, together with #case, #break, #default and #endswitch, allows the user to conveniently make code for a number of cases that are distinguished by the value of a preprocessor variable. In the past this was only possible with the use of folds in the #include instruction and the corresponding include file (see [*]). Because few people have an editor like STedi (see the FORM distribution site) that can handle the folds in a proper way, it was judged that the more common switch mechanism might be friendlier. The proper syntax of a complete construction would be
    #switch `par'
    #case 1
       some statements
    #break
    #case ax2
       other statements
    #break
    #default
       more statements
    #break
    #endswitch
The number of cases is not limited. The compare between the strings in the #switch instruction and in the #case instructions is as a text string. Hence numerical strings have no special meaning. If a #break instruction is omitted, control may go into another case. This is called fall-through. This is a way in which one can have the same statements for several cases. The #default instruction is not mandatory.

FORM will look for the first case of which the string matches the string in the #switch instruction. Input reading (control flow) starts after this #case instruction, and continues till either a #break instruction is encountered, or the #endswitch is met. After that input reading continues after the #endswitch instruction. If no case has a matching string, input reading starts after the #default instruction. If no #default instruction is found, input reading continues after the matching #endswitch instruction.

#switch constructions can be nested. They can be combined with #if constructions, #do instructions, etc. but they should obey normal nesting rules (as with nesting of brackets of different types).


#system

Syntax:

#system systemcommand

See also pipe ([*])

This forces a system command to be executed by the operating system. The complete string (excluding initial blanks or tabs) is passed to the operating system. FORM will then wait until control is returned. Note that this instruction introduces operating system dependent code. Hence it should be used with great care.


#terminate

Syntax:

#terminate [exitcode]

This forces FORM to terminate execution immediately. If an exit code is given (an integer number), this will be the return value that FORM gives to the shell program from which it was run. If no return value is specified, the value -1 will be returned.


#toexternal

Syntax:

#toexternal "formatstring" $<$,variables$>$

Sends the output to the current external command. The semantics of the "formatstring" and the [,variables] is the same as for the #write instruction, except for the trailing end-of-line symbol. In contrast to the #write instruction, the #toexternal instruction does not append any new line symbol to the end of its output.


#undefine

Syntax:

#undefine name

See also define ([*]), redefine ([*])

Name refers to the name of the preprocessor variable to be undefined. This statement causes the given preprocessor variable to be removed from the stack of preprocessor variables. If an earlier instance of this variable existed (other variable with the same name), it will become active again. There are various other ways by which preprocessor variables can become undefined. All variables belonging to a procedure are undefined at the end of a procedure, and so are all other preprocessor variables that were defined inside this procedure. The same holds for the preprocessor variable that is used as a loop parameter in the #do instruction.


#write

Syntax:

#write [$<$filename$>$] "formatstring" [,variables]

See also append ([*]), create ([*]), remove ([*]), close ([*])

If there is no file specified, the output will be to the regular output channel. If a file is specified, FORM will look whether this file is open already. If it is open already, the specified output will be added to the file. If it is not open yet it will be opened. Any previous contents will be lost. This would be equivalent to using the #create instruction first. If output has to be added to an existing file, the #append instruction should be used first.

The format string is like a format string in the language C. This means that it is placed between double quotes. It will contain text that will be printed, and it will contain special character sequences for special actions. These sequences and the corresponding actions are:

$\backslash$n
A newline character.
$\backslash$t
A tab character.
$\backslash$"
A double quote character.
$\backslash$b
A backslash character.
%%
The character %.
%
If the last character in the string, it causes the omission of a linefeed at the end of the printing. Note that if this happens in the regular output (as opposed to a file) there may be interference with the listing of the input.
%$
A dollar variable. The variable should be indicated in the list of variables. Each occurrence of %$ will look for the next variable.
%e
An active expression. The expression should be indicated in the list of variables. Each occurrence of %e will look for the next variable. Unlike the output caused by the print statement the expression will be printed without its name and there will also be no = sign unless there is one in the format string of course. If the current output format is fortran output there is an extra option. After the name of the expression one should put between parentheses the name to be used when there are too many continuation cards.
%E
Like %e, but whereas the %e terminates the expression with a ;, the %E does not give this trailing semicolon.
%s
A string. The string should be given in the list of variables and be enclosed between double quotes. Each occurrence of %s will look for the next variable in the list.
%f
A file. The name of the file will be expected in the list of variables. The file is searched for in the current directory, then in path indicated by the path variable in the setup file or at the beginning of the file (see chapter [*] on the setup file), then in the path specified in the -p option when FORM is started (see the chapter on running FORM). If this option has not been used, FORM will look for the environment variable FORMPATH. If this variable exists it will be interpreted as a path and FORM will search the indicated directories for the given file. If none is found there will be an error message and execution will be halted.
%X
Forces the printing of the list of extra symbols ([*]) and their definitions.
If no special variables are asked for (by means of %$, %e, %E or %s) the list of variables will be ignored (if present). Example:
    Symbols a,b;
    L   F = a+b;
    #$a1 = a+b;
    #$a2 = (a+b)^2;
    #$a3 = $a1^3;
    #write " One power: %$\n Two powers: %$\n Three powers: %$\n%s"\
           ,$a1,$a2,$a3," The end"
 One power: b+a
 Two powers: b^2+2*a*b+a^2
 Three powers: b^3+3*a*b^2+3*a^2*b+a^3
 The end
    .end

Time =       0.00 sec    Generated terms =          2
                F        Terms in output =          2
                         Bytes used      =         32
We see that the writing occurs immediately after the #write instruction, because it is done by the preprocessor. Hence the output comes before the execution of the expression F.
    S   x1,...,x10;
    L   MyExpression = (x1+...+x10)^4;
    .sort
    Format Fortran;
    #write <fun.f> "      FUNCTION fun(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10)"
    #write <fun.f> "      REAL x1,x2,x3,x4,x5,x6,x7,x8,x9,x10"
    #write <fun.f> "      fun = %e",MyExpression(fun)
    #write <fun.f> "      RETURN"
    #write <fun.f> "      END"
    .end
Some remarks are necessary here. Because the #write is a preprocessor instruction, the .sort is essential. Without it, the expression has not been worked out at the moment we want to write. The name of the expression is too long for fortran, and hence the output file will use a different name (in this case the name `fun' was selected). The output file looks like
      FUNCTION fun(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10)
      REAL x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
      fun = 24*x1*x2*x3*x4 + 24*x1*x2*x3*x5 + 24*x1*x2*x3*x6 + 24*x1*x2
     & *x3*x7 + 24*x1*x2*x3*x8 + 24*x1*x2*x3*x9 + 24*x1*x2*x3*x10 + 12*
          .....
     & x8 + 4*x6**3*x9 + 4*x6**3*x10 + x6**4 + 24*x7*x8*x9*x10 + 12*x7*
     & x8*x9**2
      fun = fun + 12*x7*x8*x10**2 + 12*x7*x8**2*x9 + 12*x7*x8**2*x10 + 
     & 4*x7*x8**3 + 12*x7*x9*x10**2 + 12*x7*x9**2*x10 + 4*x7*x9**3 + 4*
     & x7*x10**3 + 12*x7**2*x8*x9 + 12*x7**2*x8*x10 + 6*x7**2*x8**2 + 
     & 12*x7**2*x9*x10 + 6*x7**2*x9**2 + 6*x7**2*x10**2 + 4*x7**3*x8 + 
     & 4*x7**3*x9 + 4*x7**3*x10 + x7**4 + 12*x8*x9*x10**2 + 12*x8*x9**2
     & *x10 + 4*x8*x9**3 + 4*x8*x10**3 + 12*x8**2*x9*x10 + 6*x8**2*
     & x9**2 + 6*x8**2*x10**2 + 4*x8**3*x9 + 4*x8**3*x10 + x8**4 + 4*x9
     & *x10**3 + 6*x9**2*x10**2 + 4*x9**3*x10 + x9**4 + x10**4

      RETURN
      END
and each time after 19 continuation lines we have to break the expression and use the fun = fun + trick to continue.

Some remarks

It should be noted that the various constructions like #do/#enddo, #procedure/#endprocedure, #switch/#endswitch and #if/#endif all create a certain environment. These environments cannot be interweaved. This means that one cannot make code of the type
     #do i = 1,5
      #if ( `MAX' > `i' )
         id f(`i') = g`i'(x);
     #enddo
      some statements
     #do i = 1,5
      #endif
     #enddo
whether this could be considered useful or not. Similarly one cannot make a construction that might be very useful:
     #do i = 1,5
       #do j`i' = 1,3
     #enddo
       some statements
     #do i = 1,5
       #enddo
     #enddo
Currently the syntax does not allow this. This may change in the future.


Modules

Modules are the basic execution blocks. Statements are always part of a module, and they will be executed only when the module is executed. This is directly opposite to preprocessor instructions which are executed when they are encountered in the input stream.

Modules are terminated by a line that starts with a period. Such a line is called the module instruction. Once the module instruction has been recognized, the compilation of the module is terminated and the module will be executed. All active expressions will be processed one by one, term by term. When each term of an expression has been through all statements of the module, the combined results of all operations on all the terms of the expression will be sorted and the resulting expression will be sent to the output. This can be an intermediate file, or it can be some memory, depending on the size of the output. If the combined output of all active expressions is less than the parameter ``ScratchSize'', the results stay in memory. ScratchSize is one of the setup parameters (see chapter [*]).

A module consists in general of several types of statements:

Declarations
These are the declarations of variables.
Specifications
These tell what to do with existing expressions as a whole.
Definitions
These define new expressions.
Executable statements
The operations on all active expressions.
OutputSpecifications
These specify the output representation.
End-of-module specifications
Extra settings that are for this module only.
Mixed statements
They can occur in various classes. Most notably the print statement.
Statements must occur in such an order that no statement follows a statement of a later category. The only exception is formed by the mixed statements, which can occur anywhere. This is different from earlier versions of FORM in which the order of the statements was not fixed. This did cause a certain amount of confusion about the workings of FORM.

There are several types of modules.

.sort
The general end-of-module. Causes execution of all active expressions, and prepares them for the next module.
.end
Executes all active expressions and terminates the program.
.store
Executes all active expressions. Then it writes all active global expressions to an intermediate storage file and removes all other non-global expressions. Removes all memory of declarations except for those that were made before a .global instruction.
.global
No execution of expressions. It just saves declarations made thus far from being erased by a .store instruction.
.clear
Executes all active expressions. Then it clears all buffers with the exception of the main input stream. Continues execution in the main input stream as if the program had started at this point. The only parameters that cannot be changed at this point are the setup parameters. They remain. By default also the clock is reset. If this is not desired this can be changed by means of the ResetTimeOnClear setup variable (see chapter [*]).
Each program must be terminated by a .end instruction. If such an instruction is absent and FORM encounters an end-of-input it will issue a warning and generate a .end instruction.

Module instructions can contain a special commentary that will be printed in all statistics that are generated during the execution of the module. This special commentary is restricted to 24 characters (the statistics have a fixed format and hence there is only a limited amount of space available). This commentary is initiated by a colon and terminated by a semicolon. The characters between this colon and the semicolon are the special message, also called advertisement. Example

	.sort:Eliminate x;
would give in the statistics something like
Time =       0.46 sec    Generated terms =        360
                F        Terms in output =        360
            Eliminate x  Bytes used      =       4506
If the statistics are switched off, there will be no printing of this advertisement either.

For backwards compatibility there is still an obsolete mechanism to pass module options via the module instructions. This is a feature which will probably disappear in future versions of FORM. We do give the syntax to allow the user to identify the option properly and enable proper translation into the moduleoption statement (see [*]).

    .sort(PolyFun=functionname);
    .sort(PolyFun=functionname):advertisement;
causes the given function to be treated as a polynomial function. This means that its (single) argument would be treated as the coefficient of the terms. The action of FORM on individual terms is
  1. Ignore polynomial functions with more than one argument.
  2. If there is no polynomial function with a single argument, generate one with the argument 1.
  3. If there is more than one polynomial function with a single argument, multiply the arguments and replace these functions with a single polynomial function with the product of the arguments for a single argument.
  4. Multiply the argument of the polynomial function with the coefficient of the term. Replace the coefficient itself by one.
If, after this, two terms differ only in the argument of their polynomial function FORM will add the arguments and replace the two terms by a single term which is identical to the two previous terms except for that the argument of its polynomial function is the sum of their two arguments.

It should be noted that the proper placement of .sort instructions in a FORM program is an art by itself. Too many .sort instructions cause too much sorting, which can slow execution down considerably. It can also cause the writing of intermediate expressions which are much larger than necessary, if the next statements would cause great simplifications. Not enough .sort instructions can make that cancellations are postponed unnecessarily and hence much work will be done double. This can slow down execution by a big factor. First an example of a superfluous .sort:

    S	a1,...,a7;
    L	F = (a1+...+a7)^16;
    .sort

Time =      31.98 sec    Generated terms =      74613
                F        Terms in output =      74613
                         Bytes used      =    1904316
    id	a7 = a1+a2+a3;
    .end

Time =     290.34 sec
                F        Terms active    =      87027
                         Bytes used      =    2253572

Time =     295.20 sec    Generated terms =     735471
                F        Terms in output =      20349
                         Bytes used      =     538884
Without the sort the same program gives:
    S	a1,...,a7;
    L	F = (a1+...+a7)^16;
    id	a7 = a1+a2+a3;
    .end

Time =     262.79 sec
                F        Terms active    =      94372
                         Bytes used      =    2643640

Time =     267.81 sec    Generated terms =     735471
                F        Terms in output =      20349
                         Bytes used      =     538884
and we see that the sorting in the beginning is nearly completely wasted. Now a clear example of not enough .sort instructions. A common problem is the substitution of one power series into another. If one does this in one step one could have:
    #define MAX "36"
    S  j,x(:`MAX'),y(:`MAX');
    *
    *	Power series expansion of ln_(1+x)
    *
    L	F = -sum_(j,1,`MAX',sign_(j)*x^j/j);
    *
    *	Substitute the expansion of x = exp_(y)-1
    *
    id	x = x*y;
    #do j = 2,`MAX'+1
    id	x = 1+x*y/`j';
    #enddo
    Print;
    .end

Time =      76.84 sec    Generated terms =      99132
                F        Terms in output =          1
                         Bytes used      =         18

   F =
      y;
With an extra .sort inside the loop one obtains for the same program (after suppressing some of the statistics:
    #define MAX "36"
    S  j,x(:`MAX'),y(:`MAX');
    *
    *	Power series expansion of ln_(1+x)
    *
    L	F = -sum_(j,1,`MAX',sign_(j)*x^j/j);
    *
    *	Substitute the expansion of x = exp_(y)-1
    *
    id	x = x*y;
    #do j = 2,`MAX'+1
    id	x = 1+x*y/`j';
    .sort: step `j';

Time =       0.46 sec    Generated terms =        360
                F        Terms in output =        360
                 step 2  Bytes used      =       4506
    #enddo
           .
           .
           .
Time =       3.07 sec    Generated terms =          3
                F        Terms in output =          1
                step 37  Bytes used      =         18
    Print;
    .end

Time =       3.07 sec    Generated terms =          1
                F        Terms in output =          1
                         Bytes used      =         18

   F =
      y;
It is very hard to give general rules that are more specific than what has been said above. The user should experiment with the placements of the .sort before making a very large run.


Checkpoints

If FORM programs have to run for a long time, the reliability of the hardware(computer system or network) or of the software infrastructure becomes a critical issue. Program termination due to unforeseen failures may waste days or weeks of invested execution time. The checkpoint mechanism was introduced to protect long running FORM programs as good as possible from such accidental interruptions. With activated checkpoints FORM will save its internal state and data from time to time on the hard disk. This data then allows a recovery from a crash.

The checkpoint mechanism can be activated or deactivated by On and Off statements. If the user has activated checkpoints, recovery data will be written to disk at the end of a module execution. Options allow to influence the details of the saving mechanism. If a program is terminated during execution, FORM can be restarted with the -R option and it will continue its execution at the last saved recovery point.

The syntax of the checkpoint activation and deactivation is

    On checkpoint [<OPTIONS>];
    Off checkpoint;

If no options are given, the recovery data will be saved at the end of every module. If one gives a time

    On checkpoint <NUMBER>[<UNIT>];
the saving will only be done if the given time has passed after the last saving. Possible unit specifiers are s, m, h, d and the number will then be interpreted as seconds, minutes, hours, or days, respectively. The default unit is seconds.

If one needs to run a script before or after the saving, one can specify a script filename.

    On checkpoint runbefore="<SCRIPTFILENAME>";
    On checkpoint runafter="<SCRIPTFILENAME>";
    On checkpoint run="<SCRIPTFILENAME>";
The option run sets both the scripts to be run before and after saving.The scripts must have the executable flag set and they must reside in the execution path of the shell (unless the filename already contains the proper path).

The scripts receive the module number as an argument (accessible as $1 inside the script). The return value of the script running before the saving will be interpreted. If the script returns an error (non-zero return value), a message will be issued and the saving will be skipped.

The recovery data will be written to files named FORMrecv.* with various name extensions. If a file FORMrecv.tmp exists, FORM will not run unless one gives it the recovery option -R. This is to prevent the unintentional loss of recovery data. If FORM terminates successfully, all the additional data files will be removed.

The additional recovery files will be created in the directory containing the scratch files. The extra files will occupy roughly as much space as the scratch files and the save and hide files combined. This extra space must be made available, of course.

If recovery data exists and FORM is started with the -R option, FORM will continue execution after the last module that successfully wrote the recovery data. All the command line parameters that have been given to the crashed FORM program must also be given to the recovering FORM program. The input files are not part of the recovery data and will be read in anew when recovering. Therefore it is strongly discouraged to change any of these files between saving and recovery.

At the moment, the recovery mechanism is only implemented for sequential FORM and multi-threaded TFORM. PARFORM support is planned for the future.


Pattern matching

Substitutions are made in FORM by specifying a generic object that should be replaced by an expression. This generic object is called a pattern. Patterns that the user may already be familiar with are the regular expressions in many UNIX based systems or just a statement like ls *.frm to list only files of which the name ends in .frm. In this case the * is called a wildcard that can take any string value. In symbolic manipulation there will be wildcards also, but their nature will be different. They are also indicated in a different way.

In FORM wildcard variables are indicated by attaching a question mark (?) to the name of a variable. The type of the variable indicates what type of object we are looking for. Assume the following id statements:

    Functions f,g;
    Symbol x;

    id f(g?,x) = g(x,x);
In this statement g will match any function and hence all occurrences of f, in which the first argument is a function and the second argument is the symbol x, will match. In the right hand side the function g will be substituted by whatever identity g had to assume in the left hand side to make the match. Hence f(f,x) will be replaced by f(x,x).

In general function wildcards can only match functions. Even though tensors are special functions, regular function wildcards cannot match tensors, and tensor wildcards cannot match functions. However commuting function wildcards can match noncommuting functions et vice versa.

Index wildcards can only match indices. The dimension of the indices is not relevant. Hence:

    id f(mu?,mu?) = 4;
would match both f(ka,ka) and f(2,2). We will see later how to be more selective about such matches.

When the same wildcard occurs more than once in a pattern, it should be matched by the same object in all its occurrences. Hence the above pattern would not match f(mu,nu).

There is one complication concerning the above rule of index wildcards only matching indices. FORM writes contractions with vectors in a special shorthand notation called Schoonschip notation. Hence f(mu)*p(mu) becomes f(p). This means that the substitution

    id f(mu?)*g(nu?) = fg(mu,nu);
should also replace the term f(p)*g(q) by fg(p,q). In this case it looks like the wildcard indices matched the vectors. This is however not the case, because if we take the previous pattern (with the f(mu?,mu?)), it is not going to match the term f(p,p), because this term should be read as something of the type f(mu,nu)*p(mu)*p(nu) and that term does not fit the pattern f(mu?,mu?).

Vector wildcards can match vectors, but they can also match vector-like expressions in function arguments. A vector-like expression is an expression in which all terms contain one single vector without indices, possibly multiplied by other objects like coefficients, functions or symbols. Hence

    id f(p?) = p.p;
would match f(q), f(2*q-r) and f(a*q+f(x)*r), if p, q and r are vectors, and a and x are symbols, and f is a function. It would not match f(x) and neither would it match f(q*r), nor f(a*q+x).

Wildcard symbols are the most flexible objects. They can match symbols, numbers and expressions that do not contain loose indices or vectors without indices. These last objects are called scalar objects. Hence wildcard symbols can match all scalar objects. In

    id x^n? = x^(n+1)/(n+1);
the wildcard symbol n would normally match a numerical integer power. In
    id f(x?) = x^2;
there would be a match with f(y), with f(1+2*y) and with f(p.p), but there would not be a match with f(p) if p is a vector.

There is one extra type of wildcards. This type is rather special. It refers to groups of function arguments. The number of arguments is not specified. These variables are indicated by a question mark followed by a name (just the opposite of the other wildcard variables), and in the right hand side they are also written with the leading question mark:

    id f(?name) = g(1,?name);
In this statement all occurrences of f with any number of arguments (including no arguments) will match. Hence f(mu,nu) will be replaced by g(1,mu,nu). In the case that f is a regular function and g is a tensor, it is conceivable that the arguments in ?name will not fit inside a tensor. For instance f(x), with x a symbol, would match and FORM would try to put the symbol inside the tensor g. This would result in a runtime error. In general FORM will only accept arguments that are indices or single vectors for a substitution into a tensor. The object ?name is called an argument field wildcard.

One should realize that the use of multiple argument field wildcards can make the pattern matching slow.

    id f(?a,p1?,?b,p2?,?c,p3?,?d)*g(?e,p3?,?f,p1?,?g,p2?,?h) = ....
may involve considerable numbers of tries, especially when there are many occurrences of f and g in a term. One should be very careful with this.

A complication is the pattern matching in functions with symmetry properties. In principle FORM has to try all possible permutations before it can conclude that a match does not occur. This can become rather time consuming when many wildcards are involved. FORM has a number of tricks built in, in an attempt to speed this up, but it is clear that for many cases these tricks are not enough. This type of pattern matching is one of the weakest aspects of `artificial intelligence' in general. It is hoped that in future versions it can be improved. For the moment the practical consequence is that argument field wildcards cannot be used in symmetric and antisymmetric functions. If one needs to make a generic replacement in a symmetric function one cannot use

    CFunction f(symmetric),g(symmetric);
    id  f(?a) = ....;
but one could try something like
    CFunction f(symmetric),ff,g(symmetric);
    id  f(x1?,...,x5?) = ff(x1,...,x5);
    id  ff(?a) = ...;
    id  ff(?a) = f(?a);
if f has for instance 5 arguments. If different numbers of arguments are involved, one may need more than one statement here or a statement with the replace_ function:
    Multiply replace_(f,ff);
It just shows that one should at times be a bit careful with overuse of (anti)symmetric functions. Cyclic functions do not have this restriction.

When there are various possibilities for a match, FORM will just take the first one it encounters. Because it is not fixed how FORM searches for matches (in future versions the order of trying may be changed without notice) one should try to avoid ambiguities as in

    id f(?a,?b) = g(?a)*h(?b);
Of course the current search method is fully consistent (and starts with all arguments in ?a and none in ?b etc, but a future pattern matcher may do it in a different order.

When two argument field wildcards in the left hand side have the same name, a match will only occur, when they match the same objects. Hence

    id f(?a,?a) = g(?a);
will match f(a,b,a,b) or just f (in which case ?a will have zero arguments), but it will not match f(b,b,b).

Sometimes it is useful when a search can be restricted to a limited set of objects. For this FORM knows the concept of sets. If the name of a set is attached after the question mark, this is an indication for FORM to look only for matches in which the wildcard becomes one of the members of the set:

    Symbols a,a1,a2,a3,b,c;
    Set aa:a1,a2,a3;

    id f(a?aa) = ...
would match f(a1) but not f(b). Sets can also be defined dynamically by enclosing the elements between curly brackets as in:
    Symbols a,a1,a2,a3,b,c;

    id f(a?{a1,a2,a3}) = ...
Sets of symbols can contain (small integer) numbers as well. Similarly sets of indices can contain fixed indices (positive numbers less than the value of fixindex (see the chapter on the setup [*]). This means that some sets can be ambiguous in their nature.

Sometimes sets can be used as some type of array. In the case of

    Symbols a,a1,a2,a3,b,c,n;
    Set aa:a1,a2,a3;

    id f(a?aa[n]) = ...
not only does `a' have to be an element of the set aa, but if it is an element of that set, n will become the number of the element that has been matched. Hence for f(a2) the wildcard a would become a2 and the wildcard n would become 2. These objects can be used in the right-hand side. One can also use sets in the right-hand side with an index like the n of the previous example:
    Symbols a,a1,a2,a3,b1,b2,b3,c,n;
    Functions f,g1,g2,g3;
    Set aa:a1,a2,a3;
    Set bb:b1,b2,b3;
    Set gg:g1,g2,g3;

    id f(a?aa[n]) = gg[n](bb[n]);
which would replace f(a2) by g2(b2). One cannot do arithmetic with the number of the array element. Constructions like bb[n+1] are not allowed.

There is one more mechanism by which the array nature of sets can be used. In the statement (declarations as before)

    id f(a?aa?bb) = a*f(a);
a will have to be an element of the set aa, but after the matching it takes the identity of the corresponding element of the set bb. Hence f(a2) becomes after this statement b2*f(b2).

Wildcards can also give their value directly to $-variables (see chapter [*] about the $-variables). If a $-variable is attached to a wildcard (if there is a set restriction, it should be after the set) the $-variable will obtain the same contents as the wildcard, provided a match occurs. If there is more than one match, the last match will be in the $-variable.

    id f(a?$w) = f(a);
will put the match of a in $w. Hence in the case of f(a2) the $-variable will have the value a2. In the case of f(a2)*f(a3) the eventual value of $w depends on the order in which FORM does the matching. This is not specified and it would not be a good strategy to make programs that will depend on it. A future pattern matcher might do it differently! But one could do things like
    while ( match(f(a?$w)) );
        id f($w) = ....
        id g($w) = ....
    endwhile;
just to make sure with which match one is working.


The dollar variables

In the older versions of FORM there were two types of variables: the preprocessor variables and the algebraic variables. The preprocessor variables are string variables that are used by the edit features of the preprocessor to prepare the input for the compiler part of FORM. The algebraic objects are the expressions and the various algebraic variables like the symbols, functions, vectors etc. There existed however very few possibilities to communicate from the algebraic level to the decision taking at the preprocessor level. This has changed dramatically with version 3 and the introduction of the dollar variables.

Dollar variables are basically (little) expressions that can be used to store various types of information. They can be used both as preprocessor objects as well as algebraic objects. They can also be defined and given contents both by the preprocessor and during execution on a term by term basis. Dollar variables are kept in memory. Hence it is important not to make them too big, because in that case performance might suffer.

What is a legal name for a dollar variable? Dollar variables have a name that consists of a dollar sign ($) followed by an alphabetic character and then potentially more alphanumeric characters. Hence $a and $var and $r4t78y0 are legal names and $1a is not a legal name. The variables do not have to be declared. However FORM will complain if a dollar variable is being used, before it has encountered a statement or an instruction in which the variable has been given a value. Hence giving a variable a value counts at the same time as a declaration.

What can be stored in a dollar variable?

Actually, the parts of a term are treated as a complete term and hence as a special case of an algebraic expression. Internally they are stored slightly differently for speed, but at the user level this should not be noticeable. Actually, with the exception of the argument fields, FORM can convert one type into the other and will try so, depending on the use that is made of the specific dollar variable. In the case that a variable is used in a way that should not be possible (like the content of a variable is a symbol, but it is used in a position where an index is expected) there will be a runtime error.

How is a variable used?

How does one give a value to a dollar variable?

Note the difference between #$a = 0; and $a = 0;. One CANNOT make a wildcard construction for dollar variables themselves as in id f($var?) = ...;

Dollar variables CANNOT be indexed as in $var(2) or something equivalent. There is however a solution at the preprocessor level for this by defining individual variables $var1 to $varn and then using $var`i' or `$var`i'' for some preprocessor variable i.

Printing dollar variables:

In both cases one should use the format string. The syntax is described in the chapters on these statements. The format descriptor of a dollar variable is %$ and this looks after the format string for the next dollar variable. Of course one can also use the dollar variable as a preprocessor variable when printing/writing in the preprocessor.

Examples.

Counting terms:

    S	a,b;
    Off statistics;
    L	F = (a+b)^6;
    #$a = 0;
    $a = $a+1;
    Print "      >> After %t we have %$ term(s)",$a;
    #write "     ># $a = `$a'"
     ># $a = 0
    .sort
      >> After  + a^6 we have 1 term(s)
      >> After  + 6*a^5*b we have 2 term(s)
      >> After  + 15*a^4*b^2 we have 3 term(s)
      >> After  + 20*a^3*b^3 we have 4 term(s)
      >> After  + 15*a^2*b^4 we have 5 term(s)
      >> After  + 6*a*b^5 we have 6 term(s)
      >> After  + b^6 we have 7 term(s)
    #write "     ># $a = `$a'"
     ># $a = 7
    .end

Maximum power of x in an expression:

    S	x,a,b;
    Off statistics;
    L	F = (a+b)^4+a*(a+x)^3;
    .sort
    #$a = 0;
    if ( count(x,1) > $a ) $a = count_(x,1);
    Print "      >> After %t the maximum power of x is %$",$a;
    #write "     ># $a = `$a'"
     ># $a = 0
    .sort
      >> After  + 3*x*a^3 the maximum power of x is 1
      >> After  + 3*x^2*a^2 the maximum power of x is 2
      >> After  + x^3*a the maximum power of x is 3
      >> After  + 4*a*b^3 the maximum power of x is 3
      >> After  + 6*a^2*b^2 the maximum power of x is 3
      >> After  + 4*a^3*b the maximum power of x is 3
      >> After  + 2*a^4 the maximum power of x is 3
      >> After  + b^4 the maximum power of x is 3
    #write "     ># $a = `$a'"
     ># $a = 3
    .end


Dollar variables in a parallel environment

When FORM is used for parallel processing, either by means of PARFORM or by means of TFORM, there can be a problem with the dollar variables as in principle there is a central administration and dollar variables that are defined during running will in general have the last assigned value. In a parallel environment this can be nondeterministic. Look for instance at the following example:

    S   x,a,b;
    CF  f;
    L   F = f(a+b) + f(a+2*b);
    .sort
    id  f(x?$x) = f(x);
    Multiply,$x;
    Print;
    .end
Usually this program will give the 'correct' answer, but in principle one thread could define $x and then the next thread could overwrite this value before the first thread has used it. This is serious. Hence FORM will veto the use of multiple threads/processors for modules in which dollar variables get values during the execution of the program, unless the user can give FORM more information about the use of the dollar variables. In the above case the value of $x will be local to each term and hence to each thread. The value in previous terms is unimportant. We can tell this to FORM with a variety of the moduleoption statement (see [*]). This would be:
    S   x,a,b;
    CF  f;
    L   F = f(a+b) + f(a+2*b);
    .sort
    id  f(x?$x) = f(x);
    Multiply,$x;
    Print;
    ModuleOption,local,$x;
    .end
In this case FORM makes at the start of the execution of the module a copy of whatever value $x has at that moment (in this case no value yet and hence it gets set to zero) for each thread/processor and then each thread/processor uses its own copy during execution. After the module has been completed the local copies are removed and the original global value is accessible again. This way execution will be safe in a parallel environment.

There are more cases that FORM can handle in a parallel environment. These are also options in the moduleoption statement:

    ModuleOption,maximum,$a;
    ModuleOption,minimum,$b;
    ModuleOption,sum,$c;
Here we say that $a is accumulating a maximum numerical value, $b collects a minimum numerical value and $c is a numerical sum. In all three cases there is a central administration and the use of the variables has to be blocked for other threads/processors during the updating of the values. Sometimes that can be efficient, but in other programs that may actually make them slower. One should experiment. A sample program is given below:
    S   a1,...,a10;
    L   F = (a1+...+a10)^3;
    .sort
    #$c = 0;
    Print +f "<%w> %t";
    Multiply,(a1+...+a10);
    $c = $c+1;
    ModuleOption,sum,$c;
    .sort
    #message $c = `$c'
    #$max = 0;
    #$min = 10;
    if ( count(a1,1) > $max ) $max = count_(a1,1);
    if ( count(a4,1) < $min ) $min = count_(a4,1);
    ModuleOption,maximum,$max;
    ModuleOption,minimum,$min;
    .sort
    #message $max = `$max'
    #message $min = `$min'
    .end
The print statement is showing which thread is dealing with which term.


Statements


abrackets, antibrackets

Type Output control statement
Syntax ab[rackets][+][-] <list of names>;
  antib[rackets][+][-] <list of names>;
See also bracket ([*]) and the chapter on brackets ([*])


This statement does the opposite of the bracket statement (see [*]). In the bracket statement the variables that are mentioned are placed outside brackets and inside the brackets are all other objects. In the antibracket statement the variables in the list are the only objects that are not placed outside the brackets. For the rest of the syntax, see the bracket statement (section [*]).



also

Type Executable Statement
Syntax a[lso] [options] <pattern> = <expression>;
See also identify ([*]), idold ([*])


The also statement should follow either an id statement or another also statement. The action is that the pattern matching in the also statement takes place immediately after the pattern matching of the previous id statement (or also statement) and after possible matching patterns have been removed, but before the r.h.s. expressions are inserted. It is identical to the idold statement (see [*]). Example:

    id    x = cosphi*x-sinphi*y;
    also  y = sinphi*x+cosphi*y;

The options are explained in the section on the id statement (see [*]).



antisymmetrize

Type Executable statement
Syntax an[tisymmetrize] {<name of function/tensor> [<argument specifications>];}
See also symmetrize ([*]), cyclesymmetrize ([*]), rcyclesymmetrize ([*])


The argument specifications are explained in the section on the symmetrize statements (see [*]).


The action of this statement is to anti-symmetrize the (specified) arguments of the functions that are mentioned. This means that the arguments are brought to `natural order' in the notation of FORM and each exchange of arguments or groups of arguments results in a minus sign in the coefficient of the term. The `natural order' may depend on the order of declaration of the variables. If two arguments or groups of arguments that are part in the anti-symmetrization are identical, the function is replaced by zero.



apply

Type Executable statement
Syntax apply ["<tablename(s)>"];
See also tablebases ([*]), apply ([*])


This statement is explained in the chapter on tablebases.



argexplode

Type Executable statement
Syntax argexplode [<list of functions>]
See also argimplode ([*])


See the description of the ArgImplode [*] statement.



argimplode

Type Executable statement
Syntax argimplode [<list of functions>]
See also argexplode ([*])


This is a rather specialized statement. It converts one notation of indices, used for harmonic sums, harmonic polylogarithms and multiple zeta values into its alternative notation. The two notations are:

   Z(0,0,0,1,0,0,-1)
   Z(4,-3)
In the first notation the indices can only be 0, 1 and -1. In the second notation there can be no zeroes. The `ArgImplode,Z;' statement would be equivalent to the statement
   repeat id Z(?a,0,x?!{0,0},?b) = Z(?a,x+sig_(x),?b);
and takes one from the first notation to the second. The `ArgExplode,Z;' statement is equivalent to the statement
   repeat id Z(?a,x?!{1,0,-1},?b) = Z(?a,0,x-sig_(x),?b);
and takes one from the second notation to the first. The reason that these statements have been built in lies in the fact that for many indices the repeat statements started to become very time-consuming.

For the harmonic sums, the harmonic polylogarithms and the multiple zeta values one can use the summer6 and the harmpol packages in the FORM distribution. They are described in the papers

J. A. M. Vermaseren, Harmonic sums, Mellin transforms and integrals, Int. J. Mod. Phys. A14 (1999) 2037, http://arxiv.org/abs/hep-ph/9806280.

E. Remiddi and J. A. M. Vermaseren, Harmonic polylogarithms, Int. J. Mod. Phys. A15 (2000) 725, http://arxiv.org/abs/hep-ph/9905237.



argument

Type Executable statement
Syntax argument [<argument specifications>]
  {<name of function/set> [<argument specifications>]};
See also endargument ([*])


This statement starts an argument environment. Such an environment is terminated by an endargument statement (see [*]). The statements between the argument and the endargument statements will be applied only to the function arguments as specified by the remaining information in the argument statement. This information is given by:

The combination of a function (or set) possibly followed by numbers of arguments, can occur as many times as needed. The generic numbers of arguments that refer to all functions work in addition to the numbers specified for individual functions. Example
   Argument 2,f,1,{f,f1},3,4;
This specifies the second argument of all functions. In addition the first argument of f will be taken and then also the third and fourth arguments of f and f1 will be taken.

Argument/endargument constructions can be nested.



auto, autodeclare

Type Declaration statement
Syntax autodeclare <variable type> <list of variables to be declared>;
  auto <variable type> <list of variables to be declared>;


The variable types are

s[ymbol]

Declaration of symbols. For options see [*].

v[ector]

Declaration of vectors. For options see [*].

i[ndex]

Declaration of indices. For options see [*].

i[ndices]

Declaration of indices. For options see [*].

f[unctions]

Declaration of noncommuting functions. For options see [*].

nf[unctions]

Declaration of noncommuting functions. For options see [*].

cf[unctions]

Declaration of commuting functions. For options see [*].

co[mmuting]

Declaration of commuting functions. For options see [*].

t[ensors]

Declaration of commuting tensors. For options see [*].

nt[ensors]

Declaration of noncommuting tensors. For options see [*].

ct[ensors]

Declaration of commuting tensors. For options see [*].

The action of the autodeclare statement is to set a default for variable types. In a statement of the type

   AutoDeclare Symbol a,bc,def;
all undeclared variables of which the name starts with the character a, the string bc or the string def will be interpreted as symbols and entered in the name tables as such. In the case there are two statements as in
   AutoDeclare CFunction b,d;
   AutoDeclare Symbol a,bc,def;
all previously undeclared variables of which the name starts with a, bc or def will be declared as symbols. All other previously undeclared variables of which the name starts with a b or a d will be declared as commuting functions. This is independent of the order of the autodeclare statements. FORM starts looking for the most detailed matches first. Hence the variable defi will match with the string def first.

It is also allowed to use the properties of the various variables in the autodeclare statement:

   AutoDeclare Index i=4,i3=3,i5=5;
This declares all previously undeclared variables of which the name starts with an i to be four dimensional indices, unless their names start with i3 in which case they will be three dimensional indices, or their names start with i5 in which case they will be five dimensional indices.



bracket

Type Output control statement
Syntax b[rackets][+][-] <list of names>;
See also antibracket ([*]), keep ([*]), collect([*]) and the chapter on brackets ([*])


This statement causes the output to be reorganized in such a way that all objects in the `list of names' are placed outside brackets and all remaining objects inside brackets. This grouping will remain till the next time that the expression is active and is being manipulated. Hence the brackets can survive skip (see [*]), hide (see [*]) and even save (see [*]) and load (see [*]) statements. The bracket information can be used by the collect (see [*]) and keep (see [*]) statements, as well in r.h.s. expressions when the contents of individual brackets of an expression can be picked up (see [*]).

The list of names can contain names of symbols, vectors, functions and tensors. In addition it can contain dotproducts. There should be only one bracket or antibracket (see [*]) statement in each module. If there is more than one, only the last one has an effect.

The presence of a $+$ or $-$ after the bracket (or anti bracket) refers to potential indexing of the brackets. Usually FORM has the information inside the terms in an expression. If it needs to search for a particular bracket it does so by starting at the beginning of that expression. This can be slow. If one likes to access individual brackets, it may be faster to tell FORM to make an index by putting the $+$ after the bracket or antibracket keyword. For more information, see the chapter on brackets (see [*]). A $-$ indicates that no index should be made. Currently this is the default and hence there is no need to use this option. It is present just in case the default might be changed in a future version of FORM (in which FORM might for instance try to determine by itself what seems best. This option exists for case that the user would like to overrule such a mechanism).

See also the antibracket statement in [*].



cfunctions

Type Declaration statement
Syntax c[functions] <list of functions to be declared>;
See also functions ([*]), nfunctions ([*])


This statement declares commuting functions. The name of a function can be followed by some information that specifies additional properties of the preceding function. These can be (name indicates the name of the function to be declared):

name#r

The function is considered to be a real function (default).

name#c

The function is considered to be a complex function. This means that internally two spaces are reserved. One for the variable name and one for its complex conjugate name#.

name#i

The function is considered to be imaginary.

name(s[ymmetric])

The function is totally symmetric. This means that during normalization FORM will order the arguments according to its internal notion of order by trying permutations. The result will depend on the order of declaration of variables.

name(a[ntisymmetric])

The function is totally antisymmetric. This means that during normalization FORM will order the arguments according to its internal notion of order and if the resulting permutation of arguments is odd the coefficient of the term will change sign. The order will depend on the order of declaration of variables.

name(c[yclesymmetric])

The function is cycle symmetric in all its arguments. This means that during normalization FORM will order the arguments according to its internal notion of order by trying cyclic permutations. The result will depend on the order of declaration of variables.

name(r[cyclesymmetric)

name(r[cyclic])

name(r[eversecyclic])


The function is reverse cycle symmetric in all its arguments. This means that during normalization FORM will order the arguments according to its internal notion of order by trying cyclic permutations and/or a complete reverse order of all arguments. The result will depend on the order of declaration of variables.

The complexity properties and the symmetric properties can be combined. In that case the complexity properties should come first as in

    CFunction f1#i(antisymmetric);




chainin

Type Executable statement
Syntax Chainin,name of function;
See also chainout ([*])


Has the same effect as the statement

   repeat id f(?a)*f(?b) = f(?a,?b);
if f is the name of the function specified. The chainin statement is just a faster shortcut.



chainout

Type Executable statement
Syntax Chainout,name of function;
See also chainin ([*])


Has the same effect as the statement

   repeat id f(x1?,x2?,?a) = f(x1)*f(x2,?a);
if f is the name of the function specified. The chainout statement is just a much faster shortcut.



chisholm

Type Executable statement
Syntax chisholm [options] <spinline indices>;
See also trace4 ([*]) and the chapter on gamma algebra ([*])


This statement applies the identity

$\displaystyle \gamma_a\gamma_\mu\gamma_b {\rm Tr}[\gamma_\mu S]$ $\textstyle =$ $\displaystyle 2\gamma_a( S + S^R ) \gamma_b$  

in order to contract traces. $S$ is here a string of gamma matrices and $S^R$ is the reverse string. This identity is particularly useful when the matrices $\gamma_6 = 1+\gamma_5$ and/or $\gamma_7 = 1-\gamma_5$ are involved. The spinline index refers to which trace should be eliminated this way. The options are

symmetrize

If there is more than one contraction with other gamma matrices, the answer will be the sum of the various contractions, divided by the number of different contractions. This will often result in a minimization of the number of $\gamma_5$ matrices left in the final results.

nosymmetrize

The first contraction encountered will be taken. No attempt is made to optimize with respect to the number of $\gamma_5$ matrices left.

IMPORTANT: the above identity is only valid in 4 dimensions. For more details, see chapter [*] on gamma algebra.



cleartable

Type Declaration statement
Syntax ClearTable [<list of tables>]


This statement clears the tables that are mentioned. Sometimes sparse tables can take so much space that there is no room for new elements, while old elements are not needed any longer. In that case one can clear the table and start all over again with filling it.



collect

Type Specification statement
Syntax collect <name of function>;
  collect <name of function> <name of other function>;
  collect <name of function> <name of other function> <percentage>;
See also bracket ([*]), antibracket ([*]) and the chapter on brackets ([*])


Upon processing the expressions (hence expressions in hide as well as skipped expressions do not take part in this) the contents of the brackets (if there was a bracket or antibracket statement in the preceding module) are collected and put inside the argument of the named function. Hence if the expression F is given by

   F =
      a*(b^2+c)
    + a^2*(b+6)
    + b^3 + c*b + 12;
the statement
   Collect cfun;
will change F into
   F = a*cfun(b^2+c)+a^2*cfun(b+6)+cfun(b^3+c*b+12);
The major complication occurs if the content of a bracket is so long that it will not fit inside a single term. The maximum size of a term is limited by the setup parameter maxtermsize (see [*]). If this size is exceeded, FORM will split the bracket contents over more than one term, in each of which it will be inside the named function. It will issue a warning that it has done so.

If a second function is specified (the alternative collect function) and if a bracket takes more space than can be put inside a single term, the bracket contents will be split over more than one term, in each of which it will be inside the alternative collect function. In this case there is no need for a warning as the user can easily check whether this has occurred by checking whether the alternative function is present in the expression.

If additionally a percentage is specified (an integer in the range of 1 to 99) this determines how big the argument must be as compared to MaxTermSize (see chapter [*] on the setup) before use is made of the alternate collect function.



commuting

Type Declaration statement
Syntax co[mmuting] <list of functions to be declared>;
See also cfunctions ([*]), functions ([*])


This statement is completely identical to the cfunction statement (see [*]).



compress

Type Declaration statement
Syntax comp[ress] <on/off>;
See also on ([*]), off ([*])


This statement is obsolete. The user should try to use the compress option of the on (see [*]) or the off (see [*]) statements.



contract

Type Executable statement
Syntax contract [<argument specifications>];


Statement causes the contraction of pairs of Levi-Civita tensors e_ (see also [*]) into combinations of Kronecker delta's. If there are contracted indices, and if their dimension is identical to the number of indices of the Levi-Civita tensors, the regular shortcuts are taken. If there are contracted indices with a different dimension, the contraction treats these indices temporarily as different and lets the contraction be ruled by the contraction mechanism of the Kronecker delta's. In practise this means that the dimension will enter via $\delta^{\mu}_{\mu} \rightarrow {\rm
dim}(\mu)$.

In FORM there are no upper and lower indices. Of course the user can emulate those. The contract statement always assumes that there is a proper distribution of upper and lower indices if the user decided to work in a metric in which this makes a difference. Note however that due to the fact that the Levi-Civita tensor is considered to be imaginary, there is usually no need to do anything special. This is explained in the chapter on functions (see [*]).

There are several options to control which contractions will be taken. They are

Contract;

Here only a single pair of Levi-Civita tensors will be contracted. The pair that is selected by FORM is the pair that will give the smallest number of terms in their contraction.

Contract <number>;

This tells FORM to keep contracting pairs of Levi-Civita tensors until there are <number> or <number>$+1$ Levi-Civita tensors left. A common example is

Contract 0;

which will contract as many pairs as possible.


Contract:<number>;

Here the number indicates the number of indices in the Levi-Civita tensors to be contracted. Only a single pair will be contracted and it will be the pair that gives the smallest number of terms.

Contract:<number>

<number>;


The First number refers to the number of indices in the Levi-Civita tensors to be contracted. The second number refers to the number of Levi-Civita tensors that should be left (if possible) after contraction.

Note that the order in which FORM selects the contractions is by looking at which pair will give the smallest number of terms. This means that usually the largest buildup of terms is at the end. This is not always the case, because there can be a complicated network of contracted indices.



ctable

Type Declaration statement
Syntax ctable <options> <table to be declared>;
See also functions ([*]), table ([*]), ntable ([*])


This statement declares a commuting table and is identical to the table command (see [*]) which has the commuting property as its default.



ctensors

Type Declaration statement
Syntax ct[ensors] <list of tensors to be declared>;
See also functions ([*]), tensors ([*]), ntensors ([*])


This statement declares commuting tensors. It is equal to the tensor statement (see [*]) which has the commuting property as its default.



cyclesymmetrize

Type Executable statement
Syntax cy[clesymmetrize] {<name of function/tensor> [<argument specifications>];}
See also symmetrize ([*]), antisymmetrize ([*]), rcyclesymmetrize ([*])


The argument specifications are explained in the section on the symmetrize statements (see [*]).


The action of this statement is to cycle-symmetrize the (specified) arguments of the functions that are mentioned. This means that the arguments are brought to `natural order' in the notation of FORM by trying cyclic permutations of the arguments or groups of arguments. The `natural order' may depend on the order of declaration of the variables.



deallocatetable

Type Declaration
Syntax DeallocateTable,name(s) of sparse table(s);
See also table ([*]), fill ([*]), table bases ([*])


Works only for sparse tables. Deallocates all definitions of elements as obtained with `Fill' statements as if there never were any `Fill' statements for the given tables.

This statement exists because sometimes cleaning up big tables is needed when they take too much memory. This can be the case when a big tablebase has been used.



delete

Type Specification statement
Syntax delete storage;
See also save ([*]), load ([*])


This statement clears the complete storage file and reduces it to zero size. The effect is that all stored expressions are removed from the system. Because it is impossible to remove individual expressions from the store file (there is no mechanism to fill the resulting holes) it is the only way to clean up the storage file. If some expressions should be excluded from this elimination process, one should copy them first into active global expressions, then delete the storage file, after which the expressions can be written to storage again with a .store instruction.



denominators

Type Executable statement
Syntax denominators functionname;


This statement allows the user to rename all occurrences of the built-in denominator function. This built-in function is kind of an oddity inside FORM. Denominators are presented by a very special function which doesn't really have a name and hence is rather hard to address. In addition there are special rules connected to denominators. Hence it is usually better to collect denominators inside functions that have been defined by the user and hence allow the user to manipulate them at will. Yet, objects can end up inside denominator functions, especially when output from other programs is read in. Hence this statement allows all occurrences of the denominator function to be renamed into the function that is given in the statement. This function will work well together with the PolyRatFun statement in which we define a PolyFun with two arguments of which the second acts as a denominator and the first as a numerator:

   PolyRatFun,rat;
   Denominators,den;
   id den(x?) = rat(1,x);
For more about this one should consult the part on the PolyRatFun statement ([*]) and the chapter on polynomials (still to be included because the current version can handle only polynomials in a single variable and is also not optimized for many occurrences that have identical denominators).



dimension

Type Declaration statement
Syntax d[imension] <number or symbol>;
See also index ([*])


Sets the default dimension. This default dimension determines the dimension of the indices that are being declared without dimension specification as well as the dimension of all dummy indices. At the moment an index is declared and there is no dimension specification, FORM looks for the default dimension and uses that. This index will then have this dimension, even when the default dimension is changed at a later moment. The dummy indices always have the dimension of the current default dimension. If the default dimension is changed the dimension of all dummy indices changes with it. Varieties:

Dimension <number>;

Declares the number to be the default dimension. The number must be smaller than 32768 on 32bit architectures or 2147483648 on 64bit architectures. Negative numbers are not allowed. If one wants to work with negative dimensions, the practical workaround is to use a symbolic dimension and later replace that symbol appropriately.

Dimension <symbol>;

Symbol must be the name of a symbol, either previously declared or declarable because of an auto-declaration (see [*]). Declares the symbol to be the default dimension.

Dimension

<symbol>:<symbol>;


The symbols must be the names of symbols, either previously declared or declarable because of an auto-declaration (see [*]). The first symbol will be the default dimension. The second symbol will be the first symbol minus 4. It will be used as such in the trace contractions. See also [*] and [*].

Examples:

   Dimension 3;
   Dimension n;
   Dimension n:[n-4];
The default dimension in FORM is 4.



discard

Type Executable statement
Syntax dis[card];


This statement discards the current term. It can be very useful in statements of the type

   if ( count(x,1) > 5 ) Discard;
which eliminates all terms that have more than five powers of x.



disorder

Type Executable statement
Syntax disorder <pattern> = <expression>;
See also identify ([*])


This statement is identical to the disorder option of the id statement (see [*]). It is just a shorthand notation for `id disorder'.



drop

Type Specification statement
Syntax drop;
  drop <list of expressions>;
See also ndrop ([*])


In the first variety this statement eliminates all expressions from the system. In the second variety it eliminates only the expressions that are mentioned from the system. All expressions that are to be dropped can still be used in the r.h.s. of other expressions inside the current module. Basically the expressions to be dropped are not treated for execution and after the module has finished completely they are removed. See also the ndrop statement [*].



dropcoefficient

Type Executable statement
Syntax DropCoefficient;


This statement replaces the coefficient of the current term by one. In principle it has the same effect as

   Multiply 1/coeff_;
but there is always the philosophical issue what is the coefficient once one enters function arguments. Inside an Argument/EndArgument environment this statement would drop the coefficient of the terms inside the argument.



else

Type Executable statement
Syntax else;
See also if ([*]), elseif ([*]), endif ([*])


To be used in combination with an if statement (see [*]). The statements following the else statement until the matching endif statement (see [*]) will be executed for the current term if the conditions of the matching proceeding if statement and/or all corresponding elseif statements (see [*]) are false. If any of the conditions of the matching proceeding if or elseif statements are true the statements following the else statement will be skipped.



elseif

Type Executable statement
Syntax elseif ( <condition> );
See also if ([*]), else ([*]), endif ([*])


Should be proceeded by an if statement (see [*]) and followed at least by a matching endif statement (see [*]). If the conditions of the proceeding matching if statement and all proceeding matching elseif statements are false the condition of this elseif statement will be evaluated. If it is true, the statements following it until the next matching elseif, else or endif statement will be executed. If not, control is passed to this next elseif, else or endif statement. The syntax for the condition is exactly the same as for the condition in the if statement.



endargument

Type Executable statement
Syntax endargument;
See also argument ([*])


Terminates an argument environment (see [*]). The argument statement and its corresponding endargument statement must belong to the same module. Argument environments can be nested with all other environments.



endif

Type Executable statement
Syntax endif;
See also if ([*]), elseif ([*]), else ([*])


Terminates an if construction (see [*], [*] and [*]). If should be noted that if constructions can be nested.



endinexpression

Type Executable statement
Syntax endinexpression;
See also inexpression([*])


Only to be used in combination with the inexpression statement. The combination

   InExpression,expr;
       Statements;
   EndInExpression;
is a more readable version of the construction
   if ( expression(expr) );
       Statements;
   endif;




endinside

Type Executable statement
Syntax endinside;
See also inside ([*]) and the chapter on $-variables ([*])


Terminates an `inside' environment (see [*]) which is used to operate on the contents of $-variables (see [*]).



endrepeat

Type Executable statement
Syntax endrepeat;
See also repeat ([*]), while ([*])


Ends the repeat environment. The repeat environment is started with a repeat statement (see [*]). The repeat and its matching endrepeat should be inside the same module. Repeat environments can be nested with all other environments (and other repeat environments).



endterm

Type Executable statement
Syntax endterm;
See also term ([*]), sort ([*])


Terminates a term environment (see [*]). Term environments can be nested with other term environments and with other environments in general. The whole environment should be part of one single module. See also [*].



endwhile

Type Executable statement
Syntax endwhile;
See also while ([*]), repeat ([*])


Terminates a while environment (see [*]). The while statement and its corresponding endwhile statement must be part of the same module.



exit

Type Executable statement
Syntax exit ["<string>"];
See also setexitflag ([*])


Causes execution to be aborted immediately. The string will be printed in the output. This can be used to indicate where FORM ran into the exit statement.



extrasymbols

Type Declaration statement
Syntax extrasymbols,array/vector/underscore,name;
See also ToPolynomial ([*]) ,FromPolynomial ([*]) and the section on extra symbols ([*]).


Starting with version 4.0 of FORMsome built in operations or statements can only deal with symbols and numbers. Examples of this are factorization([*]) (which uses the topolynomial facilities automatically) and output simplification (still to be implemented). The ToPolynomial statement takes each term, looks for objects that are not symbols to positive powers and replaces them by symbols. If the object has been encountered before the same symbol will be used, otherwise a new symbol will be defined. The object represented by the `extra symbol' is stored internally and can be printed if needed with the %X option in the #write instruction ([*]). The representation of the extra symbols is by default the name Z followed by a number and an underscore character. If another name is desired this should be specified in an `ExtraSymbols' statement. The name given may contain only alphabetic characters! Because some compilers do not like the underscore character, there is an alternative notation for the extra symbols. This is just for cosmetic reasons and one cannot feed these symbols into the compiler this way. This is with an array notation. The statement

   ExtraSymbols,array,Ab;
would cause the second extra symbol to be printed as Ab(2). The total number of defined extra symbols is given by the built in symbol extrasymbols_. The option vector in the ExtraSymbols statement is identical to the option array and the option underscore reverts the notation back to the default notation with the trailing underscore.



factarg

Type Executable statement
Syntax factarg options {<name of function/set> [<argument specifications>]};
See also splitarg ([*])


Splits the indicated function arguments into individual factors. The argument specifications are as in the splitarg statement (see [*]). There are a few extra options:

(0)

Eliminates the coefficient of the term in the argument. Similar to Normalize,(0),....

(1)

The coefficient of the term and its sign are pulled out separately.

(-1)

The coefficient is pulled out with its sign.

In the case of the above options only the coefficient is treated. When these options are not used the whole term is treated as in:

    Symbols a,b,c;
    CFunctions f,f1,f2,f3;
    Local F = f(-3*a*b)+f(3*a*b)
             +f1(-3*a*b)+f1(3*a*b)
             +f2(-3*a*b)+f2(3*a*b)
             +f3(-3*a*b)+f3(3*a*b);
    FactArg,f;
    Factarg,(0),f1;
    Factarg,(1),f2;
    Factarg,(-1),f3;
    Print;
    .end

   F =
      f(a,b,-1,3) + f(a,b,3) + 2*f1(a*b) + f2(a*b,-1,3) + f2(a*b,3)
      + f3(a*b,-3) + f3(a*b,3);
When no extra options are used, starting with version 4.0, the whole argument is factorized over the rationals. This means that
    f(x^2+2*x*y+y^2) --> f(y + x,y + x,1)
It should be noticed that FORMcan although the internal algoriths can only factorize expressions with numbers and symbols, FORMredefines all non-symbol objects temporarily into symbols and at the end substitutes them back. This is done with a mechanism that is similar to that of the ToPolynomial statement.

See also the On OldfactArg; and Off OldFactArg statements for a compatibility mode with versions before version 4.0.



fill

Type Declaration statement
Syntax fill <tableelement> = <expression> [,<moreexpressions>];
See also table ([*]), fillexpression ([*]), printtable ([*])


The standard way to define elements of a table. In the left hand side one specifies the table element without the extra function arguments that could potentially occur (see [*]). In the right hand side one specifies what the table element should be substituted by. Example:

    Table tab(1:2,1:2,x?);
    Fill tab(1,1) = x+y;
    Fill tab(2,1) = (x+y)^2;
    Fill tab(1,2) = tab(1,1)+y;
    Fill tab(2,2) = tab(2,1)+y^2;
The first fill statement is a bit like a continuous attempt to try the substitution
    id  tab(1,1,x?) = x+y;
The last two fill statements show that one could use the table recursively. If a real loop occurs the program may terminate due to stack overflow.

It is possible to define several table elements in one statement. In that case the various elements are separated by commas. The last index is the first one to be raised. This means that in the above example one could have written:

    Table tab(1:2,1:2,x?);
    Fill tab(1,1) = x+y,tab(1,1)+y,(x+y)^2,tab(2,1)+y^2;



One warning is called for. One should avoid using expressions in the right hand side of fill statements:

    Table B(1:1);
    Local dummy = 1;
    .sort
    Fill B(1) = dummy;
    Drop dummy;
    .sort
    Local F = B(1);
    Print;
    .end
In the example a crash will result, because when we use the table element the expression dummy doesn't exist anymore. In a fill statement the r.h.s. is not expanded. Hence it keeps the reference to the expression dummy. When the table element is used the reference to the expression dummy is inserted and expanded. Hence one obtains the contents of dummy that exist at the moment of use. This is illustrated in the following example:
    Table B(1:1);
    Local dummy = 1;
    .sort
    Fill B(1) = dummy;
    .sort
    Local F = B(1);
    Print;
    .sort
    Drop;
    .sort
    Local dummy = 2;
    .sort
    Local F = B(1);
    Print;
    .end
The final value of F will be 2, not 1.

A way to get around this problem is to force the evaluation of the table definition by using dollar variables:

    Table B(1:1);
    Local dummy = 1;
    .sort
    #$value = dummy;
    Fill B(1) = `$value';
    Drop dummy;
    .sort
    Local F = B(1);
    Print;
    .end
Here we use the character representation of the contents of the dollar variable to obtain an expression that doesn't need any further evaluation. If we would put
    fill B(1) = $value;
a reference to the dollar variable would be inserted and it would only be evaluated at use again. In principle this could cause similar problems.

Not dropping the expression dummy can sometimes give the correct result, but is potentially still unsafe.

    Table B(1:1);
    Local u = 2;
    Local dummy = 1;
    .sort
    Fill B(1) = dummy;
    Drop dummy;
    .sort
    Local v = 5;
    Local F = B(1);
    Print;
    .end
Here the answer will be 5, because after u has been dropped the expressions will be renumbered. Hence now dummy becomes the first expression, and eventually v becomes the second expression. The references in the table elements are not renumbered. Hence the r.h.s. of B(1) keeps pointing at the second expression, which at the moment of application has the value 5. One can see now also why the original example crashes. First dummy was the first expression and at the moment of application F is the first (existing) expression. Hence the substitution of B(1) causes a self reference and hence an infinite loop. Eventually some buffer will overflow.



fillexpression

Type Declaration statement
Syntax fillexpression <table> = <expression>(<x1>,...,<xn>);
  fillexpression <table> = <expression>(<funname>);
See also table ([*]), fill ([*]) and the table_ function ([*])


Used to dynamically load a table during runtime. When there are n symbols (here called x1 to xn) it is assumed that the table is n-dimensional. The expression must previously have been bracketed in these symbols and each of the brackets has the effect of a fill statement in which the powers of the x1 to xn refer to the table elements. Brackets that do not have a corresponding table element are skipped.

In the case that only a function name is specified the arguments of the function refer to the table elements.



fixindex

Type Declaration statement
Syntax fi[xindex] {<number>:<value>};
See also index ([*]) and chapter [*].


Defines d_(number,number) = value in which number is the number of a fixed index (hence a positive short integer with a value less than ConstIndex (see [*]). The value should be a short integer, i.e. its absolute value should be less than $2^{15}$ on 32 bit computers and less than $2^{31}$ on 64 bit computers. One can define more than one fixed index in one statement. Before one would like to solve problems involving the choice of a metric with this statement, one should consult the chapter on the use of a metric (chapter [*]).



format

Type Output control statement
Syntax fo[rmat] <option>;
See also print ([*])


Controls the format for the printing of expressions. There is a variety of options.

$<$number$>$

Output will be printed using the indicated number of characters per line. The default is 72. Numbers outside the range 1-255 are corrected to 72. Positive numbers less than 39 are corrected to 39.

float
    [$<$number$>$]

Numbers are printed in floating point notation, even though internally they remain fractions. This is purely cosmetic. If no number is specified the precision of the output will be 10 digits. If a number is specified it indicates the number of digits to be used for the precision.

rational

Output format is switched back to rational numbers (in contrast to floating point output). This is the default.

nospaces

The output is printed without the spaces that make the output slightly more readable. This gives a more compact output.

spaces

The output is printed with extra spaces between the terms and around certain operators to make it slightly more readable. This is the default.

fortran

The output is printed in a way that is readable by a fortran compiler. This includes continuation characters and the splitting of the output into blocks of no more than 15 continuation lines. This number can be changed with the setup parameter ContinuationLines (see [*]). In addition dotproducts are printed with the `dotchar' in the place of the period between the vectors. This dotchar can be set in the setup file (see [*]). Its default is the underscore character.

doublefortran

Same as the fortran mode, but fractions are printed with double floating point numbers, because some compilers convert numbers like 1. into 1.E0. With this format FORM will force double precision by using 1.D0.

fortran90

Similar to the fortran option, but prints the continuation lines according to the syntax of Fortran 90. If the fortran90 option is followed by a comma and a string that does not contain white space or other comma's, this string is attached to all numbers in coefficients of terms. Example:
Format Fortran90,.0_ki;
which would give in the printout:
+23.0_ki/32.0_ki*a**2&
& +34.0_ki/1325.0_ki*a**3
When there is no string attached it defaults to a period as in the regular Fortran option.

C

Output will be C compatible. The exponent operator ($\wedge$) is represented by the function pow. It is the responsibility of the user that this function will be properly defined. Dotproducts are printed with the `dotchar' in the place of the period between the vectors. This dotchar can be set in the setup file (see [*]). Its default is the underscore character.

maple

Output will be as much as possible compatible with Maple format. It is not guaranteed that this is perfect.

mathematica

Output will be as much as possible compatible with Mathematica format. It is not guaranteed that this is perfect.

reduce

Output will be as much as possible compatible with Reduce format. It is not guaranteed that this is perfect.

The last few formats have not been tried out extensively. The author is open for suggestions.



frompolynomial

Type Executable statement
Syntax frompolynomial
See also factarg ([*]), ToPolynomial ([*]) and ExtraSymbols ([*], [*]).


Starting with version 4.0 of FORMsome built in operations or statements can only deal with symbols and numbers. Examples of this are factorization([*]) and output simplification (still to be implemented). Whereas the ToPolynomial statement takes each term, looks for objects that are not symbols to positive powers and replaces them by symbols the FromPolynomial does the opposite: it replaces the newly defined extra symbols and replaces them back by their original meaning.



functions

Type Declaration statement
Syntax f[unctions] <list of functions to be declared>;
See also cfunctions ([*]), tensors ([*]), ntensors ([*]),
  table ([*]), ntable ([*]), ctable ([*])


Used to declare one or more functions. The functions declared with this statement will be noncommuting. For commuting functions one should use the cf[unctions] statement (see [*]). Functions can have a number of properties that can be set in the declaration. This is done by appending the options to the name of the function. These options are:

name#r

The function is considered to be a real function (default).

name#c

The function is considered to be a complex function. This means that internally two spaces are reserved. One for the variable name and one for its complex conjugate name#.

name#i

The function is considered to be imaginary.

name(s[ymmetric])

The function is totally symmetric. This means that during normalization FORM will order the arguments according to its internal notion of order by trying permutations. The result will depend on the order of declaration of variables.

name(a[ntisymmetric])

The function is totally antisymmetric. This means that during normalization FORM will order the arguments according to its internal notion of order and if the resulting permutation of arguments is odd the coefficient of the term will change sign. The order will depend on the order of declaration of variables.

name(c[yclesymmetric])

The function is cycle symmetric in all its arguments. This means that during normalization FORM will order the arguments according to its internal notion of order by trying cyclic permutations. The result will depend on the order of declaration of variables.

name(r[cyclesymmetric)

name(r[cyclic])

name(r[eversecyclic])


The function is reverse cycle symmetric in all its arguments. This means that during normalization FORM will order the arguments according to its internal notion of order by trying cyclic permutations and/or a complete reverse order of all arguments. The result will depend on the order of declaration of variables.


The complexity properties and the symmetric properties can be combined. In that case the complexity properties should come first as in

    Function f1#i(symmetric);




funpowers

Type Declaration statement
Syntax funpowers <on/off>;
See also on ([*]), off ([*])


This statement is obsolete. The user should try to use the funpowers option of the on (see [*]) or the off (see [*]) statements.



global

Type Definition statement
Syntax g[lobal] <name> = <expression>;
  g[lobal] <names of expressions>;
See also local ([*])


Used to define a global expression. A global expression is an expression that remains active until the first .store instruction. At that moment it is stored into the `storage file' and stops being manipulated. After this it can still be used in the right hand side of expressions and id statements (see [*]). Global expressions that have been put in the storage file can be saved to a disk file with the save statement (see [*]) for use in later programs.

There are two versions of the global statement. In the first the expression is defined and filled with a right hand side expression. The left hand side and the right hand side are separated by an = sign. In this case the expression can have arguments which will serve as dummy arguments after the global expression has been stored with a .store instruction. Note that this use of arguments can often be circumvented with the replace_ function (see [*]) as in

    Global F(a,b) = (a+b)^2;
    .store
    Local FF = F(x,y);
    Local GG = F*replace_(a,x,b,y);
because both definitions give the same result.

The second version of the global statement has no = sign and no right hand side. It can be used to change a local expression into a global expression.



goto

Type Executable statement
Syntax go[to] <label>;
See also label ([*])


Causes processing to proceed at the indicated label statement (see [*]). This label statement must be in the same module.



hide

Type Specification statement
Syntax hide;
  hide <list of expressions>;
See also nhide ([*]), unhide ([*]), nunhide ([*]), pushhide ([*]), pophide ([*])


In the first variety this statement marks all currently active expressions for being put in hidden storage. In the second variety it marks only the specified active expressions as such.

If an expression is marked for being hidden, it will be copied to the `hide file', a storage which is either in memory or on file depending on the combined size of all expressions being hidden. If this size exceeds the size of the setup parameter scratchsize (see [*]) the storage will be on file. If it is less, the storage will be in memory. An expression that has been hidden is not affected by the statements in the modules as long as it remains hidden, but it can be used inside other expressions in the same way skipped expressions (see [*]) or active expressions can be used. In particular all its bracket information (see [*]) is retained and can be accessed, including possible bracket indexing.

The hide mechanism is particularly useful if an expression is not needed for a large number of modules. It has also advantages over the storing of global expressions after a .store instruction (see [*]), because the substitution of global expressions is slower (name definitions may have changed and have to be checked) and also a possible bracket index is not maintained by the .store instruction.

Expressions can be returned from a hidden status into active expressions with the unhide statement (see [*]). One might want to consult the nhide statement ([*]) as well.

When an expression is marked to be hidden it will remain just marked until execution starts in the current module. When it is the turn of the expression to be executed, it is copied to the hide file instead.

Note that a .store instruction will simultaneously remove all expressions from the hide system.



identify

Type Executable statement
Syntax id[entify] [<options>] <pattern> = <expression>;
See also also ([*]), idnew ([*]), idold ([*])


The statement tries to match the pattern. If the pattern matches one or more times, it will be replaced by the expression in the r.h.s. taking the possible wildcard substitutions into account. For the description of the patterns, see chapter [*].

The options are

multi

This option is for combinations of symbols and dotproducts only and it does not use wildcard powers. FORM determines how many times the pattern fits in one pattern matching action. Then the r.h.s. is substituted to that power. It is the default for these kinds of patterns.

many

This is the default for patterns that contain other objects than symbols and dotproducts. The pattern is matched and taken out. Then FORM tries again to match the pattern in the remainder of the term. This is repeated until there is no further match. Then for each match the r.h.s. is substituted (with its own wildcard substitutions).

select

This option should be followed by one or more sets. After the sets the pattern can be specified. The pattern will only be substituted if none of the objects mentioned in the sets will be left after the pattern has been taken out. This holds only for objects 'at ground level'; i.e. the pattern matcher will not look inside function arguments for this. Note that this is a special case of the option 'only'.

once

The pattern is matched only once, even if it occurs more than once in the term. The first match that FORM encounters is taken. When wildcards are involved, this may depend on the order of declaration of variables. It could also be installation dependent. Also the setting of properorder (see [*] and [*]) could be relevant. Try to write programs in such a way that the outcome does not depend on which match is taken.

only

The pattern will match only if there is an exact match in the powers of the symbols and dotproducts present.

ifmatch$-\!\!>$

This option should be followed by the name (or number) of a label. If the pattern matches, the replacement will be made after which the execution continues at the label.

ifnomatch$-\!\!>$

This option should be followed by the name (or number) of a label. If the pattern does not match, execution continues at the label.

disorder

This option is used for products of noncommuting functions or tensors. The match will only take place if the order of the functions in the match is different from what FORM would have made of it if the functions would be commuting. Hence if the functions in the term are in the order that FORM would give them if they would be commuting (which depends on the order of declaration) there will be no match. This can be rather handy when using wildcards as in F(a?)*F(b?).





idnew

Type Executable statement
Syntax idn[ew] [<options>] <pattern> = <expression>;
See also identify ([*]), also ([*]), idold ([*])


This statement and its options are completely identical to the regular id or identify statement (see [*]).



idold

Type Executable statement
Syntax ido[ld] [<options>] <pattern> = <expression>;
See also identify ([*]), also ([*]), idnew ([*])


This statement and its options are completely identical to the regular also statement (see [*]). The options are described with the id or identify statement (see [*]).



if

Type Executable statement
Syntax if ( <condition> );
  if ( <condition> ) <executable statement>
See also elseif ([*]), else ([*]), endif ([*])


Used for executing parts of code only when certain conditions are met. Works together with the else statement (see [*]), the elseif statement (see [*]) and the endif statement (see [*]). There are two versions. In the first the if statement must be accompanied by at least an endif statement. In that case the statements between the if statement and the endif statement will be executed if the condition is met. It is also possible to use elseif and else statements to be more flexible. This is done in the same way as in almost all computer languages.

In the second form the if statement does not terminate with a semicolon. It is followed by a single regular statement. No endif statement should be used. The single statement will be executed if the condition is met.

The condition in the if statement should be enclosed by parentheses. Its primary components are:

count()

Returns an integer power counting value for the current term. Should have arguments that come in pairs. The first element of the pair is a variable. The second is its integer weight. The types of variables that are allowed are symbols, dotproducts, functions, tensors, tables and vectors. The weights can be positive as well as negative. They have to be short integers (Absolute value $< 2^{15}$ on 32 bit computers and $< 2^{31}$ on 64 bit computers). The vectors can have several options appended to their name. This is done by putting a + after the name of the vector and have this followed by one or more of the following letters:

v Loose vectors with an index are taken into account.
d Vectors inside dotproducts are taken into account.
f Vectors inside tensors are taken into account.
?set
The set should be a set of functions. Vectors inside the functions that are members of the set are taken into account. It is assumed that those functions are linear in the given vector

When no options are specified the result is identical to +vfd.


match()

The argument of the match condition can be any left hand side of an id statement, including options as once, only, multi, many and select (see [*]). The id of the id statement should not be included. FORM will invoke the pattern matcher and see how many times the pattern matches. This number is returned. In the case of once or only this is of course at most one.

expression()

The argument(s) of this condition is/are a list of expressions. In the case that the current term belongs to any of the given expressions the return value is 1. If it does not belong to any of the given expressions the return value is 0.

findloop()

The arguments are as in the replaceloop statement (see [*]) with the exception of the outfun which should be omitted. If FORM detects an index loop in the current term that fulfils the specified conditions the return value is 1. It is 0 otherwise.

multipleof()

The argument should be a positive integer. This object is to be compared with a number (could be obtained from a condition) and if this number is an integer multiple of the argument there will be a match. If should be obvious that such a compare only makes sense for the == and != operators.

$<$integer$>$

To be compared either with another number, the result of a condition or a multipleof object.

coefficient

Represents the coefficient of the current term.

$-variable

Will be evaluated at runtime when the if statement is encountered. Should evaluate into a numerical value. If it does not, an error will result.

All the above primary components result in numerical objects. Such objects can be compared to each other in structures of the type $<$obj1$>$ $<$operator$>$ $<$obj2$>$. The result of such a compare is either true (or 1) or false (or 0). The operators are:

$>$

Results in true if object 1 is greater than object 2.

$<$

Results in true if object 1 is less than object 2.

$=$

Same as ==.

$==$

Results in true if both objects have the same value.

$>=$

Results in true if object 1 is greater than or equal to object 2.

$<=$

Results in true if object 1 is less than or equal to object 2.

$!=$

Results in true if object 1 does not have the same value as object 2.

If the condition for true is not met, false is returned. Several of the above compares can be combined with logical operators. For this it is necessary to enclose the above compares within parentheses. This forces FORM to interpret the hierarchy of the operators properly. The extra logical operators are

$\vert\vert$

The or operation. True if at least one of the objects 1 and 2 is true (or nonzero). False or zero if both are false or zero.

$\&\&$

The and operation. True if both the objects 1 and 2 are true (or nonzero). False or zero if at least one is false or zero.

Example:

    if ( ( match(f(1,x)*g(?a)) && ( count(x,1,v+d,1) == 3 ) )
         || ( expression(F1,F2) == 0 ) );
        some statements
    endif;
    if ( ( ( match(f(1,x)*g(?a)) == 0 ) && ( count(x,1,v+d,1) == 3 ) )
         || expression(F1,F2) );
        some statements
    endif;
We see that match() is equivalent to ( match() != 0 ) and something similar for expression(). This shorthand notation can make a program slightly more readable.

Warning! The if-statement knows only logical values as the result of operations. Hence the answer to anything that contains parenthesis (which counts as the evaluation of an expression) is either true (1) or false (0). Hence the object (5) evaluates to true.



ifmatch

Type Executable statement
Syntax ifmatch$-\!\!>$ <label> <pattern> = <expression>;
See also identify ([*])


This statement is identical to the ifmatch option of the id statement (see [*]). Hence

   ifmatch-> ....
is just a shorthand notation for
   id ifmatch-> ....




ifnomatch

Type Executable statement
Syntax ifnomatch$-\!\!>$ <label> <pattern> = <expression>;
See also identify ([*])


This statement is identical to the ifnomatch option of the id statement (see [*]). Hence

   ifnomatch-> ....
is just a shorthand notation for
   id ifnomatch-> ....




index, indices

Type Declaration statement
Syntax i[ndex] <list of indices to be declared>;
  i[ndices] <list of indices to be declared>;
See also dimension ([*]), fixindex ([*])


Declares one or more indices. In the declaration of an index one can specify its dimension. This is done by appending one or two options to the name of the index to be declared:

name=dim

The dimension is either a nonnegative integer or a previously declared symbol. If the dimension is zero this means that no dimension is attached to the index. The consequence is that the index cannot be summed over and index contractions are not performed for this index. If no dimension is specified the default dimension will be assumed (see the dimension statement [*]).

name=dim:ext

The dimension is a symbol as above. Ext is an extra symbol which indicates the value of dim-4. This option is useful when traces over gamma matrices are considered (see [*] and [*]).





inexpression

Type Executable statement
Syntax inexpression,name(s) of expression(s);
See also endinexpression([*])


The combination

   InExpression,expr;
       Statements;
   EndInExpression;
is a more readable version of the construction
   if ( expression(expr) );
       Statements;
   endif;




inparallel

Type Specification statement
Syntax inparallel;
  inparallel <list of expressions>;
See also NotInParallel ([*]), ModuleOption ([*])


This statement is only active in the context of TFORM. It causes (small) expressions to be executed side by side. Normally the terms of expressions are distributed over the processors and the expressions are executed one by one. This isn't very efficient for small expressions because there is a certain amount of overhead. When there are many small expressions, this statement can cause each expression to be executed by its own processor. A consequence is that the expressions now can finish in a semi-random order and hence may end up in the output in a order that is different from when this statement isn't used. The proper order is restored in the first module that comes after and that doesn't use this option. One should be careful using this statement for big expressions, because in that case the sorting may need sort files and the output may temporarily need scratch files and the simultaneous use of many files can slow execution down significantly.

In the case that no expressions are mentioned, all active expressions will be affected. When there is a list of expressions, only those mentioned will be affected, provided they are active. Several of these statements will work cumulatively. This statement doesn't affect expressions that are still to be defined inside the current module. If it is needed to affect such expressions inside the current module, one should use the InParallel option of the ModuleOption [*] statement. This statement works independently of the `On Parallel;' [*] and `Off Parallel;' [*] statements.



inside

Type Executable statement
Syntax inside <list of $-variables>;
See also endinside ([*]) and the chapter on $-variables ([*])


works a bit like the argument statement (see [*]) but with $-variables instead of with functions. An inside statement should be paired with an endinside statement (see [*]) inside the same module. The statements in-between will then be executed on the contents of the $-variables that are mentioned. One should pay some attention to the order of the action. The $-variables are treated sequentially. Hence, after the first one has been treated its contents are substituted by the new value. Then the second one is treated. If it uses the contents of the first variable, it will use the new value. If the first variable uses the contents of the second variable it will use its old value. Redefining any of the listed $-variables in the range of the `inside-environment' is very dangerous. It is not specified what FORM will do. Most likely it will be unpleasant.



insidefirst

Type Declaration statement
Syntax insidefirst <on/off>;
See also on ([*]), off ([*])


This statement is obsolete. The user should try to use the insidefirst option of the on (see [*]) or the off (see [*]) statements.



intohide

Type Specification statement
Syntax intohide;
  intohide <list of expressions>;
See also hide ([*])


In the first variety this statement marks all currently active expressions for being put in hidden storage at the end of the module, after it has been processed. In the second variety it marks only the specified active expressions as such.

The difference with the hide ([*]) statement is that in the hide statement the expression is copied immediately into the hide system and it will not be processed in the current module, while in the intohide statement the expression is first processed and its final output in this module is sent to the hide system rather than to the regular scratch system. The effect is the same as not putting the intohide statement in the current module and putting a hide statement in the next, but it saves one copy operation and it is possibly a bit more economical with the disk space.

Note that a .store instruction will simultaneously remove all expressions from the hide system.



keep

Type Specification statement
Syntax keep brackets;
See also bracket ([*]), antibracket ([*]) and the chapter on brackets ([*])


The effect of this statement is that during execution of the current module the contents of the brackets are not considered. The statements only act on the `outside' of the brackets. Only when the terms are considered finished and are ready for the sorting are they multiplied by the contents of the brackets. At times this can save much computer time as complicated pattern matching and multiplications of function arguments with large fractions have to be done only once, rather than for each complete term separately (assuming that each bracket contains a large number of terms).

There can be some nasty side effects. Assume an expression like:

    F = f(i1,x)*(g(i1,y)+g(i1,z));
    B  f;
    .sort
    Keep Brackets;
    sum i1;
the result will be
    F = f(N1_?,x)*g(i1,y)+f(N1_?,x)*g(i1,z);
because at the moment of summing over i1 FORM is not looking inside the brackets and hence it never sees the second occurrence of i1. There are some beneficial applications of the keep statement in the `mincer' package that comes with the FORM distribution. In this package the most costly step was made faster by a significant factor (depending on the problem) due to the keep brackets statement.



label

Type Executable statement
Syntax la[bel] <name of label>;
See also goto ([*])


Places a label at the current location. The name of the label can be any name or positive number. Control can be transfered to the position of the label by a goto statement (see [*]) or the ifmatch option of an id statement (see [*]). The only condition is that the goto statement and the label must be inside the same module. Once the module is terminated all existing labels are forgotten. This means that in a later module a label with the same name can be used again (this may not improve readability though but it is a good thing when third party libraries are used).



load

Type Declaration statement
Syntax loa[d] <filename> [<list of expressions>];
See also save ([*]), delete ([*])


Loads a previously saved file (see [*]). If no expressions are specified all expressions in the file are put in the storage file and obtain the status of stored global expressions. If a list of expressions is specified all those expressions are loaded and possible other expressions are ignored. If a specified expression is not present, an error will result. If one does not know exactly what expressions are present in a file one could load the file without a list of expressions, because FORM will list all expressions that it encountered.



local

Type Definition statement
Syntax l[ocal] <name> = <expression>;
  l[ocal] <names of expressions>;
See also global ([*])


Used to define a local expression. A local expression is an expression that will be dropped when a .store instruction is encountered. If this is not what is intended one should use global expressions (see [*]). The statement can also be used to change the status of a global expression into that of a local expression. In that case there is no = sign and no right hand side.



makeinteger

Type Executable statement
Syntax makeinteger [<argument specifications>]
  {<name of function/set> [<argument specifications>]};
See also normalize ([*])


Normalizes the indicated argument of the indicated functions(s) in such a way that all terms in this argument have integer coefficients with a their greatest common divider being one. This still leaves the possibility that the first term of this argument may be negative. If this is not desired one can first normalize the argument and then make its coefficients integer. The overall factor that is needed to make the coefficients like described is taken from the overall factor of the complete term. Example

    S   a,b,c;
    CF  f;
    L   F = f(22/3*a+14/5*b+18/7*c);
    MakeInteger,f;
    Print +f;
    .end

   F =
      2/105*f(135*c + 147*b + 385*a);

Note that this feature can be used to make outputs look much more friendly. It can be used in combination with the AntiBracket statement ([*]) and the function dum_ ([*]) to imitate a smart extra level of brackets and make outputs shorter.



many

Type Executable statement
Syntax many <pattern> = <expression>;
See also identify ([*])


This statement is identical to the many option of the id statement (see [*]). Hence

   many ....
is just a shorthand notation for
   id many ....




merge

Type Executable statement
Syntax merge,functionname;
  merge,once,functionname;
See also shuffle ([*])


This statement is exactly the same as the shuffle statement (see [*]).



metric

Type Declaration statement
Syntax metric <option>;

Remark: statement is inactive. Should have no effect.



moduleoption

Type Module control statement
Syntax moduleoption <option>[,<value>];
See also polyfun ([*]), slavepatchsize ([*]), dollar variables ([*])


Used to set a mode for just the current module. It overrides the normal setting and will revert to this normal setting after this module. The settings are:

parallel

Allows parallel execution of the current module if all other conditions are right. This is the default.

noparallel

Vetoes parallel execution of the current module.

inparallel

This option is more or less equivalent to the InParallel [*] statement. The difference is that because this statement comes at the end of the module, its effects include also the expressions that have been defined inside the current module. This is not the case for the InParallel statement. The InParallel option can be followed by the names of expressions. If no such names are present, all active expressions are affected. Otherwise only the expressions that are mentioned are affected. Once this option is mentioned no more options can be used inside the same ModuleOption statement. This is to avoid potential confusion that could arise when expressions are used with a name identical to the name of one of the options.

notinparallel

This option is more or less equivalent to the NotInParallel [*] statement. The difference is that because this statement comes at the end of the module, its effects include also the expressions that have been defined inside the current module. This is not the case for the NotInParallel statement. The NotInParallel option can be followed by the names of expressions. If no such names are present, all active expressions are affected. Otherwise only the expressions that are mentioned are affected. Once this option is mentioned no more options can be used inside the same ModuleOption statement. This is to avoid potential confusion that could arise when expressions are used with a name identical to the name of one of the options.

polyfun

Possibly followed by the name of a `polyfun'. Is similar to the polyfun statement (see [*]) but only valid for the current module.

slavepatchsize

Followed by a number. Similar to the slavepatchsize statement (see [*]) but only valid for the current module.

local

Should be followed by a list of $-variables. Indicates that the contents of the indicated $-variables are not relevant once the module has been finished and neither is the term by term order in which the $-variables obtain their value. In practise each processor/thread will work with its own copy of this variable.

maximum

Should be followed by a list of $-variables. Indicates that of the contents of the indicated $-variables the maximum is the only thing that is relevant once the module has been finished. The term by term order in which the $-variables obtain their value is not relevant.

minimum

Should be followed by a list of $-variables. Indicates that of the contents of the indicated $-variables the minimum is the only thing that is relevant once the module has been finished. The term by term order in which the $-variables obtain their value is not relevant.

sum

Should be followed by a list of $-variables. Indicates that the indicated $-variables are representing a sum. The term by term order in which the $-variables obtain their value is not relevant.

The options `local', `maximum', `minimum' and `sum' are for parallel versions of FORM. The presence of $-variables can be a problem when the order of processing of the terms is not well defined. These options tell FORM what these $-variables are used for. In the above cases FORM can take the appropriate action when gathering information from the various processors. This will allow parallel execution of the current module. If $-variables are used in a module and they are defined on a term by term basis, the normal action of FORM will be to veto parallel execution unless it is clear that no confusion can occur. See also chapter [*] on the parallel version and section [*] on the dollar variables.



modulus

Type Declaration statement
Syntax m[odulus] [option(s)] <value>;


Defines all calculus to be modulus the given integer value, provided this number is positive.

The modulus calculus extends itself to fractions. This means that if the value is not a prime number division by zero could result. It is the responsibility of the user to avoid such problems.

When the value in the modulus statement is either 0 or 1 the statement would be meaningless. It is used as a signal to FORM that modulus calculus should be switched off again.

The options are

NoFunctions
Modulus calculus is not performed inside function arguments.
AlsoFunctions
Modulus calculus is also performed inside function arguments.
CoefficientsOnly
Modulus calculus is neither performed inside function arguments nor on powers of symbols.
PlusMin
The values of numbers are reduced to the range $(-value+1)/2$ to $(value-1)/2$.
Positive
The values of numbers are reduced to the range $0$ to $value-1$.
NoDollars
The modulus calculus is not performed inside dollar variables.
AlsoDollars
The modulus calculus is performed also inside dollar expressions.
InverseTable
To speed up calculations all inverses are computed by means of a table. If the modulus value is very big, this table may be too big for the memory. That would result in an error message.
NoInverseTable
No Table of Inverses is constructed. They are calculated whenever needed.
AlsoPowers
Reduction is also used on powers of symbols with the relation $x^mod = x$ if mod is the given value
NoPowers
No reduction on powers is done.
PrintPowersOf
The proper syntax is here printpowersof(generator) in which generator is supposed to be a generator for calculus modulus the given value, which means that all numbers will be written as a power of the generator. If the number turns out not to be a proper generator an error will be given. Note that finding the powers is done by means of the construction of a table. Hence, if the modulus value is very big the table might not fit inside memory. This will result in an error message.
The default mode is NoFunctions, Positive, NoInverseTable, NoDollars, NoPowers.

The current syntax (version 4.0 and later) differs slightly from the previous syntax. As however there were many bugs in the old implementation we suspect that a slight change of the options does not inconvenience any many users.


multi

Type Executable statement
Syntax multi <pattern> = <expression>;
See also identify ([*])


This statement is identical to the multi option of the id statement (see [*]). Hence

   multi ....
is just a shorthand notation for
   id multi ....




multiply

Type Executable statement
Syntax mu[ltiply] [<option>] <expression>;


Statement multiplies all terms by the given expression. It is advisable to use the options when noncommuting variables are involved. They are:

left

Multiplication is from the left.

right

Multiplication is from the right.

There is no guarantee as to what the default is with respect to multiplication from the left or from the right. It is up to FORM to decide what it considers to be most efficient when neither option is present.

Note that one should not abbreviate this command to `multi', because there is a separate multi command (see [*]).



ndrop

Type Specification statement
Syntax ndrop;
  ndrop <list of expressions>;
See also drop ([*])


In the first variety this statement cancels all drop plans. This means that all expressions scheduled for being dropped will be restored to their previous status of local or global expressions. In the second variety this happens only to the expressions that are specified. Example:

   Drop;
   Ndrop F1,F2;
This drops all expressions, except for the expressions F1 and F2.



nfunctions

Type Declaration statement
Syntax n[functions] <list of functions to be declared>;
See also functions ([*]), cfunctions ([*])


This statement declares noncommuting functions. It is equal to the function statement (see [*]) which has the noncommuting property as its default.



nhide

Type Specification statement
Syntax nhide;
  nhide <list of expressions>;
See also hide ([*]), unhide ([*]), nunhide ([*]), pushhide ([*]), pophide ([*])


In its first variety this statement undoes all hide plans that exist thus far in the current module. In the second variety it does this only for the specified active expressions. See the hide statement in [*]. Example:

   Hide;
   Nhide F1,F2;
Here all active expressions will be transferred to the hide file except for the expressions F1 and F2.



normalize

Type Executable statement
Syntax normalize options {<name of function/set> [<argument specifications>]};
See also argument ([*]), splitarg ([*]), makeinteger ([*])


Normalizes the indicated arguments of the indicated functions. Normalization means that the argument will be multiplied by the inverse of its coefficient (provided it is not zero). This holds for single term arguments. For multiple term arguments the inverse of the coefficient of the first term of the argument is used. The options and the argument specifications are as in the SplitArg statement (see [*]). Under normal circumstances the coefficient that is removed from the argument(s) is multiplied into the coefficient of the term. This can be avoid with the extra option (0). Hence

Normalize,f;

changes f(2*x+3*y) into 2*f(x+3/2*y) but

Normalize,(0),f;

changes f(2*x+3*y) into f(x+3/2*y).





notinparallel

Type Specification statement
Syntax notinparallel;
  notinparallel <list of expressions>;
See also InParallel ([*]), ModuleOption ([*])


This statement is only active in the context of TFORM. It vetoes (small) expressions to be executed side by side. For a complete explanation of this type of running one should look at the InParallel [*] statement. Because the default is that expressions are executed one by one, the major use of this statement is in constructions like:

   InParallel;
   NotInParallel F1,F25;
which would first mark all expressions to be executed in simultaneous mode and then make an exception for F1 and F25.



nprint

Type Output control statement
Syntax np[rint] <list of names of expressions>;
See also print ([*])


Statement is used to take expressions from the list of expressions to be printed. When a print statement is used (see [*]) without specification of expressions, all active expressions are marked for printing. With this statement one can remove a number of them from the list.



nskip

Type Specification statement
Syntax nskip;
  nskip <list of expressions>;
See also skip ([*])


In the first variety it causes the cancellation of all skip plans (see [*]) for expressions. The status of these expressions is restored to their previous status (active local or global expressions). In the second variety this is done for the specified expressions only. Example:

   Skip;
   Nskip F1,F2;
This causes all active expressions to be skipped except for the expressions F1 and F2.



ntable

Type Declaration statement
Syntax ntable <options> <table to be declared>;
See also functions ([*]), table ([*]), ctable ([*])


This statement declares a noncommuting table. For the rest it is identical to the table command (see [*]) which has the commuting property as its default.



ntensors

Type Declaration statement
Syntax nt[ensors] <list of tensors to be declared>;
See also functions ([*]), tensors ([*]), ctensors ([*])


This statement declares noncommuting tensors. For the rest it is equal to the tensor statement (see [*]) which has the commuting property as its default.

The options that exist for properties of tensors are the same as those for functions (see [*]).



nunhide

Type Specification statement
Syntax nunhide;
  nunhide <list of expressions>;
See also hide ([*]), nhide ([*]), unhide ([*]), pushhide ([*]), pophide ([*])


In its first variety this statement undoes all unhide (see [*] and [*]) plans that the system has in the current module. In its second variety this happens only with the specified expressions. Example:

   Unhide;
   Nunhide F1,F2;
All expressions are taken from the hide system, except for the expressions F1 and F2.



nwrite

Type Declaration statement
Syntax nw[rite] <keyword>;
See also on ([*]), off ([*])


This statement is considered obsolete. All its varieties have been taken over by the off statement (see [*]) and the on statement (see [*]). The current version of FORM will still recognize it, but the user is advised to avoid its usage. In future versions of FORM it is scheduled to be used for a different kind of writing and hence its syntax may change considerably. The conversion program conv2to3 should help in the conversion of programs that have been written for version 2. For completeness we still give the syntax and how it should be converted. The keywords are:

stats

Same as: Off stats;

statistics

Same as: Off statistics;

shortstats

Same as: Off shortstats;

shortstatistics

Same as: Off shortstatistics;

warnings

Same as: Off warnings;

allwarnings

Same as: Off allwarnings;

setup

Same as: Off setup;

names

Same as: Off names;

allnames

Same as: Off allnames;

shortstats

Same as: Off shortstats;

highfirst

Same as: Off highfirst;

lowfirst

Same as: Off lowfirst;

powerfirst

Same as: Off powerfirst;





off

Type Declaration statement
Syntax off <keyword>;
  off <keyword> <option>;
See also on ([*])


Statement to control settings during execution. Many of these settings replace older statements. The settings and their keywords are:

allnames

Turns the allnames mode off. The default.

allwarnings

Turns off the printing of all warnings.

checkpoint

Deactivates the checkpoint mechanism. See [*].

compress

Turns compression mode off.

finalstats

Turns off the last line of statistics that is normally printed at the end of the run (introduced in version 3.2).

highfirst

Puts the sorting in a low first mode.

insidefirst

Not active at the moment.

lowfirst

Leaves the default low first mode and puts the sorting in a high first mode.

names

Turns the names mode off. This is the default.

nospacesinnumbers



Makes that very long numbers are printed with leading blank spaces at the beginning of a new line. The numbers are usually broken up by placing a backslash character at the end of the line and then continuing at the next line. For cosmetic purposes FORM puts usually a few blank spaces at the beginning of the line. FORM itself can read this but some programs cannot. This option can be turned off by the `on nospacesinnumbers;' statement. The printing of the blank characters can be restored by turning this variable off. See also page [*] for a corresponding variable in the setup file.

oldfactarg

Switches the use of the FactArg statement[*] to the new mode of version 4 or later in which expressions in the argument of the mentioned function are completely factored over the rationals. The default is off.

parallel

Disallows the running of the program in parallel mode (only relevant for parallel versions of FORM).

powerfirst

Puts the sorting back into `highfirst' mode.

propercount

Turns the propercounting mode off. This means that for the generated terms in the statistics not only the `ground level' terms are counted but also terms that were generated inside function arguments.

properorder

Turns the properorder mode off. This is the default.

setup

Switches off the mode in which the setup parameters are printed. This is the default.

stats

Same as `Off statistics'.

statistics

Turns off the printing of statistics.

shortstats

Same as `Off shortstatistics'.

shortstatistics

Takes the writing of the statistics back from shorthand mode to the regular statistics mode in which each statistics messages takes three lines of text and one blank line.

threadloadbalancing




Disallows the loadbalancing of TFORM in parallel mode. In other versions of FORM this option is ignored.

threads

Disallows multithreaded running in TFORM. In other versions of FORM this option is ignored.

threadstats

Turns off the thread by thread printing of the statistics in TFORM. Only the master thread will be printing statistics. Other versions of FORM will ignore this option.

totalsize

Switches the totalsize mode off. For a more detailed description of the totalsize mode, see the "On TotalSize;" command[*].

warnings

Turns off the printing of warnings.

If a description is too short, one should also consult the description in the on statement (see [*]).



on

Type Declaration statement
Syntax on <keyword>;
  on <keyword> <option>;
See also off ([*])


New statement to control settings during execution. Many of these settings replace older statements. The settings and their keywords are:

allnames

Same as `On names' but additionally all system variables are printed as well. Default is off.

allwarnings

Puts the printing of warnings in a mode in which all warnings, even the very unimportant warnings are printed.

checkpoint

Activates the checkpoint mechanism that allows for the recovery of a crashed FORM session. See [*] for detailed information.

compress

Turns compression mode on. This compression is a relatively simple compression that hardly costs extra computer time but saves roughly a factor two in disk storage. The old statement was `compress on' but this should be avoided in the future. This setting is the default.

compress,gzip

This option should be followed by a comma or a space and a single digit. It activates the gzip compression for the sort file. This compression can make the intermediate sort file considerably shorter at the cost of some CPU time. This option can be used when disk space is at a premium. The digit indicates the compression level. Zero means no compression and 9 is the highest level. The default level is 6. Above that the compression becomes very slow and doesn't gain very much extra.

fewerstatistics

Determines how many of the statistics FORM prints when a small buffer is full. The keyword can be followed by a positive integer in which case one out of that many of these statistics will be printed. If no number is given the default value of 10 is used. When the number that follows is zero, this feature is turned off (same effect as the value one).

fewerstats

Same as the above fewerstatistics.

finalstats

Determines whether FORM prints a final line of run time statistics at the end of the run. Default is on.

highfirst

In this mode polynomials are sorted in a way that high powers come before low powers.

insidefirst

Not active at the moment.

lowfirst

In this mode polynomials are sorted in a way that low powers come before high powers. This is the default.

names

Turns on the mode in which at the end of each module the names of all variables that have been defined by the user are printed. This is an inspection mode for debugging by the user. Default is off.

nospacesinnumbers



Makes that very long numbers are printed with no leading blank spaces at the beginning of a new line. The numbers are usually broken up by placing a backspace character at the end of the line and then continuing at the next line. For cosmetic purposes FORM puts usually a few blank spaces at the beginning of the line. FORM itself can read this but some programs cannot. Hence this printing of the blank characters can be omitted by turning this variable on. See also page [*] for a corresponding variable in the setup file.

oldfactarg

Switches the use of the FactArg statement[*] to the old mode from before version 4. This is a compatibility mode to allow oldprograms that rely on a specific working of the FactArg statement to still run. The default is off.

parallel

Allows the running of the program in parallel mode unless other problems prevent this. This is of course only relevant for parallel versions of FORM. The default is on.

powerfirst

In this mode polynomials are sorted in a way that high powers come before low powers. The most relevant is however the combined power of all symbols.

propercount

Sets the counting of the terms during generation into `propercount' mode. This means that only terms at the `ground level' are counted and terms inside functions arguments are not counted in the statistics. This setting is the default.

properorder

Turns the properorder mode on. The default is off. In the properorder mode FORM pays particular attention to function arguments when bringing terms and expressions to normal form. This may cost a considerable amount of extra time. In normal mode FORM is a bit sloppy (and much faster) about this, resulting sometimes in an ordering that appears without logic. This concerns only function arguments! This mode is mainly intended for the few moments in which the proper ordering is important.

setup

Causes the printing of the current setup parameters for inspection. Default is off.

shortstatistics

Puts the writing of the statistics in a shorthand mode in which the complete statistics are written on a single line only.

shortstats

Same as `On shortstatistics'.

statistics

Turns the writing of runtime statistics on. This is the default. It is possible to change this default with one of the setup parameters in the setup file (see [*]).

stats

Same as `On statistics'.

threadloadbalancing




Causes the load balancing mechanism in TFORM to be turned on or off. Default is on. Ignored by other versions of FORM.

threads

Allows the running of the program in multithreaded mode unless other problems prevent this. This is of course only relevant for TFORM. Other versions of FORM ignore this. The default is on.

threadstats

Only active for TFORM. It determines whether all threads print their run time statistics or only the master thread does so. Default is on.

totalsize

Puts FORM in a mode in which it tries to determine the maximum space occupied by all expressions at any given moment during the execution of the program. This space is the sum of the input/output/hide scratch files, the sort file(s) and the .str file. This maximum is printed at the end of the program. The same can be obtained with the "TotalSize ON" command in the setup (see [*]) or the -T option in the command tail when FORM is started (see [*]).

warnings

Turns on the printing of warnings in regular mode. This is the default.





once

Type Executable statement
Syntax once <pattern> = <expression>;
See also identify ([*])


This statement is identical to the once option of the id statement (see [*]). Hence

   once ....
is just a shorthand notation for
   id once ....




only

Type Executable statement
Syntax only <pattern> = <expression>;
See also identify ([*])


This statement is identical to the only option of the id statement (see [*]). Hence

   only ....
is just a shorthand notation for
   id only ....




polyfun

Type Declaration statement
Syntax polyfun <name of function>;
  polyfun;
See also moduleoption ([*])


Declares the specified function to be the `polyfun'. The polyfun is a function of which the single argument is considered to be the coefficient of the term. If two terms are otherwise identical the arguments of their polyfun will be added during the sorting, even if these arguments are little expressions. Hence

    PolyFun acc;
    Local F = 3*x^2*acc(1+y+y^2)+2*x^2*acc(1-y+y^2);
will result in
    F = x^2*acc(5+y+5*y^2);
Note that the external numerical coefficient is also pulled inside the polyfun.

If the polyfun statement has no argument, FORM reverts to its default mode in which no polyfun exists. This does not change any terms. If one would like to remove the polyfun from the terms one has to do that `manually' as in

    PolyFun;
    id  acc(x?) = x;
in which we assume that previously the function acc had been declared to be the `polyfun'.



polyratfun

Type Declaration statement
Syntax polyratfun <name of function>;
  polyratfun;
See also polyfun ([*]), moduleoption ([*])


Declares the specified function to be the `polyratfun'. The polyratfun is a function with two arguments which together form a rational polynomial that acts as the coefficient of the term. If two terms are otherwise identical the arguments of their polyratfun will be added during the sorting, even if these arguments are little nontrivial. Hence

    PolyRatFun acc;
    Local F = 3*x^2*acc(1+y+y^2,1-y)+2*x^2*acc(1-y+y^2,1+y);
will result in
    F = x^2*acc(-y^3-10*y^2-2*y-5,y^2-1);
Note that the external numerical coefficient is also pulled inside the polyratfun.

If the polyratfun statement has no argument, FORM reverts to its default mode in which no polyratfun exists. This does not change any terms.

The polyratfun has many similarities with the polyfun (see [*]). At any moment there can only be at most either one polyfun or one polyratfun. Occurrences of the polyfun or the polyratfun with the wrong number or the wrong type of arguments are treated as regular functions.

There is a fundamental difference between the polyfun and the polyratfun. The last one is far more restrictive. It can have only numbers and symbols for its arguments. Also the ordering of the terms in the arguments can be different. In the polyratfun the terms are always sorted with the highest power first. In the polyfun the ordering is as with the regular terms. By default the lowest powers come first as one usually likes for power series expansions.

REMARK: In versions after 15-nov-2007 but before 1-apr-2011 (version 4.0 beta) not all facilities were operational. Among others only rational polynomials in a single variable were supported. Starting with version 4.0 the polyratfun is supposed to be fully operational.



pophide

Type Specification statement
Syntax pophide;
See also hide ([*]), nhide ([*]), unhide ([*]), nunhide ([*]), pushhide ([*])


Undoes the action of the most recent pushhide statement (see [*]). If there is no matching pushhide statement an error will result.



print

Type Print statement
Syntax Print [<options>];
  Print {[<options>] <expression>};
  Print [<options>] "<format string>" [<objects>];
See also print[] ([*]), nprint ([*]), printtable ([*])


General purpose print statement. It has three modes. In the first two modes flags are set for the printing of expressions after the current module has been finished. The third mode concerns printing during execution. This allows the printing of individual terms or $-variables on a term by term basis. It should be considered as a useful debugging device.

In the first mode all active expressions are scheduled for printing. The options are

+f

Printing will be only to the log file.

-f

Printing will be both to the screen and to the log file. This is the default.

+s

Each term will start a new line. This is called the single term mode.

-s

Regular term mode. There can be more terms in a line. Linebreaks are placed when the line is full. The line size is set in the format statement (see [*]). This is the default.

In the second mode one can specify individual expressions to be printed. The options hold for all the expressions that follow them until new options are specified. The options are the same as for the first mode.

In the third mode there is a format string as for the printf command in the C programming language. Of course the control characters are not exactly the same as for the C language because the objects are different. The special characters are:

%t

The current term will be printed at this position including its sign, even if this is a plus sign.

%T

The current term will be printed at this position. If its coeficient is positive no leading plus sign is printed.

%w

The number of the current thread will be printed. This is for TFORM only. In the sequential version this combination is skipped. The number zero refers to the master thread.

%W

The number of the current thread and its CPU-time at the moment of printing. This is for TFORM only. In the sequential version this combination is skipped. The number zero refers to the master thread.

%$

A dollar expression will be printed at this position. The name(s) of the dollar expression(s) should follow the format string in the order in which they are used in the format string.

%%

The character %.

%

If this is the last character of the string no linefeed will be printed at the end of the print command.

$\backslash$n

A linefeed.

Each call is terminated with a linefeed. Example:

    Symbols a,b,c;
    Local F = 3*a+2*b;
    Print "> %T";
    id  a = b+c;
    Print ">> %t";
    Print;
    .end
> 3*a
>>  + 3*b
>>  + 3*c
> 2*b
>>  + 2*b

   F =
      5*b + 3*c;

In the third mode one can also use the +/-f options of the first mode. This should be placed before the format string as in

    Print +f "(%$) %t",$var;

Because of the mixed nature of this statement it can occur in more than one location in the module.



print[]

Type Output control statement
Syntax print[] {[<options>] <name>};
See also print ([*])


Print statement to cause the printing of expressions at the end of the current module. Is like the first two modes of the regular print statement (see [*]), but when printing FORM does not print the contents of each bracket, only the number of terms inside the bracket. Is to be used in combination with a bracket or an antibracket statement (see [*] and [*]). Apart from this the options are identical to those of the first two modes of the print statement.



printtable

Type Print statement
Syntax printtable [<options>] <tablename>;
  printtable [<options>] <tablename> $>$ <filename>;
  printtable [<options>] <tablename> $>\!\!>$ <filename>;
See also print ([*]), table ([*]), fill ([*]), fillexpression ([*]),
  and the table_ function ([*])


Almost the opposite of a FillExpression statement (see [*]). Prints the contents of a table according to the current format (see [*]). The output can go to standard output, the log file or a specified file. The elements of the table that have been defined and filled are written in the form of fill statements (see [*]) in such a way that they can be read in a future program to fill the table with the current contents. This is especially useful when the fillexpression statement has been used to dynamically extend tables based on what FORM has encountered during running. This way those elements will not have to be computed again in future programs.

The options are

+f

Output is to the logfile and not to the screen.

-f

Output is both to the logfile and to the screen. This is the default.

+s

Output will be in a mode in which each new term starts a new line.

-s

Output will be in the regular mode in which new terms continue to be written on the same line within the limits of the number of characters per line as set in the format statement. Default is 72 characters per line. This can be changed with the format statement (see [*]).

If redirection to a file is specified output will be only to this file. The +f option will be ignored. There are two possibilities:

$>$ filename

The old contents of the file with name `filename' will be overwritten.

$>\!\!>$ filename

The table will be appended to the file with the name `filename'. This allows the writing of more than one table to a file.





propercount

Type Declaration statement
Syntax propercount <on/off>;
See also on ([*]), off ([*])


This statement is obsolete. The user should try to use the propercount option of the on (see [*]) or the off (see [*]) statements.



pushhide

Type Specification statement
Syntax pushhide;
See also hide ([*]), nhide ([*]), unhide ([*]), nunhide ([*]), pophide ([*])


Hides all currently active expressions (see [*]). The pophide statement (see [*]) can bring them back to active status again.



ratio

Type Executable statement
Syntax ratio <symbol1> <symbol2> <symbol3>;


This statement can be used for limited but fast partial fractioning. In the statement

   ratio a,b,c;
in which a, b and c should be three symbols FORM will assume that $c = b-a$ and then make the substitutions
$\displaystyle \frac{1}{a^m}\frac{1}{b^n}$ $\textstyle =$ $\displaystyle \sum_{i=0}^{m-1}\sign(i)
\binom(n-1+i,n-1)\frac{1}{a^{m-i}}\frac{...
...}
+\sum_{i=0}^{n-1}\sign(m)
\binom(m-1+i,m-1)\frac{1}{b^{n-i}}\frac{1}{c^{m+i}}$  
$\displaystyle \frac{b^n}{a^m}$ $\textstyle =$ $\displaystyle \sum_{i=0}^n\binom(n,i)\frac{c^i}{a^{m-n+i}}
       \hfill m\ge n$  
$\displaystyle \frac{b^n}{a^m}$ $\textstyle =$ $\displaystyle \sum_{i=0}^{m-1}\binom(n,i)\frac{c^{n-i}}{a^{m-i}}
+ \sum_{i=0}^{n-m}\binom(m-1+i,m-1)
c^ib^{n-m-i}
       \hfill m<n$  

Of course, such substitutions can be made also by the user in a more flexible way. This statement has however the advantage of the best speed.

Actually the ratio statement is a leftover from the Schoonschip inheritance. For most simple partial fractioning one could use

   repeat id 1/[x+a]/[x+b] = (1/[x+a]-1/[x+b])/[b-a];
   repeat id [x+a]/[x+b] = 1-[b-a]/[x+b];
   repeat id [x+b]/[x+a] = 1+[b-a]/[x+a];
or similar constructions. This does not give the speed of the binomials, but it does make the program more readable and it is much more flexible.



rcyclesymmetrize

Type Executable statement
Syntax rc[yclesymmetrize] {<name of function/tensor> [<argument specifications>];}
See also symmetrize ([*]), cyclesymmetrize ([*]), antisymmetrize ([*])


The argument specifications are explained in the section on the symmetrize statement (see [*]).


The action of this statement is to reverse-cycle-symmetrize the (specified) arguments of the functions that are mentioned. This means that the arguments are brought to `natural order' in the notation of FORM by trying cyclic and reverse cyclic permutations of the arguments or groups of arguments. The `natural order' may depend on the order of declaration of the variables.



redefine

Type Executable statement
Syntax r[edefine] <preprocessor variable> "<string>";
See also preprocessor variables in the chapter on the preprocessor ([*])


This statement can be used to change the contents of preprocessor variables. The new contents can be used after the current module has finished execution and the preprocessor becomes active again for further translation and compilation. This termwise adaptation of the value of a preprocessor variable can be very useful in setting up multi module loops until a certain condition is not met any longer. Example:

   #do i = 1,1
      statements;
      if ( condition ) redefine i "0";
      .sort
   #enddo
As long as there is a term that fulfils the condition the loop will continue. This defines effectively a while loop (see [*]) over various modules. Note that the .sort instruction is essential. Note also that a construction like
   if ( count(x,1) > 3 ) redefine i "`i'+1";
is probably not going to do what the user intends. It is not going to count terms with more than three powers of x. The preprocessor will insert the compile time value of the preprocessor variable i. If this is 0, then each time a term has more than three powers of x, i will get the string value 0+1. If one would like to do such counting, one should use a dollar variable (see [*]).



renumber

Type Executable statement
Syntax renumber <number>;
See also sum ([*])


Renumbers the dummy indices. Dummy indices are indices of the type N1_?. Normally FORM tries to renumber these indices to make the internal representation of a term `minimal'. It does not try exhaustively though. Especially interference with symmetric or antisymmetric functions is far from perfect. This is due to considerations of economy. With the renumber statement the user can force FORM to do better. The allowable options are:

0

All exchanges of one pair of dummy indices are tried until all pair exchanges yield no improvements. This is the default if no option is specified.

1

If there are N sets of dummy indices all N! permutations are tried. This can be very costly when a large number of indices is involved. Use with care!





repeat

Type Executable statement
Syntax repeat;
  repeat <executable statement>
See also endrepeat ([*]), while ([*])


The repeat statement starts a repeat environment. It is terminated with an endrepeat statement (see [*]). The repeat statement and its matching endrepeat statement should be inside the same module.

The statements inside the repeat environment should all be executable statements (or print statements) and if any of the executable statements inside the environment has changed the current term, the action of the endrepeat statement will be to bring control back to the beginning of the environment. In that sense the repeat/endrepeat combination acts as

   do
      executable statements
   while any action due to any of the statements
The second form of the statement is a shorthand notation:
   repeat;
      single statement;
   endrepeat;
is equivalent to
   repeat single statement;
Particular attention should be given to avoid infinite loops as in
   repeat id a = a+1;
A more complicated infinite loop is
   repeat;
      id  S(x1?)*R(x2?) = T(x1,x2,x2-x1);
      id  T(x1?,x2?,x3?pos_) = T(x1,x2-2,x3-1)*X(x2);
      id  T(x1?,x2?,x3?) = S(x1)*R(x2);
   endrepeat;
If the current term is S(2)*R(2), the statements in the loop do not change it in the end. Yet the program goes into an infinite loop, because the first id statement will change the term (action) and the third statement will change it back. FORM does not check that the term is the same again. Hence there is action inside the repeat environment and hence the statements will be executed again. This kind of hidden action is a major source of premature terminations of FORM programs.

Repeat environments can be nested with all other environments (and of course also with other repeat/endrepeat combinations).



replaceloop

Type Executable statement
Syntax replaceloop <parameters>;
See also the findloop option of the if statement ([*])


This statement causes the substitution of index loops. An index loop is a sequence of contracted indices in which the indices are arguments of various instances of the same function and each contracted index occurs once in one instance of the function and once in another instance of the function. Such a contraction defines a connection and if a number of such connections between occurrences of the function form a loop this structure is a candidate for replacement. Examples of such loops are:

    f(i1,i2,j1)*f(i2,i1,j2)
    f(i1,i2,j1)*f(i2,i3,j2)*f(i1,i3,j3)
    f(i1,k1,i2,j1)*f(k2,i2,i3,j2)*f(i1,k3,i3,j3)
The first term has a loop of two functions or vertices and the other two terms each define a loop of three vertices. The parameters are:

$<$name$>$

The name of the function that defines the `vertices'. This must always be the first parameter.

arguments=number

Only occurrences of the vertex function with the specified number of arguments will be considered. The specification of this parameter is mandatory.

loopsize=number

Only a loop with this number of vertices will be considered.

loopsize=all

All loop sizes will be considered and the smallest loop is substituted.

loopsize$<$number

Only loops with fewer vertices than `number' will be considered and the smallest looop will be substituted.

outfun=$<$name$>$

Name of an output function in which the remaining arguments of all the vertex functions will be given. This parameter is mandatory.

include-$<$name$>$

Name of a summable index that must be one of the links in the loop. This parameter is optional.

The loopsize parameter is mandatory. Hence one of its options must be specified. The order of the parameters is not important. The only important thing is that the name of the vertex function must be first. The names of the keywords may be abbreviated as in

    ReplaceLoop f,a=3,l=all,o=ff,i=i2;
although this does not improve the readability of the program. Hence a more readable abbreviated version might be
    ReplaceLoop f,arg=3,loop=all,out=ff,inc=i2;

The action of the statement is to remove the vertex functions that constitute the loop and replace them by the output function. This outfun will have the arguments of all the vertex functions minus the contracted indices that define the loop. The order of the arguments is the order in which they are encountered when following the loop. The order of the arguments in the outfun depends however on the order in which FORM encounters the vertices. Hence the outfun will often be cyclesymmetric (see [*] and [*]). If FORM has to exchange indices to make a `proper loop' (i.e. giving relevance to the first index as if it is something incoming and the second index as if it is something outgoing) and if the vertex function is antisymmetric, each exchange will result in a minus sign. Examples:

    Functions f(antisymmetric),ff(cyclesymmetric);
    Indices i1,...,i8;
    Local F = f(i1,i4,i2)*f(i5,i2,i3)*f(i3,i1,i6)*f(i4,i7,i8);
    ReplaceLoop f,arg=3,loop=3,out=ff;
would result in
    -f(i4,i7,i8)*ff(i4,i5,i6)
and
    Functions f(antisymmetric),ff(cyclesymmetric);
    Indices i1,...,i9;
    Local F = f(i1,i4,i2)*f(i5,i2,i3)*f(i3,i1,i6)*f(i4,i7,i8)
            *f(i6,i7,i8);
    ReplaceLoop f,arg=3,loop=all,out=ff;
would give
    -f(i1,i4,i2)*f(i5,i2,i3)*f(i3,i1,i6)*ff(i4,i6)
because the smallest loop will be taken. A number of examples can be found in the package `color' for group theory invariants that is part of the FORM distribution.

A related object is the findloop option of the if statement (see [*]). This option just probes whether a loop is present but makes no replacements.



save

Type Declaration statement
Syntax sa[ve] <filename> [<names of global expressions>];
See also load ([*])


Saves the contents of the store file (all global expressions that were stored in .store instructions) to a file with the indicated name. If a list of expressions is provided only those expressions are saved and the others are ignored.

Together with the load statement (see [*]) the save statement provides a mechanism to transfer data in internal notation from one program to another. It is the preferred method to keep results of a lengthy job for further analysis without the need for the long initial running time.

In order to avoid confusion .sav is the preferred extension of saved files.



select

Type Executable statement
Syntax select <list of sets> <pattern> = <expression>;
See also identify ([*])


This statement is identical to the select option of the id statement (see [*]). Hence

   select ....
is just a shorthand notation for
   id select ....




set

Type Declaration statement
Syntax set <set to be declared>:<element> [<more elements>];


Declares a single set and specifies its elements. Sets have a type of variables connected to them. There can be sets of symbols, sets of functions, sets of vectors, sets of indices and sets of numbers. For the purpose of sets tensors and tables count as functions.

There can also be mixed sets of indices and numbers. When a number could be either a fixed index or just a number FORM will keep the type of the set unfixed. This can change either when the next element is a symbolic index or a number that cannot be a fixed index (like a negative number). If the status does not get resolved the set can be used in the wildcarding of both symbols and indices. Normally sets of numbers can be used only in the wildcarding of symbols.



setexitflag

Type Executable statement
Syntax setexitflag;
See also exit ([*])


Causes termination of the program after execution of the current module has finished.



shuffle

Type Executable statement
Syntax shuffle,functionname;
  shuffle,once,functionname;
See also stuffle ([*])
  merge ([*])


This statement is exactly the same as the merge statement. It takes two occurrences of the mentioned function and outputs terms, each with one function in which the two argument lists have been merged in all different ways, keeping the relative ordering of the two lists preserved. It is the opposite of the distrib_ function (see [*]). Hence

   Local F = f(a,b)*f(c,d);
   shuffle,f;
will result in
      +f(a,b,c,d)+f(a,c,b,d)+f(a,c,d,b)+f(c,a,b,d)+f(c,a,d,b)+f(c,d,a,b)
One can also obtain the same result with the statements
   Multiply,ff;
   repeat id f(x1?,?a)*f(x2?,?b)*ff(?c) =
            +f(?a)*f(x2,?b)*ff(?c,x1)
            +f(x1,?a)*f(?b)*ff(?c,x2);
   id f(?a)*f(?b)*ff(?c) = f(?c,?a,?b);
but the advantage of the shuffle statement is that is also does a certain amount of combinatorics when there are identical arguments. Unfortunately the combinatorics doesn't extend over groups of arguments that are identical as in
    CF  f;
    L   F = f(0,1,0,1,0,1)*f(0,1,0,1,0,1);
    Shuffle,f;
    .end

Time =       0.00 sec    Generated terms =        141
               F         Terms in output =         32
                         Bytes used      =        892
It does get the combinatorics between two zeroes or two ones, but it cannot handle the groups. The explicit method above however doesn't do any combinatorics and generates 924 terms.

One of the applications of this statement is in the field of harmonic sums, harmonic polylogarithms and multiple zeta values. Its twin brother is the stuffle statement (see [*]).

When the option once is mentioned, only one pair will be contracted this way. Without this option all occurrences of the function inside a term will be treated till there are only terms with a single occurrence of the function.



skip

Type Specification statement
Syntax skip;
  skip <list of expressions>;
See also nskip ([*])


In the first variety this statement marks all active expressions that are in existence at the moment this statement is compiled, to be skipped. In the second variety this is done only to the active expressions that are specified. If an expression is skipped in a given module, the statements in the module have no effect on it. Also it will not be sorted again at the end of the module. This means that any bracket information (see [*]) in the expression remains the way it was. Consult also the nskip statement in [*].

Skipped expressions can be used in the expressions in the r.h.s. of id statements (see [*]) or multiply statements (see [*]), etc.



slavepatchsize

Type Declaration statement
Syntax slavepatchsize <value>;
See also moduleoption ([*])


Sets the size of the buffer for sending terms to the secondary processors in PARFORM, one of the parallel versions of FORM (see chapter [*]). In all other versions this statement is ignored. If the value of slavepatchsize is less than the maximum term size (see [*]) it will be readjusted to the value of maxtermsize (see [*]).



sort

Type Executable statement
Syntax sort;
See also term ([*]), endterm ([*])


Statement to be used inside the term environment (see [*] and [*]). It forces a sort in the same way as a .sort instruction forces a sort for entire expressions.



splitarg

Type Executable statement
Syntax splitarg options {<name of function/set> [<argument specifications>]};
See also splitfirstarg ([*]), splitlastarg ([*]), factarg ([*])


Takes the indicated argument of a function and if such an argument is a subexpression that consists on more than one term, all terms become single arguments of the function as in

   f(a+b-5*c*d) --> f(a,b,-5*c*d)
The way arguments are indicated is rather similar to the way this is done in the argument statement (see [*]). One can however indicate only a single group of functions in one statement. Additionally there are other options. All options are in the order that they should be specified:

(term)

Only terms that are a numerical multiple of the given term are split off. The terms that are split off will trail the remainder.

((term))

Only terms that contain the given term will be split off. The terms that are split off will trail the remainder.

The statement is terminated with a sequence of functions or sets of functions. The splitting action will apply only to the specified functions or to members of the set(s). If no functions or sets of functions are specified all functions will be treated, including the built in functions.

The argument specifications consist of a list of numbers, indicating the arguments that should be treated. If no arguments are specified, all arguments will be treated.



splitfirstarg

Type Executable statement
Syntax splitfirstarg {<name of function/set> [<argument specifications>]};
See also splitarg ([*]), splitlastarg ([*])


A little bit like the SplitArg statement (see [*]). Splits the given argument(s) into its first term and a remainder. Then replaces the argument by the remainder, followed by the first term.

The statement is terminated with a sequence of functions or sets of functions. The splitting action will apply only to the specified functions or to members of the set(s). If no functions or sets of functions are specified all functions will be treated, including the built in functions.

The argument specifications consist of a list of numbers, indicating the arguments that should be treated. If no arguments are specified all arguments will be treated.



splitlastarg

Type Executable statement
Syntax splitlastarg {<name of function/set> [<argument specifications>]};
See also splitarg ([*]), splitfirstarg ([*])


A little bit like the SplitArg statement (see [*]). Splits the given argument(s) into its last term and a remainder. Then replaces the argument by the remainder, followed by the last term.

The statement is terminated with a sequence of functions or sets of functions. The splitting action will apply only to the specified functions or to members of the set(s). If no functions or sets of functions are specified all functions will be treated, including the built in functions.

The argument specifications consist of a list of numbers, indicating the arguments that should be treated. If no arguments are specified all arguments will be treated.



stuffle

Type Executable statement
Syntax stuffle,functionname+;
  stuffle,functionname-;
  stuffle,once,functionname+;
  stuffle,once,functionname-;
   
See also stuffle ([*])


This statement takes two occurrences of the mentioned function and outputs terms, each with one function in which the two argument lists have been merged according to the rules for nested sums. The plus and minus signs refer to ones favorite definition for nested sums. In the case of the plus sign, the definition is

$\displaystyle \sum_{i=1}^N \sum_{i=1}^N$ $\textstyle =$ $\displaystyle \sum_{i=1}^N \sum_{j=1}^{i-1}
+ \sum_{j=1}^N \sum_{i=1}^{j-1}
+ \sum_{i=j=1}^N$ (7.1)

while in the case of the minus the definition is
$\displaystyle \sum_{i=1}^N \sum_{i=1}^N$ $\textstyle =$ $\displaystyle \sum_{i=1}^N \sum_{j=1}^{i}
+ \sum_{j=1}^N \sum_{i=1}^{j}
- \sum_{i=j=1}^N$ (7.2)

It is assumed that we have harmonic sums (see the summer library in the FORM distribution). For such sums we expect functions with lists of nonzero integer arguments. Example:
    CF  S,R;
    Symbols N,n;
    L   F = S(R(1,-3),N)*S(R(-5,1),N);
    id  S(R(?a),n?)*S(R(?b),n?) = S(?a)*S(?b)*R(n);
    Stuffle,S-;
    id  S(?a)*R(n?) = S(R(?a),n);
    Print +s;
    .end

Time =       0.00 sec    Generated terms =         12
               F         Terms in output =         12
                         Bytes used      =        462

   F =
       + S(R(-6,-4),N)
       - S(R(-6,-3,1),N)
       - S(R(-6,1,-3),N)
       - S(R(-5,1,-4),N)
       + S(R(-5,1,-3,1),N)
       + 2*S(R(-5,1,1,-3),N)
       - S(R(-5,2,-3),N)
       - S(R(1,-5,-4),N)
       + S(R(1,-5,-3,1),N)
       + S(R(1,-5,1,-3),N)
       + S(R(1,-3,-5,1),N)
       - S(R(1,8,1),N)
      ;
The above program is equivalent to the basis procedure in the summer library. As with the shuffle statement (see [*]) a certain amount of combinatorics has been built in.

When the option once is mentioned, only one pair will be contracted this way. Without this option all occurrences of the function inside a term will be treated till there are only terms with a single occurrence of the function.

The stuffle command takes also the effect of roots of unity[*] into account in the same way that the signs of alternating sums are taken into account. This means that the sum indices don't have to be integers, but could be multiples of a single symbol that has been declared to be a root of unity[*].



sum

Type Executable statement
Syntax sum <list of indices>;
See also renumber ([*])


The given indices will be summed over. There are two varieties. In the first the index is followed by a sequence of nonnegative short integers. In that case the summation means that for each of the integers a new instance of the term is created in which the index is replaced by that integer. In the second variety the index is either the last object in the statement or followed by another index. In that case the index is replaced by an internal dummy index of the type N1_? (or with another number instead of the 1). Such indices have the current default dimension and can be renamed at will by FORM to bring terms into standard notation. For example:

   f(N2_?,N1_?)*g(N2_?,N1_?)
will be changed into
   f(N1_?,N2_?)*g(N1_?,N2_?).
The user can use these dummy indices in the left hand side of id statements.



symbols

Type Declaration statement
Syntax s[ymbols] <list of symbols to be declared>;


Declares one or more symbols. Each symbol can be followed by a number of options. These are (assuming that x is the symbol to be declared):

x#r

The symbol is real. This is the default.

x#c

The symbol is complex. This means that two spaces are reserved for this symbol, one for x and one for x#(the complex conjugate).

x#i

The symbol is imaginary.

x#=number

The symbol is a number-th root of unity This means that the number-th power of the symbol will be replaced by one and half this power (if even) by -1. Negative powers will be replaced by corresponding positive powers.

x(:5)

The symbol has the maximum power 5. This means that $x^6$ and higher powers are automatically eliminated during the normalization of a term. Of course any other number, positive or negative, is allowed.

x(-3:)

The symbol has the minimum power -3. This means that $x^{-4}$ and lower powers are automatically eliminated during the normalization of a term. Of course any other number, positive or negative, is allowed. Note that when the minimum power is positive, terms that have no power of x should technically be eliminated, but FORM will not do so. Such an action can be achieved at any moment with a combination of the count option of an if statement (see [*]) and a discard statement (see [*]).

x(-3:5)

The combination of a maximum and a minimum power restriction (see above).



Complexity properties and power restrictions can be combined. In that case the complexity properties come first and then the power restrictions.



symmetrize

Type Executable statement
Syntax symm[etrize] {<name of function/tensor> [<argument specifications>];}
See also antisymmetrize ([*]), cyclesymmetrize ([*]), rcyclesymmetrize ([*])


The arguments consist of the name of a function (or a tensor), possibly followed by some specifications. Hence we have the following varieties:

<name>

The function is symmetrized in all its arguments.

<name><numbers>

The function is symmetrized in the arguments that are mentioned. If there are fewer arguments than the highest number mentioned in the list or arguments, no symmetrization will take place.

<name>:<number>

Only functions with the specified number of arguments will be considered. Note: the number should follow the colon directly without intermediate space or comma.

<name>:<number><numbers>

If there is a number immediately following the colon, only functions with exactly that number of arguments will be considered. If the list of arguments contains numbers greater than this number, they will be ignored. If no number follows the colon directly, this indicates that symmetrization will take place, no matter the number of arguments of the function. If the list of arguments has numbers greater than the number of arguments of the function, these numbers will be ignored.

<name>

<(groups of numbers)>


The groups are specified as lists of numbers of arguments between parenthesis. All groups must have the same number of arguments or there will be a compile error. The groups are symmetrized as groups. The arguments do not have to be adjacent. Neither do they have to be ordered. The symmetrization takes place in a way that the first elements of the groups are most significant, etc. If any argument number is greater than the number of arguments of the function, no symmetrization will take place.

<name>:<number>

<(groups of numbers)>


The groups are specified as lists of numbers of arguments between parenthesis. All groups must have the same number of arguments or there will be a compile error. The groups are symmetrized as groups. The arguments do not have to be adjacent. Neither do they have to be ordered. The symmetrization takes place in a way that the first elements of the groups are most significant, etc. If no number follows the colon directly symmetrization takes place no matter the number of arguments of the function. Groups that contain a number that is greater than the number of arguments of the function will be ignored. If a number follows the colon directly, only functions with that number of arguments will be symmetrized. Again, groups that contain a number that is greater than the number of arguments of the function will be ignored.



The action of this statement is to symmetrize the (specified) arguments of the functions that are mentioned. This means that the arguments are brought to `natural order' in the notation of FORM by trying permutations of the arguments or groups of arguments. The `natural order' may depend on the order of declaration of the variables.

Examples:

   Symmetrize Fun;
   Symmetrize Fun 1,2,4;
   Symmetrize Fun:5;
   Symmetrize Fun: 1,2,4;
   Symmetrize Fun:5 1,2,4;
   Symmetrize Fun (1,6),(7,3),(5,2);
   Symmetrize Fun:8 (1,6),(7,3),(5,2);
   Symmetrize Fun: (1,6),(7,3),(5,2);




table

Type Declaration statement
Syntax table <options> <table to be declared>;
See also functions ([*]), ctable ([*]), ntable ([*]), fill ([*])


The statement declares a single table. A table is a very special instance of a function. Hence it can be either commuting or noncommuting. The table statement declares its function to be commuting. A noncommuting table is declared with the ntable statement (see [*]). A table has a number of table indices (at least one!) and after that it can have a number of regular function arguments with or without wildcarding. The table indices can come in two varieties: matrix like or sparse. In the case of a matrix like table, for each of the indices a range has to be specified. FORM then reserves a location for each of the potential elements. For a sparse table one only specifies the number of indices. Sparse tables take less space, but they require more time searching whether an element has been defined. For a matrix like table FORM can look directly whether an element has been defined. Hence one has a tradeoff between space and speed.

Table elements are defined with the fill statement (see [*]). Fill statements for table elements cannot be used before the table has been declared with a table or ntable statement.

When FORM encounters an unsubstituted table it will look for its indices. Then it can check whether the table element has been defined. If not, it can either complain (when the `strict' option is used) or continue without substitution. Note that an unsubstituted table element is a rather expensive object as FORM will frequently check whether it can be substituted (new elements can be defined in a variety of ways....). If the indices match a defined table element, FORM will check whether the remaining arguments of the table will match the function-type arguments given in the table declaration in the same way regular function arguments are matched. Hence these arguments can contain wildcards and even argument field wildcards. If a match occurs, the table is replaced immediately.

The options are

check

A check is executed on table boundaries. An element that is outside the table boundaries (regular matrix type tables only) will cause an error message and execution will be halted.

relax

Normally all elements of a table should be defined during execution and an undefined element will give an error message. The relax option switches this off and undefined elements will remain as if they are regular functions.

sparse

The table is considered to be sparse. In the case of a sparse table only the number of indices should be specified. Ranges are not relevant. Each table element is stored separately. Searching for table elements is done via a balanced tree. This takes of course more time than the matrix type search with is just by indexing. A matrix like table is the default.

strict

If this option is specified all table elements that are encountered during execution should be defined. An undefined table element will result in an error and execution is halted. Additionally all table elements should be properly defined at the end of the module in which the table has been defined.

zerofill

Any undefined table element is considered to be zero.




The defaults are that the table is matrix like and table elements that cannot be substituted will result in an error.

Ranges for indices in matrix like tables are indicated with a colon as in

   Symbol x;
   Table t1(1:3,-2:4);
   Table t2(0:3,0:3,x?);
   Table sparse,t3(4);
The table t1 is two dimensional and has 21 elements. The table t2 is also two dimensional and has 16 elements. In addition there is an extra argument which can be anything that a wildcard symbol will match. The table t3 is a sparse table with 4 indices.

If the computer on which FORM runs is a 32 bit computer no table can have more than $2^{15} = 32768$ elements. On a 64 bit computer the limit is $2^{31}$, but one should take into account that each element declared causes some overhead.

If the wildcarding in the declaration of a table involves the definition of a dollar variable (this is allowed! See [*]) parallel execution of the entire remainder of the FORM program is switched off. This is of course only relevant for parallel versions of FORM. But if at all possible one should try to find better solutions than this use of dollar variables, allowing future parallel processing of the program.

In some cases tables are built up slowly during the execution of a program and used incrementally. This means that more and more CPU memory is needed. Eventually this can cause a crash by lack of memory. In the case that the earlier elements of the table aren't needed anymore, one could use the ClearTable [*] statement.



tablebase

This statement is explained in the chapter on tablebases ([*]).



tensors

Type Declaration statement
Syntax t[ensors] <list of tensors to be declared>;
See also functions ([*]), ctensors ([*]), ntensors ([*])


A tensor is a special function that can have only indices for its arguments. If an index a contracted with the index of a vector Schoonschip notation is used. This means that the vector is written as a pseudo argument of the tensor. It should always be realized that in that case in principle the actual argument is a dummy index. Tensors come in two varieties: commuting and noncommuting. The tensor statement declares a tensor to be commuting. In order to declare a tensor to be noncommuting one should use the ntensor statement (see [*]).

The options that exist for properties of tensors are the same as those for functions (see [*]).



term

Type Executable statement
Syntax term;
See also endterm ([*]), sort ([*])


Begins the term environment. This environment is terminated with the endterm statement (see [*]). The action is that temporarily the current term is seen as a little expression by itself. The statements inside the environment are applied to it and one can even sort the results with the sort statement (see [*]) which should not be confused with the .sort instruction that terminates a module. Inside the term environment one can have only executable statements and possibly term-wise print statements (see [*]). When the end of the term environment is reached, the results are sorted (as would be done with an expression at the end of a module) and execution continues with the resulting terms. This environment can be nested.



testuse

Type Executable statement
Syntax testuse ["<tablename(s)>"];
See also tablebases ([*]), testuse ([*])


This statement is explained in the chapter on tablebases.



threadbucketsize

Type Declaration
Syntax ThreadBucketSize,number;
See also the section on TFORM([*])


This statement is only active in TFORM. In all other versions of FORM it is ignored. It sets the size of the buckets that the master thread prepares for treatment by the workers. Bigger buckets means less overhead in signals, but when the buckets are too big the workers may have to wait too long before getting tasks. The best bucket size is usually between 100 and 1000, although this depends very much on the problem. The default value is currently 500. For more ways to set this variable one should consult the section on TFORM ([*]). To find out what its value is, use the `ON,setup;' statement ([*] and [*]).



topolynomial

Type Executable statement
Syntax topolynomial
See also factarg ([*]), FromPolynomial ([*]) and ExtraSymbols ([*], [*]).


Starting with version 4.0 of FORMsome built in operations or statements can only deal with symbols and numbers. Examples of this are factorization([*]) and output simplification (still to be implemented). The ToPolynomial statement takes each term, looks for objects that are not symbols to positive powers and replaces them by symbols. If the object has been encountered before the same symbol will be used, otherwise a new symbol will be defined. The object represented by the `extra symbol' is stored internally and can be printed if needed with the %X option in the #write instruction ([*]). Note that negative powers of symbols will also be replaced.



totensor

Type Executable statement
Syntax totensor [nosquare] [functions] [!<vector or set>] <vector> <tensor>;
  totensor [nosquare] [functions] [!<vector or set>] <tensor> <vector>;
See also tovector ([*])


Looks for multiple occurrences of the given vector, either inside dotproducts, contracted with a tensor, as argument of a function or as a loose vector with an index. In all occurrences in which the vector has been contracted a dummy index is introduced to make the contraction apparent. Then all these vectors with their indices are replaced by the specified tensor with all the indices of these vectors. To make this clearer:

$\displaystyle p^{\mu_1}p^{\mu_2}p^{\mu_3} \rightarrow t^{\mu_1\mu_2\mu_3}$      

and hence
   p.p1^2*f(p,p1)*p(mu)*tt(p1,p,p2,p)
gives after totensor p,t;
   f(N1_?,p1)*tt(p1,N2_?,p2,N3_?)*t(p1,p1,mu,N1_?,N2_?,N3_?)


The options are

nosquare

Dotproducts with twice the specified vector (square of the vector) are not taken into account.

functions

Vectors that are arguments of regular functions will also be considered. By default this is not done.

!vector

Dotproducts involving the specified vector are not treated.

!set

The set should be a set of vectors. All dotproducts involving a vector of the set are not treated.





tovector

Type Executable statement
Syntax tovector <tensor> <vector>;
  tovector <vector> <tensor>;
See also totensor ([*])


The opposite of the totensor statement. The tensor is replaced by a product of the given vectors, each with one of the indices of the tensor as in:

$\displaystyle t^{\mu_1\mu_2\mu_3} \rightarrow p^{\mu_1}p^{\mu_2}p^{\mu_3}$      





trace4

Type Executable statement
Syntax trace4 [<options>] <index>;
See also tracen ([*]), chisholm ([*]), unittrace ([*])
  and the chapter on gamma algebra ([*])


Takes the trace of the gamma matrices with the given trace line index. It assumes that the matrices are defined in four dimensions, hence it uses some relations that are only valid in four dimensions. For details about these relations and other methods used, consult chapter [*] on gamma matrices. The options are:

contract

Try to use the Chisholm identity to eliminate this trace and contract it with other gamma matrices. See also [*]. This is the default.

nocontract

Do not use the Chisholm identity to eliminate this trace and contract it with other gamma matrices. See also [*].

nosymmetrize

When using the Chisholm identity to eliminate this trace and contract it with other gamma matrices, do not do it in the symmetric fashion, but use the first contraction encountered. See also [*].

notrick

The final stage of trace taking, when all indices are different and there are no contractions with identical vectors, as well as no $\gamma_5$ matrices present, is done with n-dimensional methods, rather than with 4-dimensional tricks.

symmetrize

When using the Chisholm identity to eliminate this trace and contract it with other gamma matrices, try to do it in the symmetric fashion. See also [*].

trick

The final stage of trace taking, when all indices are different and there are no contractions with identical vectors is done using the 4-dimensional relation

$\gamma^a\gamma^b\gamma^c = \epsilon^{abcd}\gamma_5\gamma^d
+\gamma^a\delta^{bc}-\gamma^b\delta^{ac}+\gamma^c\delta^{ab}$

This gives a shorter result for long traces. It is the default.






tracen

Type Executable statement
Syntax tracen <index>;
See also trace4 ([*]), chisholm ([*]), unittrace ([*])
  and the chapter on gamma algebra ([*])


Takes the trace of the gamma matrices with the spin line indicated by the index. It is assumed that the trace is over a symbolic number of dimensions. Hence no special 4-dimensional tricks are used. The presence of $\gamma_5$, $\gamma_6$ or $\gamma_7$ is not tolerated. When indices are contracted FORM will try to use the special symbol for the dimension$-4$ if it has been defined in the declaration of the index (see [*]. This results in relatively compact expressions. For more details on the algorithm used, see chapter [*] on gamma matrices.



transform

Type Executable statement
Syntax transform,function(s),<one or more transformations>;


Statement to manipulation function arguments and fields of arguments. Allows speedy transformations without the need of multiple statements or repeat loops.

The function(s) is/are indicated as individual, comma or blank space separated, functions or sets of functions.

If there is more than one transformation, the transformations are separated by comma's (or blanks, unless the blank space would not induce a comma).

Each transformation consists of its keyword, indicating its type, followed by a range of arguments that is enclosed by parentheses. After that specific information may follow. The range is as in

	(1,4)
	(3,last)
	(last-6,last-2)
hence two indicators, separated by a comma. If the first number is bigger than the second the arguments will be processed in reverse order whenever this is relevant. In the descriptions below we will indicate the range by (r1,r2).

The transformations that are allowed currently are:

replace

replace(r1,r2)=(from1,to1,from2,to2,...,fromn,ton) in which the from-to pairs are as in the replace_ function. Here however there are more options than in the replace_ function as we can specify (small) numbers as well as in
replace(1,last)=(0,1,1,0) which would replace arguments that are zero by one and arguments that are one by zero. Generic arguments are indicated by the new variables xarg_, iarg_, parg_ and farg_ as in
replace(1,last)=(xarg_,2xarg_+1,p) which would replace f(2,a) by f(5, 2a+1,p) if a is a symbol and p a vector. To catch p one would need to use parg_.

encode

encode(r1,r2):base=number will interprete the arguments as the digits in a base 2 number system, compute the complete number and replace the arguments by a single argument that is that number. The number must fit inside a single FORM word and so must each of the original arguments. They should actually be smaller than the number of the base.

decode

decode(r1,r2):base=number will do the opposite of encode. It will take a single argument (the smallest of the two given) and expand it into digits in a number system given by the base. It will create the specified number of digits and replace the original number by the given number of arguments representing these digits. If r2 is less than r1 the digits will be in reverse order.

tosumnotation

tosumnotation(r1,r2) or implode(r1,r2) realizes an encoding in which zeroes are absorbed as extra values in the first nonzero argument that is following. This is used when dealing with harmonic sums and harmonic polylogarithms. An example is that (0,0,1,0,a,0,0,0,-1) (which is in integral notation) goes into (3,2*a,-4) (which is in sum notation). Currently only a single symbol is allowed and the numbers should be (small) integers because otherwise the reverse operation (explode) would generate too many arguments. Instead of ``tosumnotation'' one may also use the word ``implode'' in accordance with the argimplode statement.

tointegralnotation

tointegralnotation(r1,r2) or explode(r1,r2) undoes what implode might have done. Hence each integer with an absolute value $n$ generates $n-1$ zeroes and leaves something with absolute value one. Instead of ``tointegralnotation'' one may also use the word ``explode'' in accordance with the argexplode statement.

permute

permute(1,3,5)(2,6) will permute the arguments according to the cycles indicated. The cycles are executed in order and may overlap. Their number is not restricted.

reverse

reverse(r1,r2) reverses the order of the arguments in specified range.

cycle

cycle(r1,r2)=+/-number will perform a cyclic permutation of the indicated range of arguments. If the number is preceeded by a - the cycling is to the left. If there is a plus sign the cycling is to the right. Note that either the plus or the minus sign is mandatory.

islyndon

islyndon(r1,r2)=(yes,no) will test whether the indicated range of arguments forms a Lyndon word according to the ordering of arguments in FORM. The yes and no arguments are what the main term will be multiplied by when the range forms a Lyndon word or does not respectively. Because the definition of a Lyndon word is the unique minimal cyclic permutation of the arguments, and because often we may need the unique maximal cyclic permutation there are varieties: for the minimum one may also use islyndon$<$(r1,r2)=(yes,no) or islyndon-(r1,r2)=(yes,no), while for the maximum one may use islyndon$>$(r1,r2)=(yes,no) or islyndon+(r1,r2)=(yes,no).

tolyndon

tolyndon(r1,r2)=(yes,no) will permute the given range in a cyclic manner till it is (if possible) a Lyndon word according to the ordering of arguments in FORM. The yes and no arguments are what the main term will be multiplied by when afterwards the range forms a Lyndon word or does not respectively. Because the definition of a Lyndon word is the unique minimal cyclic permutation of the arguments, and because often we may need the unique maximal cyclic permutation there are varieties: for the minimum one may also use tolyndon$<$(r1,r2)=(yes,no) or tolyndon-(r1,r2)=(yes,no), while for the maximum one may use tolyndon$>$(r1,r2)=(yes,no) or tolyndon+(r1,r2)=(yes,no). If the output is not a Lyndon word, this will be due to that it is a minimum or maximum that is not unique.

Some Examples. Assume that we have some Multiple Zeta Values (see the papers on harmonic sums, harmonic polylogarithms and the MZV data mine) in the sum notation, but for calculational reasone we want to use a binary encoding (as used in the MZV programs). We could have

    Symbol x,x1,x2;
    CF  H,H1;
    Off Statistics;
    L   F = H(3,4,2,6,1,1,1,2);
    repeat id H(?a,x?!{0,1},?b) = H(?a,0,x-1,?b);
    Print;
    .sort

   F =
      H(0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,1,1,1,0,1);

    Multiply H1;
    repeat id H(x?,?a)*H1(?b) = H(?a)*H1(?b,1-x);
    id  H1(?a)*H = H(?a);
    Print;
    .sort

   F =
      H(1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,0,0,0,1,0);

    repeat id H(x1?,x2?,?a) = H(2*x1+x2,?a);
    Print;
    .end

   F =
      H(907202);
The new version of the same program would be
    Symbol x,x1,x2;
    CF  H,H1;
    Off Statistics;
    L   F = H(3,4,2,6,1,1,1,2);
    Transform,H,explode(1,last),
                replace(1,last)=(0,1,1,0),
                encode(1,last):base=2;
    Print;
    .end

   F =
      H(907202);
It should be clear that this is simpler and faster. On a 64-bits computer it is faster by more than a factor 100.





tryreplace

Type Executable statement
Syntax tryreplace {<name> <replacement>};
See also the replace_ function ([*])


The list of potential replacements should be similar to the arguments of the replace_ function (see [*]). FORM will make a copy of the current term, try the replacement and if the replacement results in a term which, by the internal ordering of FORM, comes before the current term, the current term is replaced by the new variety.



unhide

Type Specification statement
Syntax unhide;
  unhide <list of expressions>;
See also hide ([*]), nhide ([*]), nunhide ([*]), pushhide ([*]), pophide ([*])


In its first variety this statement causes all statements in the hide file to become active expressions again. In its second variety only the specified expressions are taken from the hide system and become active again. An expression that is made active again can be manipulated again in the module in which the unhide statement occurs. For more information one should look at the hide statement in [*].

Note that if only a number of expressions is taken from the hide system, the hide file may be left with `holes', i.e. space between the remaining expressions that contain no relevant information any longer. FORM contains no mechanism to use the space in these holes. Hence if space is at a premium and many holes develop one should unhide all expressions (this causes the hide system to be started from zero size again) and then send the relevant expressions back to the hide system.



unittrace

Type Declaration statement
Syntax u[nittrace] <value>;
See also trace4 ([*]), tracen ([*]), chisholm ([*]) and the chapter on gamma algebra ([*])


Sets the value of the trace of the unit matrix in the Dirac algebra (i.e. the object g1_(n) for trace line n)). The parameter value can be either a short positive number or any symbol with the exception of i_. See also chapter [*].



vectors

Type Declaration statement
Syntax v[ectors] <list of vectors to be declared>;


Used for the declaration of vectors. Example:

   Vectors p,q,q1,q2,q3;




while

Type Executable statement
Syntax while ( condition );
See also endwhile ([*]), repeat ([*]), if ([*])


This statement starts the while environment. It should be paired with an endwhile statement (see [*]) which terminates the while environment. The statements between the while and the endwhile statements will be executed as long as the condition is met. For the description of the condition one should consult the if statement (see [*]). The while/endwhile combination is equivalent to the construction

   repeat;
      if ( condition );


      endif;
   endrepeat;
If only a single statement is inside the environment one can also use
   while ( condition ) statement;
Of course one should try to avoid infinite loops. In order to maximize the speed of FORM not all internal stacks are protected and hence the result may be that FORM may crash. It is also possible that FORM may detect a shortage of buffer space and quit with an error message.

For each term for which execution reaches the endwhile statement, control is brought back to the while statement. For each term that reaches the while statement the condition is checked and if it is met, the statements inside the environment are executed again on this term. If the condition is not met, execution continues after the endwhile statement.



write

Type Declaration statement
Syntax w[rite] <keyword>;
See also on ([*]), off ([*])


This statement is considered obsolete. All its varieties have been taken over by the on statement (see [*]) and the off statement (see