---------------------------
A' transpose
---------------------------
-A negate
---------------------------
A * B product
A .* B element-wise product
A ./ B element-wise division
---------------------------
A + B sum
A - B difference
---------------------------
This includes all types that are appropriate. The
result is the minimal type that can be inferred from
the type of the arguments.
So you can write multivariate expressions like:
(mu - y)' * Sigma * (mu - y)
and
sigma * Omega * sigma'
I'm going to doc this on an op-by-op basis. Product's
the worst:
(real * real) : real
(real * vector) : vector
(real * row_vector) : row_vector
(real * matrix) : matrix
(vector * real) : vector
(vector * row_vector) : matrix
(row_vector * real) : row_vector
(row_vector * vector) : real
(row_vector * matrix) : row_vector
(matrix * real) : matrix
(matrix * vector) : vector
(matrix * matrix) : matrix
And remember that int values are promoted to real where
necessary.
We'll catch as syntax errors, things like (matrix * row_vector).
Even though the sizes are dynamic and not type checked, we
don't allow this operation even if the matrix is (N x 1).
The only other op that seems reasonable to add is
power:
(real ^ real) : real (pow)
and matrix power:
(matrix ^ int) : matrix (matrix power)
and elementwise powers:
(matrix .^ real) : matrix
(vector .^ real) : vector
(row_vector .^ real) : row_vector
which has higher precedence than product.
No one seems to use an operator for inverse, but we
probably want to discourage it in favor of more
stable alternatives.
- Bob
P.S. Math terminology quiz: Product is to multiplication
as ??? is to division?
Done. We now have, in groups of descending
precedence:
We'll catch as syntax errors, things like (matrix * row_vector).
Even though the sizes are dynamic and not type checked, we
don't allow this operation even if the matrix is (N x 1).
No one seems to use an operator for inverse, but we
probably want to discourage it in favor of more
stable alternatives.
P.S. Math terminology quiz: Product is to multiplication
as ??? is to division?
The main reason is to catch type errors in the programs
at compile time rather than run time.
The Eigen types implementing the basic types are:
vector_d ==> Eigen<double,Dynamic,1>
row_vector_d ==> Eigen<double,1,Dynamic>
matrix_d ==> Eigen<double,Dynamic,Dynamic>
with vector_v, row_vector_v, and matrix_v being the
same with double replaced by stan::agrad::var auto-dif
variables (Stan figures out which to use on a case-by-case
basis at compile time.)
Because Eigen specializes the class template for the
situation where one of the dimensions is 1, these are
really different types and behave differently (though
implement many of the same concepts, including matrix).
Eigen allows you to use a vector like a matrix, but
not vice versa, even if it has vector dimensions.
So if you declare a matrix variable
Eigen<double,Dynamic,Dynamic> v(5,1);
even though you have a (5 x 1) matrix, aka a vector, it
doesn't support vector operations like dot product that
are built into the specialized vector types.
I could allow the same thing as Eigen, and keep the one
way "vectors may be used as matrices, but not vice-versa",
but I thought it'd be cleaner just to fully separate
the types here. I think that makes more sense for the kind
of models we foresee people building.
Having said that, we could support lifting of vectors
to matrices:
to_matrix(vector) : matrix
to_matrix(row_vector) : matrix
which would always work. The other way around could
throw runtime errors if the dimensions are wrong:
to_vector(matrix) : vector
to_row_vector(matrix) : row_vector
When in doubt, I tend to go with "don't include it" and
"be strict in the syntax".
> No one seems to use an operator for inverse, but we
> probably want to discourage it in favor of more
> stable alternatives.
>
>
> Matlab uses \ and / to denote the solution of linear systems, i.e., x =
> A\b. It helps to discourage people doing things like x = inv(A)*b.
Cool. That'd be easy to add and potentially useful.
Is the operation left associative at the same precedence
as multiplication.
a / b * c == (a / b) * c
a * b / c == (a * b) / c
That is, do we have:
A \ b * C == (A \ b) * C
C * A \ b == (C * A) \ b
Does anyone ever use the rightward version?
b / A == b * inv(A)
and does it have the precednece I'd expect
C * b / A == (C * b) / A
b / A * C == (b / A) * C
This is bringing back my algebra days -- I used left and
right residuals in the string semigroup for models of natural
language syntax (categorial grammars based on some algebraic
work of Lambek in the 1950s). I didn't realize they were
used for matrices.
> P.S. Math terminology quiz: Product is to multiplication
> as ??? is to division?
>
>
> Quotient?
Thanks. I couldn't think of that word for the life of me.
And more seriously, thanks for the technical input.
- Bob
Having said that, we could support lifting of vectors
to matrices:
to_matrix(vector) : matrix
to_matrix(row_vector) : matrix
which would always work. The other way around could
throw runtime errors if the dimensions are wrong:
to_vector(matrix) : vector
to_row_vector(matrix) : row_vector
When in doubt, I tend to go with "don't include it" and
"be strict in the syntax".
Cool. That'd be easy to add and potentially useful.
No one seems to use an operator for inverse, but we
probably want to discourage it in favor of more
stable alternatives.
Matlab uses \ and / to denote the solution of linear systems, i.e., x =
A\b. It helps to discourage people doing things like x = inv(A)*b.
Is the operation left associative at the same precedence
as multiplication.
a / b * c == (a / b) * c
a * b / c == (a * b) / c
That is, do we have:
A \ b * C == (A \ b) * C
C * A \ b == (C * A) \ b
Does anyone ever use the rightward version?
b / A == b * inv(A)
and does it have the precednece I'd expect
C * b / A == (C * b) / A
b / A * C == (b / A) * C
This is bringing back my algebra days -- I used left and
right residuals in the string semigroup for models of natural
language syntax (categorial grammars based on some algebraic
work of Lambek in the 1950s). I didn't realize they were
used for matrices.
double b_0[N];
you want:
vector(N) b_0;
I'm just sitting down to write that section of the
manual! Things specified with [] are array types.
Some multi-variate ops are defined on arrays, but not
many.
- Bob