// @(#)root/physics:$Id$
// Author: Eric Anciant 28/06/2005


//////////////////////////////////////////////////////////////////////////
//____________________
//
//  A Quaternion Class
// Begin_html
// <p> Quaternion is a 4-component mathematic object quite convenient when dealing with
// space rotation (or reference frame transformation). </p>
// </p>
// <p> In short, think of quaternion Q as a 3-vector augmented by a real number. Q = Q|<sub>r</sub> + Q|<sub>V</sub>
//
// <p> <u> Quaternion multiplication :</u>
// </p>
// <p> Quaternion multiplication is given by :
// <br> Q.Q'        = (Q|<sub>r</sub> + Q|<sub>V</sub> )*( Q'|<sub>r</sub> + Q'|<sub>V</sub>)
// <br>         = [ Q|<sub>r</sub>*Q'|<sub>r</sub> - Q|<sub>V</sub>*Q'|<sub>V</sub> ] + [ Q|<sub>r</sub>*Q'|<sub>V</sub> + Q'|<sub>r</sub>*Q|<sub>V</sub> + Q|<sub>V</sub> X Q'|<sub>V</sub> ]
// <br>
// <br> where :
// <br> Q|<sub>r</sub>*Q'|<sub>r</sub>  is a real number product of real numbers
// <br> Q|<sub>V</sub>*Q'|<sub>V</sub> is a real number, scalar product of two 3-vectors
// <br> Q|<sub>r</sub>*Q'|<sub>V</sub> is a 3-vector, scaling of a 3-vector by a real number
// <br> Q|<sub>V</sub>XQ'|<sub>V</sub> is a 3-vector, cross product of two 3-vectors
// <br>
// <br> Thus, quaternion product is a generalization of real number product and product of a vector by a real number. Product of two pure vectors gives a quaternion whose real part is the opposite of scalar product and the vector part the cross product.
// </p>
//
// <p> The conjugate of a quaternion Q = Q|<sub>r</sub> + Q|<sub>V</sub> is Q_bar = Q|<sub>r</sub> - Q|<sub>V</sub>
// </p>
// <p> The magnitude of a quaternion Q is given by |Q|² = Q.Q_bar = Q_bar.Q = Q²|<sub>r</sub> + |Q|<sub>V</sub>|²
// </p>
// <p> Therefore, the inverse of a quaternion is Q<sup>-1</sup> = Q_bar /|Q|²
// </p>
// <p> "unit" quaternion is a quaternion of magnitude 1 : |Q|² = 1.
// <br> Unit quaternions are a subset of the quaternions set.
// </p>
//
// <p> <u>Quaternion and rotations :</u>
// </p>
//
// <p> A rotation of angle <font face="Symbol">f</font> around a given axis, is represented by a unit quaternion Q :
// <br> -        The axis of the rotation is given by the vector part of Q.
// <br> -        The ratio between the magnitude of the vector part and the real part of Q equals tan(<font face="Symbol">f</font>/2).
// </p>
// <p> In other words : Q = Q|<sub>r</sub> + Q|<sub>V</sub> = cos(<font face="Symbol">f</font>/2) + sin(<font face="Symbol">f</font>/2).
// <br> (where u is a unit vector // to the rotation axis,
//                        cos(<font face="Symbol">f</font>/2) is the real part, sin(<font face="Symbol">f</font>/2).u is the vector part)
// <br> Note : The quaternion of identity is Q<sub>I</sub> = cos(0) + sin(0)*(any vector) = 1.
// </p>
// <p> The composition of two rotations is described by the product of the two corresponding quaternions.
// <br> As for 3-space rotations, quaternion multiplication is not commutative !
// <br>
// <br> Q = Q<sub>1</sub>.Q<sub>2</sub> represents the composition of the successive rotation R1 and R2 expressed in the <b>current</b> frame (the axis of rotation hold by Q<sub>2</sub> is expressed in the frame as it is after R1 rotation).
// <br> Q = Q<sub>2</sub>.Q<sub>1</sub> represents the composition of the successive rotation R1 and R2 expressed in the <b>initial</b> reference frame.
// </p>
// <p> The inverse of a rotation is a rotation about the same axis but of opposite angle, thus if Q is a unit quaternion,
// <br> Q = cos(<font face="Symbol">f</font>/2) + sin(<font face="Symbol">f</font>/2).u = Q|<sub>r</sub> + Q|<sub>V</sub>, then :
// <br> Q<sup>-1</sup> =cos(-<font face="Symbol">f</font>/2) + sin(-<font face="Symbol">f</font>/2).u = cos(<font face="Symbol">f</font>/2) - sin(<font face="Symbol">f</font>/2).u = Q|<sub>r</sub> -Q|<sub>V</sub> is its inverse quaternion.
// </p>
// <p> One verifies that :
// <br> Q.Q<sup>-1</sup> = Q<sup>-1</sup>.Q = Q|<sub>r</sub>*Q|<sub>r</sub> + Q|<sub>V</sub>*Q|<sub>V</sub> + Q|<sub>r</sub>*Q|<sub>V</sub> -Q|<sub>r</sub>*Q|<sub>V</sub> + Q|<sub>V</sub>XQ|<sub>V</sub>
// <br>                 = Q²|<sub>r</sub> + Q²|<sub>V</sub> = 1
// </p>
// <br>
// <p> The rotation of a vector V by the rotation described by a unit quaternion Q is obtained by the following operation : V' = Q*V*Q<sup>-1</sup>, considering V as a quaternion whose real part is null.
// </p>
// <p> <u>Numeric computation considerations :</u>
// </p>
// <p> Numerically, the quaternion multiplication involves 12 additions and 16 multiplications.
// <br> It is therefore faster than 3x3 matrixes multiplication involving 18 additions and 27 multiplications.
// <br>
// <br> On the contrary, rotation of a vector by the above formula ( Q*V*Q<sup>-1</sup> ) involves 18 additions and 24 multiplications, whereas multiplication of a 3-vector by a 3x3 matrix involves only 6 additions and 9 multiplications.
// <br>
// <br> When dealing with numerous composition of space rotation, it is therefore faster to use quaternion product. On the other hand if a huge set of vectors must be rotated by a given quaternion, it is more optimized to convert the quaternion into a rotation matrix once, and then use that later to rotate the set of vectors.
// </p>
// <p> <u>More information :</u>
// </p>
// <p>
// <A HREF="http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation">
//  en.wikipedia.org/wiki/Quaternions_and_spatial_rotation </A>.
// <br> <br>
// <A HREF="http://en.wikipedia.org/wiki/Quaternion">
//  en.wikipedia.org/wiki/Quaternion </A>.
// </p>
// <p> _______________________________________________
// <br>
// <p> This Class represents all quaternions (unit or non-unit)
// <br> It possesses a Normalize() method to make a given quaternion unit
// <br> The Rotate(TVector3&) and Rotation(TVector3&) methods can be used even for a non-unit quaternion, in that case, the proper normalization is applied to perform the rotation.
// <br>
// <br> A TRotation constructor exists than takes a quaternion for parameter (even non-unit), in that cas the proper normalisation is applied.
// </p>
// End_html

