diff options
author | Gael Guennebaud <g.gael@free.fr> | 2014-09-02 14:41:14 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2014-09-02 14:41:14 +0200 |
commit | 3eb5253ca1352391f4ea31c4a2dd06c34c4a33e7 (patch) | |
tree | 841bbcfca8d5e802635d1c04cd78c84807290d58 | |
parent | 305aa1f9c570db60a92e49020f21e70311bbed36 (diff) |
Optimization: "matrix<complex> * real" did not call the special path and the real was converted to a complex. Add respective unit test to avoid future regression.
-rw-r--r-- | Eigen/src/Core/MatrixBase.h | 1 | ||||
-rw-r--r-- | Eigen/src/Core/util/XprHelper.h | 10 | ||||
-rw-r--r-- | test/linearstructure.cpp | 26 |
3 files changed, 36 insertions, 1 deletions
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index f5987d194..3cb5e04fd 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -81,6 +81,7 @@ template<typename Derived> class MatrixBase using Base::operator-=; using Base::operator*=; using Base::operator/=; + using Base::operator*; typedef typename Base::CoeffReturnType CoeffReturnType; typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index 1b3e122e1..7c77b2263 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -383,13 +383,21 @@ struct special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public DenseCo const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> operator*(const OtherScalar& scalar) const { +#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN + EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN +#endif return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar)); } inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived> operator*(const OtherScalar& scalar, const Derived& matrix) - { return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); } + { +#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN + EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN +#endif + return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); + } }; template<typename XprType, typename CastType> struct cast_return_type diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp index 618984d5c..b627915ce 100644 --- a/test/linearstructure.cpp +++ b/test/linearstructure.cpp @@ -2,11 +2,16 @@ // for linear algebra. // // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> +// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +static bool g_called; + +#define EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN { g_called = true; } + #include "main.h" template<typename MatrixType> void linearStructure(const MatrixType& m) @@ -68,6 +73,24 @@ template<typename MatrixType> void linearStructure(const MatrixType& m) VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1); } +// Make sure that complex * real and real * complex are properly optimized +template<typename MatrixType> void real_complex(DenseIndex rows = MatrixType::RowsAtCompileTime, DenseIndex cols = MatrixType::ColsAtCompileTime) +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + + RealScalar s = internal::random<RealScalar>(); + MatrixType m1 = MatrixType::Random(rows, cols); + + g_called = false; + VERIFY_IS_APPROX(s*m1, Scalar(s)*m1); + VERIFY(g_called && "real * matrix<complex> not properly optimized"); + + g_called = false; + VERIFY_IS_APPROX(m1*s, m1*Scalar(s)); + VERIFY(g_called && "matrix<complex> * real not properly optimized"); +} + void test_linearstructure() { for(int i = 0; i < g_repeat; i++) { @@ -80,5 +103,8 @@ void test_linearstructure() CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) ); CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) ); CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) ); + + CALL_SUBTEST_10( real_complex<Matrix4cd>() ); + CALL_SUBTEST_10( real_complex<MatrixXcf>(10,10) ); } } |