## 4.4 Variables

Within the `VARIABLES`

, `ASSIGNMENTS`

, `PREPARATIONS`

and
`EXPERIMENT`

section variables may be used. Each variable that is
used in an `EDL`

script must have been declared previously, i.e.
it has to be listed in the `VARIABLES`

section before it may be
used. The start of the `VARIABLES`

section is indicated by a line
stating

VARIABLES: |

• Variable names | ||

• Variable types | ||

• Arrays and matrices | ||

• Variable sized arrays and matrices |

### 4.4.1 Variable names

Names of variables (and also of functions) always start with a
character, i.e. A-Z or a-z. The remaining part of the variable name
can consist of characters, numbers and underscore characters,
'`_`

' (if you understand regular expressions, valid names
must follow the pattern `[A-Za-z][A-Za-z_0-9]*`

). Thus,
'`AbC_12x`

' and '`aBc_12X`

' are legal variable names,
while '`12xy`

' or '`_Yx2`

' are not. Please note that variable
names are case sensitive, i.e. '`XY`

', '`Xy`

', '`xY`

'
and '`xy`

' are all different variables!

There's no built-in upper limit on te length of variable (or function) names, they can, at least in principle, consist of as many characters as you wish (I hope nobody is going to the trouble of creating a variable name with, say, a few hundred thousand characters just to prove me wrong - I tested it only with two variables with names consisting of 10000 characters each and differing only in the last character...)

There are some combinations of characters that can't be used as variable names. First of all, variable names are not allowed to be identical to function names, neither to names of built-in nor device function.

Further, the keywords used by `EDL`

also may not be used as
variable names (to make it easier to avoid these, they are all spelled
with capitals only). In the appendix you'll find a list of (hopefully)
all reserved words.

Finally, some combinations of characters take on a special meaning when
they directly follow a number (i.e. with only spaces or tabs
between the number and the following character(s)). These are some
physical units with or without the characters `n`

(nano),
`u`

(micro), `m`

(milli), `k`

(kilo), `M`

(Mega)
and `G`

(Giga) (only wave numbers can't be preceeded by such a
character). Here's the complete list:

`s`

Seconds (and `ns, us, ms, ks, Ms`

and`Gs`

)`m`

Meter (and `nm, um, mm, km, Mm`

and`Gm`

)`G`

Gauss (and `nG, uG, mG, kG, MG`

and`GG`

)`T`

Tesla (and `nT, uT, mT, kT, MT`

and`GT`

)`V`

Volt (and `nV, uV, mV, kV, MV`

and`GV`

)`A`

Ampere (and `nA, uA, mA, kA, MA`

and`GA`

)`Hz`

Hertz (and `nHz, uHz, mHz, kHz, MHz`

and`GHz`

)`K`

Kelvin (and `nK, uK, mK, kK, MK`

and`GK`

)`dB`

Decibel (and `ndB, udB, mdB, kdB, MdB`

and`GdB`

)`dBm`

Decibel (and `ndBm, udBm, mdBm, kdBm, MdBm`

and`GdBm`

)`cm^-1`

wave numbers, i.e. inverse of a `cm`

Please note that all device functions return values in units of seconds,
meters, Gauss, Volts, Amperes, Hertz, Kelvin, dB and cm^-1 or products
of these units. While you can use Tesla in the `EDL`

script all
functions return values in Gauss!

### 4.4.2 Variable types

Variables can be divided into two classes, variables to hold integer values and variables for storing floating point numbers.

Integer variables (on machines with 32-bit processors) can hold data in
the interval [-2^31, 2^31 - 1], i.e. they run from -2147483648
all the way up to +2147483647. In contrast, floating point variables
can have much larger values (typically up to ca. 10^300), the exact
limits depending on the machine `fsc2`

is running on. The larger
range for floating point numbers comes with a price: they have only a
limited precision, normally not more than about 14 to 15 digits can be
trusted and rounding errors can lead to quite large errors if not used
with great care in calculations.

To distinguish between integer and floating point variables the case of
the first character of the variables name is important: if the name
starts with an upper case letter, i.e. A-Z, it's an integer variable
while variables starting with a lower case character, i.e. a-z, are
floating point variables. (Actually, changing just one line of
`fsc2`

allows to change to a completely different behavior.)

### 4.4.3 Arrays and matrices

