This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Wrong result of scalar * vector multiplication.

Tags: None
(comma "," separated)
Oxyd
Registered Member
Posts
14
Karma
0
OS
Hi. I've got the following testcase:
Code: Select all
#include <Eigen/Core>
#include <iostream>

template <typename T>
struct foo {
  foo(T t) : t(t) { }
  operator T () { return t; }
  T t;
};

int main() {
  foo<Eigen::Vector3d> f(Eigen::Vector3d(1.0, 1.0, 1.0));
  std::cout << (0.5 * f) << '\n';
}

It produces the following output:
Code: Select all
-1.55252e+231
-1.55252e+231
-1.55252e+231

That is clearly the wrong answer (I'm expecting the vector (0.5, 0.5, 0.5)^T). I can reproduce this problem with GCC 4.7.0 (Fedora 17) with Eigen 3.1.1, and with GCC 4.6.3 (Ubuntu 12.04) with Eigen 3.0.5. Making foo a non-template, replacing all T's for Eigen::Vector3, results in “error: no match for ‘operator*’ in ‘5.0e-1 * f’”. Since I have been unable to reproduce this problem without Eigen, I assume this must be something to do with Eigen or with my using Eigen.

So – does anyone have an idea what might be wrong here?

Thanks.
John Jumper
Registered Member
Posts
3
Karma
0
If you replace the last line with "std::cout << (0.5 * Eigen::Vector3d(f)) << '\n';" the problem goes away. The is something strange occurring in your implicit cast (implicit casts should be avoided IMHO).
Oxyd
Registered Member
Posts
14
Karma
0
OS
Indeed, with an explicit conversion it works. There can't be much wrong going on in the implicit conversion function, as it's just a simple return of a copy of a vector. The problem must be in the interaction of this implicit conversion with the rest of Eigen. I'm still wondering what kind of interaction that is. :-\
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
To be honest I'm surprised this does compile. It seems the cast operator is implicitly called only for a scalar multiple product, not for other operators involving a foo<> and a Vector3d. I also cannot reproduce the error with clang. Returning a const reference also fixes the issue.
Oxyd
Registered Member
Posts
14
Karma
0
OS
I agree, this code probably shouldn't compile. I dug into it, and didn't really find a reason why it compiles at all. I tried explicitely calling op *, using Eigen::operator * (0.5, f), but that failed to compile. Yet, tracing through a debugger, I can clearly see Eigen::operator * (Scalar, Eigen::MatrixBase<Eigen::Matrix<…> >::StorageBaseType const&) called.

Unfortunately, I haven't been able to isolate those parts of Eigen that make this compile either.

It's strange you haven't reproduced the problem with Clang, though. I have been able to reproduce it with Clang 3.0 and Microsoft's Visual C++ 2010.

Also, from my debugging, I learned that what happens is roughly the following: operator T () gets called, and the vector gets copied. Then Eigen::op * (Scalar, Matrix) is called, which in turn calls Eigen::Matrix::operator * (Scalar). Then an object of type CwiseUnaryOp gets created which is supposed to contain the vector – however, the Matrix instance inside CwiseUnaryOp (m_xpr member) appears to be uninitialized – it also appears to have a different address from that copy that was created by calling operator T (). Then the product of 0.5 with this uninitialized matrix is computed and printed.


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Yahoo [Bot]