
Hi Emil, I am trying qvm in a small project that uses complex numbers and have expressions of the kind : cv3 = c1*rv3_1 + c2*rv3_2 (the v3's are vectors, the c's are complex and the r's are real). I wrote it as : cv3 = scalar_cast<complex>(rv3_1)*c1 + scalar_cast<complex>(rv3_2)*c2; but this seems to invoke 6 complex constructors (unnecessarily) I have not tested to see if the constructors will be optimized away, but it seems to me that if : v_traits<vector_scalar_cast_>::scalar_type == complex , bit v_traits<vector_scalar_cast_>::r/ir return real the expression will compile and no complex constructors will be invoked. It seems to me that there is a need for another kind of scalar_cast that just adapts the v_traits<>:scalar_type but leaves the r() and ir() unchanged Another question I have is if there is a reason why vector*scalar works but scalar*vector does not? Thanks in advance, Nikolay PS I can send patches if you'd like.

On Sat, Nov 3, 2012 at 4:00 PM, Nikolay Mladenov <nikolay.mladenov@gmail.com> wrote:
I am trying qvm in a small project that uses complex numbers and have expressions of the kind : cv3 = c1*rv3_1 + c2*rv3_2 (the v3's are vectors, the c's are complex and the r's are real).
I wrote it as :
cv3 = scalar_cast<complex>(rv3_1)*c1 + scalar_cast<complex>(rv3_2)*c2;
but this seems to invoke 6 complex constructors (unnecessarily) I have not tested to see if the constructors will be optimized away, but it seems to me that if : v_traits<vector_scalar_cast_>::scalar_type == complex , bit v_traits<vector_scalar_cast_>::r/ir return real the expression will compile and no complex constructors will be invoked.
If I understand correctly, you mean that if a complex can be implicitly constructed from a float, then r/ir can return float and it'll all work. I don't think that it is a safe assumption to make in general, that any scalar type would define a suitable implicit constructor. That said, it might be a good idea to specify in the documentation that the return value from r/ir must be implicitly convertible to ::scalar_type, which would allow a partial specialization for your complex type of the vector_scalar_cast_ and the other related scalar_cast type templates. Are you willing to give this a try? (As for scalar multiplication requiring the scalar on the right, you're right it should work from the left too.) Thanks, Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Mon, Nov 5, 2012 at 4:38 PM, Emil Dotchevski <emildotchevski@gmail.com>wrote:
On Sat, Nov 3, 2012 at 4:00 PM, Nikolay Mladenov <nikolay.mladenov@gmail.com> wrote:
I am trying qvm in a small project that uses complex numbers and have expressions of the kind : cv3 = c1*rv3_1 + c2*rv3_2 (the v3's are vectors, the c's are complex and the r's are real).
I wrote it as :
cv3 = scalar_cast<complex>(rv3_1)*c1 + scalar_cast<complex>(rv3_2)*c2;
but this seems to invoke 6 complex constructors (unnecessarily) I have not tested to see if the constructors will be optimized away, but it seems to me that if : v_traits<vector_scalar_cast_>::scalar_type == complex , bit v_traits<vector_scalar_cast_>::r/ir return real the expression will compile and no complex constructors will be invoked.
If I understand correctly, you mean that if a complex can be implicitly constructed from a float, then r/ir can return float and it'll all work. I don't think that it is a safe assumption to make in general, that any scalar type would define a suitable implicit constructor.
No. the reason it works is because (i'll use [i] for indexing) rv1[0]*c1+rv2[0]*c2 is well defined linear combination of two complex numbers with real coefficients the cast is only needed to force rv3_1*c1 's result to be complex ( the default operator tries to build result with the same scalar type as the rv3_1) no implicit conversions or constructions are needed to calculate the result. it is almost as if operator * and / should have return type from the kind of deduce_v2<vec1, scalar2>
That said, it might be a good idea to specify in the documentation that the return value from r/ir must be implicitly convertible to ::scalar_type, which would allow a partial specialization for your complex type of the vector_scalar_cast_ and the other related scalar_cast type templates. Are you willing to give this a try?
(As for scalar multiplication requiring the scalar on the right, you're right it should work from the left too.)
I think I understood the reason for the right only scalar multiplication: it is probably because scalar*vec%X will do multiple times the work of vec%X * scalar
Thanks, Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Mon, Nov 5, 2012 at 7:38 PM, Nikolay Mladenov <nikolay.mladenov@gmail.com> wrote:
it is almost as if operator * and / should have return type from the kind of deduce_v2<vec1, scalar2>
I think I got it. Incidentally, the documentation of deduce_v2 does indicate that either one of its input types may be a non-vector type, and that's precisely to support deducing the return type for operations between a vector and something else (say, a matrix.) It appears that your observation is correct, and that vector*scalar should also use deduce_v2 to figure out its return type. Can you make this change and see if it'll work with the rest of the library? If all is well, I'll merge it back into the next release.
I think I understood the reason for the right only scalar multiplication: it is probably because scalar*vec%X will do multiple times the work of vec%X * scalar
I thought about that but it wasn't my reasoning. I decided not to define scalar multiplication on either side because I thought it isn't _needed_. Having done that, I've been confused myself when I get compile errors multiplying scalars on the left, so this is on my list of things to be fixed. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
participants (2)
-
Emil Dotchevski
-
Nikolay Mladenov