Beside `normal' variables you can also use arrays and matrices (i.e.
more-dimensional arrays). The names of arrays follow the same convention
as that of normal variables, i.e. if an array name starts with an
upper case character it's an array consisting of integers only and if it
starts with a lower case character it's a floating point array. To
define a normal (fixed sized) array in the `VARIABLES`

section just
append the sizes of the dimensions of the array, separated by commas, in
square brackets. E.g. the lines

F[ 100 ]; b[ 4, 7, 3 ]; |

define an 1-dimensional array `F`

of 100 integers and a
3-dimensional floating point array `b`

of rank 4x7x3. Indices of
arrays start with 1 (like in MathLab and FORTRAN, but this can actually
be easily changed if you adjust a single line in the code for
`fsc2`

...).

All elements of an arrays are automatically initialized to zero. On the
other hand, arrays can also be initialized within the `EDL`

file by
equating the array (in the 1-dimensional case) to a list of values,
enclosed in curly braces:

C[ 3 ] = { 2, 1, -1 }; d[ 5 ] = { sqrt( 2.0 ), sqrt( 3.0 ) + 1 }; |

The first line in the example shows the simplest way - each element of
the integer array `C`

is initialized by an element from the
list. In the second line there are less initializers than the array
`d`

has elements, thus only the first two elements are set, i.e.
`d[1]`

and `d[2]`

, while the remaining elements are
automatically set to zero. Besides, you can see that function calls,
arithmetic etc. can be used in the initialization.

To initialize more-dimensional arrays you must enclose the 1-dimensional arrays they basically are built up from each in a pair of curly braces, but you also can use an already initialized matrix of a lower dimension. You may also leave out parts of the initialization by using a pair of empty curly braces as an empty set (the dimension of the empty set is recognized automatically, so you won't need empty sets within empty sets).

E[ 3, 4 ] = { { 1, 2, 3 }, { 4, 5, 6 } }; F[ 2, 3, 4 ] = { { { 1, 2, 3, 4 }, { }, { 9, 8, 7, 6 }, { 3, 5, 7, 9 } }, E }; G[ 4, 3, 4 ] = { { }, { E[ 3 ], E[ 2 ], E[ 1 ] } }; |

In the last statement of the example sub-arrays of the matrix `E`

are used, e.g. `E[3]`

is the whole third sub-array of `E`

.
You also need not to specify as many initializer elements as there are
elements in the matrix to be initialized, for missing elements the
matrix remains uninitialized.

You can also initialize all elements of an array or a matrix by just equating it to a number:

D[ 3 ] = 1; f[ 3, 6 ] = sqrt( 42.0 ); |

This will assign the value 1 to all elements of the array `D`

and
the square root of 42 to all 18 elements of the 2-dimensional matrix
`f`

.

### 4.4.4 Variable sized arrays and matrices

There are some situations where one doesn't know the size of an array in
advance, e.g. the size of an array to be used for storing a trace
from a digitizer or the size of a 2-dimensional field for a complete
picture from a CCD-camera. So declaring the size in advance in the
`VARIABLES`

section is harly possible. To handle this kind of
situation one can create arrays with sizes that change automatically
when required. This is done by specifying a `*`

instead of a number
for the size:

M[ * ]; h[ 2, * ]; I[ *, *, * ]; |

These three statements define a 1-dimensional integer array `G`

with
a non-fixed (and still unknown) number of elements, a 2-dimensional
floating point matrix `h`

with two rows of unknown length and a
3-dimensional array with all sizes being variable sized.

The only restriction in declaring variable sized matrices is that you
can't declare matrices with only the higher dimensions being variable
sized but the lower ones being fixed. I.e. the following definition is
**not** possible:

h[ *, 2 ]; /* WRONG! */ |

The length of the 1-dimensional array `M`

from the above example
remains undetermined until a value has been assigned to at least one
of the arrays elements. If you assign a value to the 25th element of a
previously uninitialized variable length array

M[ 25 ] = 42; |

the array will suddenly have 25 elements with the first 24 being set
to zero and the 25th set to `42`

. You can also make the array
longer at a later time by assigning a value to an element with an
higher index, e.g.

M[ 50 ] = 84; |

Now the array has 50 elements, the newly added elements between and including the 26th and 49th element being initialized to zero.

But there's also another way to change the size of the array. You can
assign another array to `M`

and in this case the length of `M`

is resized to fit the length of the array you assign to it. E.g. if
you had an array defined as

H[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; |

and you now assign `H`

to `M`

M = H; |

`M`

will also have 10 elements with the same values as the
elements of `H`

.

Some care has to be taken: it is also possible to shrink the length of a
variable sized array by assigning another array to it. If `M`

had already been given a length by e.g. assigning a value to its 25th
element then assigning it the shorter array `H`

will automatically
shorten it to 10 elements and the values stored in the 11th to the 25th
element are lost!

To understand how more-dimensional, variable sized arrays work it is probably best to think of them not in terms of matrices but of arrays of arrays (of arrays... etc.). For example, a two-dimensional array like

j[ *, * ]; |

can be thought of as an array (of still undetermined length) of arrays which also have no length yet (or a length of 0). When you now assign a value to one an element like this

j[ 7, 9 ] = 3.1415927; |

the 7th sub-array of `j`

will suddenly spring into existence,
having a length of 9 (with all elements of this sub-array except the 9th
being initialized to 0.0). But this does **not** also create other
sub-arrays - the 1st to the 6th sub-array are still undefined (having a
length of 0).

Only if you assign a value to the elements of one of these other sub-arrays it will spring into existence, e.g. by having

j[ 3, 2 ] = 2.7182818; |

Now both the 3rd and the 7th sub-array of `j`

exist - but no others
(i.e. the 1st, 2nd, 4th, 5th and 6th sub-array do not exist yet and
trying to use a value of one of these sub-arrays will result in an error
message). And both these sub-arrays have different lengths, the 3rd
sub-array has a length of only 2, while the 7th sub-array has a length
of 9.

Of course, the sub-arrays can also be created by assigning another array. E.g.

k[ 3 ] = { -1.0, 0. 1.0 }; j[ 5 ] = k; |

will create the 5th sub-array of `j`

with a length of 3 and its
values being identical to the ones of the array `k`

. From this
example you can also see that sub-arrays of an array can be simply
specified by the index of the sub-array, i.e. `j[5]`

stands
for the complete 5th sub-array of `j`

(and the `k`

on the
right hand side represents the complete array `k`

).

But `j`

can also be set by assigning another 2-dimensional matrix
to it.

r[ 3, 2 ] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }; j = r; |

Since `r`

is a matrix of rank 3x2 after the assignment `j`

will have the same rank (and the elements of `j`

and `r`

will, of course, be identical).

The same, of course, can be done with "matrices" of higher dimensions. If you have a 3-dimensional matrix you can assign numbers to its elements, 1-dimensional arrays to its sub-sub-arrays, 2-dimensional "matrices" to its sub-matrices and, of course, assign a complete 3-dimensional matrix to it.

This document was generated by *Jens Thoms Toerring* on *September 6, 2017* using *texi2html 1.82*.