Go to the previous, next section.

Vectors and Arithmetic

The basic unit of data in SM is the `vector', a named set of one or more numbers or strings. There is no limit to the number of vectors that may be defined. SM allows the user to read vectors from files or define them from the keyboard, to plot them and to perform arithmetic operations upon them. SM's string-valued vectors are less generally useful, but can be used for such purposes as labelling points on a graph.

To read a vector vec from a column of numbers in a file, where the filename has been specified using DATA and, possibly, the range of lines in the file to be used has been specified using the LINES command, use READ vec nn where nn is the column number, or READ { vec1 n1 vec2 n2 ... 2 to read many vectors. It is also possible to read a row, using READ ROW vec nn, where nn is the row number in the file. See READ for how to read a string-valued vector.

Instead of using simple column-orientated input it is possible to specify a format like those used by C's scanf functions (Fortran formats are not supported); if you provide your own format string you can only read numbers. For example, if your data file has lines like

	1:12:30  -45:30:11
you could read it with read '%d:%d:%d %f:%f:%f' { hr min sec deg dmin dsec 2.

A vector may also be defined as SET vec = x1,x2,dx to take on the values x1,x1+dx,...,x2, where dx defaults to 1 if omitted. If a scalar is encountered where a vector is expected, it is promoted to be a vector of the appropriate dimension; all other dimension mismatches are errors. Example:

SET value = 5
SET x = 0, 50, 2
SET y = x
SET y = x*0 + value
SET y[0] = 2*pi
SET y = value
SET x=0,1,.1 SET y=IMAGE(x,1.5)
SET s=str
SET s='str'
SET s[0]=1.23
SET x=1.23
SET s=x
will define a scalar, value, with a value of 5, then define a vector, x, with 26 elements, valued 0, 2, 4, 6,..., 50, then define another vector, y with size 26 and the same values as x, set all 26 elements of y to have the value 5, set the first element of y to be 2 pi, set y to be a vector with one element with value 5, and finally set y to be a vector with the values taken from a horizontal cross-section from 0 to 1 through the current image. Unless a vector str is defined SET s=str is an error; to make s a string-valued vector use SET s='str'. SET s[0]=1.23 makes s[0] have the value "1.23" (a string), as s is now a pre-existing string vector. An arithmetic vector x is then defined, and s is redefined as an arithmetic vector too -- you must be careful when dealing with string vectors! Finally, we explicitly convert an arithmetic vector to a string-valued one with the STRING operator. This is a somewhat contrived example, designed mainly to illustrate the convenience of the SET command. The ability to set particular elements is mostly used in macros such as smirnov2 which calculates the Kolmogorov-Smirnov statistic from a pair of vectors.

If you don't have many data points, rather than type them into a file, and use READ vec nn to define a vector, you can use the command@example SET vec = { list 2 For example@example SET r = 0,10 is equivalent to@example SET r = { 0 1 2 3 4 5 6 8 9 10 2 In fact, { list 2 is an expression, so SET vec = 2*{1 3 12 is also legal. If the first element of a list is a word, the vector is taken to be string-valued: SET s={ William William Henry Steven 2 defines a 4-element string vector, or you can use a string in quotes: SET s=<'1' 2 3 4> (if you used SET s={'1' 2 3 42 the first element would be '1' rather than 1). Once a vector is defined, you can write it to a file for later study using the PRINT command.

A scalar may be an integer, a floating point number, a scalar expression, DIMEN(vector), or WORD[expr]. The last two are the dimension of a vector, and an element of the vector with expr a scalar subscript. Note that subscripts start at 0 and that [ ] `not' () are used to subscript variables. The expression WORD[expr] is in fact allowed even if expr is not a scalar, in which case the result is a vector with the same dimension as expr, and with the values taken from WORD in the obvious way.

Once vectors are defined, they may be combined into expressions using the operators +, -, *, /, **, CONCAT and the functions COS(), SIN(), TAN(), ACOS(), ASIN(), ATAN(), ATAN2(), ABS(), DIMEN(), INT(), LG(), EXP(), LN(), SQRT(), STRING(), STRLEN(), and SUM(). The meaning of most of these is obvious, ATAN2 is like ATAN but takes two arguments, x and y and returns an angle in the proper sector. DIMEN returns the number of elements in a vector, SUM gives the sum of all the elements, CONCAT concatenates two vectors, INT gives the integral part of a vector, STRING converts a number to a string, and STRLEN gives the length of a string (in plotting units, not just the number of characters). STRING uses the same code as the axis-labelling routines, so FORMAT can be used to modify its behaviour; whether the x- or y-axis formats is used depends on whether the label is more nearly horizontal or vertical. An example would be

