15.1 Basic Motivation

Stan provides two basic scalar types, int and real, and three basic linear algebra types, vector, row_vector, and matrix. Then Stan allows arrays to be of any dimension and contain any type of element (though that type must be declared and must be the same for all elements).

This leaves us in the awkward situation of having three one-dimensional containers, as exemplified by the following declarations.

real a[N];
vector[N] a;
row_vector[N] a;

These distinctions matter. Matrix types, like vector and row vector, are required for linear algebra operations. There is no automatic promotion of arrays to vectors because the target, row vector or column vector, is ambiguous. Similarly, row vectors are separated from column vectors because multiplying a row vector by a column vector produces a scalar, whereas multiplying in the opposite order produces a matrix.

The following code fragment shows all four ways to declare a two-dimensional container of size \(M \times N\).

real b[M, N];          // b[m] : real[]     (efficient)
vector[N] b[M];        // b[m] : vector     (efficient)
row_vector[N] b[M];    // b[m] : row_vector (efficient)
matrix[M, N] b;        // b[m] : row_vector (inefficient)

The main differences among these choices involve efficiency for various purposes and the type of b[m], which is shown in comments to the right of the declarations. Thus the only way to efficiently iterate over row vectors is to use the third declaration, but if you need linear algebra on matrices, but the only way to use matrix operations is to use the fourth declaration.

The inefficiencies due to any manual reshaping of containers is usually slight compared to what else is going on in a Stan program (typically a lot of gradient calculations).