diff --git a/Eigen/src/Core/Cwise.h b/Eigen/src/Core/Cwise.h index 7c935a9ac..a04fff3db 100644 --- a/Eigen/src/Core/Cwise.h +++ b/Eigen/src/Core/Cwise.h @@ -31,6 +31,18 @@ #define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \ CwiseBinaryOp::Scalar>, ExpressionType, OtherDerived> +#define EIGEN_CWISE_PRODUCT_RETURN_TYPE \ + CwiseBinaryOp< \ + ei_scalar_product_op< \ + typename ei_scalar_product_traits< \ + typename ei_traits::Scalar, \ + typename ei_traits::Scalar \ + >::ReturnType \ + >, \ + ExpressionType, \ + OtherDerived \ + > + /** \internal * convenient macro to defined the return type of a cwise unary operation */ #define EIGEN_CWISE_UNOP_RETURN_TYPE(OP) \ @@ -74,7 +86,7 @@ template class Cwise inline const ExpressionType& _expression() const { return m_matrix; } template - const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op) + const EIGEN_CWISE_PRODUCT_RETURN_TYPE operator*(const MatrixBase &other) const; template diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h index 834a9b820..87d7123dd 100644 --- a/Eigen/src/Core/CwiseBinaryOp.h +++ b/Eigen/src/Core/CwiseBinaryOp.h @@ -54,7 +54,6 @@ struct ei_traits > typename Rhs::Scalar ) >::type Scalar; - typedef typename Lhs::Nested LhsNested; typedef typename Rhs::Nested RhsNested; typedef typename ei_unref::type _LhsNested; @@ -99,7 +98,9 @@ class CwiseBinaryOp : ei_no_assignment_operator, // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to // add together a float matrix and a double matrix. - EIGEN_STATIC_ASSERT((ei_is_same_type::ret), + EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex::ret + ? int(ei_is_same_type::ret) + : int(ei_is_same_type::ret)), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) // require the sizes to match EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) @@ -202,10 +203,10 @@ MatrixBase::operator+=(const MatrixBase& other) */ template template -EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op) +EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE Cwise::operator*(const MatrixBase &other) const { - return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_product_op)(_expression(), other.derived()); + return EIGEN_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived()); } /** \returns an expression of the coefficient-wise quotient of *this and \a other diff --git a/Eigen/src/Core/Functors.h b/Eigen/src/Core/Functors.h index 6784ea946..347f1b252 100644 --- a/Eigen/src/Core/Functors.h +++ b/Eigen/src/Core/Functors.h @@ -348,11 +348,15 @@ template struct ei_functor_traits > { enum { Cost = NumTraits::AddCost, PacketAccess = false, IsRepeatable = true }; }; -// FIXME quick hack: // all functors allow linear access, except ei_scalar_identity_op. So we fix here a quick meta // to indicate whether a functor allows linear access, just always answering 'yes' except for // ei_scalar_identity_op. template struct ei_functor_has_linear_access { enum { ret = 1 }; }; template struct ei_functor_has_linear_access > { enum { ret = 0 }; }; +// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication +// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex. +template struct ei_functor_allows_mixing_real_and_complex { enum { ret = 0 }; }; +template struct ei_functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; + #endif // EIGEN_FUNCTORS_H diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index 97535caa1..c65c52ef4 100644 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -69,7 +69,7 @@ template struct ei_cleantype { typedef typename ei_cleant * * It supports both the current STL mechanism (using the result_type member) as well as * upcoming next STL generation (using a templated result member). - * If none of these members is provided, then the type of the first argument is returned. + * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack. */ template struct ei_result_of {}; @@ -146,4 +146,38 @@ class ei_meta_sqrt template class ei_meta_sqrt { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; }; +/** \internal determines whether the product of two numeric types is allowed and what the return type is */ +template struct ei_scalar_product_traits +{ + // dummy general case where T and U aren't compatible -- not allowed anyway but we catch it elsewhere + //enum { Cost = NumTraits::MulCost }; + typedef T ReturnType; +}; + +template struct ei_scalar_product_traits +{ + //enum { Cost = NumTraits::MulCost }; + typedef T ReturnType; +}; + +template struct ei_scalar_product_traits > +{ + //enum { Cost = 2*NumTraits::MulCost }; + typedef std::complex ReturnType; +}; + +template struct ei_scalar_product_traits, T> +{ + //enum { Cost = 2*NumTraits::MulCost }; + typedef std::complex ReturnType; +}; + +// FIXME quick workaround around current limitation of ei_result_of +template +struct ei_result_of(ArgType0,ArgType1)> { +typedef typename ei_scalar_product_traits::type, typename ei_cleantype::type>::ReturnType type; +}; + + + #endif // EIGEN_META_H