// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2007-2009 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SKEWSYMMETRICMATRIX3_H #define EIGEN_SKEWSYMMETRICMATRIX3_H // IWYU pragma: private #include "./InternalHeaderCheck.h" namespace Eigen { /** \class SkewSymmetricBase * \ingroup Core_Module * * \brief Base class for skew symmetric matrices and expressions * * This is the base class that is inherited by SkewSymmetricMatrix3 and related expression * types, which internally use a three vector for storing the entries. SkewSymmetric * types always represent square three times three matrices. * * This implementations follows class DiagonalMatrix * * \tparam Derived is the derived type, a SkewSymmetricMatrix3 or SkewSymmetricWrapper. * * \sa class SkewSymmetricMatrix3, class SkewSymmetricWrapper */ template class SkewSymmetricBase : public EigenBase { public: typedef typename internal::traits::SkewSymmetricVectorType SkewSymmetricVectorType; typedef typename SkewSymmetricVectorType::Scalar Scalar; typedef typename SkewSymmetricVectorType::RealScalar RealScalar; typedef typename internal::traits::StorageKind StorageKind; typedef typename internal::traits::StorageIndex StorageIndex; enum { RowsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, ColsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, MaxColsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, IsVectorAtCompileTime = 0, Flags = NoPreferredStorageOrderBit }; typedef Matrix DenseMatrixType; typedef DenseMatrixType DenseType; typedef SkewSymmetricMatrix3 PlainObject; /** \returns a reference to the derived object. */ EIGEN_DEVICE_FUNC inline const Derived& derived() const { return *static_cast(this); } /** \returns a const reference to the derived object. */ EIGEN_DEVICE_FUNC inline Derived& derived() { return *static_cast(this); } /** * Constructs a dense matrix from \c *this. Note, this directly returns a dense matrix type, * not an expression. * \returns A dense matrix, with its entries set from the the derived object. */ EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); } /** Determinant vanishes */ EIGEN_DEVICE_FUNC constexpr Scalar determinant() const { return 0; } /** A.transpose() = -A */ EIGEN_DEVICE_FUNC PlainObject transpose() const { return (-vector()).asSkewSymmetric(); } /** \returns the exponential of this matrix using Rodrigues’ formula */ EIGEN_DEVICE_FUNC DenseMatrixType exponential() const { DenseMatrixType retVal = DenseMatrixType::Identity(); const SkewSymmetricVectorType& v = vector(); if (v.isZero()) { return retVal; } const Scalar norm2 = v.squaredNorm(); const Scalar norm = numext::sqrt(norm2); retVal += ((((1 - numext::cos(norm)) / norm2) * derived()) * derived()) + (numext::sin(norm) / norm) * derived().toDenseMatrix(); return retVal; } /** \returns a reference to the derived object's vector of coefficients. */ EIGEN_DEVICE_FUNC inline const SkewSymmetricVectorType& vector() const { return derived().vector(); } /** \returns a const reference to the derived object's vector of coefficients. */ EIGEN_DEVICE_FUNC inline SkewSymmetricVectorType& vector() { return derived().vector(); } /** \returns the number of rows. */ EIGEN_DEVICE_FUNC constexpr Index rows() const { return 3; } /** \returns the number of columns. */ EIGEN_DEVICE_FUNC constexpr Index cols() const { return 3; } /** \returns the matrix product of \c *this by the dense matrix, \a matrix */ template EIGEN_DEVICE_FUNC Product operator*( const MatrixBase& matrix) const { return Product(derived(), matrix.derived()); } /** \returns the matrix product of \c *this by the skew symmetric matrix, \a matrix */ template EIGEN_DEVICE_FUNC Product operator*( const SkewSymmetricBase& matrix) const { return Product(derived(), matrix.derived()); } template using SkewSymmetricProductReturnType = SkewSymmetricWrapper; /** \returns the wedge product of \c *this by the skew symmetric matrix \a other * A wedge B = AB - BA */ template EIGEN_DEVICE_FUNC SkewSymmetricProductReturnType wedge( const SkewSymmetricBase& other) const { return vector().cross(other.vector()).asSkewSymmetric(); } using SkewSymmetricScaleReturnType = SkewSymmetricWrapper; /** \returns the product of \c *this by the scalar \a scalar */ EIGEN_DEVICE_FUNC inline SkewSymmetricScaleReturnType operator*(const Scalar& scalar) const { return (vector() * scalar).asSkewSymmetric(); } using ScaleSkewSymmetricReturnType = SkewSymmetricWrapper; /** \returns the product of a scalar and the skew symmetric matrix \a other */ EIGEN_DEVICE_FUNC friend inline ScaleSkewSymmetricReturnType operator*(const Scalar& scalar, const SkewSymmetricBase& other) { return (scalar * other.vector()).asSkewSymmetric(); } template using SkewSymmetricSumReturnType = SkewSymmetricWrapper; /** \returns the sum of \c *this and the skew symmetric matrix \a other */ template EIGEN_DEVICE_FUNC inline SkewSymmetricSumReturnType operator+( const SkewSymmetricBase& other) const { return (vector() + other.vector()).asSkewSymmetric(); } template using SkewSymmetricDifferenceReturnType = SkewSymmetricWrapper; /** \returns the difference of \c *this and the skew symmetric matrix \a other */ template EIGEN_DEVICE_FUNC inline SkewSymmetricDifferenceReturnType operator-( const SkewSymmetricBase& other) const { return (vector() - other.vector()).asSkewSymmetric(); } }; /** \class SkewSymmetricMatrix3 * \ingroup Core_Module * * \brief Represents a 3x3 skew symmetric matrix with its storage * * \tparam Scalar_ the type of coefficients * * \sa class SkewSymmetricBase, class SkewSymmetricWrapper */ namespace internal { template struct traits> : traits> { typedef Matrix SkewSymmetricVectorType; typedef SkewSymmetricShape StorageKind; enum { Flags = LvalueBit | NoPreferredStorageOrderBit | NestByRefBit }; }; } // namespace internal template class SkewSymmetricMatrix3 : public SkewSymmetricBase> { public: #ifndef EIGEN_PARSED_BY_DOXYGEN typedef typename internal::traits::SkewSymmetricVectorType SkewSymmetricVectorType; typedef const SkewSymmetricMatrix3& Nested; typedef Scalar_ Scalar; typedef typename internal::traits::StorageKind StorageKind; typedef typename internal::traits::StorageIndex StorageIndex; #endif protected: SkewSymmetricVectorType m_vector; public: /** const version of vector(). */ EIGEN_DEVICE_FUNC inline const SkewSymmetricVectorType& vector() const { return m_vector; } /** \returns a reference to the stored vector of coefficients. */ EIGEN_DEVICE_FUNC inline SkewSymmetricVectorType& vector() { return m_vector; } /** Default constructor without initialization */ EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3() {} /** Constructor from three scalars */ EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3(const Scalar& x, const Scalar& y, const Scalar& z) : m_vector(x, y, z) {} /** \brief Constructs a SkewSymmetricMatrix3 from an r-value vector type */ EIGEN_DEVICE_FUNC explicit inline SkewSymmetricMatrix3(SkewSymmetricVectorType&& vec) : m_vector(std::move(vec)) {} /** generic constructor from expression of the coefficients */ template EIGEN_DEVICE_FUNC explicit inline SkewSymmetricMatrix3(const MatrixBase& other) : m_vector(other) {} /** Copy constructor. */ template EIGEN_DEVICE_FUNC inline SkewSymmetricMatrix3(const SkewSymmetricBase& other) : m_vector(other.vector()) {} #ifndef EIGEN_PARSED_BY_DOXYGEN /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */ inline SkewSymmetricMatrix3(const SkewSymmetricMatrix3& other) : m_vector(other.vector()) {} #endif /** Copy operator. */ template EIGEN_DEVICE_FUNC SkewSymmetricMatrix3& operator=(const SkewSymmetricBase& other) { m_vector = other.vector(); return *this; } #ifndef EIGEN_PARSED_BY_DOXYGEN /** This is a special case of the templated operator=. Its purpose is to * prevent a default operator= from hiding the templated operator=. */ EIGEN_DEVICE_FUNC SkewSymmetricMatrix3& operator=(const SkewSymmetricMatrix3& other) { m_vector = other.vector(); return *this; } #endif typedef SkewSymmetricWrapper, SkewSymmetricVectorType>> InitializeReturnType; /** Initializes a skew symmetric matrix with coefficients set to zero */ EIGEN_DEVICE_FUNC static InitializeReturnType Zero() { return SkewSymmetricVectorType::Zero().asSkewSymmetric(); } /** Sets all coefficients to zero. */ EIGEN_DEVICE_FUNC inline void setZero() { m_vector.setZero(); } }; /** \class SkewSymmetricWrapper * \ingroup Core_Module * * \brief Expression of a skew symmetric matrix * * \tparam SkewSymmetricVectorType_ the type of the vector of coefficients * * This class is an expression of a skew symmetric matrix, but not storing its own vector of coefficients, * instead wrapping an existing vector expression. It is the return type of MatrixBase::asSkewSymmetric() * and most of the time this is the only way that it is used. * * \sa class SkewSymmetricMatrix3, class SkewSymmetricBase, MatrixBase::asSkewSymmetric() */ namespace internal { template struct traits> { typedef SkewSymmetricVectorType_ SkewSymmetricVectorType; typedef typename SkewSymmetricVectorType::Scalar Scalar; typedef typename SkewSymmetricVectorType::StorageIndex StorageIndex; typedef SkewSymmetricShape StorageKind; typedef typename traits::XprKind XprKind; enum { RowsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, ColsAtCompileTime = SkewSymmetricVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, MaxColsAtCompileTime = SkewSymmetricVectorType::MaxSizeAtCompileTime, Flags = (traits::Flags & LvalueBit) | NoPreferredStorageOrderBit }; }; } // namespace internal template class SkewSymmetricWrapper : public SkewSymmetricBase>, internal::no_assignment_operator { public: #ifndef EIGEN_PARSED_BY_DOXYGEN typedef SkewSymmetricVectorType_ SkewSymmetricVectorType; typedef SkewSymmetricWrapper Nested; #endif /** Constructor from expression of coefficients to wrap. */ EIGEN_DEVICE_FUNC explicit inline SkewSymmetricWrapper(SkewSymmetricVectorType& a_vector) : m_vector(a_vector) {} /** \returns a const reference to the wrapped expression of coefficients. */ EIGEN_DEVICE_FUNC const SkewSymmetricVectorType& vector() const { return m_vector; } protected: typename SkewSymmetricVectorType::Nested m_vector; }; /** \returns a pseudo-expression of a skew symmetric matrix with *this as vector of coefficients * * \only_for_vectors * * \sa class SkewSymmetricWrapper, class SkewSymmetricMatrix3, vector(), isSkewSymmetric() **/ template EIGEN_DEVICE_FUNC inline const SkewSymmetricWrapper MatrixBase::asSkewSymmetric() const { return SkewSymmetricWrapper(derived()); } /** \returns true if *this is approximately equal to a skew symmetric matrix, * within the precision given by \a prec. */ template bool MatrixBase::isSkewSymmetric(const RealScalar& prec) const { if (cols() != rows()) return false; return (this->transpose() + *this).isZero(prec); } /** \returns the matrix product of \c *this by the skew symmetric matrix \a skew. */ template template EIGEN_DEVICE_FUNC inline const Product MatrixBase::operator*( const SkewSymmetricBase& skew) const { return Product(derived(), skew.derived()); } namespace internal { template <> struct storage_kind_to_shape { typedef SkewSymmetricShape Shape; }; struct SkewSymmetric2Dense {}; template <> struct AssignmentKind { typedef SkewSymmetric2Dense Kind; }; // SkewSymmetric matrix to Dense assignment template struct Assignment { EIGEN_DEVICE_FUNC static void run( DstXprType& dst, const SrcXprType& src, const internal::assign_op& /*func*/) { if ((dst.rows() != 3) || (dst.cols() != 3)) { dst.resize(3, 3); } dst.diagonal().setZero(); const typename SrcXprType::SkewSymmetricVectorType v = src.vector(); dst(0, 1) = -v(2); dst(1, 0) = v(2); dst(0, 2) = v(1); dst(2, 0) = -v(1); dst(1, 2) = -v(0); dst(2, 1) = v(0); } EIGEN_DEVICE_FUNC static void run( DstXprType& dst, const SrcXprType& src, const internal::add_assign_op& /*func*/) { dst.vector() += src.vector(); } EIGEN_DEVICE_FUNC static void run( DstXprType& dst, const SrcXprType& src, const internal::sub_assign_op& /*func*/) { dst.vector() -= src.vector(); } }; } // namespace internal } // end namespace Eigen #endif // EIGEN_SKEWSYMMETRICMATRIX3_H