6.3 Vector, Matrix, and Array Expressions

Expressions for the Stan container objects arrays, vectors, and matrices can be constructed via a sequence of expressions enclosed in either curly braces for arrays, or square brackets for vectors and matrices.

Vector Expressions

Square brackets may be wrapped around a sequence of comma separated primitive expressions to produce a row vector expression. For example, the expression [ 1, 10, 100 ] denotes a row vector of three elements with real values 1.0, 10.0, and 100.0. Applying the transpose operator to a row vector expression produces a vector expression. This syntax provides a way declare and define small vectors a single line, as follows.

row_vector[2] rv2=  [ 1, 2 ];
vector[3] v3 = [ 3, 4, 5 ]';

The vector expression values may be compound expressions or variable names, so it is legal to write [ 2 * 3, 1 + 4] or [ x, y ], providing that x and y are primitive variables.

Matrix Expressions

A matrix expression consists of square brackets wrapped around a sequence of comma separated row vector expressions. This syntax provides a way declare and define a matrix in a single line, as follows.

matrix[3,2] m1 = [ [ 1, 2 ], [ 3, 4 ], [5, 6 ] ];

Any expression denoting a row vector can be used in a matrix expression. For example, the following code is valid:

vector[2] vX = [ 1, 10 ]';
row_vector[2] vY = [ 100, 1000 ];
matrix[3,2] m2 = [ vX', vY, [ 1, 2 ]  ];

No empty vector or matrix expressions

The empty expression [ ] is ambiguous and therefore is not allowed and similarly expressions such as [ [ ] ] or [ [ ], [ ] ] are not allowed.

Array Expressions

Curly braces may be wrapped around a sequence of expressions to produce an array expression. For example, the expression { 1, 10, 100 } denotes an integer array of three elements with values 1, 10, and 100. This syntax is particularly convenient to define small arrays in a single line, as follows.

int a[3] = { 1, 10, 100 };

The values may be compound expressions, so it is legal to write { 2 * 3, 1 + 4 }. It is also possible to write two dimensional arrays directly, as in the following example.

int b[2, 3] = { { 1, 2, 3 }, { 4, 5, 6 } };

This way, b[1] is { 1, 2, 3 } and b[2] is { 4, 5, 6 }.

Whitespace is always interchangeable in Stan, so the above can be laid out as follows to more clearly indicate the row and column structure of the resulting two dimensional array.

int b[2, 3] = { { 1, 2, 3 },
                { 4, 5, 6 } };

Array Expression Types

Any type of expression may be used within braces to form an array expression. In the simplest case, all of the elements will be of the same type and the result will be an array of elements of that type. For example, the elements of the array can be vectors, in which case the result is an array of vectors.

vector[3] b;
vector[3] c;
...
vector[3] d[2] = { b, c };

The elements may also be a mixture of int and real typed expressions, in which case the result is an array of real values.

real b[2] = { 1, 1.9 };

Restrictions on Values

There are some restrictions on how array expressions may be used that arise from their types being calculated bottom up and the basic data type and assignment rules of Stan.

Rectangular array expressions only

Although it is tempting to try to define a ragged array expression, all Stan data types are rectangular (or boxes or other higher-dimensional generalizations). Thus the following nested array expression will cause an error when it tries to create a non-rectangular array.

{ { 1, 2, 3 }, { 4, 5 } }  // compile time error: size mismatch

This may appear to be OK, because it is creating a two-dimensional integer array (int[ , ]) out of two one-dimensional array integer arrays (int[ ]). But it is not allowed because the two one-dimensional arrays are not the same size. If the elements are array expressions, this can be diagnosed at compile time. If one or both expressions is a variable, then that won’t be caught until runtime.

{ { 1, 2, 3 }, m }  // runtime error if m not size 3

No empty array expressions

Because there is no way to infer the type of the result, the empty array expression ({ }) is not allowed. This does not sacrifice expressive power, because a declaration is sufficient to initialize a zero-element array.

int a[0];   // a is fully defined as zero element array

Integer only array expressions

If an array expression contains only integer elements, such as { 1, 2, 3 }, then the result type will be an integer array, int[]. This means that the following will not be legal.

real a[2] = { -3, 12 };  // error: int[] can't be assigned to real[]

Integer arrays may not be assigned to real values. However, this problem is easily sidestepped by using real literal expressions.

real a[2] = { -3.0, 12.0 };

Now the types match and the assignment is allowed.