#include "TMath.h"
#include "TQuaternion.h"

ClassImp(TQuaternion)

/****************** CONSTRUCTORS ****************************************************/
//______________________________________________________________________________
TQuaternion::TQuaternion(const TQuaternion & q) : TObject(q),
  fRealPart(q.fRealPart), fVectorPart(q.fVectorPart) {}

TQuaternion::TQuaternion(const TVector3 & vect, Double_t real)
        : fRealPart(real), fVectorPart(vect)  {}

TQuaternion::TQuaternion(const Double_t * x0)
        : fRealPart(x0[3]), fVectorPart(x0) {}

TQuaternion::TQuaternion(const Float_t * x0)
        : fRealPart(x0[3]), fVectorPart(x0) {}

TQuaternion::TQuaternion(Double_t real, Double_t X, Double_t Y, Double_t Z)
        : fRealPart(real), fVectorPart(X,Y,Z) {}

TQuaternion::~TQuaternion() {}

//______________________________________________________________________________
Double_t TQuaternion::operator () (int i) const {
   //dereferencing operator const
   switch(i) {
      case 0:
      case 1:
      case 2:
         return fVectorPart(i);
      case 3:
         return fRealPart;
      default:
         Error("operator()(i)", "bad index (%d) returning 0",i);
   }
   return 0.;
}

//______________________________________________________________________________
Double_t & TQuaternion::operator () (int i) {
   //dereferencing operator
   switch(i) {
      case 0:
      case 1:
      case 2:
         return fVectorPart(i);
      case 3:
         return fRealPart;
      default:
         Error("operator()(i)", "bad index (%d) returning &fRealPart",i);
   }
   return fRealPart;
}
//_____________________________________
Double_t TQuaternion::GetQAngle() const {
   // Get angle of quaternion (rad)
   // N.B : this angle is half of the corresponding rotation angle

   if (fRealPart == 0) return TMath::PiOver2();
   Double_t denominator = fVectorPart.Mag();
   return atan(denominator/fRealPart);
}

//_____________________________________
TQuaternion& TQuaternion::SetQAngle(Double_t angle) {
   // Set angle of quaternion (rad) - keep quaternion norm
   // N.B : this angle is half of the corresponding rotation angle

   Double_t norm = Norm();
   Double_t normSinV = fVectorPart.Mag();
   if (normSinV != 0) fVectorPart *= (sin(angle)*norm/normSinV);
   fRealPart = cos(angle)*norm;

   return (*this);
}

//_____________________________________
TQuaternion& TQuaternion::SetAxisQAngle(TVector3& v,Double_t QAngle) {
   // set quaternion from vector and angle (rad)
   // quaternion is set as unitary
   // N.B : this angle is half of the corresponding rotation angle

   fVectorPart = v;
   double norm = v.Mag();
   if (norm>0) fVectorPart*=(1./norm);
   fVectorPart*=sin(QAngle);
   fRealPart = cos(QAngle);

   return (*this);
}

