Re: [eigen] Mapping array of scalars into quaternions

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]



ok, sorry it got me so long. i've been on a honeymoon with my new
computer, getting the new hardware working with linux...

I understand :)

Indeed, 'Scalar' isn't known by the QuaternionBase class. Yet this
class uses 'Scalar', for example in the prototype of the x() method.
So i'm puzzled, how could the code work for you?

The visual studio compiler seem more permissive. And i didn't check with gcc.

The solution to this problem might interest you, since below you write

Ok, the fact that my previous patch worked despite the missing definition of Scalar added to my confusion. With the rewriting, it's clearer.

The second error that I got was that the derived() methods that you
call in QuaternionBase, aren't defined. It should be just a matter of
static_cast'ing the 'this' pointer, like in MatrixBase.h.

Indeed.

Now if you do this, one should let QuaternionBase know that the
pointer is aligned. in the ei_traits, you'd add an enum that says
whether the pointer is aligned. When it's aligned,
QuaternionBase::operator* could use the vectorized path!

Actually the multiplication of two quaternions is not vectorized? Are you refering to the version proposed by Rohit in the archives ?

As usual, I have some questions :) I don't understand the difference in your enum between :

	enum { Unaligned=0, Aligned=1 };
and 	enum { AsRequested=0, EnforceAlignedAccess=2 };

Aligned is used In map in test/map.cpp :

	VectorType ma1 = Map<VectorType, Aligned>(array1, size);

and AsRequested is used in ForwardDeclarations.h as the default argument for PacketAccess.

Does it means that "AsRequested" and "Unaligned" are equivalent ? Because I am actually not comfortable how to use PacketAccess and which value to provide to QuaternionWrapper.

There's actually no tests, I'll do them when I can.

--
Mathieu Gautier
# HG changeset patch
# User Mathieu Gautier <mathieu.gautier@xxxxxx>
# Date 1256572951 0
# Node ID e8cafd6fb24cd53d625d04fddbabd4e9bdb33e19
# Parent  c3748f1896fcea50883cc0d8bc7e7f7ecd9109a2
* Use VectorBlock
* Add Align Flag
* Compile with gcc :)

diff -r c3748f1896fc -r e8cafd6fb24c Eigen/src/Core/util/ForwardDeclarations.h
--- a/Eigen/src/Core/util/ForwardDeclarations.h	Fri Oct 23 17:13:49 2009 +0200
+++ b/Eigen/src/Core/util/ForwardDeclarations.h	Mon Oct 26 16:02:31 2009 +0000
@@ -129,8 +129,9 @@
 // Geometry module:
 template<typename Derived, int _Dim> class RotationBase;
 template<typename Lhs, typename Rhs> class Cross;
+template<typename Derived> class QuaternionBase;
 template<typename Scalar> class Quaternion;
-template<typename Scalar> class QuaternionWrapper;
+template<typename Scalar, int PacketAccess = AsRequested> class QuaternionWrapper;
 template<typename Scalar> class Rotation2D;
 template<typename Scalar> class AngleAxis;
 template<typename Scalar,int Dim,int Mode=Affine> class Transform;
diff -r c3748f1896fc -r e8cafd6fb24c Eigen/src/Geometry/Quaternion.h
--- a/Eigen/src/Geometry/Quaternion.h	Fri Oct 23 17:13:49 2009 +0200
+++ b/Eigen/src/Geometry/Quaternion.h	Mon Oct 26 16:02:31 2009 +0000
@@ -518,12 +518,23 @@
 
 template<typename Scalar> class Quat; // [XXX] remove
 
