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
SET s=STRING(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 12` 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 42` 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 `expr`s 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
```DELETE vec
```
and listed with the command
```LIST SET
```
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)
CONNECT x y
```
as the former will only connect contiguous points.

Go to the previous, next section.