set x=3.08e16 define s (string(x)) relocate 0.5 0.5 putlabel 5 $s
The precedence and binding are as for C (or Fortran), and may be altered by using parentheses (CONCAT has a binding just below + and -). All of these operators work element by element, so
y = 2 + sin(x)
is interpreted as

If there is a size mismatch the operation will only be carried out up
to the length of the shorter vector and a message is printed; if
VERBOSE is 1 or more, the line where the error occurred will
be printed too.
The constant PI is predefined.

You can also use WORD([ expr [ , ... ]]) as part of an expression, where WORD is a macro taking zero or more arguments. It is a bit dishonest to write the arguments as expr, as in fact they must be either the names of vectors or numbers. Suppose we define a macro pow with two arguments as@example SET $0 = $1**$2 then the command@example SET y = 10 + 2*pow(x,3) is equivalent to SET y = 10 + 2*x**3.

In addition to these arithmetic operations, there are also logical operators == (equals), != (not equals), >, >=, <, <=, && (logical and), and || (logical or). The meanings of the symbols are the same as in C, and as in C the value 0 is false while all other values are true.

String vectors may only be concatenated, added, or tested for (in)equality. Adding two string-valued vectors concatenates their elements, so

{ a b c 2 + { x y z 2
results in the vector ax by cz.

Testing equality for string vectors seems to cause some confusion. Consider

set str=<'a' b c d>
if('a' == 'str') {     # test if the strings `a' and `str' are equal
if('a' == str) {       # test if the string `a' equals the vector `str'
if(a == str) {         # test if the vector `a' equals the vector `str'
The second of these tests will succeed, but if you then try
if('b' == str) {       # try to see if `b' is an element of str
the test will fail as 'b' == str is the 4-element vector { 0 1 0 1 2 and only its first element is used by the if test; what you want is
if(sum('b' == str)) {  # is `b' an element of str?

There are also a number of less mathematical operations. If you have an IMAGE (@xref{IMAGE}) defined, you can extract a set of values using the expression IMAGE(expr,expr), where the two exprs give the coordinates where the values are desired. Note that this may be used as a way of reading large data files that are stored unformatted. The expression HISTOGRAM(expr : expr) can be used to convert a vector into a histogram. The second expression is taken to be the centres of the desired bins: bin boundaries are taken at the mean points (and points in the first expression lying on a boundary are taken to fall into the lower bin. Note the use of `:' not `,').

Vectors may be assigned to, using the syntax

SET vec = expr
or@example SET vec[ expr ] = expr or@example SET vec = WORD(expr) or@example SET DIMEN(vec) = number or@example SET vec = expr1 IF(expr2) or@example SET vec = expr1 ? expr2 : expr3 The first form sets vec to have the value expr, element by element, vec is the name of the new vector. The form vec[expr] may be used to assign to an element of a vector, as usual the index starts at 0. Before you can use SET to assign values to the elements of a vector, you must create it using one of the other forms of the SET command.

If you want to define a vector to which you will subsequently assign values using SET vec[ expr ] = expr, you may use SET DIMEN(vec) = number which declares vec to be a vector of size number, and initialises it to zero. You can optionally supply a qualifier to the number, either a .f (the default), or a .s to specify that the vector is string valued.

If the IF clause is present, only those elements of expr1 for which the corresponding element of expr2 is true (non-zero) are copied into vec; in general vec will have a smaller dimension than expr1. The last SET statement (with ?:) again borrows from C. If expr1_i is true, then vec_i is set to expr2_i, otherwise it is set to expr3_i. In this form of conditional assignment, the dimension of vec is the same as that of the right hand side. It may look strange, but it can be just what you want.

Each vector also has a help field, which may be used to provide a string describing the vector. The field is set by

SET HELP vec str
and viewed by
HELP vec
If VERBOSE is one or more, if a vector is arithmetic or string will also be noted. Vectors may be printed using the
PRINT [ file ] [format] { vec1, ..., vecn 2
command, where if the optional file is missing, the values are typed to the keyboard; if the optional format is omitted, a suitable one will be chosen for you. Any combination of string- and arithmetic-vectors may be printed. If a value exceeds 1e36, it is printed as a *. This is consistent with the convention used in reading data that a `missing' number is represented as 1.001e36; see READ for details. Vectors may be deleted with the command
and listed with the command
Vectors are listed in ascii order along with their dimension, and any help string specified using the SET HELP command

An IF clause has been added to the plotting commands, to allow only those elements of a vector which satisfy some condition to be plotted, for example

POINTS x y IF(z > 3*x)
Of course, you could have used the IF command and the regular POINTS command if you had preferred. In fact,@example CONNECT x y IF(z > 3*x) isn't quite the same as
SET log = z > 3*x SET x = x IF(log)  SET y = y IF(log) 
as the former will only connect contiguous points.

Go to the previous, next section.