+template<typename Derived>
+struct ei_traits<QuaternionBase<Derived> >
+{
+  typedef typename Derived::Scalar Scalar;
+  enum {
+    PacketAccess = Derived::PacketAccess
+  };
+};
+
 template<class Derived>
 class QuaternionBase : public RotationBase<Derived, 3> {
   typedef RotationBase<Derived, 3> Base;
 public:
   using Base::operator*;
 
+  typedef typename ei_traits<QuaternionBase<Derived> >::Scalar Scalar;
+
  // typedef typename Matrix<Scalar,4,1> Coefficients;
   /** the type of a 3D vector */
   typedef Matrix<Scalar,3,1> Vector3;
@@ -533,34 +544,34 @@
   typedef AngleAxis<Scalar> AngleAxisType;
 
   /** \returns the \c x coefficient */
-  inline Scalar x() const { return derived().coeffs().coeff(0); }
+  inline Scalar x() const { return this->derived().coeffs().coeff(0); }
   /** \returns the \c y coefficient */
-  inline Scalar y() const { return derived().coeffs().coeff(1); }
+  inline Scalar y() const { return this->derived().coeffs().coeff(1); }
   /** \returns the \c z coefficient */
-  inline Scalar z() const { return derived().coeffs().coeff(2); }
+  inline Scalar z() const { return this->derived().coeffs().coeff(2); }
   /** \returns the \c w coefficient */
-  inline Scalar w() const { return derived().coeffs().coeff(3); }
+  inline Scalar w() const { return this->derived().coeffs().coeff(3); }
 
   /** \returns a reference to the \c x coefficient */
-  inline Scalar& x() { return derived().coeffs().coeffRef(0); }
+  inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
   /** \returns a reference to the \c y coefficient */
-  inline Scalar& y() { return derived().coeffs().coeffRef(1); }
+  inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
   /** \returns a reference to the \c z coefficient */
-  inline Scalar& z() { return derived().coeffs().coeffRef(2); }
+  inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
   /** \returns a reference to the \c w coefficient */
-  inline Scalar& w() { return derived().coeffs().coeffRef(3); }
+  inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
 
   /** \returns a read-only vector expression of the imaginary part (x,y,z) */
-  inline const Block<typename ei_traits<Derived>::Coefficients,3,1> vec() const { return derived().coeffs().template start<3>(); }
+  inline const VectorBlock<typename ei_traits<Derived>::Coefficients,3,1> vec() const { return this->derived().coeffs().template start<3>(); }
 
   /** \returns a vector expression of the imaginary part (x,y,z) */
-  inline Block<typename ei_traits<Derived>::Coefficients,3,1> vec() { return derived().coeffs().template start<3>(); }
+  inline VectorBlock<typename ei_traits<Derived>::Coefficients,3,1> 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 derived().coeffs(); }
+  inline const typename ei_traits<Derived>::Coefficients& coeffs() const { return this->derived().coeffs(); }
 
   /** \returns a vector expression of the coefficients (x,y,z,w) */
-  inline typename ei_traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
+  inline typename ei_traits<Derived>::Coefficients& coeffs() { return this->derived().coeffs(); }
 
   template<class OtherDerived> QuaternionBase& operator=(const QuaternionBase<OtherDerived>& other);
   QuaternionBase& operator=(const AngleAxisType& aa);
@@ -630,19 +641,23 @@
 
 template<typename _Scalar>
 struct ei_traits<Quat<_Scalar> >
