bug #1484: restore deleted line for 128 bits long doubles, and improve dispatching logic.

(grafted from 0a1cc7394226c7439b586f5bac3e94cf287622f1
)
This commit is contained in:
Gael Guennebaud 2017-11-10 10:25:41 +01:00
parent 7a875acfb0
commit c8e663fe87

View File

@ -326,6 +326,7 @@ struct matrix_exp_computeUV<MatrixType, long double>
} else if (l1norm < 1.125358383453143065081397882891878e+000L) { } else if (l1norm < 1.125358383453143065081397882891878e+000L) {
matrix_exp_pade13(arg, U, V); matrix_exp_pade13(arg, U, V);
} else { } else {
const long double maxnorm = 2.884233277829519311757165057717815L;
frexp(l1norm / maxnorm, &squarings); frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0; if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings)); MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings));
@ -342,25 +343,17 @@ struct matrix_exp_computeUV<MatrixType, long double>
} }
}; };
template<typename T> struct is_exp_known_type : false_type {};
template<> struct is_exp_known_type<float> : true_type {};
template<> struct is_exp_known_type<double> : true_type {};
#if LDBL_MANT_DIG <= 112
template<> struct is_exp_known_type<long double> : true_type {};
#endif
/* Computes the matrix exponential
*
* \param arg argument of matrix exponential (should be plain object)
* \param result variable in which result will be stored
*/
template <typename ArgType, typename ResultType> template <typename ArgType, typename ResultType>
void matrix_exp_compute(const ArgType& arg, ResultType &result) void matrix_exp_compute(const ArgType& arg, ResultType &result, true_type) // natively supported scalar type
{ {
typedef typename ArgType::PlainObject MatrixType; typedef typename ArgType::PlainObject MatrixType;
#if LDBL_MANT_DIG > 112 // rarely happens
typedef typename traits<MatrixType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
if (sizeof(RealScalar) > 14) {
result = arg.matrixFunction(internal::stem_function_exp<ComplexScalar>);
return;
}
#endif
MatrixType U, V; MatrixType U, V;
int squarings; int squarings;
matrix_exp_computeUV<MatrixType>::run(arg, U, V, squarings); // Pade approximant is (U+V) / (-U+V) matrix_exp_computeUV<MatrixType>::run(arg, U, V, squarings); // Pade approximant is (U+V) / (-U+V)
@ -371,6 +364,22 @@ void matrix_exp_compute(const ArgType& arg, ResultType &result)
result *= result; // undo scaling by repeated squaring result *= result; // undo scaling by repeated squaring
} }
/* Computes the matrix exponential
*
* \param arg argument of matrix exponential (should be plain object)
* \param result variable in which result will be stored
*/
template <typename ArgType, typename ResultType>
void matrix_exp_compute(const ArgType& arg, ResultType &result, false_type) // default
{
typedef typename ArgType::PlainObject MatrixType;
typedef typename traits<MatrixType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
result = arg.matrixFunction(internal::stem_function_exp<ComplexScalar>);
}
} // end namespace Eigen::internal } // end namespace Eigen::internal
/** \ingroup MatrixFunctions_Module /** \ingroup MatrixFunctions_Module
@ -402,7 +411,7 @@ template<typename Derived> struct MatrixExponentialReturnValue
inline void evalTo(ResultType& result) const inline void evalTo(ResultType& result) const
{ {
const typename internal::nested_eval<Derived, 10>::type tmp(m_src); const typename internal::nested_eval<Derived, 10>::type tmp(m_src);
internal::matrix_exp_compute(tmp, result); internal::matrix_exp_compute(tmp, result, internal::is_exp_known_type<typename Derived::Scalar>());
} }
Index rows() const { return m_src.rows(); } Index rows() const { return m_src.rows(); }