1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
|
\chapter{The dollar variables}
\label{dollars}
In the older versions of \FORM\ there were two types of variables: the
preprocessor variables\index{variables!preprocessor} and the algebraic
variables\index{variables!algebraic}. 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\index{variables!dollar}.
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 (\verb:$:)
followed by an alphabetic character and then potentially more alphanumeric
characters. Hence \verb:$a: and \verb:$var: and \verb:$r4t78y0: are legal
names and \verb:$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?
\begin{itemize}
\item Algebraic expressions as in \verb:$var = (a+b)^2;:
\item Individual objects like indices, numbers, symbols.
\item Zero.
\item Parts of a term.
\item Argument\index{argument field} fields that consist of zero, one or
more arguments.
\end{itemize}
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\index{runtime error} error\index{error!runtime}.
How is a variable used?
\begin{itemize}
\item As a preprocessor variable\index{variable!preprocessor}. This is done
by putting the variable between a pair of `' as in \verb:`$var':. In this
case the regular print routines of \FORM\ make a textual
representation\index{representation!textual} of
the variable as it exists at the moment that the preprocessor encounters
this object, and this string is then substituted by the preprocessor as if
it were the contents of a preprocessor variable.
\item Like an expression during execution time. This would be the case in
the statement
\begin{verbatim}
id x = y + $var;
\end{verbatim}
in which \verb:$var: is substituted
in a way that is similar to the substitution of a local expression \verb:F:
in the statement
\begin{verbatim}
id x = y + F;
\end{verbatim}
except for that the dollar variable is always stored in the CPU memory.
\item As an algebraic object during execution time. This could be the case
with any value of the variable that is not an expression. An example would
be
\begin{verbatim}
id f(?a) = f(?a,$var);
\end{verbatim}
in which the dollar variable contains an
argument field.
\item As an algebraic object in a delayed substitution of a pattern or a
special statement. This may need some clarification. If we have the
statement
\begin{verbatim}
id f($var) = anything;
\end{verbatim}
the compiler does not substitute
the current value of \verb:$var:. The reason is that \verb:$var: could have
a different value for each term that runs into this statement, while the
compiler compiles the statement only once. Hence \FORM\ will substitute the
value of \verb:$var: only at the moment that it will attempt the pattern
matching. This is called delayed\index{delayed substitution}
substitution\index{substitution!delayed}. If one likes the compiler to
substitute a value, one can basically let the preprocessor take care of
this by typing
\begin{verbatim}
id f(`$var') = anything;
\end{verbatim}
A similar delayed
substitution takes place in statements of the type \verb:Trace,$var;:.
\end{itemize}
How does one give a value to a dollar variable?
\begin{itemize}
\item In the preprocessor. This is done with an instruction of the type
\verb:#$var = 0;:. This is an instruction that can run over more than one
line. The r.h.s. can be any algebraic expression. Specifically it can
contain dollar variables or local/global expressions. Such
expressions are worked out during the preprocessing. Hence this variable
acquires a value immediately.
\item During execution when control reaches a statement of the form
\verb:$var = expression;:. Again the r.h.s. can contain any normal
algebraic expression including dollar variables and local/global
expressions. The r.h.s. will be evaluated and the value will be assigned to
\verb:$var:. In the case that \verb:$var: had already a value, the old
value will be deleted and the new value will be `installed'.
\item During execution when the dollar variable is assigned the value of a
wildcard as in
\begin{verbatim}
id f(x?$var) = whatever;
\end{verbatim}
If the function \verb:f:
occurs more than once in a term, \verb:$var: will have the value of the
last match. In the case that the value of the first match is needed one can
use the option `once' in the id-statement as in
\begin{verbatim}
id,once,f(x?$var) = whatever;
\end{verbatim}
In general one can paste the dollar variable to the end of any
wildcard description. Hence one can use \verb:id f(x?{1,2,3}$var) = ...;:
and
\begin{verbatim}
id f(x?set[n?$var1]$var2) = ...;
\end{verbatim}
\end{itemize}
Note the difference between \verb:#$a = 0;: and \verb:$a = 0;:. One CANNOT
make a wildcard\index{wildcard} construction for dollar variables
themselves as in \verb:id f($var?) = ...;:
Dollar variables CANNOT have arguments as in \verb:$var(2): or something
equivalent. There is however a solution at the preprocessor level for this
by defining individual variables \verb:$var1: to \verb:$varn: and then
using \verb:$var`i': or \verb:`$var`i'': for some preprocessor variable
\verb:i:. The exception is the indication of factors when a dollar variable
has been factorized (see the \#factdollar instruction~\ref{prefactdollar}
and the factdollar statement~\ref{substafactdollar}). This is explained
later in this chapter and in the chapter about
polynomials~\ref{polynomials}.
Printing dollar\index{dollar!printing} variables:
\begin{itemize}
\item In the preprocessor one can use the \verb:#write: instruction
(see \ref{prewrite}).
\item During execution one can use the Print statement (see
\ref{substaprint}).
\end{itemize}
In both cases one should use the format\index{format} string. The syntax is
described in the chapters on these statements. The format descriptor of a
dollar variable is \verb:%$: 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:
\begin{verbatim}
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
\end{verbatim}
\noindent Maximum power of x in an expression:
% THIS EXAMPLE IS PART OF THE TESTSUITE. CHANGES HERE SHOULD BE APPLIED THERE AS
% WELL!
\begin{verbatim}
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
\end{verbatim}
Starting with version 4, \FORM\ has the capability to factorize polynomials
(see the chapter on polynomials~\ref{polynomials}). One type of objects
that can be factorized is the dollar variables. The immediate question here
is how to access the factors. As we mentioned before in this chapter,
normally there is no direct way to use arguments for dollar variables. For
the factors however we have a way of indexing the dollar variables as in
\verb:$var[1]:,...,\verb:$var[n]: when there are n factors. The number of
factors can be obtained as \verb:$var[0]:. In the index field can only be
(nonnegative integer) numbers, dollar variables or factors of dollar
variables that evaluate into (nonnegative integer) numbers.
\begin{verbatim}
Symbol x,y;
CFunction f1,f2;
Local F = f1(x^2+2*x*y+y^2)+f1(x^4-y^4);
id f1(x?$x) = f2(x);
FactDollar,$x;
Do $i = 1,$x[0];
Print "In %t factor %$ is %$",$i,$x[$i];
Enddo;
.end
In + f2(y^2 + 2*x*y + x^2) factor 1 is y + x
In + f2(y^2 + 2*x*y + x^2) factor 2 is y + x
In + f2( - y^4 + x^4) factor 1 is - 1
In + f2( - y^4 + x^4) factor 2 is y - x
In + f2( - y^4 + x^4) factor 3 is y + x
In + f2( - y^4 + x^4) factor 4 is y^2 + x^2
\end{verbatim}
One thing to note is that the use of
\begin{verbatim}
f(<$x[1]>,...,<$x[$x[0]]>)
\end{verbatim}
is illegal. \verb:$x[0]: will be inserted during execution time, while the
expansion of the triple dot operator is done by the preprocessor. Hence we
should use \verb:`$x[0]': but then \verb:$x: must be known and factorized
already at compile time.
\section{Dollar variables in a parallel environment}
\label{pardollars}
When \FORM\ is used for parallel\index{parallel processing} processing,
either by means of \ParFORM\index{ParFORM} or by means of
\TFORM\index{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\index{nondeterministic}.
Look for instance at the following example:
\begin{verbatim}
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
\end{verbatim}
Usually this program will give the 'correct' answer, but in principle one
thread could define \verb:$x: and then the next thread could overwrite this
value before the first thread has used it. This is serious. Hence \FORM\
will veto\index{veto} the use of multiple threads/processors for modules in
which dollar variables obtain 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 \verb:$x: will be local to
each term and hence to each thread\index{thread}. The value in previous
terms is unimportant. We can tell this to \FORM\ with a variety of the
moduleoption\index{moduleoption} statement (see \ref{substamoduleoption}).
This would be:
\begin{verbatim}
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
\end{verbatim}
In this case \FORM\ makes at the start of the execution of the module a
copy of whatever value \verb:$x: has at that moment for each
thread/processor (in this case no value yet and hence it gets set to zero)
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:
\begin{verbatim}
ModuleOption,maximum,$a;
ModuleOption,minimum,$b;
ModuleOption,sum,$c;
\end{verbatim}
Here we say that \verb:$a: is accumulating a maximum numerical value,
\verb:$b: collects a minimum numerical value and \verb:$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:
% THIS EXAMPLE IS PART OF THE TESTSUITE. CHANGES HERE SHOULD BE APPLIED THERE AS
% WELL!
\begin{verbatim}
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
\end{verbatim}
The print statement is showing which thread is dealing with which term.
|