6.5 Arithmetic and Matrix Operations on Expressions
For integer and real-valued expressions, Stan supports the basic binary arithmetic operations of addition (+
), subtraction (-
), multiplication (*
) and division (/
) in the usual ways.
For integer expressions, Stan supports the modulus (%
) binary arithmetic operation. Stan also supports the unary operation of negation for integer and real-valued expressions. For example, assuming n
and m
are integer variables and x
and y
real variables, the following expressions are legal.
3.0 + 0.14
-15
2 * 3 + 1
(x - y) / 2.0
(n * (n + 1)) / 2
x / n
m % n
The negation, addition, subtraction, and multiplication operations are extended to matrices, vectors, and row vectors. The transpose operation, written using an apostrophe ('
) is also supported for vectors, row vectors, and matrices. Return types for matrix operations are the smallest types that can be statically guaranteed to contain the result. The full set of allowable input types and corresponding return types is detailed in the list of functions.
For example, if y
and mu
are variables of type vector
and Sigma
is a variable of type matrix
, then (y - mu)' * Sigma * (y - mu)
is a well-formed expression of type real
. The type of the complete expression is inferred working outward from the subexpressions. The subexpression(s) y - mu
are of type vector
because the variables y
and mu
are of type vector
. The transpose of this expression, the subexpression (y - mu)'
is of type row_vector
. Multiplication is left associative and transpose has higher precedence than multiplication, so the above expression is equivalent to the following fully specified form (((y - mu)') * Sigma) * (y - mu)
.
The type of subexpression (y - mu)' * Sigma
is inferred to be row_vector
, being the result of multiplying a row vector by a matrix. The whole expression’s type is thus the type of a row vector multiplied by a (column) vector, which produces a real
value.
Stan provides elementwise matrix multiplication (e.g., a .* b
) and division (e.g., a ./ b
) operations. These provide a shorthand to replace loops, but are not intrinsically more efficient than a version programmed with an elementwise calculations and assignments in a loop. For example, given declarations,
vector[N] a;
vector[N] b;
vector[N] c;
the assignment,
c = a .* b;
produces the same result with roughly the same efficiency as the loop
for (n in 1:N)
c[n] = a[n] * b[n];
Stan supports exponentiation (^
) of integer and real-valued expressions. The return type of exponentiation is always a real-value. For example, assuming n
and m
are integer variables and x
and y
real variables, the following expressions are legal.
3 ^ 2
3.0 ^ -2
3.0 ^ 0.14
x ^ n
n ^ x
n ^ m
x ^ y
Exponentiation is right associative, so the expression 2 ^ 3 ^ 4
is equivalent to the fully specified form 2 ^ (3 ^ 4)
.
Operator Precedence and Associativity
The precedence and associativity of operators, as well as built-in syntax such as array indexing and function application is given in tabular form in the operator precedence table.
Operator Precedence Table. Stan’s unary, binary, and ternary operators, with their precedences, associativities, place in an expression, and a description. The last two lines list the precedence of function application and array, matrix, and vector indexing. The operators are listed in order of precedence, from least tightly binding to most tightly binding. The full set of legal arguments and corresponding result types are provided in the function documentation for the operators (i.e., operator*(int,int):int
indicates the application of the multiplication operator to two integers, which returns an integer). Parentheses may be used to group expressions explicitly rather than relying on precedence and associativity.
Op. | Prec. | Assoc. | Placement | Description |
---|---|---|---|---|
? ~ : |
10 | right | ternary infix | conditional |
|| |
9 | left | binary infix | logical or |
&& |
8 | left | binary infix | logical and |
== |
7 | left | binary infix | equality |
!= |
7 | left | binary infix | inequality |
< |
6 | left | binary infix | less than |
<= |
6 | left | binary infix | less than or equal |
> |
6 | left | binary infix | greater than |
>= |
6 | left | binary infix | greater than or equal |
+ |
5 | left | binary infix | addition |
- |
5 | left | binary infix | subtraction |
* |
4 | left | binary infix | multiplication |
.* |
4 | left | binary infix | elementwise multiplication |
/ |
4 | left | binary infix | (right) division |
./ |
4 | left | binary infix | elementwise division |
% |
4 | left | binary infix | modulus |
\ |
3 | left | binary infix | left division |
! |
2 | n/a | unary prefix | logical negation |
- |
2 | n/a | unary prefix | negation |
+ |
2 | n/a | unary prefix | promotion (no-op in Stan) |
^ |
1 | right | binary infix | exponentiation |
' |
0 | n/a | unary postfix | transposition |
() |
0 | n/a | prefix, wrap | function application |
[] |
0 | left | prefix, wrap | array, matrix indexing |
Other expression-forming operations, such as function application and subscripting bind more tightly than any of the arithmetic operations.
The precedence and associativity determine how expressions are interpreted. Because addition is left associative, the expression a + b + c
is interpreted as (a + b) + c
. Similarly, a / b * c
is interpreted as (a / b) * c
.
Because multiplication has higher precedence than addition, the expression a * b + c
is interpreted as (a * b) + c
and the expression a + b * c
is interpreted as a + (b * c)
. Similarly, 2 * x + 3 * - y
is interpreted as (2 * x) + (3 * (-y))
.
Transposition and exponentiation bind more tightly than any other arithmetic or logical operation. For vectors, row vectors, and matrices, -u'
is interpreted as -(u')
, u * v'
as u* (v')
, and u' * v
as (u') * v
. For integer and reals, -n ^ 3
is interpreted as -(n ^ 3)
.