/**************** REAL TO QUATERNION ALGEBRA ****************************************/

//_____________________________________
TQuaternion TQuaternion::operator+(Double_t real) const {
   // sum of quaternion with a real

   return TQuaternion(fVectorPart, fRealPart + real);
}

//_____________________________________
TQuaternion TQuaternion::operator-(Double_t real) const {
   // substraction of real to quaternion

   return TQuaternion(fVectorPart, fRealPart - real);
}

//_____________________________________
TQuaternion TQuaternion::operator*(Double_t real) const {
   // product of quaternion with a real

   return TQuaternion(fRealPart*real,fVectorPart.x()*real,fVectorPart.y()*real,fVectorPart.z()*real);
}


//_____________________________________
TQuaternion TQuaternion::operator/(Double_t real) const {
   // division by a real

   if (real !=0 ) {
      return TQuaternion(fRealPart/real,fVectorPart.x()/real,fVectorPart.y()/real,fVectorPart.z()/real);
   } else {
      Error("operator/(Double_t)", "bad value (%f) ignored",real);
   }

   return (*this);
}

TQuaternion operator + (Double_t r, const TQuaternion & q) { return (q+r); }
TQuaternion operator - (Double_t r, const TQuaternion & q) { return (-q+r); }
TQuaternion operator * (Double_t r, const TQuaternion & q) { return (q*r); }
TQuaternion operator / (Double_t r, const TQuaternion & q) { return (q.Invert()*r); }

/**************** VECTOR TO QUATERNION ALGEBRA ****************************************/

//_____________________________________
TQuaternion TQuaternion::operator+(const TVector3 &vect) const {
   // sum of quaternion with a real

   return TQuaternion(fVectorPart + vect, fRealPart);
}

//_____________________________________
TQuaternion TQuaternion::operator-(const TVector3 &vect) const {
   // substraction of real to quaternion

   return TQuaternion(fVectorPart - vect, fRealPart);
}

//_____________________________________
TQuaternion& TQuaternion::MultiplyLeft(const TVector3 &vect) {
   // left multitplication

   Double_t savedRealPart = fRealPart;
   fRealPart = - (fVectorPart * vect);
   fVectorPart = vect.Cross(fVectorPart);
   fVectorPart += (vect * savedRealPart);

   return (*this);
}

