From 98ff17eb9e70ad62a2dad2eaee2900eb2f110720 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 26 Jun 2015 16:08:15 +0200 Subject: [PATCH] Add special path for matrix/real. This also fixes underflow issues when scaling complex matrices through complex/complex operator. --- Eigen/src/Core/DenseBase.h | 2 ++ Eigen/src/Core/MatrixBase.h | 1 + Eigen/src/Core/functors/BinaryFunctors.h | 12 ++++++++++++ Eigen/src/Core/util/ForwardDeclarations.h | 1 + Eigen/src/Core/util/XprHelper.h | 14 +++++++++++++- test/linearstructure.cpp | 4 ++++ 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index e7370da96..d486f3fd5 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -49,6 +49,8 @@ template class DenseBase public: using internal::special_scalar_op_base::Scalar, typename NumTraits::Scalar>::Real>::operator*; + using internal::special_scalar_op_base::Scalar, + typename NumTraits::Scalar>::Real>::operator/; /** Inner iterator type to iterate over the coefficients of a row or column. diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index c2a0d6d30..8549cf83c 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -81,6 +81,7 @@ template 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/functors/BinaryFunctors.h b/Eigen/src/Core/functors/BinaryFunctors.h index 85e605889..5dee6247e 100644 --- a/Eigen/src/Core/functors/BinaryFunctors.h +++ b/Eigen/src/Core/functors/BinaryFunctors.h @@ -392,6 +392,18 @@ template struct functor_traits > { enum { Cost = 2 * NumTraits::MulCost, PacketAccess = packet_traits::HasDiv }; }; +template +struct scalar_quotient2_op { + typedef typename scalar_product_traits::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const scalar_quotient2_op& other) : m_other(other.m_other) { } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const Scalar2& other) : m_other(other) { } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a / m_other; } + typename add_const_on_value_type::Nested>::type m_other; +}; +template +struct functor_traits > +{ enum { Cost = 2 * NumTraits::MulCost, PacketAccess = false }; }; + // In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication // where the mixing of different types is handled by scalar_product_traits // In particular, real * complex is allowed. diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index ba75d25af..7c20fed5e 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -213,6 +213,7 @@ template struct scalar_identity_op; template struct scalar_product_op; template struct scalar_multiple2_op; template struct scalar_quotient_op; +template struct scalar_quotient2_op; } // end namespace internal diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index 2cd78576e..8c280432b 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -427,7 +427,9 @@ struct special_scalar_op_base : public DenseCoeffsBase { // dummy operator* so that the // "using special_scalar_op_base::operator*" compiles - void operator*() const; + struct dummy {}; + void operator*(dummy) const; + void operator/(dummy) const; }; template @@ -451,6 +453,16 @@ struct special_scalar_op_base : public DenseCo #endif return static_cast(matrix).operator*(scalar); } + + const CwiseUnaryOp, Derived> + operator/(const OtherScalar& scalar) const + { +#ifdef EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN + EIGEN_SPECIAL_SCALAR_MULTIPLE_PLUGIN +#endif + return CwiseUnaryOp, Derived> + (*static_cast(this), scalar_quotient2_op(scalar)); + } }; template struct cast_return_type diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp index 8e3cc9a86..3c7cdbe41 100644 --- a/test/linearstructure.cpp +++ b/test/linearstructure.cpp @@ -88,6 +88,10 @@ template void real_complex(DenseIndex rows = MatrixType::Ro g_called = false; VERIFY_IS_APPROX(m1*s, m1*Scalar(s)); VERIFY(g_called && "matrix * real not properly optimized"); + + g_called = false; + VERIFY_IS_APPROX(m1/s, m1/Scalar(s)); + VERIFY(g_called && "matrix / real not properly optimized"); } void test_linearstructure()