Reputation: 5393
I'm trying to use the Eigen3 library in a scientific program but I'm struggling to make some simple functions and member functions. For example, I'm not certain what kind of return type should I choose for something like the following:
template <typename DerivedA,typename DerivedB>
inline **something** mult(const MatrixBase<DerivedA>& p1,
const MatrixBase<DerivedB>& p2)
{
return p1*p2;
}
I assume that there is some class, say productOp
, that I could return without a problem. I still could not imagine what would happen in a function involving a large number of operations, or even worse, an iteration that depends on the input:
template <typename Derived>
**something** foo(const MatrixBase<Derived>& p1))
{
**something** p2;
p2.setZero();
while(p2(0,0) < 1)
p2 += p1;
return p2;
}
My questions are:
p1*p2
?Upvotes: 5
Views: 844
Reputation: 29205
In the first example, returning auto
will works well because it is a single expression that does not reference any local temporary.
In the second, you need to create and return an actual matrix/vector with its own storage, for instance:
typename Derived::PlainObject p2;
p2.resizeLike(p1);
and the return type will be typename Derived::PlainObject
.
Upvotes: 3
Reputation: 18807
Here is a manual solution for the first expression, in case you don't want to use C++11 or you want to be sure that the expression is actually evaluated:
template<class DerivedA, class DerivedB>
Eigen::Matrix<typename Eigen::ScalarBinaryOpTraits<typename DerivedA::Scalar, typename DerivedB::Scalar>::ReturnType,
DerivedA::RowsAtCompileTime, DerivedB::ColsAtCompileTime>
mult(const Eigen::MatrixBase<DerivedA>& p1, const Eigen::MatrixBase<DerivedB>& p2)
{
return p1*p2;
}
ScalarBinarayOpTraits
is used to determine if two different scalar types can be combined (e.g., double
and std::complex<double>
).
Example usage:
Eigen::Matrix3Xcd M1 = mult(Eigen::Matrix3d(), Eigen::Matrix3Xcd(3,20));
This is also safer, if you pass temporary objects to mult
and store the result in an auto
variable, e.g.:
double *someData = ...;
Eigen::MatrixXd someMatrix = ...;
auto result = mult(Eigen::Matrix3d::Map(someData), someMatrix.topLeftCorner<3,4>());
For the second example, as ggael wrote typename Derived::PlainObject
would be sufficient. And you can use p2.setZero(p1.rows(), p2.cols()); to initialize
p2`;
Upvotes: 1
Reputation: 180500
One thing you could do if the documentation does not like auto
for the return type is use trailing return type and get they type of DerivedA * DerivedB
. That would look like
inline auto mult(...) -> MatrixBase<decltype(std::declval<DerivedA>() * std::decval<DerivedB>())>
Upvotes: 1