//_____________________________________
TQuaternion& TQuaternion::operator*=(const TVector3 &vect) {
   // right multiplication

   Double_t savedRealPart = fRealPart;
   fRealPart = -(fVectorPart * vect);
   fVectorPart = fVectorPart.Cross(vect);
   fVectorPart += (vect * savedRealPart );

   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::LeftProduct(const TVector3 &vect) const {
   // left product

   return TQuaternion(vect * fRealPart + vect.Cross(fVectorPart), -(fVectorPart * vect));
}

//_____________________________________
TQuaternion TQuaternion::operator*(const TVector3 &vect) const {
   // right product

   return TQuaternion(vect * fRealPart + fVectorPart.Cross(vect), -(fVectorPart * vect));
}

//_____________________________________
TQuaternion& TQuaternion::DivideLeft(const TVector3 &vect) {
   // left division

   Double_t norm2 = vect.Mag2();
   MultiplyLeft(vect);
   if (norm2 > 0 ) {
      // use (1./nom2) to be numericaly compliant with LeftQuotient(const TVector3 &)
      (*this) *= -(1./norm2); // minus <- using conjugate of vect
   } else {
      Error("DivideLeft(const TVector3)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion& TQuaternion::operator/=(const TVector3 &vect) {
   // right division

   Double_t norm2 = vect.Mag2();
   (*this) *= vect;
   if (norm2 > 0 ) {
      // use (1./real) to be numericaly compliant with operator/(const TVector3 &)
      (*this) *= - (1./norm2); // minus <- using conjugate of vect
   } else {
      Error("operator/=(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::LeftQuotient(const TVector3 &vect) const {
   // left quotient

   Double_t norm2 = vect.Mag2();

   if (norm2>0) {
      double invNorm2 = 1./norm2;
      return TQuaternion((vect * -fRealPart - vect.Cross(fVectorPart))*invNorm2,
                                                                                                        (fVectorPart * vect ) * invNorm2 );
   } else {
      Error("LeftQuotient(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::operator/(const TVector3 &vect) const {
   //  right quotient

   Double_t norm2 = vect.Mag2();

   if (norm2>0) {
      double invNorm2 = 1./norm2;
      return TQuaternion((vect * -fRealPart - fVectorPart.Cross(vect)) * invNorm2,
                                                                                                                (fVectorPart * vect) * invNorm2 );
   } else {
      Error("operator/(const TVector3 &)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

TQuaternion operator + (const TVector3 &V, const TQuaternion &Q) { return (Q+V); }
TQuaternion operator - (const TVector3 &V, const TQuaternion &Q) { return (-Q+V); }
TQuaternion operator * (const TVector3 &V, const TQuaternion &Q) { return Q.LeftProduct(V); }

TQuaternion operator / (const TVector3 &vect, const TQuaternion &quat) {
   //divide operator
   TQuaternion res(vect);
   res /= quat;
   return res;
}

/**************** QUATERNION ALGEBRA ****************************************/

//_____________________________________
TQuaternion& TQuaternion::operator*=(const TQuaternion &quaternion) {
   // right multiplication

   Double_t saveRP = fRealPart;
   TVector3 cross(fVectorPart.Cross(quaternion.fVectorPart));

   fRealPart = fRealPart * quaternion.fRealPart - fVectorPart * quaternion.fVectorPart;

   fVectorPart *= quaternion.fRealPart;
   fVectorPart += quaternion.fVectorPart * saveRP;
   fVectorPart += cross;
   return (*this);
}

//_____________________________________
TQuaternion& TQuaternion::MultiplyLeft(const TQuaternion &quaternion) {
   // left multiplication

   Double_t saveRP = fRealPart;
   TVector3 cross(quaternion.fVectorPart.Cross(fVectorPart));

   fRealPart = fRealPart * quaternion.fRealPart - fVectorPart * quaternion.fVectorPart;

   fVectorPart *= quaternion.fRealPart;
   fVectorPart += quaternion.fVectorPart * saveRP;
   fVectorPart += cross;

   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::LeftProduct(const TQuaternion &quaternion) const {
   // left product

   return TQuaternion( fVectorPart*quaternion.fRealPart + quaternion.fVectorPart*fRealPart
                                 + quaternion.fVectorPart.Cross(fVectorPart),
                                   fRealPart*quaternion.fRealPart - fVectorPart*quaternion.fVectorPart );
}

//_____________________________________
TQuaternion TQuaternion::operator*(const TQuaternion &quaternion) const {
   // right product

   return TQuaternion(fVectorPart*quaternion.fRealPart + quaternion.fVectorPart*fRealPart
                    + fVectorPart.Cross(quaternion.fVectorPart),
                      fRealPart*quaternion.fRealPart - fVectorPart*quaternion.fVectorPart );
}

//_____________________________________
TQuaternion& TQuaternion::DivideLeft(const TQuaternion &quaternion) {
   // left division

   Double_t norm2 = quaternion.Norm2();

   if (norm2 > 0 ) {
      MultiplyLeft(quaternion.Conjugate());
      (*this) *= (1./norm2);
   } else {
      Error("DivideLeft(const TQuaternion &)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion& TQuaternion::operator/=(const TQuaternion& quaternion) {
   // right division

   Double_t norm2 = quaternion.Norm2();

   if (norm2 > 0 ) {
      (*this) *= quaternion.Conjugate();
      // use (1./norm2) top be numericaly compliant with operator/(const TQuaternion&)
      (*this) *= (1./norm2);
   } else {
      Error("operator/=(const TQuaternion&)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::LeftQuotient(const TQuaternion& quaternion) const {
   // left quotient

   Double_t norm2 = quaternion.Norm2();

   if (norm2 > 0 ) {
      double invNorm2 = 1./norm2;
      return TQuaternion(
             (fVectorPart*quaternion.fRealPart - quaternion.fVectorPart*fRealPart
                        - quaternion.fVectorPart.Cross(fVectorPart)) * invNorm2,
                        (fRealPart*quaternion.fRealPart + fVectorPart*quaternion.fVectorPart)*invNorm2 );
   } else {
      Error("LeftQuotient(const TQuaternion&)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::operator/(const TQuaternion &quaternion) const {
   // right quotient

   Double_t norm2 = quaternion.Norm2();

   if (norm2 > 0 ) {
      double invNorm2 = 1./norm2;
      return TQuaternion(
             (fVectorPart*quaternion.fRealPart - quaternion.fVectorPart*fRealPart
                        - fVectorPart.Cross(quaternion.fVectorPart)) * invNorm2,
                         (fRealPart*quaternion.fRealPart + fVectorPart*quaternion.fVectorPart) * invNorm2 );
   } else {
      Error("operator/(const TQuaternion &)", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
TQuaternion TQuaternion::Invert() const {
   // invert

   double norm2 = Norm2();
   if (norm2 > 0 ) {
      double invNorm2 = 1./norm2;
      return TQuaternion(fVectorPart*(-invNorm2), fRealPart*invNorm2 );
   } else {
      Error("Invert()", "bad norm2 (%f) ignored",norm2);
   }
   return (*this);
}

//_____________________________________
void TQuaternion::Rotate(TVector3 & vect) const {
   // rotate vect by current quaternion

   vect = Rotation(vect);
}

//_____________________________________
TVector3 TQuaternion::Rotation(const TVector3 & vect) const {
   // rotation of vect by current quaternion

   // Vres = (*this) * vect * (this->Invert());
   double norm2 = Norm2();

   if (norm2>0) {
      TQuaternion quat(*this);
      quat *= vect;

      // only compute vect part : (real part has to be 0 ) :
      // VECT [ quat * ( this->Conjugate() ) ] = quat.fRealPart * -this->fVectorPart
      //                                                                                        + this->fRealPart * quat.fVectorPart
      //                                                                                        + quat.fVectorPart X (-this->fVectorPart)
      TVector3 cross(fVectorPart.Cross(quat.fVectorPart));
      quat.fVectorPart *=  fRealPart;
      quat.fVectorPart -= fVectorPart * quat.fRealPart;
      quat.fVectorPart += cross;

      return quat.fVectorPart*(1./norm2);
   } else {
      Error("Rotation()", "bad norm2 (%f) ignored",norm2);
   }
   return vect;
}

//_____________________________________
void TQuaternion::Print(Option_t*) const
{
   //Print Quaternion parameters
   Printf("%s %s (r,x,y,z)=(%f,%f,%f,%f) \n (alpha,rho,theta,phi)=(%f,%f,%f,%f)",GetName(),GetTitle(),
            fRealPart,fVectorPart.X(),fVectorPart.Y(),fVectorPart.Z(),
            GetQAngle()*TMath::RadToDeg(),fVectorPart.Mag(),fVectorPart.Theta()*TMath::RadToDeg(),fVectorPart.Phi()*TMath::RadToDeg());
}
 TQuaternion.cxx:1
 TQuaternion.cxx:2
 TQuaternion.cxx:3
 TQuaternion.cxx:4
 TQuaternion.cxx:5
 TQuaternion.cxx:6
 TQuaternion.cxx:7
 TQuaternion.cxx:8
 TQuaternion.cxx:9
 TQuaternion.cxx:10
 TQuaternion.cxx:11
 TQuaternion.cxx:12
 TQuaternion.cxx:13
 TQuaternion.cxx:14
 TQuaternion.cxx:15
 TQuaternion.cxx:16
 TQuaternion.cxx:17
 TQuaternion.cxx:18
 TQuaternion.cxx:19
 TQuaternion.cxx:20
 TQuaternion.cxx:21
 TQuaternion.cxx:22
 TQuaternion.cxx:23
 TQuaternion.cxx:24
 TQuaternion.cxx:25
 TQuaternion.cxx:26
 TQuaternion.cxx:27
 TQuaternion.cxx:28
 TQuaternion.cxx:29
 TQuaternion.cxx:30
 TQuaternion.cxx:31
 TQuaternion.cxx:32
 TQuaternion.cxx:33
 TQuaternion.cxx:34
 TQuaternion.cxx:35
 TQuaternion.cxx:36
 TQuaternion.cxx:37
 TQuaternion.cxx:38
 TQuaternion.cxx:39
 TQuaternion.cxx:40
 TQuaternion.cxx:41
 TQuaternion.cxx:42
 TQuaternion.cxx:43
 TQuaternion.cxx:44
 TQuaternion.cxx:45
 TQuaternion.cxx:46
 TQuaternion.cxx:47
 TQuaternion.cxx:48
 TQuaternion.cxx:49
 TQuaternion.cxx:50
 TQuaternion.cxx:51
 TQuaternion.cxx:52
 TQuaternion.cxx:53
 TQuaternion.cxx:54
 TQuaternion.cxx:55
 TQuaternion.cxx:56
 TQuaternion.cxx:57
 TQuaternion.cxx:58
 TQuaternion.cxx:59
 TQuaternion.cxx:60
 TQuaternion.cxx:61
 TQuaternion.cxx:62
 TQuaternion.cxx:63
 TQuaternion.cxx:64
 TQuaternion.cxx:65
 TQuaternion.cxx:66
 TQuaternion.cxx:67
 TQuaternion.cxx:68
 TQuaternion.cxx:69
 TQuaternion.cxx:70
 TQuaternion.cxx:71
 TQuaternion.cxx:72
 TQuaternion.cxx:73
 TQuaternion.cxx:74
 TQuaternion.cxx:75
 TQuaternion.cxx:76
 TQuaternion.cxx:77
 TQuaternion.cxx:78
 TQuaternion.cxx:79
 TQuaternion.cxx:80
 TQuaternion.cxx:81
 TQuaternion.cxx:82
 TQuaternion.cxx:83
 TQuaternion.cxx:84
 TQuaternion.cxx:85
 TQuaternion.cxx:86
 TQuaternion.cxx:87
 TQuaternion.cxx:88
 TQuaternion.cxx:89
 TQuaternion.cxx:90
 TQuaternion.cxx:91
 TQuaternion.cxx:92
 TQuaternion.cxx:93
 TQuaternion.cxx:94
 TQuaternion.cxx:95
 TQuaternion.cxx:96
 TQuaternion.cxx:97
 TQuaternion.cxx:98
 TQuaternion.cxx:99
 TQuaternion.cxx:100
 TQuaternion.cxx:101
 TQuaternion.cxx:102
 TQuaternion.cxx:103
 TQuaternion.cxx:104
 TQuaternion.cxx:105
 TQuaternion.cxx:106
 TQuaternion.cxx:107
 TQuaternion.cxx:108
 TQuaternion.cxx:109
 TQuaternion.cxx:110
 TQuaternion.cxx:111
 TQuaternion.cxx:112
 TQuaternion.cxx:113
 TQuaternion.cxx:114
 TQuaternion.cxx:115
 TQuaternion.cxx:116
 TQuaternion.cxx:117
 TQuaternion.cxx:118
 TQuaternion.cxx:119
 TQuaternion.cxx:120
 TQuaternion.cxx:121
 TQuaternion.cxx:122
 TQuaternion.cxx:123
 TQuaternion.cxx:124
 TQuaternion.cxx:125
 TQuaternion.cxx:126
 TQuaternion.cxx:127
 TQuaternion.cxx:128
 TQuaternion.cxx:129
 TQuaternion.cxx:130
 TQuaternion.cxx:131
 TQuaternion.cxx:132
 TQuaternion.cxx:133
 TQuaternion.cxx:134
 TQuaternion.cxx:135
 TQuaternion.cxx:136
 TQuaternion.cxx:137
 TQuaternion.cxx:138
 TQuaternion.cxx:139
 TQuaternion.cxx:140
 TQuaternion.cxx:141
 TQuaternion.cxx:142
 TQuaternion.cxx:143
 TQuaternion.cxx:144
 TQuaternion.cxx:145
 TQuaternion.cxx:146
 TQuaternion.cxx:147
 TQuaternion.cxx:148
 TQuaternion.cxx:149
 TQuaternion.cxx:150
 TQuaternion.cxx:151
 TQuaternion.cxx:152
 TQuaternion.cxx:153
 TQuaternion.cxx:154
 TQuaternion.cxx:155
 TQuaternion.cxx:156
 TQuaternion.cxx:157
 TQuaternion.cxx:158
 TQuaternion.cxx:159
 TQuaternion.cxx:160
 TQuaternion.cxx:161
 TQuaternion.cxx:162
 TQuaternion.cxx:163
 TQuaternion.cxx:164
 TQuaternion.cxx:165
 TQuaternion.cxx:166
 TQuaternion.cxx:167
 TQuaternion.cxx:168
 TQuaternion.cxx:169
 TQuaternion.cxx:170
 TQuaternion.cxx:171
 TQuaternion.cxx:172
 TQuaternion.cxx:173
 TQuaternion.cxx:174
 TQuaternion.cxx:175
 TQuaternion.cxx:176
 TQuaternion.cxx:177
 TQuaternion.cxx:178
 TQuaternion.cxx:179
 TQuaternion.cxx:180
 TQuaternion.cxx:181
 TQuaternion.cxx:182
 TQuaternion.cxx:183
 TQuaternion.cxx:184
 TQuaternion.cxx:185
 TQuaternion.cxx:186
 TQuaternion.cxx:187
 TQuaternion.cxx:188
 TQuaternion.cxx:189
 TQuaternion.cxx:190
 TQuaternion.cxx:191
 TQuaternion.cxx:192
 TQuaternion.cxx:193
 TQuaternion.cxx:194
 TQuaternion.cxx:195
 TQuaternion.cxx:196
 TQuaternion.cxx:197
 TQuaternion.cxx:198
 TQuaternion.cxx:199
 TQuaternion.cxx:200
 TQuaternion.cxx:201
 TQuaternion.cxx:202
 TQuaternion.cxx:203
 TQuaternion.cxx:204
 TQuaternion.cxx:205
 TQuaternion.cxx:206
 TQuaternion.cxx:207
 TQuaternion.cxx:208
 TQuaternion.cxx:209
 TQuaternion.cxx:210
 TQuaternion.cxx:211
 TQuaternion.cxx:212
 TQuaternion.cxx:213
 TQuaternion.cxx:214
 TQuaternion.cxx:215
 TQuaternion.cxx:216
 TQuaternion.cxx:217
 TQuaternion.cxx:218
 TQuaternion.cxx:219
 TQuaternion.cxx:220
 TQuaternion.cxx:221
 TQuaternion.cxx:222
 TQuaternion.cxx:223
 TQuaternion.cxx:224
 TQuaternion.cxx:225
 TQuaternion.cxx:226
 TQuaternion.cxx:227
 TQuaternion.cxx:228
 TQuaternion.cxx:229
 TQuaternion.cxx:230
 TQuaternion.cxx:231
 TQuaternion.cxx:232
 TQuaternion.cxx:233
 TQuaternion.cxx:234
 TQuaternion.cxx:235
 TQuaternion.cxx:236
 TQuaternion.cxx:237
 TQuaternion.cxx:238
 TQuaternion.cxx:239
 TQuaternion.cxx:240
 TQuaternion.cxx:241
 TQuaternion.cxx:242
 TQuaternion.cxx:243
 TQuaternion.cxx:244
 TQuaternion.cxx:245
 TQuaternion.cxx:246
 TQuaternion.cxx:247
 TQuaternion.cxx:248
 TQuaternion.cxx:249
 TQuaternion.cxx:250
 TQuaternion.cxx:251
 TQuaternion.cxx:252
 TQuaternion.cxx:253
 TQuaternion.cxx:254
 TQuaternion.cxx:255
 TQuaternion.cxx:256
 TQuaternion.cxx:257
 TQuaternion.cxx:258
 TQuaternion.cxx:259
 TQuaternion.cxx:260
 TQuaternion.cxx:261
 TQuaternion.cxx:262
 TQuaternion.cxx:263
 TQuaternion.cxx:264
 TQuaternion.cxx:265
 TQuaternion.cxx:266
 TQuaternion.cxx:267
 TQuaternion.cxx:268
 TQuaternion.cxx:269
 TQuaternion.cxx:270
 TQuaternion.cxx:271
 TQuaternion.cxx:272
 TQuaternion.cxx:273
 TQuaternion.cxx:274
 TQuaternion.cxx:275
 TQuaternion.cxx:276
 TQuaternion.cxx:277
 TQuaternion.cxx:278
 TQuaternion.cxx:279
 TQuaternion.cxx:280
 TQuaternion.cxx:281
 TQuaternion.cxx:282
 TQuaternion.cxx:283
 TQuaternion.cxx:284
 TQuaternion.cxx:285
 TQuaternion.cxx:286
 TQuaternion.cxx:287
 TQuaternion.cxx:288
 TQuaternion.cxx:289
 TQuaternion.cxx:290
 TQuaternion.cxx:291
 TQuaternion.cxx:292
 TQuaternion.cxx:293
 TQuaternion.cxx:294
 TQuaternion.cxx:295
 TQuaternion.cxx:296
 TQuaternion.cxx:297
 TQuaternion.cxx:298
 TQuaternion.cxx:299
 TQuaternion.cxx:300
 TQuaternion.cxx:301
 TQuaternion.cxx:302
 TQuaternion.cxx:303
 TQuaternion.cxx:304
 TQuaternion.cxx:305
 TQuaternion.cxx:306
 TQuaternion.cxx:307
 TQuaternion.cxx:308
 TQuaternion.cxx:309
 TQuaternion.cxx:310
 TQuaternion.cxx:311
 TQuaternion.cxx:312
 TQuaternion.cxx:313
 TQuaternion.cxx:314
 TQuaternion.cxx:315
 TQuaternion.cxx:316
 TQuaternion.cxx:317
 TQuaternion.cxx:318
 TQuaternion.cxx:319
 TQuaternion.cxx:320
 TQuaternion.cxx:321
 TQuaternion.cxx:322
 TQuaternion.cxx:323
 TQuaternion.cxx:324
 TQuaternion.cxx:325
 TQuaternion.cxx:326
 TQuaternion.cxx:327
 TQuaternion.cxx:328
 TQuaternion.cxx:329
 TQuaternion.cxx:330
 TQuaternion.cxx:331
 TQuaternion.cxx:332
 TQuaternion.cxx:333
 TQuaternion.cxx:334
 TQuaternion.cxx:335
 TQuaternion.cxx:336
 TQuaternion.cxx:337
 TQuaternion.cxx:338
 TQuaternion.cxx:339
 TQuaternion.cxx:340
 TQuaternion.cxx:341
 TQuaternion.cxx:342
 TQuaternion.cxx:343
 TQuaternion.cxx:344
 TQuaternion.cxx:345
 TQuaternion.cxx:346
 TQuaternion.cxx:347
 TQuaternion.cxx:348
 TQuaternion.cxx:349
 TQuaternion.cxx:350
 TQuaternion.cxx:351
 TQuaternion.cxx:352
 TQuaternion.cxx:353
 TQuaternion.cxx:354
 TQuaternion.cxx:355
 TQuaternion.cxx:356
 TQuaternion.cxx:357
 TQuaternion.cxx:358
 TQuaternion.cxx:359
 TQuaternion.cxx:360
 TQuaternion.cxx:361
 TQuaternion.cxx:362
 TQuaternion.cxx:363
 TQuaternion.cxx:364
 TQuaternion.cxx:365
 TQuaternion.cxx:366
 TQuaternion.cxx:367
 TQuaternion.cxx:368
 TQuaternion.cxx:369
 TQuaternion.cxx:370
 TQuaternion.cxx:371
 TQuaternion.cxx:372
 TQuaternion.cxx:373
 TQuaternion.cxx:374
 TQuaternion.cxx:375
 TQuaternion.cxx:376
 TQuaternion.cxx:377
 TQuaternion.cxx:378
 TQuaternion.cxx:379
 TQuaternion.cxx:380
 TQuaternion.cxx:381
 TQuaternion.cxx:382
 TQuaternion.cxx:383
 TQuaternion.cxx:384
 TQuaternion.cxx:385
 TQuaternion.cxx:386
 TQuaternion.cxx:387
 TQuaternion.cxx:388
 TQuaternion.cxx:389
 TQuaternion.cxx:390
 TQuaternion.cxx:391
 TQuaternion.cxx:392
 TQuaternion.cxx:393
 TQuaternion.cxx:394
 TQuaternion.cxx:395
 TQuaternion.cxx:396
 TQuaternion.cxx:397
 TQuaternion.cxx:398
 TQuaternion.cxx:399
 TQuaternion.cxx:400
 TQuaternion.cxx:401
 TQuaternion.cxx:402
 TQuaternion.cxx:403
 TQuaternion.cxx:404
 TQuaternion.cxx:405
 TQuaternion.cxx:406
 TQuaternion.cxx:407
 TQuaternion.cxx:408
 TQuaternion.cxx:409
 TQuaternion.cxx:410
 TQuaternion.cxx:411
 TQuaternion.cxx:412
 TQuaternion.cxx:413
 TQuaternion.cxx:414
 TQuaternion.cxx:415
 TQuaternion.cxx:416
 TQuaternion.cxx:417
 TQuaternion.cxx:418
 TQuaternion.cxx:419
 TQuaternion.cxx:420
 TQuaternion.cxx:421
 TQuaternion.cxx:422
 TQuaternion.cxx:423
 TQuaternion.cxx:424
 TQuaternion.cxx:425
 TQuaternion.cxx:426
 TQuaternion.cxx:427
 TQuaternion.cxx:428
 TQuaternion.cxx:429
 TQuaternion.cxx:430
 TQuaternion.cxx:431
 TQuaternion.cxx:432
 TQuaternion.cxx:433
 TQuaternion.cxx:434
 TQuaternion.cxx:435
 TQuaternion.cxx:436
 TQuaternion.cxx:437
 TQuaternion.cxx:438
 TQuaternion.cxx:439
 TQuaternion.cxx:440
 TQuaternion.cxx:441
 TQuaternion.cxx:442
 TQuaternion.cxx:443
 TQuaternion.cxx:444
 TQuaternion.cxx:445
 TQuaternion.cxx:446
 TQuaternion.cxx:447
 TQuaternion.cxx:448
 TQuaternion.cxx:449
 TQuaternion.cxx:450
 TQuaternion.cxx:451
 TQuaternion.cxx:452
 TQuaternion.cxx:453
 TQuaternion.cxx:454
 TQuaternion.cxx:455
 TQuaternion.cxx:456
 TQuaternion.cxx:457
 TQuaternion.cxx:458
 TQuaternion.cxx:459
 TQuaternion.cxx:460
 TQuaternion.cxx:461
 TQuaternion.cxx:462
 TQuaternion.cxx:463
 TQuaternion.cxx:464
 TQuaternion.cxx:465
 TQuaternion.cxx:466
 TQuaternion.cxx:467
 TQuaternion.cxx:468
 TQuaternion.cxx:469
 TQuaternion.cxx:470
 TQuaternion.cxx:471
 TQuaternion.cxx:472
 TQuaternion.cxx:473
 TQuaternion.cxx:474
 TQuaternion.cxx:475
 TQuaternion.cxx:476
 TQuaternion.cxx:477
 TQuaternion.cxx:478
 TQuaternion.cxx:479
 TQuaternion.cxx:480
 TQuaternion.cxx:481
 TQuaternion.cxx:482
 TQuaternion.cxx:483
 TQuaternion.cxx:484
 TQuaternion.cxx:485
 TQuaternion.cxx:486
 TQuaternion.cxx:487
 TQuaternion.cxx:488
 TQuaternion.cxx:489
 TQuaternion.cxx:490
 TQuaternion.cxx:491
 TQuaternion.cxx:492
 TQuaternion.cxx:493
 TQuaternion.cxx:494
 TQuaternion.cxx:495
 TQuaternion.cxx:496
 TQuaternion.cxx:497
 TQuaternion.cxx:498
 TQuaternion.cxx:499
 TQuaternion.cxx:500
 TQuaternion.cxx:501
 TQuaternion.cxx:502
 TQuaternion.cxx:503
 TQuaternion.cxx:504
 TQuaternion.cxx:505
 TQuaternion.cxx:506
 TQuaternion.cxx:507
 TQuaternion.cxx:508
 TQuaternion.cxx:509
 TQuaternion.cxx:510
 TQuaternion.cxx:511
 TQuaternion.cxx:512
 TQuaternion.cxx:513
 TQuaternion.cxx:514
 TQuaternion.cxx:515
 TQuaternion.cxx:516
 TQuaternion.cxx:517
 TQuaternion.cxx:518
 TQuaternion.cxx:519
 TQuaternion.cxx:520
 TQuaternion.cxx:521
 TQuaternion.cxx:522
 TQuaternion.cxx:523
 TQuaternion.cxx:524
 TQuaternion.cxx:525
 TQuaternion.cxx:526
 TQuaternion.cxx:527
 TQuaternion.cxx:528
 TQuaternion.cxx:529
 TQuaternion.cxx:530
 TQuaternion.cxx:531
 TQuaternion.cxx:532