5.7 Variable types vs. constraints and sizes
The type information associated with a variable only contains the underlying type and dimensionality of the variable.
Type information excludes sizes
The size associated with a given variable is not part of its data type. For example, declaring a variable using
array[3] real a;
declares the variable a
to be an array. The fact that it was
declared to have size 3 is part of its declaration, but not part of
its underlying type.
When are sizes checked?
Sizes are determined dynamically (at run time) and thus cannot be type-checked statically when the program is compiled. As a result, any conformance error on size will raise a run-time error. For example, trying to assign an array of size 5 to an array of size 6 will cause a run-time error. Similarly, multiplying an \(N \times M\) by a \(J \times K\) matrix will raise a run-time error if \(M \neq J\).
Type information excludes constraints
Like sizes, constraints are not treated as part of a variable’s type in Stan when it comes to the compile-time check of operations it may participate in. Anywhere Stan accepts a matrix as an argument, it will syntactically accept a correlation matrix or covariance matrix or Cholesky factor. Thus a covariance matrix may be assigned to a matrix and vice-versa.
Similarly, a bounded real may be assigned to an unconstrained real and vice-versa.
When are function argument constraints checked?
For arguments to functions, constraints are sometimes, but not always checked when the function is called. Exclusions include C++ standard library functions. All probability functions and cumulative distribution functions check that their arguments are appropriate at run time as the function is called.
When are declared variable constraints checked?
For data variables, constraints are checked after the variable is read from a data file or other source. For transformed data variables, the check is done after the statements in the transformed data block have executed. Thus it is legal for intermediate values of variables to not satisfy declared constraints.
For parameters, constraints are enforced by the transform applied and do not need to be checked. For transformed parameters, the check is done after the statements in the transformed parameter block have executed.
For all blocks defining variables (transformed data, transformed
parameters, generated quantities), real values are initialized to
NaN
and integer values are initialized to the smallest legal
integer (i.e., a large absolute value negative number).
For generated quantities, constraints are enforced after the statements in the generated quantities block have executed.
Type naming notation
In order to refer to data types, it is convenient to have a way to refer to them. The type naming notation outlined in this section is not part of the Stan programming language, but rather a convention adopted in this document to enable a concise description of a type.
Because size information is not part of a data type, data types will
be written without size information. For instance, array[] real
is the
type of one-dimensional array of reals and matrix
is the type of
matrices. The three-dimensional integer array type is written as
array[,,] int
, indicating the number slots available for indexing.
Similarly, array[,] vector
is the type of a two-dimensional array of
vectors.