Generalize ScalarBinaryOpTraits to any complex-real combination as defined by NumTraits (instead of supporting std::complex only).

This commit is contained in:
Gael Guennebaud 2016-09-06 17:23:15 +02:00
parent 447f269561
commit 85fb517eaf
2 changed files with 23 additions and 13 deletions

View File

@ -255,6 +255,9 @@ private:
static inline std::string quiet_NaN();
};
// Empty specialization for void to allow template specialization based on NumTraits<T>::Real with T==void and SFINAE.
template<> struct NumTraits<void> {};
} // end namespace Eigen
#endif // EIGEN_NUMTRAITS_H

View File

@ -707,7 +707,7 @@ std::string demangle_flags(int f)
* This class permits to control the scalar return type of any binary operation performed on two different scalar types through (partial) template specializations.
*
* For instance, let \c U1, \c U2 and \c U3 be three user defined scalar types for which most operations between instances of \c U1 and \c U2 returns an \c U3.
* You can let Eigen knows that by defining:
* You can let %Eigen knows that by defining:
\code
template<typename BinaryOp>
struct ScalarBinaryOpTraits<U1,U2,BinaryOp> { typedef U3 ReturnType; };
@ -725,6 +725,14 @@ std::string demangle_flags(int f)
struct ScalarBinaryOpTraits<U1,U2,internal::scalar_sum_op<U1,U2> > { typedef U1 ReturnType; };
\endcode
*
* By default, the following generic combinations are supported:
<table class="manual">
<tr><th>ScalarA</th><th>ScalarB</th><th>BinaryOp</th><th>ReturnType</th><th>Note</th></tr>
<tr ><td>\c T </td><td>\c T </td><td>\c * </td><td>\c T </td><td></td></tr>
<tr class="alt"><td>\c NumTraits<T>::Real </td><td>\c T </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
<tr ><td>\c T </td><td>\c NumTraits<T>::Real </td><td>\c * </td><td>\c T </td><td>Only if \c NumTraits<T>::IsComplex </td></tr>
</table>
*
* \sa CwiseBinaryOp
*/
template<typename ScalarA, typename ScalarB, typename BinaryOp=internal::scalar_product_op<ScalarA,ScalarB> >
@ -741,6 +749,17 @@ struct ScalarBinaryOpTraits<T,T,BinaryOp>
typedef T ReturnType;
};
template <typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<T, typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, BinaryOp>
{
typedef T ReturnType;
};
template <typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<typename NumTraits<typename internal::enable_if<NumTraits<T>::IsComplex,T>::type>::Real, T, BinaryOp>
{
typedef T ReturnType;
};
// For Matrix * Permutation
template<typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<T,void,BinaryOp>
@ -762,18 +781,6 @@ struct ScalarBinaryOpTraits<void,void,BinaryOp>
typedef void ReturnType;
};
template<typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<T,std::complex<T>,BinaryOp>
{
typedef std::complex<T> ReturnType;
};
template<typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<std::complex<T>, T,BinaryOp>
{
typedef std::complex<T> ReturnType;
};
// We require Lhs and Rhs to have "compatible" scalar types.
// 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