I want to pointwise multiply the each row of a matrix by a vector which can easily be done with broadcasting as `A.rowwise() * a.transpose()` (where `A` and `a` are appropriately defined). However, the mathematically equivalent expression `a.transpose * A.rowwise()` results in a compilation error saying that `operator*` is not defined for the types involved. From Bug 157 it looks like the operator is just not implemented with the visitor on the right rather than a shortcoming of the expression generation. However, this seems like a pretty high-priority issue to address since the expressions are mathematically the same and it seems ridiculous that people are forced to write them one way. If these missing cases cannot be implemented then at the very least there should be clear documentation in the broadcasting section on this.
Conceptually it is usually better to express this kind of operation as a non uniform scaling through the product with a diagonal matrix: A * a.asDiagonal(); This is much closer to what you would write in a formula, and the generated code will be the same. Regarding rowwise/colwise, the asymmetry is on purpose. A.rowwise() followed by something has to be read as for row of A do something. So I wonder whether adding what you suggest would not be counter-productive.
I'm not really sure what you intend to do. If `A` is a matrix and `a` a column vector, then the operation should not work according to the docu. Maybe both are actually arrays? ('pointwise multiply' suggests they are). Generally, I would read `A.rowwise() OPERATOR B` as `A rowwiseOperator B`, which I would interpret as (assuming all sizes are appropriate): for(int r=0; r<A.rows(); ++r) result.row(r) = A.row(r) OPERATOR a; Allowing your suggestion will likely lead to strange behavior if you write strange expressions such as A OPERATOR B.rowwise() OPERATOR C; which operation is rowwise? Shall there be a runtime error if sizes don't fit? If you really like to swap the order of `A` and `a` in your example, you can use some kind of .replicate() syntax instead. However, I am totally open for any clarifications in the documentation. Perhaps adding something to http://eigen.tuxfamily.org/dox-devel/group__TutorialReductionsVisitorsBroadcasting.html or linking to that page more prominently.
The asDiagonal suggestion would be fine, but it doesn't work for Arrays. If it's a design decision that the visitor needs to come first then this needs to be prominently documented. Regarding the example of strange behavior from strange expressions, I'm not sure why the behavior would be strange. Operator precedence will determine an evaluation of the expression, it may not be what the user wanted, but that's what parentheses are for. Maybe replicate should be linked from the broadcasting section so that people are aware it can be useful for broadcasting. It's fine if Eigen deviates from math, but these deviations need to be clearly documented.
Christoph expressed in a better way what I wanted to say. OK to improve the doc.
(In reply to nfoti01 from comment #3) > The asDiagonal suggestion would be fine, but it doesn't work for Arrays. If > it's a design decision that the visitor needs to come first then this needs > to be prominently documented. Yes, asDiagonal() only works for matrices, but you asked about matrix and vector in your first post (thus our confusion). > Regarding the example of strange behavior from strange expressions, I'm not > sure why the behavior would be strange. Operator precedence will determine > an evaluation of the expression, it may not be what the user wanted, but > that's what parentheses are for. Sure, in C++ multiplication is left-associative, so there is no ambiguity. But mathematically multiplication is (usually) associative, so it would be confusing if (A*B.rowwise())*C results in a run-time error, whereas A*(B.rowwise()*C) works. > Maybe replicate should be linked from the > broadcasting section so that people are aware it can be useful for > broadcasting. Adding information about replicate is definitely a good idea. > It's fine if Eigen deviates from math, but these deviations need to be > clearly documented. The rowwise()/colwise() broadcasting alone is an extension of Eigen -- in "math", I would usually write it with some indexed expression, i.e. R_{ij}=A_{ij}*a_j for R=A.rowwise()*a.
-- GitLab Migration Automatic Message -- This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/906.