The **-expression**
argument is a single string that describes the function to evaluate.
The function expression is typically written in terms of the vector A.

For example, the following expression will sum the first two input files
together:

A[0] + A[1]

Multiple expressions can be given separated by semicolons, in which
case only the value of the last expression is used. These expression
lists can be used with assignment expressions to make the syntax very
C-like:

ratio = A[0]/A[1]; A[2]*exp(-ratio)

An expression list in curly brackets is a valid expression and returns
the value of last expression in the list. This is particularly useful
in **for** and **if** expressions (see below).

There are two types of values in the language: vectors and scalars.
Scalars literals are floating point numbers or may appear as symbols
whose name starts with a lowercase letter.

Besides normal scalar operators such as +, -, * and /, the expression
language also supports the infix exponentiation operator ^ , the
usual relational operators <, <=, >, >=, ==, != as well as the boolean operators
&& (and), || (or) and ! (not). Note that the && and || boolean operators always
evaluate both operands, unlike C. Scalar mathematical functions include
**abs**, **sqrt**, **exp**, **log**, **sin**, **cos**, **tan**,
**asin**, **acos** and **atan**. There are also some specialized
functions:

isnan(v) - 1 if v is invalid and 0 otherwise

clamp(v1,v2,v3) - v1 bounded by [v2, v3]

segment(v1,v2,v3) - tests if v1 is in [v2, v3]

The scalar constant NaN is defined such that isnan(NaN) return 1.

Vectors can be written in the following ‘extensional’ form

[ value1, value2, ... ]

or by using the following range-generating notations:

[ a : b ] generates {a, a+1, ..., b-1, b}

[ a : b ) generates {a, a+1, ..., b-1}

( a : b ] generates {a+1, ..., b-1, b}

( a : b ) generates {a+1, ..., b-1}

or be generated, by ‘intension’. The following intension expression
generates the vector {3,2,1}:

{ i in [1:3] | 4 - i }

Vectors may also appear as symbols whose name starts with an uppercase
letter.

In addition to the scalar operators, the following vector operators are
supplied:

avg - the average value of the scalars in vector

len - the length of

sum - the sum of the elements of

prod - the product of the elements of

max - the maximum value of

min - the minimum value of

imax - the index of the maximum value of

imin - the index of the minimum value of

V[s] - the s’th element of vector V with origin 0.

Symbol names are introduced into a global symbol table by assignment
expressions of the form

a = A[2] * log(2)

Symbols starting with a lowercase letter represent scalars while those
starting with an uppercase letter represent vectors. Since = is an
operator, its result can be used in an expression (as in C).

A few control constructs are provided:

For loops can be created to loop over a vector, assigning each value
to a symbol and then evaluating an expression. This is done with
expressions of the form

total=0; for{i in [0:len(A))} total=total+A[i]; total

which is equivalent to sum(A). Note that this is similar to using

total=0; len{i in [0:len(A)) | total=total+A[i]}; total

since the **for** construct is actually an operator (although it is
usually only used for changing symbol values). Note also that without
the final "total", the expression would not be very useful since it would
only return the length of the vector.

As in C, a list of expressions can be specified in curlies:

total=total2 = 0;

for {i in [0:len(A))} {

total = total + A[i];

total2 = total2 + A[i]^2

}

There are also a few forms of the **if-then-else** construct:

A[0]<0 ? 0 : A[0]

if (A[0]<0) result=0 else result=A[0]

The **else** is optional. Again, the if construct is an operator, and the
**then** or **else** expressions can be expression lists in curlies,
in which case the value of the last expression is returned. If the **else**
expression is missing, then the value 0 is returned when the test
expression is 0 (false).

The principal oddity with the **for** and **if** constructs is that
unlike C statements, they must be separated from the next expression by a
semicolon even when an expression list in curlies is used:

for i in [0:len(A)) {total=total+A[i]} ; total/len(A)

if (A[i]>0) {result=2;} else {result=1} ; result*5

An alternative way to introduce symbol names is through **let**-expressions.
For example, the following expression will always evaluate to 3:

let a = 1, b = 2 in a + b

These were originally designed to create variables only within the
evaluated expression, but modifications have been made so that the
global symbol table is changed.

Here is an expression for calculating standard deviation, taking into account
the possibility of invalid input data, which is ignored:

s0 = s1 = s2 = 0;

for { i in [0:len(A)) } {

v=A[i];

if (!isnan(v)) {

s0 = s0 + 1;

s1 = s1 + v;

s2 = s2 + v*v;

}

};

if (s0 > 1) {

sqrt((s2 - s1*s1/s0) / (s0-1));

}

else {

NaN;

};

The last if could be changed to return 0 if s0 is > 0 but <= 1. We also
drop the curly brackets, but then there must not be a ";" between the if
and the else

if (s0 > 1)

sqrt((s2 - s1*s1/s0) / (s0-1))

else if (s0 > 0)

0

else

NaN

If we want both the mean and the standard deviation, we can use the
**-outfile** option, invoking the command with

minccalc -expfile stdev \

-outfile mean mean.mnc \

-outfile stdev stdev.mnc \

infile1.mnc infile2.mnc ...

And using the expression file (with yet another form of if expression):

s0 = s1 = s2 = 0;

for {i in [0:len(A))} {

v=A[i];

if (!isnan(v)) {

s0 = s0 + 1;

s1 = s1 + v;

s2 = s2 + v*v;

}

};

stdev = (s0 > 1) ? sqrt((s2 - s1*s1/s0) / (s0-1)) :

(s0 > 0) ? 0 : NaN ;

mean = (s0 > 0) ? s1 / s0 : NaN ;