mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-10 18:59:01 +08:00
Implement and document MatrixBase::sqrt().
This commit is contained in:
parent
dac4bb640a
commit
d7e3c949be
@ -465,6 +465,7 @@ template<typename Derived> class MatrixBase
|
|||||||
const MatrixFunctionReturnValue<Derived> sinh() const;
|
const MatrixFunctionReturnValue<Derived> sinh() const;
|
||||||
const MatrixFunctionReturnValue<Derived> cos() const;
|
const MatrixFunctionReturnValue<Derived> cos() const;
|
||||||
const MatrixFunctionReturnValue<Derived> sin() const;
|
const MatrixFunctionReturnValue<Derived> sin() const;
|
||||||
|
const MatrixSquareRootReturnValue<Derived> sqrt() const;
|
||||||
|
|
||||||
#ifdef EIGEN2_SUPPORT
|
#ifdef EIGEN2_SUPPORT
|
||||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||||
|
@ -283,6 +283,7 @@ template<typename MatrixType,int Direction> class Homogeneous;
|
|||||||
// MatrixFunctions module
|
// MatrixFunctions module
|
||||||
template<typename Derived> struct MatrixExponentialReturnValue;
|
template<typename Derived> struct MatrixExponentialReturnValue;
|
||||||
template<typename Derived> class MatrixFunctionReturnValue;
|
template<typename Derived> class MatrixFunctionReturnValue;
|
||||||
|
template<typename Derived> class MatrixSquareRootReturnValue;
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
|
@ -53,6 +53,7 @@ namespace Eigen {
|
|||||||
* - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
|
* - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
|
||||||
* - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
|
* - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
|
||||||
* - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
|
* - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
|
||||||
|
* - \ref matrixbase_sqrt "MatrixBase::sqrt()", for computing the matrix square root
|
||||||
*
|
*
|
||||||
* These methods are the main entry points to this module.
|
* These methods are the main entry points to this module.
|
||||||
*
|
*
|
||||||
@ -246,7 +247,7 @@ Output: \verbinclude MatrixSine.out
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section matrixbase_sinh const MatrixBase::sinh()
|
\section matrixbase_sinh MatrixBase::sinh()
|
||||||
|
|
||||||
Compute the matrix hyperbolic sine.
|
Compute the matrix hyperbolic sine.
|
||||||
|
|
||||||
@ -262,6 +263,74 @@ This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdSt
|
|||||||
Example: \include MatrixSinh.cpp
|
Example: \include MatrixSinh.cpp
|
||||||
Output: \verbinclude MatrixSinh.out
|
Output: \verbinclude MatrixSinh.out
|
||||||
|
|
||||||
|
|
||||||
|
\section matrixbase_sqrt MatrixBase::sqrt()
|
||||||
|
|
||||||
|
Compute the matrix square root.
|
||||||
|
|
||||||
|
\code
|
||||||
|
const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\param[in] M invertible matrix whose square root is to be computed.
|
||||||
|
\returns expression representing the matrix square root of \p M.
|
||||||
|
|
||||||
|
The matrix square root of \f$ M \f$ is the matrix \f$ M^{1/2} \f$
|
||||||
|
whose square is the original matrix; so if \f$ S = M^{1/2} \f$ then
|
||||||
|
\f$ S^2 = M \f$.
|
||||||
|
|
||||||
|
In the <b>real case</b>, the matrix \f$ M \f$ should be invertible and
|
||||||
|
it should have no eigenvalues which are real and negative (pairs of
|
||||||
|
complex conjugate eigenvalues are allowed). In that case, the matrix
|
||||||
|
has a square root which is also real, and this is the square root
|
||||||
|
computed by this function.
|
||||||
|
|
||||||
|
The matrix square root is computed by first reducing the matrix to
|
||||||
|
quasi-triangular form with the real Schur decomposition. The square
|
||||||
|
root of the quasi-triangular matrix can then be computed directly. The
|
||||||
|
cost is approximately \f$ 25 n^3 \f$ real flops for the real Schur
|
||||||
|
decomposition and \f$ 3\frac13 n^3 \f$ real flops for the remainder
|
||||||
|
(though the computation time in practice is likely more than this
|
||||||
|
indicates).
|
||||||
|
|
||||||
|
Details of the algorithm can be found in: Nicholas J. Highan,
|
||||||
|
"Computing real square roots of a real matrix", <em>Linear Algebra
|
||||||
|
Appl.</em>, 88/89:405–430, 1987.
|
||||||
|
|
||||||
|
If the matrix is <b>positive-definite symmetric</b>, then the square
|
||||||
|
root is also positive-definite symmetric. In this case, it is best to
|
||||||
|
use SelfAdjointEigenSolver::operatorSqrt() to compute it.
|
||||||
|
|
||||||
|
In the <b>complex case</b>, the matrix \f$ M \f$ should be invertible;
|
||||||
|
this is a restriction of the algorithm. The square root computed by
|
||||||
|
this algorithm is the one whose eigenvalues have an argument in the
|
||||||
|
interval \f$ (-\frac12\pi, \frac12\pi] \f$. This is the usual branch
|
||||||
|
cut.
|
||||||
|
|
||||||
|
The computation is the same as in the real case, except that the
|
||||||
|
complex Schur decomposition is used to reduce the matrix to a
|
||||||
|
triangular matrix. The theoretical cost is the same. Details are in:
|
||||||
|
Åke Björck and Scen Hammarling, "A Schur method for the
|
||||||
|
square root of a matrix", <em>Linear Algebra Appl.</em>,
|
||||||
|
52/53:127–140, 1983.
|
||||||
|
|
||||||
|
Example: The following program checks that the square root of
|
||||||
|
\f[ \left[ \begin{array}{cc}
|
||||||
|
\cos(\frac13\pi) & -\sin(\frac13\pi) \\
|
||||||
|
\sin(\frac13\pi) & \cos(\frac13\pi)
|
||||||
|
\end{array} \right], \f]
|
||||||
|
corresponding to a rotation over 60 degrees, is a rotation over 30 degrees:
|
||||||
|
\f[ \left[ \begin{array}{cc}
|
||||||
|
\cos(\frac16\pi) & -\sin(\frac16\pi) \\
|
||||||
|
\sin(\frac16\pi) & \cos(\frac16\pi)
|
||||||
|
\end{array} \right]. \f]
|
||||||
|
|
||||||
|
\include MatrixSquareRoot.cpp
|
||||||
|
Output: \verbinclude MatrixSquareRoot.out
|
||||||
|
|
||||||
|
\sa class RealSchur, class ComplexSchur, class MatrixSquareRoot,
|
||||||
|
SelfAdjointEigenSolver::operatorSqrt().
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -320,4 +320,65 @@ void MatrixSquareRoot<MatrixType, 1>::compute(ResultType &result)
|
|||||||
result.noalias() = tmp * U.adjoint();
|
result.noalias() = tmp * U.adjoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup MatrixFunctions_Module
|
||||||
|
*
|
||||||
|
* \brief Proxy for the matrix square root of some matrix (expression).
|
||||||
|
*
|
||||||
|
* \tparam Derived Type of the argument to the matrix square root.
|
||||||
|
*
|
||||||
|
* This class holds the argument to the matrix square root 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
|
||||||
|
* MatrixBase::sqrt() and most of the time this is the only way it is
|
||||||
|
* used.
|
||||||
|
*/
|
||||||
|
template<typename Derived> class MatrixSquareRootReturnValue
|
||||||
|
: public ReturnByValue<MatrixSquareRootReturnValue<Derived> >
|
||||||
|
{
|
||||||
|
typedef typename Derived::Index Index;
|
||||||
|
public:
|
||||||
|
/** \brief Constructor.
|
||||||
|
*
|
||||||
|
* \param[in] src %Matrix (expression) forming the argument of the
|
||||||
|
* matrix square root.
|
||||||
|
*/
|
||||||
|
MatrixSquareRootReturnValue(const Derived& src) : m_src(src) { }
|
||||||
|
|
||||||
|
/** \brief Compute the matrix square root.
|
||||||
|
*
|
||||||
|
* \param[out] result the matrix square root of \p src in the
|
||||||
|
* constructor.
|
||||||
|
*/
|
||||||
|
template <typename ResultType>
|
||||||
|
inline void evalTo(ResultType& result) const
|
||||||
|
{
|
||||||
|
const typename Derived::PlainObject srcEvaluated = m_src.eval();
|
||||||
|
MatrixSquareRoot<typename Derived::PlainObject> me(srcEvaluated);
|
||||||
|
me.compute(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Index rows() const { return m_src.rows(); }
|
||||||
|
Index cols() const { return m_src.cols(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const Derived& m_src;
|
||||||
|
private:
|
||||||
|
MatrixSquareRootReturnValue& operator=(const MatrixSquareRootReturnValue&);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template<typename Derived>
|
||||||
|
struct traits<MatrixSquareRootReturnValue<Derived> >
|
||||||
|
{
|
||||||
|
typedef typename Derived::PlainObject ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
|
||||||
|
{
|
||||||
|
eigen_assert(rows() == cols());
|
||||||
|
return MatrixSquareRootReturnValue<Derived>(derived());
|
||||||
|
}
|
||||||
|
|
||||||
#endif // EIGEN_MATRIX_FUNCTION
|
#endif // EIGEN_MATRIX_FUNCTION
|
||||||
|
@ -60,9 +60,7 @@ void testMatrixSqrt(const MatrixType& m)
|
|||||||
{
|
{
|
||||||
MatrixType A;
|
MatrixType A;
|
||||||
generateTestMatrix<MatrixType>::run(A, m.rows());
|
generateTestMatrix<MatrixType>::run(A, m.rows());
|
||||||
MatrixSquareRoot<MatrixType> msr(A);
|
MatrixType sqrtA = A.sqrt();
|
||||||
MatrixType sqrtA;
|
|
||||||
msr.compute(sqrtA);
|
|
||||||
VERIFY_IS_APPROX(sqrtA * sqrtA, A);
|
VERIFY_IS_APPROX(sqrtA * sqrtA, A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user