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)
.