From c519be2bac43aa8ccaa8d568c3bfafd311286a9f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 20 Mar 2013 21:19:16 +0100 Subject: [PATCH] Allow multiplication like binary operators to be applied on type couples supported by scalar_product_traits --- Eigen/src/Core/CwiseBinaryOp.h | 4 ++-- Eigen/src/Core/Functors.h | 13 +++++++------ Eigen/src/Core/products/CoeffBasedProduct.h | 2 +- Eigen/src/Core/util/Meta.h | 20 ++++++++++++++++---- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h index 686c2afa3..586f77aaf 100644 --- a/Eigen/src/Core/CwiseBinaryOp.h +++ b/Eigen/src/Core/CwiseBinaryOp.h @@ -94,8 +94,8 @@ struct traits > // 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. #define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ - EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex::ret \ - ? int(internal::is_same::Real, typename NumTraits::Real>::value) \ + EIGEN_STATIC_ASSERT((internal::functor_is_product_like::ret \ + ? int(internal::scalar_product_traits::Defined) \ : int(internal::is_same::value)), \ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) diff --git a/Eigen/src/Core/Functors.h b/Eigen/src/Core/Functors.h index 147df3a50..0ab767f30 100644 --- a/Eigen/src/Core/Functors.h +++ b/Eigen/src/Core/Functors.h @@ -648,13 +648,14 @@ template struct linspaced_op template struct functor_has_linear_access { enum { ret = 1 }; }; template struct 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. +// 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. // FIXME move this to functor_traits adding a functor_default -template struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; }; -template struct functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; -template struct functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; -template struct functor_allows_mixing_real_and_complex > { enum { ret = 1 }; }; +template struct functor_is_product_like { enum { ret = 0 }; }; +template struct functor_is_product_like > { enum { ret = 1 }; }; +template struct functor_is_product_like > { enum { ret = 1 }; }; +template struct functor_is_product_like > { enum { ret = 1 }; }; /** \internal diff --git a/Eigen/src/Core/products/CoeffBasedProduct.h b/Eigen/src/Core/products/CoeffBasedProduct.h index 403d25fa9..c06a0df1c 100644 --- a/Eigen/src/Core/products/CoeffBasedProduct.h +++ b/Eigen/src/Core/products/CoeffBasedProduct.h @@ -150,7 +150,7 @@ class CoeffBasedProduct { // we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable. // We still allow to mix T and complex. - EIGEN_STATIC_ASSERT((internal::is_same::value), + EIGEN_STATIC_ASSERT((internal::scalar_product_traits::Defined), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) eigen_assert(lhs.cols() == rhs.rows() && "invalid matrix product" diff --git a/Eigen/src/Core/util/Meta.h b/Eigen/src/Core/util/Meta.h index a5f31164d..71d587108 100644 --- a/Eigen/src/Core/util/Meta.h +++ b/Eigen/src/Core/util/Meta.h @@ -186,23 +186,35 @@ template class 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 scalar_product_traits; +template struct scalar_product_traits +{ + enum { Defined = 0 }; +}; template struct scalar_product_traits { - //enum { Cost = NumTraits::MulCost }; + enum { + // Cost = NumTraits::MulCost, + Defined = 1 + }; typedef T ReturnType; }; template struct scalar_product_traits > { - //enum { Cost = 2*NumTraits::MulCost }; + enum { + // Cost = 2*NumTraits::MulCost, + Defined = 1 + }; typedef std::complex ReturnType; }; template struct scalar_product_traits, T> { - //enum { Cost = 2*NumTraits::MulCost }; + enum { + // Cost = 2*NumTraits::MulCost, + Defined = 1 + }; typedef std::complex ReturnType; };