diff options
-rw-r--r-- | Eigen/src/Core/MatrixBase.h | 3 | ||||
-rw-r--r-- | Eigen/src/Core/Redux.h | 12 | ||||
-rw-r--r-- | Eigen/src/Core/Visitor.h | 10 | ||||
-rw-r--r-- | Eigen/src/Geometry/Cross.h | 81 | ||||
-rw-r--r-- | Eigen/src/Geometry/Quaternion.h | 185 |
5 files changed, 109 insertions, 182 deletions
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 7e22caa75..5bcd6991d 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -558,7 +558,8 @@ template<typename Derived> class MatrixBase : public ArrayBase<Derived> /////////// Geometry module /////////// template<typename OtherDerived> - const Cross<Derived,OtherDerived> cross(const MatrixBase<OtherDerived>& other) const; + typename ei_eval<Derived>::type + cross(const MatrixBase<OtherDerived>& other) const; }; diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h index 821d3813d..e7db140c5 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -27,7 +27,7 @@ #define EIGEN_REDUX_H template<typename BinaryOp, typename Derived, int Start, int Length> -struct ei_redux_unroller +struct ei_redux_impl { enum { HalfLength = Length/2 @@ -38,13 +38,13 @@ struct ei_redux_unroller static Scalar run(const Derived &mat, const BinaryOp& func) { return func( - ei_redux_unroller<BinaryOp, Derived, Start, HalfLength>::run(mat, func), - ei_redux_unroller<BinaryOp, Derived, Start+HalfLength, Length - HalfLength>::run(mat, func)); + ei_redux_impl<BinaryOp, Derived, Start, HalfLength>::run(mat, func), + ei_redux_impl<BinaryOp, Derived, Start+HalfLength, Length - HalfLength>::run(mat, func)); } }; template<typename BinaryOp, typename Derived, int Start> -struct ei_redux_unroller<BinaryOp, Derived, Start, 1> +struct ei_redux_impl<BinaryOp, Derived, Start, 1> { enum { col = Start / Derived::RowsAtCompileTime, @@ -60,7 +60,7 @@ struct ei_redux_unroller<BinaryOp, Derived, Start, 1> }; template<typename BinaryOp, typename Derived, int Start> -struct ei_redux_unroller<BinaryOp, Derived, Start, Dynamic> +struct ei_redux_impl<BinaryOp, Derived, Start, Dynamic> { typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar; static Scalar run(const Derived& mat, const BinaryOp& func) @@ -91,7 +91,7 @@ MatrixBase<Derived>::redux(const BinaryOp& func) const const bool unroll = SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * ei_functor_traits<BinaryOp>::Cost <= EIGEN_UNROLLING_LIMIT; - return ei_redux_unroller<BinaryOp, Derived, 0, + return ei_redux_impl<BinaryOp, Derived, 0, unroll ? int(SizeAtCompileTime) : Dynamic> ::run(derived(), func); } diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h index bd469f747..18e90ca62 100644 --- a/Eigen/src/Core/Visitor.h +++ b/Eigen/src/Core/Visitor.h @@ -26,7 +26,7 @@ #define EIGEN_VISITOR_H template<typename Visitor, typename Derived, int UnrollCount> -struct ei_visitor_unroller +struct ei_visitor_impl { enum { col = (UnrollCount-1) / Derived::RowsAtCompileTime, @@ -35,13 +35,13 @@ struct ei_visitor_unroller inline static void run(const Derived &mat, Visitor& visitor) { - ei_visitor_unroller<Visitor, Derived, UnrollCount-1>::run(mat, visitor); + ei_visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor); visitor(mat.coeff(row, col), row, col); } }; template<typename Visitor, typename Derived> -struct ei_visitor_unroller<Visitor, Derived, 1> +struct ei_visitor_impl<Visitor, Derived, 1> { inline static void run(const Derived &mat, Visitor& visitor) { @@ -50,7 +50,7 @@ struct ei_visitor_unroller<Visitor, Derived, 1> }; template<typename Visitor, typename Derived> -struct ei_visitor_unroller<Visitor, Derived, Dynamic> +struct ei_visitor_impl<Visitor, Derived, Dynamic> { inline static void run(const Derived& mat, Visitor& visitor) { @@ -85,7 +85,7 @@ void MatrixBase<Derived>::visit(Visitor& visitor) const const bool unroll = SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * ei_functor_traits<Visitor>::Cost <= EIGEN_UNROLLING_LIMIT; - return ei_visitor_unroller<Visitor, Derived, + return ei_visitor_impl<Visitor, Derived, unroll ? int(SizeAtCompileTime) : Dynamic >::run(derived(), visitor); } diff --git a/Eigen/src/Geometry/Cross.h b/Eigen/src/Geometry/Cross.h index debe43ca4..1ee9a007c 100644 --- a/Eigen/src/Geometry/Cross.h +++ b/Eigen/src/Geometry/Cross.h @@ -25,78 +25,21 @@ #ifndef EIGEN_CROSS_H #define EIGEN_CROSS_H -/** \class Cross - * - * \brief Expression of the cross product of two vectors - * - * \param Lhs the type of the left-hand side - * \param Rhs the type of the right-hand side - * - * This class represents an expression of the cross product of two 3D vectors. - * It is the return type of MatrixBase::cross(), and most - * of the time this is the only way it is used. - */ -template<typename Lhs, typename Rhs> -struct ei_traits<Cross<Lhs, Rhs> > -{ - typedef typename Lhs::Scalar Scalar; - typedef typename ei_nested<Lhs,2>::type LhsNested; - typedef typename ei_nested<Rhs,2>::type RhsNested; - typedef typename ei_unref<LhsNested>::type _LhsNested; - typedef typename ei_unref<RhsNested>::type _RhsNested; - enum { - RowsAtCompileTime = 3, - ColsAtCompileTime = 1, - MaxRowsAtCompileTime = 3, - MaxColsAtCompileTime = 1, - Flags = ((_RhsNested::Flags | _LhsNested::Flags) & HereditaryBits) - | EvalBeforeAssigningBit, - CoeffReadCost = NumTraits<Scalar>::AddCost + 2 * NumTraits<Scalar>::MulCost - }; -}; - -template<typename Lhs, typename Rhs> class Cross : ei_no_assignment_operator, - public MatrixBase<Cross<Lhs, Rhs> > -{ - public: - - EIGEN_GENERIC_PUBLIC_INTERFACE(Cross) - typedef typename ei_traits<Cross>::LhsNested LhsNested; - typedef typename ei_traits<Cross>::RhsNested RhsNested; - - Cross(const Lhs& lhs, const Rhs& rhs) - : m_lhs(lhs), m_rhs(rhs) - { - assert(lhs.isVector()); - assert(rhs.isVector()); - assert(lhs.size() == 3 && rhs.size() == 3); - } - - private: - - int _rows() const { return 3; } - int _cols() const { return 1; } - - Scalar _coeff(int i, int) const - { - return m_lhs[(i+1)%3]*m_rhs[(i+2)%3] - m_lhs[(i+2)%3]*m_rhs[(i+1)%3]; - } - - protected: - const LhsNested m_lhs; - const RhsNested m_rhs; -}; - -/** \returns an expression of the cross product of \c *this and \a other - * - * \sa class Cross - */ +/** \returns the cross product of \c *this and \a other */ template<typename Derived> template<typename OtherDerived> -const Cross<Derived,OtherDerived> -MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const +typename ei_eval<Derived>::type +inline MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const { - return Cross<Derived,OtherDerived>(derived(),other.derived()); + // Note that there is no need for an expression here since the compiler + // optimize such a small temporary very well (even within a complex expression) + const typename ei_nested<Derived,2>::type lhs(derived()); + const typename ei_nested<OtherDerived,2>::type rhs(other.derived()); + return typename ei_eval<Derived>::type( + lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1), + lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2), + lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0) + ); } #endif // EIGEN_CROSS_H diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index 1d0a3294f..2a575691a 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -41,113 +41,80 @@ * */ template<typename _Scalar> -struct ei_traits<Quaternion<_Scalar> > +class Quaternion { - typedef _Scalar Scalar; - enum { - RowsAtCompileTime = 4, - ColsAtCompileTime = 1, - MaxRowsAtCompileTime = 4, - MaxColsAtCompileTime = 1, - Flags = ei_corrected_matrix_flags<_Scalar, 4, 0>::ret, - CoeffReadCost = NumTraits<Scalar>::ReadCost - }; -}; - -template<typename _Scalar> -class Quaternion : public MatrixBase<Quaternion<_Scalar> > -{ -public: + typedef Matrix<_Scalar, 4, 1> Coefficients; + Coefficients m_coeffs; public: - EIGEN_GENERIC_PUBLIC_INTERFACE(Quaternion) - - private: - - EIGEN_ALIGN_128 Scalar m_data[4]; + /** the scalar type of the coefficients */ + typedef _Scalar Scalar; - inline int _rows() const { return 4; } - inline int _cols() const { return 1; } - - inline const Scalar& _coeff(int i, int) const { return m_data[i]; } + typedef Matrix<Scalar,3,1> Vector3; + typedef Matrix<Scalar,3,3> Matrix3; - inline Scalar& _coeffRef(int i, int) { return m_data[i]; } + inline Scalar x() const { return m_coeffs.coeff(0); } + inline Scalar y() const { return m_coeffs.coeff(1); } + inline Scalar z() const { return m_coeffs.coeff(2); } + inline Scalar w() const { return m_coeffs.coeff(3); } - template<int LoadMode> - inline PacketScalar _packetCoeff(int row, int) const - { - ei_internal_assert(Flags & VectorizableBit); - if (LoadMode==Eigen::Aligned) - return ei_pload(&m_data[row]); - else - return ei_ploadu(&m_data[row]); - } + inline Scalar& x() { return m_coeffs.coeffRef(0); } + inline Scalar& y() { return m_coeffs.coeffRef(1); } + inline Scalar& z() { return m_coeffs.coeffRef(2); } + inline Scalar& w() { return m_coeffs.coeffRef(3); } - template<int StoreMode> - inline void _writePacketCoeff(int row, int , const PacketScalar& x) - { - ei_internal_assert(Flags & VectorizableBit); - if (StoreMode==Eigen::Aligned) - ei_pstore(&m_data[row], x); - else - ei_pstoreu(&m_data[row], x); - } + /** \returns a read-only vector expression of the imaginary part (x,y,z) */ + inline const Block<Coefficients,3,1> vec() const { return m_coeffs.template start<3>(); } - inline int _stride(void) const { return _rows(); } + /** \returns a vector expression of the imaginary part (x,y,z) */ + inline Block<Coefficients,3,1> vec() { return m_coeffs.template start<3>(); } - public: + /** \returns a read-only vector expression of the coefficients */ + inline const Coefficients& _coeffs() const { return m_coeffs; } - typedef Matrix<Scalar,3,1> Vector3; - typedef Matrix<Scalar,3,3> Matrix3; + /** \returns a vector expression of the coefficients */ + inline Coefficients& _coeffs() { return m_coeffs; } // FIXME what is the prefered order: w x,y,z or x,y,z,w ? inline Quaternion(Scalar w = 1.0, Scalar x = 0.0, Scalar y = 0.0, Scalar z = 0.0) { - m_data[0] = x; - m_data[1] = y; - m_data[2] = z; - m_data[3] = w; + m_coeffs.coeffRef(0) = x; + m_coeffs.coeffRef(1) = y; + m_coeffs.coeffRef(2) = z; + m_coeffs.coeffRef(3) = w; } - /** Constructor copying the value of the expression \a other */ - template<typename OtherDerived> - inline Quaternion(const Eigen::MatrixBase<OtherDerived>& other) - { - *this = other; - } /** Copy constructor */ - inline Quaternion(const Quaternion& other) - : Base() - { - *this = other; - } - - /** Copies the value of the expression \a other into \c *this. - */ - template<typename OtherDerived> - inline Quaternion& operator=(const MatrixBase<OtherDerived>& other) - { - return Base::operator=(other.derived()); - } + inline Quaternion(const Quaternion& other) { m_coeffs = other.m_coeffs; } /** This is a special case of the templated operator=. Its purpose is to * prevent a default operator= from hiding the templated operator=. */ inline Quaternion& operator=(const Quaternion& other) { - return operator=<Quaternion>(other); + m_coeffs = other.m_coeffs; + return *this; } - /** \overload - * \returns a quaternion representing an identity rotation + /** \returns a quaternion representing an identity rotation + * \sa MatrixBase::identity() */ - static Quaternion identity() { return Quaternion(1, 0, 0, 0); } + inline static Quaternion identity() { return Quaternion(1, 0, 0, 0); } - /** \overload - * \sa Quaternion::identity() + /** \sa Quaternion::identity(), MatrixBase::setIdentity() */ - Quaternion& setIdentity() { *this << 1, 0, 0, 0; return *this; } + inline Quaternion& setIdentity() { m_coeffs << 1, 0, 0, 0; return *this; } + + /** \returns the squared norm of the quaternion's coefficients + * \sa Quaternion::norm(), MatrixBase::norm2() + */ + inline Scalar norm2() const { return m_coeffs.norm2(); } + + /** \returns the norm of the quaternion's coefficients + * \sa Quaternion::norm2(), MatrixBase::norm() + */ + inline Scalar norm() const { return m_coeffs.norm(); } template<typename Derived> Quaternion& fromRotationMatrix(const MatrixBase<Derived>& m); @@ -175,8 +142,23 @@ public: template<typename Derived> Vector3 operator* (const MatrixBase<Derived>& vec) const; -private: - // TODO discard here unreliable members. +protected: + + /** Constructor copying the value of the expression \a other */ + template<typename OtherDerived> + inline Quaternion(const Eigen::MatrixBase<OtherDerived>& other) + { + m_coeffs = other; + } + + /** Copies the value of the expression \a other into \c *this. + */ + template<typename OtherDerived> + inline Quaternion& operator=(const MatrixBase<OtherDerived>& other) + { + m_coeffs = other.derived(); + return *this; + } }; @@ -217,8 +199,8 @@ Quaternion<Scalar>::operator* (const MatrixBase<Derived>& v) const // in the litterature (30 versus 39 flops). It also requires two // Vector3 as temporaries. Vector3 uv; - uv = 2 * this->template start<3>().cross(v); - return v + this->w() * uv + this->template start<3>().cross(uv); + uv = 2 * this->vec().cross(v); + return v + this->w() * uv + this->vec().cross(uv); } /** Convert the quaternion to a 3x3 rotation matrix */ @@ -264,38 +246,39 @@ Quaternion<Scalar>::toRotationMatrix(void) const */ template<typename Scalar> template<typename Derived> -Quaternion<Scalar>& Quaternion<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& m) +Quaternion<Scalar>& Quaternion<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat) { // FIXME maybe this function could accept 4x4 and 3x4 matrices as well ? (simply update the assert) + // FIXME this function could also be static and returns a temporary ? ei_assert(Derived::RowsAtCompileTime==3 && Derived::ColsAtCompileTime==3); // This algorithm comes from "Quaternion Calculus and Fast Animation", // Ken Shoemake, 1987 SIGGRAPH course notes - Scalar t = m.trace(); + Scalar t = mat.trace(); if (t > 0) { t = ei_sqrt(t + 1.0); this->w() = 0.5*t; t = 0.5/t; - this->x() = (m.coeff(2,1) - m.coeff(1,2)) * t; - this->y() = (m.coeff(0,2) - m.coeff(2,0)) * t; - this->z() = (m.coeff(1,0) - m.coeff(0,1)) * t; + this->x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t; + this->y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t; + this->z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t; } else { int i = 0; - if (m(1,1) > m(0,0)) + if (mat.coeff(1,1) > mat.coeff(0,0)) i = 1; - if (m(2,2) > m(i,i)) + if (mat.coeff(2,2) > mat.coeff(i,i)) i = 2; int j = (i+1)%3; int k = (j+1)%3; - t = ei_sqrt(m.coeff(i,i)-m.coeff(j,j)-m.coeff(k,k) + 1.0); - this->coeffRef(i) = 0.5 * t; + t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + 1.0); + m_coeffs.coeffRef(i) = 0.5 * t; t = 0.5/t; - this->w() = (m.coeff(k,j)-m.coeff(j,k))*t; - this->coeffRef(j) = (m.coeff(j,i)+m.coeff(i,j))*t; - this->coeffRef(k) = (m.coeff(k,i)+m.coeff(i,k))*t; + this->w() = (mat.coeff(k,j)-mat.coeff(j,k))*t; + m_coeffs.coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t; + m_coeffs.coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t; } return *this; @@ -313,7 +296,7 @@ inline Quaternion<Scalar>& Quaternion<Scalar> ei_assert(Derived::SizeAtCompileTime==3); Scalar ha = 0.5*angle; this->w() = ei_cos(ha); - this->template start<3>() = ei_sin(ha) * axis; + this->vec() = ei_sin(ha) * axis; return *this; } @@ -327,7 +310,7 @@ void Quaternion<Scalar>::toAngleAxis(Scalar& angle, Vector3& axis) const // FIXME should we split this function to an "angle" and an "axis" functions ? // the drawbacks is that this approach would require to compute twice the norm of (x,y,z)... // or we returns a Vector4, or a small AngleAxis object... ??? - Scalar n2 = this->template start<3>().norm2(); + Scalar n2 = this->vec().norm2(); if (ei_isMuchSmallerThan(n2,Scalar(1))) { angle = 0; @@ -336,7 +319,7 @@ void Quaternion<Scalar>::toAngleAxis(Scalar& angle, Vector3& axis) const else { angle = 2*std::acos(this->w()); - axis = this->template start<3>() / ei_sqrt(n2); + axis = this->vec() / ei_sqrt(n2); } } @@ -394,11 +377,11 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::fromTwoVectors(const MatrixBase<D if (ei_isApprox(c,Scalar(1))) { // set to identity - this->w() = 1; this->template start<3>().setZero(); + this->w() = 1; this->vec().setZero(); } Scalar s = ei_sqrt((1+c)*2); Scalar invs = 1./s; - this->template start<3>() = axis * invs; + this->vec() = axis * invs; this->w() = s * 0.5; return *this; @@ -416,11 +399,11 @@ inline Quaternion<Scalar> Quaternion<Scalar>::inverse() const // FIXME should this funtion be called multiplicativeInverse and conjugate() be called inverse() or opposite() ?? Scalar n2 = this->norm2(); if (n2 > 0) - return conjugate() / n2; + return conjugate()._coeffs() / n2; else { // return an invalid result to flag the error - return this->zero(); + return Coefficients::zero(); } } |