diff options
Diffstat (limited to 'Eigen/src')
-rw-r--r-- | Eigen/src/Geometry/Quaternion.h | 578 | ||||
-rw-r--r-- | Eigen/src/Geometry/arch/Geometry_SSE.h | 23 |
2 files changed, 60 insertions, 541 deletions
diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index f3f60a08a..67b040165 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -2,6 +2,7 @@ // for linear algebra. // // Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr> +// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr> // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,11 +26,6 @@ #ifndef EIGEN_QUATERNION_H #define EIGEN_QUATERNION_H -template<typename Other, - int OtherRows=Other::RowsAtCompileTime, - int OtherCols=Other::ColsAtCompileTime> -struct ei_quaternion_assign_impl; - /** \geometry_module \ingroup Geometry_Module * * \class Quaternion @@ -52,471 +48,12 @@ struct ei_quaternion_assign_impl; * \sa class AngleAxis, class Transform */ -template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> > -{ - typedef _Scalar Scalar; -}; - -template<typename _Scalar> -class Quaternion : public RotationBase<Quaternion<_Scalar>,3> -{ - typedef RotationBase<Quaternion<_Scalar>,3> Base; - - - -public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4) - - using Base::operator*; - - /** the scalar type of the coefficients */ - typedef _Scalar Scalar; - - /** the type of the Coefficients 4-vector */ - typedef Matrix<Scalar, 4, 1> Coefficients; - /** the type of a 3D vector */ - typedef Matrix<Scalar,3,1> Vector3; - /** the equivalent rotation matrix type */ - typedef Matrix<Scalar,3,3> Matrix3; - /** the equivalent angle-axis type */ - typedef AngleAxis<Scalar> AngleAxisType; - - /** \returns the \c x coefficient */ - inline Scalar x() const { return m_coeffs.coeff(0); } - /** \returns the \c y coefficient */ - inline Scalar y() const { return m_coeffs.coeff(1); } - /** \returns the \c z coefficient */ - inline Scalar z() const { return m_coeffs.coeff(2); } - /** \returns the \c w coefficient */ - inline Scalar w() const { return m_coeffs.coeff(3); } - - /** \returns a reference to the \c x coefficient */ - inline Scalar& x() { return m_coeffs.coeffRef(0); } - /** \returns a reference to the \c y coefficient */ - inline Scalar& y() { return m_coeffs.coeffRef(1); } - /** \returns a reference to the \c z coefficient */ - inline Scalar& z() { return m_coeffs.coeffRef(2); } - /** \returns a reference to the \c w coefficient */ - inline Scalar& w() { return m_coeffs.coeffRef(3); } - - /** \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>(); } - - /** \returns a vector expression of the imaginary part (x,y,z) */ - inline Block<Coefficients,3,1> vec() { return m_coeffs.template start<3>(); } - - /** \returns a read-only vector expression of the coefficients (x,y,z,w) */ - inline const Coefficients& coeffs() const { return m_coeffs; } - - /** \returns a vector expression of the coefficients (x,y,z,w) */ - inline Coefficients& coeffs() { return m_coeffs; } - - /** Default constructor leaving the quaternion uninitialized. */ - inline Quaternion() {} - - /** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from - * its four coefficients \a w, \a x, \a y and \a z. - * - * \warning Note the order of the arguments: the real \a w coefficient first, - * while internally the coefficients are stored in the following order: - * [\c x, \c y, \c z, \c w] - */ - inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z) - { m_coeffs << x, y, z, w; } - - /** Copy constructor */ - inline Quaternion(const Quaternion& other) { m_coeffs = other.m_coeffs; } - - /** Constructs and initializes a quaternion from the angle-axis \a aa */ - explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; } - - /** Constructs and initializes a quaternion from either: - * - a rotation matrix expression, - * - a 4D vector expression representing quaternion coefficients. - * \sa operator=(MatrixBase<Derived>) - */ - template<typename Derived> - explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; } - - Quaternion& operator=(const Quaternion& other); - Quaternion& operator=(const AngleAxisType& aa); - template<typename Derived> - Quaternion& operator=(const MatrixBase<Derived>& m); - - /** \returns a quaternion representing an identity rotation - * \sa MatrixBase::Identity() - */ - inline static Quaternion Identity() { return Quaternion(1, 0, 0, 0); } - - /** \sa Quaternion::Identity(), MatrixBase::setIdentity() - */ - inline Quaternion& setIdentity() { m_coeffs << 0, 0, 0, 1; return *this; } - - /** \returns the squared norm of the quaternion's coefficients - * \sa Quaternion::norm(), MatrixBase::squaredNorm() - */ - inline Scalar squaredNorm() const { return m_coeffs.squaredNorm(); } - - /** \returns the norm of the quaternion's coefficients - * \sa Quaternion::squaredNorm(), MatrixBase::norm() - */ - inline Scalar norm() const { return m_coeffs.norm(); } - - /** Normalizes the quaternion \c *this - * \sa normalized(), MatrixBase::normalize() */ - inline void normalize() { m_coeffs.normalize(); } - /** \returns a normalized version of \c *this - * \sa normalize(), MatrixBase::normalized() */ - inline Quaternion normalized() const { return Quaternion(m_coeffs.normalized()); } - - /** \returns the dot product of \c *this and \a other - * Geometrically speaking, the dot product of two unit quaternions - * corresponds to the cosine of half the angle between the two rotations. - * \sa angularDistance() - */ - inline Scalar dot(const Quaternion& other) const { return m_coeffs.dot(other.m_coeffs); } - - inline Scalar angularDistance(const Quaternion& other) const; - - Matrix3 toRotationMatrix(void) const; - - template<typename Derived1, typename Derived2> - Quaternion& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b); - - inline Quaternion operator* (const Quaternion& q) const; - inline Quaternion& operator*= (const Quaternion& q); - - Quaternion inverse(void) const; - Quaternion conjugate(void) const; - - Quaternion slerp(Scalar t, const Quaternion& other) const; - - /** \returns \c *this with scalar type casted to \a NewScalarType - * - * Note that if \a NewScalarType is equal to the current scalar type of \c *this - * then this function smartly returns a const reference to \c *this. - */ - template<typename NewScalarType> - inline typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const - { return typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); } - - /** Copy constructor with scalar type conversion */ - template<typename OtherScalarType> - inline explicit Quaternion(const Quaternion<OtherScalarType>& other) - { m_coeffs = other.coeffs().template cast<Scalar>(); } - - /** \returns \c true if \c *this is approximately equal to \a other, within the precision - * determined by \a prec. - * - * \sa MatrixBase::isApprox() */ - bool isApprox(const Quaternion& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const - { return m_coeffs.isApprox(other.m_coeffs, prec); } - - Vector3 _transformVector(Vector3 v) const; - -protected: - Coefficients m_coeffs; -}; - -/** \ingroup Geometry_Module - * single precision quaternion type */ -typedef Quaternion<float> Quaternionf; -/** \ingroup Geometry_Module - * double precision quaternion type */ -typedef Quaternion<double> Quaterniond; - -// Generic Quaternion * Quaternion product -template<int Arch,typename Scalar> inline Quaternion<Scalar> -ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b) -{ - return Quaternion<Scalar> - ( - a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(), - a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(), - a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(), - a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x() - ); -} - -/** \returns the concatenation of two rotations as a quaternion-quaternion product */ -template <typename Scalar> -inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const -{ - return ei_quaternion_product<EiArch>(*this,other); -} - -/** \sa operator*(Quaternion) */ -template <typename Scalar> -inline Quaternion<Scalar>& Quaternion<Scalar>::operator*= (const Quaternion& other) -{ - return (*this = *this * other); -} - -/** Rotation of a vector by a quaternion. - * \remarks If the quaternion is used to rotate several points (>1) - * then it is much more efficient to first convert it to a 3x3 Matrix. - * Comparison of the operation cost for n transformations: - * - Quaternion: 30n - * - Via a Matrix3: 24 + 15n - */ -template <typename Scalar> -inline typename Quaternion<Scalar>::Vector3 -Quaternion<Scalar>::_transformVector(Vector3 v) const -{ - // Note that this algorithm comes from the optimization by hand - // of the conversion to a Matrix followed by a Matrix/Vector product. - // It appears to be much faster than the common algorithm found - // in the litterature (30 versus 39 flops). It also requires two - // Vector3 as temporaries. - Vector3 uv = Scalar(2) * this->vec().cross(v); - return v + this->w() * uv + this->vec().cross(uv); -} - -template<typename Scalar> -inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const Quaternion& other) -{ - m_coeffs = other.m_coeffs; - return *this; -} - -/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this - */ -template<typename Scalar> -inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const AngleAxisType& aa) -{ - Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings - this->w() = ei_cos(ha); - this->vec() = ei_sin(ha) * aa.axis(); - return *this; -} - -/** Set \c *this from the expression \a xpr: - * - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion - * - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix - * and \a xpr is converted to a quaternion - */ -template<typename Scalar> -template<typename Derived> -inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const MatrixBase<Derived>& xpr) -{ - ei_quaternion_assign_impl<Derived>::run(*this, xpr.derived()); - return *this; -} - -/** Convert the quaternion to a 3x3 rotation matrix. The quaternion is required to - * be normalized, otherwise the result is undefined. - */ -template<typename Scalar> -inline typename Quaternion<Scalar>::Matrix3 -Quaternion<Scalar>::toRotationMatrix(void) const -{ - // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!) - // if not inlined then the cost of the return by value is huge ~ +35%, - // however, not inlining this function is an order of magnitude slower, so - // it has to be inlined, and so the return by value is not an issue - Matrix3 res; - - const Scalar tx = 2*this->x(); - const Scalar ty = 2*this->y(); - const Scalar tz = 2*this->z(); - const Scalar twx = tx*this->w(); - const Scalar twy = ty*this->w(); - const Scalar twz = tz*this->w(); - const Scalar txx = tx*this->x(); - const Scalar txy = ty*this->x(); - const Scalar txz = tz*this->x(); - const Scalar tyy = ty*this->y(); - const Scalar tyz = tz*this->y(); - const Scalar tzz = tz*this->z(); - - res.coeffRef(0,0) = 1-(tyy+tzz); - res.coeffRef(0,1) = txy-twz; - res.coeffRef(0,2) = txz+twy; - res.coeffRef(1,0) = txy+twz; - res.coeffRef(1,1) = 1-(txx+tzz); - res.coeffRef(1,2) = tyz-twx; - res.coeffRef(2,0) = txz-twy; - res.coeffRef(2,1) = tyz+twx; - res.coeffRef(2,2) = 1-(txx+tyy); - - return res; -} - -/** Sets \c *this to be a quaternion representing a rotation between - * the two arbitrary vectors \a a and \a b. In other words, the built - * rotation represent a rotation sending the line of direction \a a - * to the line of direction \a b, both lines passing through the origin. - * - * \returns a reference to \c *this. - * - * Note that the two input vectors do \b not have to be normalized, and - * do not need to have the same norm. - */ -template<typename Scalar> -template<typename Derived1, typename Derived2> -inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b) -{ - Vector3 v0 = a.normalized(); - Vector3 v1 = b.normalized(); - Scalar c = v1.dot(v0); - - // if dot == -1, vectors are nearly opposites - // => accuraletly compute the rotation axis by computing the - // intersection of the two planes. This is done by solving: - // x^T v0 = 0 - // x^T v1 = 0 - // under the constraint: - // ||x|| = 1 - // which yields a singular value problem - if (c < Scalar(-1)+precision<Scalar>()) - { - c = std::max<Scalar>(c,-1); - Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose(); - SVD<Matrix<Scalar,2,3> > svd(m); - Vector3 axis = svd.matrixV().col(2); - - Scalar w2 = (Scalar(1)+c)*Scalar(0.5); - this->w() = ei_sqrt(w2); - this->vec() = axis * ei_sqrt(Scalar(1) - w2); - return *this; - } - Vector3 axis = v0.cross(v1); - Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2)); - Scalar invs = Scalar(1)/s; - this->vec() = axis * invs; - this->w() = s * Scalar(0.5); - - return *this; -} - -/** \returns the multiplicative inverse of \c *this - * Note that in most cases, i.e., if you simply want the opposite rotation, - * and/or the quaternion is normalized, then it is enough to use the conjugate. - * - * \sa Quaternion::conjugate() - */ -template <typename Scalar> -inline Quaternion<Scalar> Quaternion<Scalar>::inverse() const -{ - // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ?? - Scalar n2 = this->squaredNorm(); - if (n2 > 0) - return Quaternion(conjugate().coeffs() / n2); - else - { - // return an invalid result to flag the error - return Quaternion(Coefficients::Zero()); - } -} - -/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse - * if the quaternion is normalized. - * The conjugate of a quaternion represents the opposite rotation. - * - * \sa Quaternion::inverse() - */ -template <typename Scalar> -inline Quaternion<Scalar> Quaternion<Scalar>::conjugate() const -{ - return Quaternion(this->w(),-this->x(),-this->y(),-this->z()); -} - -/** \returns the angle (in radian) between two rotations - * \sa dot() - */ -template <typename Scalar> -inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const -{ - double d = ei_abs(this->dot(other)); - if (d>=1.0) - return 0; - return Scalar(2) * std::acos(d); -} - -/** \returns the spherical linear interpolation between the two quaternions - * \c *this and \a other at the parameter \a t - */ -template <typename Scalar> -Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const -{ - static const Scalar one = Scalar(1) - precision<Scalar>(); - Scalar d = this->dot(other); - Scalar absD = ei_abs(d); - if (absD>=one) - return *this; - - // theta is the angle between the 2 quaternions - Scalar theta = std::acos(absD); - Scalar sinTheta = ei_sin(theta); - - Scalar scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta; - Scalar scale1 = ei_sin( ( t * theta) ) / sinTheta; - if (d<0) - scale1 = -scale1; - - return Quaternion(scale0 * m_coeffs + scale1 * other.m_coeffs); -} - -// set from a rotation matrix -template<typename Other> -struct ei_quaternion_assign_impl<Other,3,3> -{ - typedef typename Other::Scalar Scalar; - inline static void run(Quaternion<Scalar>& q, const Other& mat) - { - // This algorithm comes from "Quaternion Calculus and Fast Animation", - // Ken Shoemake, 1987 SIGGRAPH course notes - Scalar t = mat.trace(); - if (t > 0) - { - t = ei_sqrt(t + Scalar(1.0)); - q.w() = Scalar(0.5)*t; - t = Scalar(0.5)/t; - q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t; - q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t; - q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t; - } - else - { - int i = 0; - if (mat.coeff(1,1) > mat.coeff(0,0)) - i = 1; - if (mat.coeff(2,2) > mat.coeff(i,i)) - i = 2; - int j = (i+1)%3; - int k = (j+1)%3; - - t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0)); - q.coeffs().coeffRef(i) = Scalar(0.5) * t; - t = Scalar(0.5)/t; - q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t; - q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t; - q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t; - } - } -}; - -// set from a vector of coefficients assumed to be a quaternion -template<typename Other> -struct ei_quaternion_assign_impl<Other,4,1> -{ - typedef typename Other::Scalar Scalar; - inline static void run(Quaternion<Scalar>& q, const Other& vec) - { - q.coeffs() = vec; - } -}; - -/*################################################################### - QuaternionBase and Map<Quaternion> and Quat - ###################################################################*/ - template<typename Other, int OtherRows=Other::RowsAtCompileTime, int OtherCols=Other::ColsAtCompileTime> struct ei_quaternionbase_assign_impl; -template<typename Scalar> class Quat; // [XXX] => remove when Quat becomes Quaternion +template<typename Scalar> class Quaternion; // [XXX] => remove when Quaternion becomes Quaternion template<typename Derived> struct ei_traits<QuaternionBase<Derived> > @@ -528,7 +65,8 @@ struct ei_traits<QuaternionBase<Derived> > }; template<class Derived> -class QuaternionBase : public RotationBase<Derived, 3> { +class QuaternionBase : public RotationBase<Derived, 3> +{ typedef RotationBase<Derived, 3> Base; public: using Base::operator*; @@ -563,10 +101,10 @@ public: inline Scalar& w() { return this->derived().coeffs().coeffRef(3); } /** \returns a read-only vector expression of the imaginary part (x,y,z) */ - inline const VectorBlock<typename ei_traits<Derived>::Coefficients,3,1> vec() const { return this->derived().coeffs().template start<3>(); } + inline const VectorBlock<typename ei_traits<Derived>::Coefficients,3> vec() const { return this->derived().coeffs().template start<3>(); } /** \returns a vector expression of the imaginary part (x,y,z) */ - inline VectorBlock<typename ei_traits<Derived>::Coefficients,3,1> vec() { return this->derived().coeffs().template start<3>(); } + inline VectorBlock<typename ei_traits<Derived>::Coefficients,3> vec() { return this->derived().coeffs().template start<3>(); } /** \returns a read-only vector expression of the coefficients (x,y,z,w) */ inline const typename ei_traits<Derived>::Coefficients& coeffs() const { return this->derived().coeffs(); } @@ -582,7 +120,7 @@ public: /** \returns a quaternion representing an identity rotation * \sa MatrixBase::Identity() */ - inline static Quat<Scalar> Identity() { return Quat<Scalar>(1, 0, 0, 0); } + inline static Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); } /** \sa Quaternion2::Identity(), MatrixBase::setIdentity() */ @@ -603,7 +141,7 @@ public: inline void normalize() { coeffs().normalize(); } /** \returns a normalized version of \c *this * \sa normalize(), MatrixBase::normalized() */ - inline Quat<Scalar> normalized() const { return Quat<Scalar>(coeffs().normalized()); } + inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); } /** \returns the dot product of \c *this and \a other * Geometrically speaking, the dot product of two unit quaternions @@ -619,29 +157,38 @@ public: template<typename Derived1, typename Derived2> QuaternionBase& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b); - template<class OtherDerived> inline Quat<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const; + template<class OtherDerived> inline Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const; template<class OtherDerived> inline QuaternionBase& operator*= (const QuaternionBase<OtherDerived>& q); - Quat<Scalar> inverse(void) const; - Quat<Scalar> conjugate(void) const; + Quaternion<Scalar> inverse(void) const; + Quaternion<Scalar> conjugate(void) const; - template<class OtherDerived> Quat<Scalar> slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const; + template<class OtherDerived> Quaternion<Scalar> slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const; /** \returns \c true if \c *this is approximately equal to \a other, within the precision * determined by \a prec. * * \sa MatrixBase::isApprox() */ - bool isApprox(const QuaternionBase& other, typename RealScalar prec = precision<Scalar>()) const + bool isApprox(const QuaternionBase& other, RealScalar prec = precision<Scalar>()) const { return coeffs().isApprox(other.coeffs(), prec); } Vector3 _transformVector(Vector3 v) const; + /** \returns \c *this with scalar type casted to \a NewScalarType + * + * Note that if \a NewScalarType is equal to the current scalar type of \c *this + * then this function smartly returns a const reference to \c *this. + */ + template<typename NewScalarType> + inline typename ei_cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const + { + return typename ei_cast_return_type<Derived,Quaternion<NewScalarType> >::type( + coeffs().template cast<NewScalarType>()); + } }; -/* ########### Quat -> Quaternion */ - template<typename _Scalar> -struct ei_traits<Quat<_Scalar> > +struct ei_traits<Quaternion<_Scalar> > { typedef _Scalar Scalar; typedef Matrix<_Scalar,4,1> Coefficients; @@ -651,18 +198,18 @@ struct ei_traits<Quat<_Scalar> > }; template<typename _Scalar> -class Quat : public QuaternionBase<Quat<_Scalar> >{ - typedef QuaternionBase<Quat<_Scalar> > Base; +class Quaternion : public QuaternionBase<Quaternion<_Scalar> >{ + typedef QuaternionBase<Quaternion<_Scalar> > Base; public: using Base::operator=; typedef _Scalar Scalar; - typedef typename ei_traits<Quat<Scalar> >::Coefficients Coefficients; + typedef typename ei_traits<Quaternion<Scalar> >::Coefficients Coefficients; typedef typename Base::AngleAxisType AngleAxisType; /** Default constructor leaving the quaternion uninitialized. */ - inline Quat() {} + inline Quaternion() {} /** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from * its four coefficients \a w, \a x, \a y and \a z. @@ -671,38 +218,29 @@ public: * while internally the coefficients are stored in the following order: * [\c x, \c y, \c z, \c w] */ - inline Quat(Scalar w, Scalar x, Scalar y, Scalar z) + inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z) { coeffs() << x, y, z, w; } /** Constructs and initialize a quaternion from the array data * This constructor is also used to map an array */ - inline Quat(const Scalar* data) : m_coeffs(data) {} + inline Quaternion(const Scalar* data) : m_coeffs(data) {} /** Copy constructor */ -// template<class Derived> inline Quat(const QuaternionBase<Derived>& other) { m_coeffs = other.coeffs(); } [XXX] redundant with 703 +// template<class Derived> inline Quaternion(const QuaternionBase<Derived>& other) { m_coeffs = other.coeffs(); } [XXX] redundant with 703 /** Constructs and initializes a quaternion from the angle-axis \a aa */ - explicit inline Quat(const AngleAxisType& aa) { *this = aa; } + explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; } /** Constructs and initializes a quaternion from either: * - a rotation matrix expression, * - a 4D vector expression representing quaternion coefficients. */ template<typename Derived> - explicit inline Quat(const MatrixBase<Derived>& other) { *this = other; } - - /** \returns \c *this with scalar type casted to \a NewScalarType - * - * Note that if \a NewScalarType is equal to the current scalar type of \c *this - * then this function smartly returns a const reference to \c *this. - */ - template<class Derived> - inline typename ei_cast_return_type<Quat, QuaternionBase<Derived> >::type cast() const - { return typename ei_cast_return_type<Quat, QuaternionBase<Derived> >::type(*this); } + explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; } /** Copy constructor with scalar type conversion */ template<class Derived> - inline explicit Quat(const QuaternionBase<Derived>& other) + inline explicit Quaternion(const QuaternionBase<Derived>& other) { m_coeffs = other.coeffs().template cast<Scalar>(); } inline Coefficients& coeffs() { return m_coeffs;} @@ -712,9 +250,9 @@ protected: Coefficients m_coeffs; }; -/* ########### Map<Quat> */ +/* ########### Map<Quaternion> */ -/** \class Map<Quat> +/** \class Map<Quaternion> * \nonstableyet * * \brief Expression of a quaternion @@ -724,8 +262,8 @@ protected: * \sa class Quaternion, class QuaternionBase */ template<typename _Scalar, int _PacketAccess> -struct ei_traits<Map<Quat<_Scalar>, _PacketAccess> >: -ei_traits<Quat<_Scalar> > +struct ei_traits<Map<Quaternion<_Scalar>, _PacketAccess> >: +ei_traits<Quaternion<_Scalar> > { typedef _Scalar Scalar; typedef Map<Matrix<_Scalar,4,1> > Coefficients; @@ -735,14 +273,14 @@ ei_traits<Quat<_Scalar> > }; template<typename _Scalar, int PacketAccess> -class Map<Quat<_Scalar>, PacketAccess > : public QuaternionBase<Map<Quat<_Scalar>, PacketAccess> >, ei_no_assignment_operator { +class Map<Quaternion<_Scalar>, PacketAccess > : public QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> >, ei_no_assignment_operator { public: typedef _Scalar Scalar; - typedef typename ei_traits<Map<Quat<Scalar>, PacketAccess> >::Coefficients Coefficients; + typedef typename ei_traits<Map<Quaternion<Scalar>, PacketAccess> >::Coefficients Coefficients; - inline Map<Quat<Scalar>, PacketAccess >(const Scalar* coeffs) : m_coeffs(coeffs) {} + inline Map<Quaternion<Scalar>, PacketAccess >(const Scalar* coeffs) : m_coeffs(coeffs) {} inline Coefficients& coeffs() { return m_coeffs;} inline const Coefficients& coeffs() const { return m_coeffs;} @@ -751,16 +289,16 @@ class Map<Quat<_Scalar>, PacketAccess > : public QuaternionBase<Map<Quat<_Scalar Coefficients m_coeffs; }; -typedef Map<Quat<double> > QuaternionMapd; -typedef Map<Quat<float> > QuaternionMapf; -typedef Map<Quat<double>, Aligned> QuaternionMapAlignedd; -typedef Map<Quat<float>, Aligned> QuaternionMapAlignedf; +typedef Map<Quaternion<double> > QuaternionMapd; +typedef Map<Quaternion<float> > QuaternionMapf; +typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd; +typedef Map<Quaternion<float>, Aligned> QuaternionMapAlignedf; // Generic Quaternion * Quaternion product template<int Arch, class Derived, class OtherDerived, typename Scalar, int PacketAccess> struct ei_quat_product { - inline static Quat<Scalar> run(const QuaternionBase<Derived>& a, const QuaternionBase<OtherDerived>& b){ - return Quat<Scalar> + inline static Quaternion<Scalar> run(const QuaternionBase<Derived>& a, const QuaternionBase<OtherDerived>& b){ + return Quaternion<Scalar> ( a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(), a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(), @@ -773,12 +311,12 @@ template<int Arch, class Derived, class OtherDerived, typename Scalar, int Packe /** \returns the concatenation of two rotations as a quaternion-quaternion product */ template <class Derived> template <class OtherDerived> -inline Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const +inline Quaternion<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const { EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret), YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) return ei_quat_product<EiArch, Derived, OtherDerived, - ei_traits<Derived>::Scalar, + typename ei_traits<Derived>::Scalar, ei_traits<Derived>::PacketAccess && ei_traits<OtherDerived>::PacketAccess>::run(*this, other); } @@ -938,16 +476,16 @@ inline QuaternionBase<Derived>& QuaternionBase<Derived>::setFromTwoVectors(const * \sa Quaternion2::conjugate() */ template <class Derived> -inline Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::inverse() const +inline Quaternion<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::inverse() const { // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ?? Scalar n2 = this->squaredNorm(); if (n2 > 0) - return Quat<Scalar>(conjugate().coeffs() / n2); + return Quaternion<Scalar>(conjugate().coeffs() / n2); else { // return an invalid result to flag the error - return Quat<Scalar>(ei_traits<Derived>::Coefficients::Zero()); + return Quaternion<Scalar>(ei_traits<Derived>::Coefficients::Zero()); } } @@ -958,9 +496,9 @@ inline Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase * \sa Quaternion2::inverse() */ template <class Derived> -inline Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::conjugate() const +inline Quaternion<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::conjugate() const { - return Quat<Scalar>(this->w(),-this->x(),-this->y(),-this->z()); + return Quaternion<Scalar>(this->w(),-this->x(),-this->y(),-this->z()); } /** \returns the angle (in radian) between two rotations @@ -981,13 +519,13 @@ inline typename ei_traits<QuaternionBase<Derived> >::Scalar QuaternionBase<Deriv */ template <class Derived> template <class OtherDerived> -Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const +Quaternion<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const { static const Scalar one = Scalar(1) - precision<Scalar>(); Scalar d = this->dot(other); Scalar absD = ei_abs(d); if (absD>=one) - return Quat<Scalar>(*this); + return Quaternion<Scalar>(*this); // theta is the angle between the 2 quaternions Scalar theta = std::acos(absD); @@ -998,7 +536,7 @@ Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derive if (d<0) scale1 = -scale1; - return Quat<Scalar>(scale0 * coeffs() + scale1 * other.coeffs()); + return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs()); } // set from a rotation matrix diff --git a/Eigen/src/Geometry/arch/Geometry_SSE.h b/Eigen/src/Geometry/arch/Geometry_SSE.h index c608e4843..1b8f6aead 100644 --- a/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -26,31 +26,12 @@ #ifndef EIGEN_GEOMETRY_SSE_H #define EIGEN_GEOMETRY_SSE_H -template<> inline Quaternion<float> -ei_quaternion_product<EiArch_SSE,float>(const Quaternion<float>& _a, const Quaternion<float>& _b) -{ - const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000)); - Quaternion<float> res; - __m128 a = _a.coeffs().packet<Aligned>(0); - __m128 b = _b.coeffs().packet<Aligned>(0); - __m128 flip1 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,1,2,0,2), - ei_vec4f_swizzle1(b,2,0,1,2)),mask); - __m128 flip2 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,3,3,3,1), - ei_vec4f_swizzle1(b,0,1,2,1)),mask); - ei_pstore(&res.x(), - _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,ei_vec4f_swizzle1(b,3,3,3,3)), - _mm_mul_ps(ei_vec4f_swizzle1(a,2,0,1,0), - ei_vec4f_swizzle1(b,1,2,0,0))), - _mm_add_ps(flip1,flip2))); - return res; -} - template<class Derived, class OtherDerived> struct ei_quat_product<EiArch_SSE, Derived, OtherDerived, float, Aligned> { - inline static Quat<float> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b) + inline static Quaternion<float> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b) { const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000)); - Quat<float> res; + Quaternion<float> res; __m128 a = _a.coeffs().packet<Aligned>(0); __m128 b = _b.coeffs().packet<Aligned>(0); __m128 flip1 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,1,2,0,2), |