diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index ac79de66d..fd9577ca4 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -372,6 +372,16 @@ template class MatrixBase template void applyOnTheRight(int p, int q, const PlanarRotation& j); +///////// MatrixFunctions module ///////// + + typedef typename ei_stem_function::type StemFunction; + const MatrixExponentialReturnValue exp() const; + const MatrixFunctionReturnValue matrixFunction(StemFunction f) const; + const MatrixFunctionReturnValue cosh() const; + const MatrixFunctionReturnValue sinh() const; + const MatrixFunctionReturnValue cos() const; + const MatrixFunctionReturnValue sin() const; + #ifdef EIGEN2_SUPPORT template Derived& operator+=(const Flagged, 0, diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 129b78e6a..073366d73 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -167,6 +167,17 @@ template class Translation; template class UniformScaling; template class Homogeneous; +// MatrixFunctions module +template struct MatrixExponentialReturnValue; +template struct MatrixFunctionReturnValue; +template +struct ei_stem_function +{ + typedef std::complex::Real> ComplexScalar; + typedef ComplexScalar type(ComplexScalar, int); +}; + + #ifdef EIGEN2_SUPPORT template class Cwise; #endif diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h b/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h index 2c761e648..3ef91a7b2 100644 --- a/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h +++ b/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h @@ -290,8 +290,8 @@ void MatrixExponential::computeUV(double) * This class holds the argument to the matrix exponential until it * is assigned or evaluated for some other reason (so the argument * should not be changed in the meantime). It is the return type of - * ei_matrix_exponential() and most of the time this is the only way - * it is used. + * MatrixBase::exp() and most of the time this is the only way it is + * used. */ template struct MatrixExponentialReturnValue : public ReturnByValue > @@ -381,11 +381,10 @@ struct ei_traits > * \c complex or \c complex . */ template -MatrixExponentialReturnValue -ei_matrix_exponential(const MatrixBase &M) +const MatrixExponentialReturnValue MatrixBase::exp() const { - ei_assert(M.rows() == M.cols()); - return MatrixExponentialReturnValue(M.derived()); + ei_assert(rows() == cols()); + return MatrixExponentialReturnValue(derived()); } #endif // EIGEN_MATRIX_EXPONENTIAL diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h index e8069154c..72e42aa7c 100644 --- a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h +++ b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h @@ -59,7 +59,7 @@ class MatrixFunction * \param[out] result the function \p f applied to \p A, as * specified in the constructor. * - * See ei_matrix_function() for details on how this computation + * See MatrixBase::matrixFunction() for details on how this computation * is implemented. */ template @@ -486,8 +486,8 @@ typename MatrixFunction::DynMatrixType MatrixFunction class MatrixFunctionReturnValue : public ReturnByValue > @@ -533,6 +533,9 @@ struct ei_traits > }; +/********** MatrixBase methods **********/ + + /** \ingroup MatrixFunctions_Module * * \brief Compute a matrix function. @@ -571,7 +574,7 @@ struct ei_traits > * \end{array} \right]. \f] * This corresponds to a rotation of \f$ \frac14\pi \f$ radians around * the z-axis. This is the same example as used in the documentation - * of ei_matrix_exponential(). + * of MatrixBase::exp(). * * \include MatrixFunction.cpp * Output: \verbinclude MatrixFunction.out @@ -580,16 +583,14 @@ struct ei_traits > * \c x, even though the matrix \c A is over the reals. Instead of * \c expfn, we could also have used StdStemFunctions::exp: * \code - * ei_matrix_function(A, StdStemFunctions >::exp, &B); + * A.matrixFunction(StdStemFunctions >::exp, &B); * \endcode */ template -MatrixFunctionReturnValue -ei_matrix_function(const MatrixBase &M, - typename ei_stem_function::Scalar>::type f) +const MatrixFunctionReturnValue MatrixBase::matrixFunction(typename ei_stem_function::Scalar>::type f) const { - ei_assert(M.rows() == M.cols()); - return MatrixFunctionReturnValue(M.derived(), f); + ei_assert(rows() == cols()); + return MatrixFunctionReturnValue(derived(), f); } /** \ingroup MatrixFunctions_Module @@ -599,19 +600,17 @@ ei_matrix_function(const MatrixBase &M, * \param[in] M a square matrix. * \returns expression representing \f$ \sin(M) \f$. * - * This function calls ei_matrix_function() with StdStemFunctions::sin(). + * This function calls matrixFunction() with StdStemFunctions::sin(). * * \include MatrixSine.cpp * Output: \verbinclude MatrixSine.out */ template -MatrixFunctionReturnValue -ei_matrix_sin(const MatrixBase& M) +const MatrixFunctionReturnValue MatrixBase::sin() const { - ei_assert(M.rows() == M.cols()); - typedef typename ei_traits::Scalar Scalar; + ei_assert(rows() == cols()); typedef typename ei_stem_function::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue(M.derived(), StdStemFunctions::sin); + return MatrixFunctionReturnValue(derived(), StdStemFunctions::sin); } /** \ingroup MatrixFunctions_Module @@ -621,18 +620,16 @@ ei_matrix_sin(const MatrixBase& M) * \param[in] M a square matrix. * \returns expression representing \f$ \cos(M) \f$. * - * This function calls ei_matrix_function() with StdStemFunctions::cos(). + * This function calls matrixFunction() with StdStemFunctions::cos(). * * \sa ei_matrix_sin() for an example. */ template -MatrixFunctionReturnValue -ei_matrix_cos(const MatrixBase& M) +const MatrixFunctionReturnValue MatrixBase::cos() const { - ei_assert(M.rows() == M.cols()); - typedef typename ei_traits::Scalar Scalar; + ei_assert(rows() == cols()); typedef typename ei_stem_function::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue(M.derived(), StdStemFunctions::cos); + return MatrixFunctionReturnValue(derived(), StdStemFunctions::cos); } /** \ingroup MatrixFunctions_Module @@ -642,19 +639,17 @@ ei_matrix_cos(const MatrixBase& M) * \param[in] M a square matrix. * \returns expression representing \f$ \sinh(M) \f$ * - * This function calls ei_matrix_function() with StdStemFunctions::sinh(). + * This function calls matrixFunction() with StdStemFunctions::sinh(). * * \include MatrixSinh.cpp * Output: \verbinclude MatrixSinh.out */ template -MatrixFunctionReturnValue -ei_matrix_sinh(const MatrixBase& M) +const MatrixFunctionReturnValue MatrixBase::sinh() const { - ei_assert(M.rows() == M.cols()); - typedef typename ei_traits::Scalar Scalar; + ei_assert(rows() == cols()); typedef typename ei_stem_function::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue(M.derived(), StdStemFunctions::sinh); + return MatrixFunctionReturnValue(derived(), StdStemFunctions::sinh); } /** \ingroup MatrixFunctions_Module @@ -664,18 +659,16 @@ ei_matrix_sinh(const MatrixBase& M) * \param[in] M a square matrix. * \returns expression representing \f$ \cosh(M) \f$ * - * This function calls ei_matrix_function() with StdStemFunctions::cosh(). + * This function calls matrixFunction() with StdStemFunctions::cosh(). * * \sa ei_matrix_sinh() for an example. */ template -MatrixFunctionReturnValue -ei_matrix_cosh(const MatrixBase& M) +const MatrixFunctionReturnValue MatrixBase::cosh() const { - ei_assert(M.rows() == M.cols()); - typedef typename ei_traits::Scalar Scalar; + ei_assert(rows() == cols()); typedef typename ei_stem_function::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue(M.derived(), StdStemFunctions::cosh); + return MatrixFunctionReturnValue(derived(), StdStemFunctions::cosh); } #endif // EIGEN_MATRIX_FUNCTION diff --git a/unsupported/Eigen/src/MatrixFunctions/StemFunction.h b/unsupported/Eigen/src/MatrixFunctions/StemFunction.h index 90965c7dd..260690b63 100644 --- a/unsupported/Eigen/src/MatrixFunctions/StemFunction.h +++ b/unsupported/Eigen/src/MatrixFunctions/StemFunction.h @@ -25,13 +25,6 @@ #ifndef EIGEN_STEM_FUNCTION #define EIGEN_STEM_FUNCTION -template -struct ei_stem_function -{ - typedef std::complex::Real> ComplexScalar; - typedef ComplexScalar type(ComplexScalar, int); -}; - /** \ingroup MatrixFunctions_Module * \brief Stem functions corresponding to standard mathematical functions. */ diff --git a/unsupported/doc/examples/MatrixExponential.cpp b/unsupported/doc/examples/MatrixExponential.cpp index 60ef315d7..ebd3b9675 100644 --- a/unsupported/doc/examples/MatrixExponential.cpp +++ b/unsupported/doc/examples/MatrixExponential.cpp @@ -12,7 +12,5 @@ int main() pi/4, 0, 0, 0, 0, 0; std::cout << "The matrix A is:\n" << A << "\n\n"; - - MatrixXd B = ei_matrix_exponential(A); - std::cout << "The matrix exponential of A is:\n" << B << "\n\n"; + std::cout << "The matrix exponential of A is:\n" << A.exp() << "\n\n"; } diff --git a/unsupported/doc/examples/MatrixFunction.cpp b/unsupported/doc/examples/MatrixFunction.cpp index ccef85cef..a4172e4ae 100644 --- a/unsupported/doc/examples/MatrixFunction.cpp +++ b/unsupported/doc/examples/MatrixFunction.cpp @@ -19,5 +19,5 @@ int main() std::cout << "The matrix A is:\n" << A << "\n\n"; std::cout << "The matrix exponential of A is:\n" - << ei_matrix_function(A, expfn) << "\n\n"; + << A.matrixFunction(expfn) << "\n\n"; } diff --git a/unsupported/doc/examples/MatrixSine.cpp b/unsupported/doc/examples/MatrixSine.cpp index e85e6a754..9eea9a081 100644 --- a/unsupported/doc/examples/MatrixSine.cpp +++ b/unsupported/doc/examples/MatrixSine.cpp @@ -8,10 +8,10 @@ int main() MatrixXd A = MatrixXd::Random(3,3); std::cout << "A = \n" << A << "\n\n"; - MatrixXd sinA = ei_matrix_sin(A); + MatrixXd sinA = A.sin(); std::cout << "sin(A) = \n" << sinA << "\n\n"; - MatrixXd cosA = ei_matrix_cos(A); + MatrixXd cosA = A.cos(); std::cout << "cos(A) = \n" << cosA << "\n\n"; // The matrix functions satisfy sin^2(A) + cos^2(A) = I, diff --git a/unsupported/doc/examples/MatrixSinh.cpp b/unsupported/doc/examples/MatrixSinh.cpp index 89566d87a..f77186724 100644 --- a/unsupported/doc/examples/MatrixSinh.cpp +++ b/unsupported/doc/examples/MatrixSinh.cpp @@ -8,10 +8,10 @@ int main() MatrixXf A = MatrixXf::Random(3,3); std::cout << "A = \n" << A << "\n\n"; - MatrixXf sinhA = ei_matrix_sinh(A); + MatrixXf sinhA = A.sinh(); std::cout << "sinh(A) = \n" << sinhA << "\n\n"; - MatrixXf coshA = ei_matrix_cosh(A); + MatrixXf coshA = A.cosh(); std::cout << "cosh(A) = \n" << coshA << "\n\n"; // The matrix functions satisfy cosh^2(A) - sinh^2(A) = I, diff --git a/unsupported/test/matrix_exponential.cpp b/unsupported/test/matrix_exponential.cpp index 61f30334d..66e52e100 100644 --- a/unsupported/test/matrix_exponential.cpp +++ b/unsupported/test/matrix_exponential.cpp @@ -57,11 +57,11 @@ void test2dRotation(double tol) angle = static_cast(pow(10, i / 5. - 2)); B << cos(angle), sin(angle), -sin(angle), cos(angle); - C = ei_matrix_function(angle*A, expfn); + C = (angle*A).matrixFunction(expfn); std::cout << "test2dRotation: i = " << i << " error funm = " << relerr(C, B); VERIFY(C.isApprox(B, static_cast(tol))); - C = ei_matrix_exponential(angle*A); + C = (angle*A).exp(); std::cout << " error expm = " << relerr(C, B) << "\n"; VERIFY(C.isApprox(B, static_cast(tol))); } @@ -82,11 +82,11 @@ void test2dHyperbolicRotation(double tol) A << 0, angle*imagUnit, -angle*imagUnit, 0; B << ch, sh*imagUnit, -sh*imagUnit, ch; - C = ei_matrix_function(A, expfn); + C = A.matrixFunction(expfn); std::cout << "test2dHyperbolicRotation: i = " << i << " error funm = " << relerr(C, B); VERIFY(C.isApprox(B, static_cast(tol))); - C = ei_matrix_exponential(A); + C = A.exp(); std::cout << " error expm = " << relerr(C, B) << "\n"; VERIFY(C.isApprox(B, static_cast(tol))); } @@ -106,11 +106,11 @@ void testPascal(double tol) for (int j=0; j<=i; j++) B(i,j) = static_cast(binom(i,j)); - C = ei_matrix_function(A, expfn); + C = A.matrixFunction(expfn); std::cout << "testPascal: size = " << size << " error funm = " << relerr(C, B); VERIFY(C.isApprox(B, static_cast(tol))); - C = ei_matrix_exponential(A); + C = A.exp(); std::cout << " error expm = " << relerr(C, B) << "\n"; VERIFY(C.isApprox(B, static_cast(tol))); } @@ -132,11 +132,11 @@ void randomTest(const MatrixType& m, double tol) for(int i = 0; i < g_repeat; i++) { m1 = MatrixType::Random(rows, cols); - m2 = ei_matrix_function(m1, expfn) * ei_matrix_function(-m1, expfn); + m2 = m1.matrixFunction(expfn) * (-m1).matrixFunction(expfn); std::cout << "randomTest: error funm = " << relerr(identity, m2); VERIFY(identity.isApprox(m2, static_cast(tol))); - m2 = ei_matrix_exponential(m1) * ei_matrix_exponential(-m1); + m2 = m1.exp() * (-m1).exp(); std::cout << " error expm = " << relerr(identity, m2) << "\n"; VERIFY(identity.isApprox(m2, static_cast(tol))); } diff --git a/unsupported/test/matrix_function.cpp b/unsupported/test/matrix_function.cpp index e40af7b4e..16995d836 100644 --- a/unsupported/test/matrix_function.cpp +++ b/unsupported/test/matrix_function.cpp @@ -114,8 +114,7 @@ void testMatrixExponential(const MatrixType& A) typedef typename NumTraits::Real RealScalar; typedef std::complex ComplexScalar; - VERIFY_IS_APPROX(ei_matrix_exponential(A), - ei_matrix_function(A, StdStemFunctions::exp)); + VERIFY_IS_APPROX(A.exp(), A.matrixFunction(StdStemFunctions::exp)); } template @@ -123,10 +122,8 @@ void testHyperbolicFunctions(const MatrixType& A) { // Need to use absolute error because of possible cancellation when // adding/subtracting expA and expmA. - MatrixType expA = ei_matrix_exponential(A); - MatrixType expmA = ei_matrix_exponential(-A); - VERIFY_IS_APPROX_ABS(ei_matrix_sinh(A), (expA - expmA) / 2); - VERIFY_IS_APPROX_ABS(ei_matrix_cosh(A), (expA + expmA) / 2); + VERIFY_IS_APPROX_ABS(A.sinh(), (A.exp() - (-A).exp()) / 2); + VERIFY_IS_APPROX_ABS(A.cosh(), (A.exp() + (-A).exp()) / 2); } template @@ -143,15 +140,13 @@ void testGonioFunctions(const MatrixType& A) ComplexMatrix Ac = A.template cast(); - ComplexMatrix exp_iA = ei_matrix_exponential(imagUnit * Ac); - ComplexMatrix exp_miA = ei_matrix_exponential(-imagUnit * Ac); + ComplexMatrix exp_iA = (imagUnit * Ac).exp(); + ComplexMatrix exp_miA = (-imagUnit * Ac).exp(); - MatrixType sinA = ei_matrix_sin(A); - ComplexMatrix sinAc = sinA.template cast(); + ComplexMatrix sinAc = A.sin().template cast(); VERIFY_IS_APPROX_ABS(sinAc, (exp_iA - exp_miA) / (two*imagUnit)); - MatrixType cosA = ei_matrix_cos(A); - ComplexMatrix cosAc = cosA.template cast(); + ComplexMatrix cosAc = A.cos().template cast(); VERIFY_IS_APPROX_ABS(cosAc, (exp_iA + exp_miA) / 2); }