<num>
<id> (not follow by a '(')
are valid expressions. The result of these expressions is simply the value
of the number respectively the variable. Also a single string can be an
expression:
<string>
Brand new are the mathematical constant expressions:
~<id>
The Parser simply searches for a known constant <id> and
replaces it by the corresponding value. Known constants are:
~pi Yust Pi (that thing with the diameter and the circumfence)
~e Yust e (the Euler constant)
~log2e this is log_2 e
~log10e this is log_10 e
~ln this is ln 2 respectively log_e 2
~ln10 this is ln 10 respectively log_e 10
~pi_2 this is pi/2
~pi_4 this is pi/4
~1_pi this is 1/pi
~2_pi this is 2/pi
~sqrt2 this is sqrt(2)
~sqrt1_2 this is 1/sqrt(2)
... and a couple more out of math.h .
If the variable is an array there are two equivalent ways to get an element of this array:
<id> [ <expr> , <expr> , ...]
<id> [ <expr> ] [ <expr> ]...
Where the ... means at least one or more, and <expr> is
another expression. Of course strings are not allowed at this point, but
you can make any type of calculation here. For example:
a[5,10],a[5,2*5],a[5][10] are valid expressions
with the same result (see Calculation Expressions below).
Sometimes you may not only want a single element but a whole subarray of a bigger array. For this purpose a special index access does exist:
<id> [ <expr1> .. <expr2> ,... ]
<id> [ <expr1> .. <expr2> : <expr3> ,... ]
<id> [ * ,... ]
The * represents the whole row where
<expr1>..<expr2> <expr1> defines the lower bound,
<expr2> the upperbound of a row and
<expr1>..<expr2>:<expr3>. You can additionally
define a stepsize <expr3> for that row (at the moment
<expr3>
must be greater or equal one, and <expr2> should be greater or equal
<expr1>).
If this index access still dosn't satisfy you Xi can also perform a where access:
<id> [ where <expr> ]
Here the result of <expr> is an integer array containing
the indices of the array <id>. Usually <expr>
is a Comparison between arrays.
<id> ( )
The () are essential at this point, they are the only way for the
Parser to distinguish between a variable and a function. If and
<id>
are followed by a '(' . The Parser seeks for a function with that name or otherwise
for a variable. The above rule describes the function call to a function with no parameter. Usually a function may have several parameters that have to be set by arguments in the function call:
<id> ( <expr1> , <expr2> ,...)
<expr1>,<expr2>,... are the arguments of the functions. So far we are C compatible. In C the order of the function arguments is fixed. There is actually no way to set the first parameter with the second argument and vice versa. For this purpose Xi has named arguments:
<id> ( \ <id1> = <expr1> , \ <id2> = <expr2> ,...)
That means: The parameter <id1> of function <id> is set to
the result of <expr1>, the parameter <id2>is set to the
result of <expr2> and so on. In this way you can
control the order of calculations of a function call's arguments (if you need
dirty stuff like this). Xi first calculates <expr1>, then <expr2> and so on.
Furthermore the named arguments are useful if the function has flags.
<id> ( \ <id1> , \ <id2> ,...)
will be translated to
<id> ( \ <id1> = 1 , \ <id2> = 1 ,...)
which means that the parameters <id1>,
<id2>,... of function
<id> are all set to one respectively to true
(since Xi has no boolean
type a nonzero integer is true and zero is false. See
Compare Expressions for more detail)
- <expr> (unary minus)
<expr1> + <expr2>
<expr1> - <expr2>
<expr1> * <expr2>
<expr1> / <expr2>
( <expr> )
Note that these operators have the same precendencs as in C, i.e.:
An expression 4*5+1 will be evaluated as (4*5)+1, and
4/-1+5 will be evaluated as (4/(-1))+5. Also the operators
are left-associative, i.e.: An expression 1-2-3 will be evaluated as
(1-2)-3 and 4/5*6 will be evaluated as (4/5)*6.
If you want more informations consult a C introduction.
Please keep in mind though that in Xi all operations also work on arrays e.g.
you can add an array with a scalar or two arrays with the same dimensions.
In Addition to these standard operations Xi has a special matrix multiplication for arrays:
<expr1> # <expr2>
<expr1> ## <expr2>
<expr1> ### <expr2>
.
.
.
The first operation is a simple matrix multiplication between an nxm matrix
<expr1> and a mxk matrix <expr2>,
the second operation will
multiply a (...,m,k)-tensor with a (m,k,...)-tensor by summing over the two inner
indices. The third will multiply a (...,n,m,k)-tensor with a (n,m,k,...)-tensor
by summing over the three inner indizes and so on. If you want to calculate with complex numbers, you certainly want to enter the real and imaginary part of this number directly.
( <expr1> , <expr2> )
This expression also works if <expr1> and <expr2>
are arrays with the same dimenstions. If you want to build up an array element by element, Xi offers you the folling expression:
{ <expr1> , <expr2> , ... , <exprn> }
If <expr1> to <exprn> are scalars (i.e. no
arrays) the above expression will generate a n-dimensional vector with
corresponding entries. If <expr1> to <exprn>
are all m-dimensional vectors the expression will generate a nxm matrix
and so on. In this way it is possible to construct the wildest arrays you
can think of.
Sometimes it comes handy to cast a double value into an integer an vice versa. In Xi there are two equivalent ways to cast a value to a specific type:
( <type> ) <expr>
<type> ( <expr> )
The first possibility is C compatible the second is the C++ way - pick one.
<expr1> == <expr2>
<expr1> != <expr2>
<expr1> < <expr2>
<expr1> <= <expr2>
<expr1> > <expr2>
<expr1> >= <expr2>
are all implented comparisons between two expressions. If <expr1>
and <expr2> are scalars the above expressions should be
clear, they can be found in every common C-introduction. If one or both are
arrays Xi will compare an array with a scalar or two arrays element by
element. The result is an array of integers filled with the indices of the
array where the comparison is true. Besides the pure comparisons there also exist logical operations usually used in connection with comparisons:
<expr1> && <expr2>
<expr1> || <expr2>
If <expr1> and <expr2> are simple comparisons
between scalars these two operators act in the same way as in C.
If <expr1> and <expr2> are both
comparisons between arrays && (||)
takes the union (cut) of the two resulting index arrays (see
above).
<id> = <expr>
which sets the variable <id> to the result of
<expr>. The result of the whole expression is the new value
of the Variable. Note that = is a right-associative operator, i.e. an input
a=b=c=3 will be interpreted as a=(b=(c=3)) or, in human
words, first set variable c to 3. Then set variable
b to the result of this assignment (which is the new value of c and therefore also 3). Finally the a to the result of the
last assignment (which is the new value of b; 3).
Consequently a, b and c are all set to the
value 3.
Assignments are also defined to set one or more elements of an array:
<id> [ <indx> ] = <expr>
<id> [ where <expr> ] = <expr>
Where <indx> means a list of indices which may contain ranges.
Like in C there the folling operations that directly act on variables exist:
<id> += <expr>
<id> -= <expr>
<id> *= <expr>
<id> /= <expr>
<id> ++
<id> --
++ <id>
-- <id>
All these operations act in the same way as in C except that in Xi they also
work on arrays. +=,-=,*= and /= add,
subtract, multiply respectively divide the variable <id> by
the result of <expr>. As in the previous case the result of
the whole expression is the new value of <id>. ++
and -- increments respectively decrements the variable
<id> by one. The result of this operation depends on whether
++ or -- stands before or after <id>. In
the first case the result is the new value of <id> in the
latter it is the old value of <id>. For a more detailed
description have a look into a C-introduction. The operation from above also works with elements of an array:
<id> [ <indx> ] += <expr>
<id> [ where <expr> ] += <expr>
<id> [ <indx> ] -= <expr>
<id> [ where <expr> ] -= <expr>
<id> [ <indx> ] *= <expr>
<id> [ where <expr> ] *= <expr>
<id> [ <indx> ] /= <expr>
<id> [ where <expr> ] /= <expr>
<id> [ <indx> ] ++
<id> [ where <expr> ] ++
<id> [ <indx> ] --
<id> [ where <expr> ] --
++ <id> [ <indx> ]
++ <id> [ where <expr> ]
-- <id> [ <indx> ]
-- <id> [ where <expr> ]
In addition to these standard assignments Xi also has an extended assignment to set the values of several variables at once:
[ <id1> , <id2> ,... ] = [ <expr1> , <expr2> ,..
. ]
With this the variable <id1> will be set to the result of
<expr1>, <id2> to the result of
<expr2> and so on. The result of the whole expression is
the new value of <id1>. This assignment is not useful
under normal circumstances with the exception of a function having more
than one return value.
[ <id1> , <id2> ,... ] = <id_f> ( <args> )
Here the Variables <id1>, <id2>, ... will be
set to the results of the function <id_f ( args means the
arguments of this functions; see Function calls for
more detail).