18.1 Basic motivation
Stan provides two basic scalar types,
three basic linear algebra types,
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.
array[N] real a; 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\).
array[M, N] real b; // b[m] : array real (efficient) array[M] vector[N] b; // b[m] : vector (efficient) array[M] row_vector[N] b; // 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).