- : ei_traits<Matrix<_Scalar,4,1> >
 {
-  typedef typename Matrix<_Scalar,4,1> Coefficients;
+  typedef Matrix<_Scalar,4,1> Coefficients; //[XXX] MVSC -> + typename
+  enum{
+    PacketAccess = Aligned 
+  };
 };
 
 template<typename _Scalar>
 class Quat : public QuaternionBase<Quat<_Scalar> >{
-  typedef QuaternionBase<Quat<Scalar> > Base;
+  typedef QuaternionBase<Quat<_Scalar> > Base;
 public:
+  using Base::operator=;
 
-  typename typedef ei_traits<Quat<_Scalar> >::Coefficients Coefficients;
+  typedef _Scalar Scalar;
 
-  using Base::operator=;
+  typedef typename ei_traits<Quat<Scalar> >::Coefficients Coefficients; //[XXX] MVSC -> + typename
+  typedef typename Base::AngleAxisType AngleAxisType;
 
   /** Default constructor leaving the quaternion uninitialized. */
   inline Quat() {}
@@ -662,7 +677,7 @@
   inline Quat(const Scalar* data) : m_coeffs(data) {}
 
   /** Copy constructor */
-  inline Quat(const QuaternionBase& other) { m_coeffs = other.coeffs(); }
+//  template<class Derived> inline Quat(const QuaternionBase<Derived>& other) { m_coeffs = other.coeffs(); } [XXX] see 693
 
   /** Constructs and initializes a quaternion from the angle-axis \a aa */
   explicit inline Quat(const AngleAxisType& aa) { *this = aa; }
@@ -679,13 +694,13 @@
     * 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<QuaternionBase, QuaternionBase<NewScalarType> >::type cast() const
-  { return typename ei_cast_return_type<QuaternionBase, QuaternionBase<NewScalarType> >::type(*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); }
 
   /** Copy constructor with scalar type conversion */
-  template<typename OtherScalarType>
-  inline explicit Quat(const QuaternionBase<OtherScalarType>& other)
+  template<class Derived>
+  inline explicit Quat(const QuaternionBase<Derived>& other)
   { m_coeffs = other.coeffs().template cast<Scalar>(); }
 
   inline Coefficients& coeffs() { return m_coeffs;}
@@ -706,12 +721,14 @@
   *
   * \sa class Quaternion, class QuaternionBase
   */
-template<typename _Scalar>
-struct ei_traits<QuaternionWrapper<_Scalar> >
+template<typename _Scalar, int _PacketAccess>
+struct ei_traits<QuaternionWrapper<_Scalar, _PacketAccess> >
 {
-  typedef Map<Matrix<_Scalar, 4, 1> > Coefficients;
-  typedef Matrix<_Scalar, 4, 1> CoeffType;
-  typedef typename Coefficients::Scalar Scalar;
+  typedef _Scalar Scalar;
+  typedef Map<Matrix<Scalar, 4, 1>, _PacketAccess> Coefficients;
+  enum {
+    PacketAccess = _PacketAccess
+  };
  /* enum {
     RowsAtCompileTime = Coefficients::SizeAtCompileTime,
     ColsAtCompileTime = Coefficients::SizeAtCompileTime,
@@ -721,11 +738,13 @@
   }; */ //[XXX] ??
 };
 
-template<typename _Scalar>
-class QuaternionWrapper : public QuaternionBase<QuaternionWrapper<_Scalar> >, ei_no_assignment_operator {
+template<typename _Scalar, int PacketAccess>
+class QuaternionWrapper : public QuaternionBase<QuaternionWrapper<_Scalar, PacketAccess> >, ei_no_assignment_operator {
   public:
-    typename typedef ei_traits<QuaternionWrapper<_Scalar> >::Coefficients Coefficients;
-    typename typedef ei_traits<QuaternionWrapper<_Scalar> >::CoeffType CoeffType;
+    
+    typedef _Scalar Scalar;
+
+    typedef typename ei_traits<QuaternionWrapper<Scalar, PacketAccess> >::Coefficients Coefficients;
 
     inline QuaternionWrapper(const Scalar* coeffs) : m_coeffs(coeffs) {}
     
@@ -733,17 +752,19 @@
     inline const Coefficients& coeffs() const { return m_coeffs;}
 
   protected:
-    typename Coefficients m_coeffs;
+    Coefficients m_coeffs;
 };
 
 typedef QuaternionWrapper<double> QuaternionMapd;
 typedef QuaternionWrapper<float> QuaternionMapf;
+typedef QuaternionWrapper<double, Aligned> QuaternionMapAlignedd;
+typedef QuaternionWrapper<float, Aligned> QuaternionMapAlignedf;
 
 // Generic Quaternion * Quaternion product
 template<class Derived, class OtherDerived> inline Quat<typename ei_traits<Derived>::Scalar>
 ei_quat_product(const QuaternionBase<Derived>& a, const QuaternionBase<OtherDerived>& b)
 {
-  return Quat<ei_traits<Derived>::Scalar>
+  return Quat<ei_traits<Derived> >::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(),
@@ -755,7 +776,7 @@
 /** \returns the concatenation of two rotations as a quaternion-quaternion product */
 template <class Derived>
 template <class OtherDerived>
-inline Quat<typename ei_traits<Derived>::Scalar> QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
+inline Quat<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)
@@ -794,7 +815,7 @@
 template<class OtherDerived>
 inline QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
 {
-  m_coeffs = other.coeffs();
+  coeffs() = other.coeffs();
   return *this;
 }
 
@@ -918,7 +939,7 @@
   * \sa Quaternion2::conjugate()
   */
 template <class Derived>
-inline Quat<typename ei_traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
+inline Quat<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();
@@ -927,7 +948,7 @@
   else
   {
     // return an invalid result to flag the error
-    return Quat<Scalar>(Coefficients::Zero());
+    return Quat<Scalar>(ei_traits<Derived>::Coefficients::Zero());
   }
 }
 
@@ -938,7 +959,7 @@
   * \sa Quaternion2::inverse()
   */
 template <class Derived>
-inline Quat<typename ei_traits<Derived>::Scalar> QuaternionBase<Derived>::conjugate() const
+inline Quat<typename ei_traits<QuaternionBase<Derived> >::Scalar> QuaternionBase<Derived>::conjugate() const
 {
   return Quat<Scalar>(this->w(),-this->x(),-this->y(),-this->z());
 }
@@ -948,7 +969,7 @@
   */
 template <class Derived>
 template <class OtherDerived>
-inline typename ei_traits<Derived>::Scalar QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
+inline typename ei_traits<QuaternionBase<Derived> >::Scalar QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
 {
   double d = ei_abs(this->dot(other));
   if (d>=1.0)
@@ -961,7 +982,7 @@
   */
 template <class Derived>
 template <class OtherDerived>
-Quat<typename ei_traits<Derived>::Scalar> QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
+Quat<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);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/