7.2 Assignment statements
An assignment statement consists of a variable (possibly multivariate with indexing information) and an expression. Executing an assignment statement evaluates the expression on the right-hand side and assigns it to the (indexed) variable on the left-hand side. An example of a simple assignment is as follows.
0; n =
Executing this statement assigns the value of the expression 0
,
which is the integer zero, to the variable n
. For an assignment
to be well formed, the type of the expression on the right-hand side
should be compatible with the type of the (indexed) variable on the
left-hand side. For the above example, because 0
is an
expression of type int
, the variable n
must be declared
as being of type int
or of type real
. If the variable
is of type real
, the integer zero is promoted to a
floating-point zero and assigned to the variable. After the
assignment statement executes, the variable n
will have the
value zero (either as an integer or a floating-point value, depending on
its type).
Syntactically, every assignment statement must be followed by a semicolon. Otherwise, whitespace between the tokens does not matter (the tokens here being the left-hand-side (indexed) variable, the assignment operator, the right-hand-side expression and the semicolon).
Because the right-hand side is evaluated first, it is possible to increment a variable in Stan just as in C++ and other programming languages by writing
1; n = n +
Such self assignments are not allowed in BUGS, because they induce a cycle into the directed graphical model.
The left-hand side of an assignment may contain indices for array,
matrix, or vector data structures. For instance, if Sigma
is
of type matrix
, then
1, 1] = 1.0; Sigma[
sets the value in the first column of the first row of Sigma
to one.
Assignments to subcomponents of larger multi-variate data structures
are supported by Stan. For example, a
is an array of type
array[,] real
and b
is an array of type array[] real
, then
the following two statements are both well-formed.
3] = b;
a[4]; b = a[
Similarly, if x
is a variable declared to have type
row_vector
and Y
is a variable declared as type
matrix
, then the following sequence of statements to swap the
first two rows of Y
is well formed.
1];
x = Y[1] = Y[2];
Y[2] = x; Y[
Promotion
Stan allows assignment of lower types to higher types, but not
vice-versa. That is, we can assign an expression of type int
to an
lvalue of type real
, and we can assign an expression of type real
to an lvalue of type complex
. Furthermore, promotion is transitive,
so that we can assign an expression of type int
to an lvalue of type
complex
.
Promotion extends to containers, so that arrays of int
can be
promoted to arrays of real
during assignment, and arrays of real
can be assigned to an lvalue of type array of complex
. Similarly,
an expression of type vector
may be assigned to an lvalue of type
complex_vector
, and similarly for row vectors and matrices.
Lvalue summary
The expressions that are legal left-hand sides of assignment statements are known as “lvalues.” In Stan, there are only two kinds of legal lvalues,
- a variable, or
- a variable with one or more indices.
To be used as an lvalue, an indexed variable must have at least as many dimensions as the number of indices provided. An array of real or integer types has as many dimensions as it is declared for. A matrix has two dimensions and a vector or row vector one dimension; this also holds for the constrained types, covariance and correlation matrices and their Cholesky factors and ordered, positive ordered, and simplex vectors. An array of matrices has two more dimensions than the array and an array of vectors or row vectors has one more dimension than the array. Note that the number of indices can be less than the number of dimensions of the variable, meaning that the right hand side must itself be multidimensional to match the remaining dimensions.
Multiple indexes
Multiple indexes, as described in the multi-indexing section, are also permitted on the left-hand side of assignments. Indexing on the left side works exactly as it does for expressions, with multiple indexes preserving index positions and single indexes reducing them. The type on the left side must still match the type on the right side.
Compound arithmetic and assignment statement
Stan’s arithmetic operators may be used in compound arithmetic and assignment operations. For example, consider the following example of compound addition and assignment.
real x = 5;
7; // value of x is now 12 x +=
The compound arithmetic and assignment statement above is equivalent to the following long form.
7; x = x +
In general, the compound form
x op= y
will be equivalent to
x = x op y;
The compound statement will be legal whenever the long form is legal.
This requires that the operation x op y
must itself be well
formed and that the result of the operation be assignable to x
.
For the expression x
to be assignable, it must be an indexed
variable where the variable is defined in the current block. For
example, the following compound addition and assignment statement will
increment a single element of a vector by two.
vector[N] x;
3] += 2; x[
As a further example, consider
matrix[M, M] x;
vector[M] y;
real z;
// OK, (x * x) is a matrix
x *= x; // OK, (x * z) is a matrix
x *= z; // BAD, (x * y) is a vector x *= y;
The supported compound arithmetic and assignment
operations are listed in the compound arithmetic/assignment table; they
are also listed in the index prefaced by operator
, e.g.,
operator+=
.
Compound Arithmetic/Assignment Table. Stan allows compound arithmetic and assignment statements of the forms listed in the table. The compound form is legal whenever the corresponding long form would be legal and it has the same effect.
operation | compound | unfolded |
---|---|---|
addition | x += y |
x = x + y |
subtraction | x -= y |
x = x - y |
multiplication | x *= y |
x = x * y |
division | x /= y |
x = x / y |
elementwise multiplication | x .*= y |
x = x .* y |
elementwise division | x ./= y |
x = x ./ y |