5.5 Array Data Types

Stan supports arrays of arbitrary dimension. The values in an array can be any type, so that arrays may contain values that are simple reals or integers, vectors, matrices, or other arrays. Arrays are the only way to store sequences of integers, and some functions in Stan, such as discrete distributions, require integer arguments.

A two-dimensional array is just an array of arrays, both conceptually and in terms of current implementation. When an index is supplied to an array, it returns the value at that index. When more than one index is supplied, this indexing operation is chained. For example, if a is a two-dimensional array, then a[m, n] is just a convenient shorthand for a[m][n].

Vectors, matrices, and arrays are not assignable to one another, even if their dimensions are identical.

Declaring Array Variables

Arrays are declared by enclosing the dimensions in square brackets following the name of the variable.

The variable n is declared as an array of five integers as follows.

int n[5];

A two-dimensional array of real values with three rows and four columns is declared with the following.

real a[3, 4];

A three-dimensional array z of positive reals with five rows, four columns, and two shelves can be declared as follows.

real<lower=0> z[5, 4, 2];

Arrays may also be declared to contain vectors. For example,

vector[7] mu[3];

declares mu to be an array of size 3 containing vectors with 7 elements. Arrays may also contain matrices. The example

matrix[7, 2] mu[15, 12];

declares a 15 by 12 array of \(7 \times 2\) matrices. Any of the constrained types may also be used in arrays, as in the declaration

cholesky_factor_cov[5, 6] mu[2, 3, 4];

of a \(2 \times 3 \times 4\) array of \(5 \times 6\) Cholesky factors of covariance matrices.

Accessing Array Elements and Subarrays

If x is a 1-dimensional array of length 5, then x[1] is the first element in the array and x[5] is the last. For a \(3 \times 4\) array y of two dimensions, y[1, 1] is the first element and y[3, 4] the last element. For a three-dimensional array z, the first element is z[1, 1, 1], and so on.

Subarrays of arrays may be accessed by providing fewer than the full number of indexes. For example, suppose y is a two-dimensional array with three rows and four columns. Then y[3] is one-dimensional array of length four. This means that y[3][1] may be used instead of y[3, 1] to access the value of the first column of the third row of y. The form y[3, 1] is the preferred form (see note in this chapter).

Assigning

Subarrays may be manipulated and assigned just like any other variables. Similar to the behavior of matrices, Stan allows blocks such as

real w[9, 10, 11];
real x[10, 11];
real y[11];
real z;
// ...
x = w[5];
y = x[4];  // y == w[5][4] == w[5, 4]
z = y[3];  // z == w[5][4][3] == w[5, 4, 3]

Arrays of Matrices and Vectors

Arrays of vectors and matrices are accessed in the same way as arrays of doubles. Consider the following vector and scalar declarations.

vector[5] a[3, 4];
vector[5] b[4];
vector[5] c;
real x;

With these declarations, the following assignments are legal.

b = a[1];      // result is array of vectors
c = a[1, 3];    // result is vector
c = b[3];      //   same result as above
x = a[1, 3, 5];  // result is scalar
x = b[3, 5];    //   same result as above
x = c[5];      //   same result as above

Row vectors and other derived vector types (simplex and ordered) behave the same way in terms of indexing.

Consider the following matrix, vector and scalar declarations.

matrix[6, 5] d[3, 4];
matrix[6, 5] e[4];
matrix[6, 5] f;
row_vector[5] g;
real x;

With these declarations, the following definitions are legal.

e = d[1];        // result is array of matrices
f = d[1,3];      // result is matrix
f = e[3];        //   same result as above
g = d[1,3,2];    // result is row vector
g = e[3,2];      //   same result as above
g = f[2];        //   same result as above
x = d[1,3,5,2];  // result is scalar
x = e[3,5,2];    //   same result as above
x = f[5,2];      //   same result as above
x = g[2];        //   same result as above

As shown, the result f[2] of supplying a single index to a matrix is the indexed row, here row 2 of matrix f.

Partial Array Assignment

Subarrays of arrays may be assigned by indexing on the left-hand side of an assignment statement. For example, the following is legal.

real x[I,J,K];
real y[J,K];
real z[K];
// ...
x[1] = y;
x[1,1] = z;

The sizes must match. Here, x[1] is a J by K array, as is y.

Partial array assignment also works for arrays of matrices, vectors, and row vectors.

Mixing Array, Vector, and Matrix Types

Arrays, row vectors, column vectors and matrices are not interchangeable in Stan. Thus a variable of any one of these fundamental types is not assignable to any of the others, nor may it be used as an argument where the other is required (use as arguments follows the assignment rules).

Mixing Vectors and Arrays

For example, vectors cannot be assigned to arrays or vice-versa.

real a[4];
vector[4] b;
row_vector c[4];
// ...
a = b; // illegal assignment of vector to array
b = a; // illegal assignment of array to vector
a = c; // illegal assignment of row vector to array
c = a; // illegal assignment of array to row vector

Mixing Row and Column Vectors

It is not even legal to assign row vectors to column vectors or vice versa.

vector b[4];
row_vector c[4];
// ...
b = c; // illegal assignment of row vector to column vector
c = b; // illegal assignment of column vector to row vector

Mixing Matrices and Arrays

The same holds for matrices, where 2-dimensional arrays may not be assigned to matrices or vice-versa.

real a[3,4];
matrix[3,4] b;
// ...
a = b;  // illegal assignment of matrix to array
b = a;  // illegal assignment of array to matrix

Mixing Matrices and Vectors

A \(1 \times N\) matrix cannot be assigned a row vector or vice versa.

matrix[1,4] a;
row_vector[4] b;
// ...
a = b;  // illegal assignment of row vector to matrix
b = a;  // illegal assignment of matrix to row vector

Similarly, an \(M \times 1\) matrix may not be assigned to a column vector.

matrix[4,1] a;
vector[4] b;
// ...
a = b;  // illegal assignment of column vector to matrix
b = a;  // illegal assignment of matrix to column vector

Size Declaration Restrictions

An integer expression is used to pick out the sizes of arrays. The same restrictions as for vector and matrix sizes apply, namely that the size is declared with an integer-denoting expression that does not contain any parameters, transformed parameters, or generated quantities.

Size Zero Arrays

If any of an array’s dimensions is size zero, the entire array will be of size zero. That is, if we declare

real a[3, 0];

then the resulting size of a is zero and querying any of its dimensions at run time will result in the value zero. Declared as above, a[1] will be a size-zero one-dimensional array. For comparison, declaring

real b[0, 3];

also produces an array with an overall size of zero, but in this case, there is no way to index legally into b, because b[0] is undefined. The array will behave at run time as if it’s a \(0 \times 0\) array. For example, the result of to_matrix(b) will be a \(0 \times 0\) matrix, not a \(0 \times 3\) matrix.