// @(#)root/physics:$Id$
// Author: Peter Malzacher   19/06/99

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-*-*-*-*The Physics Vector package *-*-*-*-*-*-*-*-*-*-*-*
//*-*                    ==========================                       *
//*-* The Physics Vector package consists of five classes:                *
//*-*   - TVector2                                                        *
//*-*   - TVector3                                                        *
//*-*   - TRotation                                                       *
//*-*   - TLorentzVector                                                  *
//*-*   - TLorentzRotation                                                *
//*-* It is a combination of CLHEPs Vector package written by             *
//*-* Leif Lonnblad, Andreas Nilsson and Evgueni Tcherniaev               *
//*-* and a ROOT package written by Pasha Murat.                          *
//*-* for CLHEP see:  http://wwwinfo.cern.ch/asd/lhc++/clhep/             *
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//BEGIN_HTML <!--
/* -->
<H2>
TRotation</H2>
The TRotation class describes a rotation of objects of the TVector3 class.
It is a 3*3 matrix of Double_t:

<P><TT>| xx&nbsp; xy&nbsp; xz |</TT>
<BR><TT>| yx&nbsp; yy&nbsp; yz |</TT>
<BR><TT>| zx&nbsp; zy&nbsp; zz |</TT>

<P>It describes a so called active rotation, i.e. rotation of objects inside
a static system of coordinates. In case you want to rotate the frame and
want to know the coordinates of objects in the rotated system, you should
apply the inverse rotation to the objects. If you want to transform coordinates
from the rotated frame to the original frame you have to apply the direct
transformation.

<P>A rotation around a specified axis means counterclockwise rotation around
the positive direction of the axis.
<BR>&nbsp;
<H3>
Declaration, Access, Comparisons</H3>
<TT>&nbsp; TRotation r;&nbsp;&nbsp;&nbsp; // r initialized as identity</TT>
<BR><TT>&nbsp; TRotation m(r); // m = r</TT>

<P>There is no direct way to set the matrix elements - to ensure that
a <TT>TRotation</TT> object always describes a real rotation. But you can get the
values by the member functions <TT>XX()..ZZ()</TT> or the<TT> (,)</TT>
operator:

<P><TT>&nbsp; Double_t xx = r.XX();&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; the
same as xx=r(0,0)</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xx
= r(0,0);</TT>

<P><TT>&nbsp; if (r==m) {...}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// test for equality</TT>
<BR><TT>&nbsp; if (r!=m) {..}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// test for inequality</TT>
<BR><TT>&nbsp; if (r.IsIdentity()) {...} // test for identity</TT>
<BR>&nbsp;
<H3>
Rotation around axes</H3>
The following matrices desrcibe counterclockwise rotations around coordinate
axes

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 1&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp; |</TT>
<BR><TT>Rx(a) = | 0 cos(a) -sin(a) |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 0 sin(a) cos(a)&nbsp;
|</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | cos(a)&nbsp; 0 sin(a)
|</TT>
<BR><TT>Ry(a) = |&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp; |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | -sin(a) 0 cos(a) |</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | cos(a) -sin(a) 0 |</TT>
<BR><TT>Rz(a) = | sin(a) cos(a) 0 |</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0&nbsp;&nbsp;&nbsp;&nbsp; 1 |</TT>
<BR>and are implemented as member functions <TT>RotateX()</TT>, <TT>RotateY()</TT>
and <TT>RotateZ()</TT>:

<P><TT>&nbsp; r.RotateX(TMath::Pi()); // rotation around the x-axis</TT>
<H3>
Rotation around arbitary axis</H3>
The member function <TT>Rotate()</TT> allows to rotate around an arbitary vector
(not neccessary a unit one) and returns the result.

<P><TT>&nbsp; r.Rotate(TMath::Pi()/3,TVector3(3,4,5));</TT>

<P>It is possible to find a unit vector and an angle, which describe the
same rotation as the current one:

<P><TT>&nbsp; Double_t angle;</TT>
<BR><TT>&nbsp; TVector3 axis;</TT>
<BR><TT>&nbsp; r.GetAngleAxis(angle,axis);</TT>
<H3>
Rotation of local axes</H3>
Member function <TT>RotateAxes()</TT> adds a rotation of local axes to
the current rotation and returns the result:

<P><TT>&nbsp; TVector3 newX(0,1,0);</TT>
<BR><TT>&nbsp; TVector3 newY(0,0,1);</TT>
<BR><TT>&nbsp; TVector3 newZ(1,0,0);</TT>
<BR><TT>&nbsp; a.RotateAxes(newX,newY,newZ);</TT>

<P>Member functions <TT>ThetaX()</TT>, <TT>ThetaY()</TT>, <TT>ThetaZ()</TT>,
<TT>PhiX()</TT>, <TT>PhiY()</TT>,<TT>PhiZ()</TT> return azimuth and polar
angles of the rotated axes:

<P><TT>&nbsp; Double_t tx,ty,tz,px,py,pz;</TT>
<BR><TT>&nbsp; tx= a.ThetaX();</TT>
<BR><TT>&nbsp; ...</TT>
<BR><TT>&nbsp; pz= a.PhiZ();</TT>

<H3>
Setting The Rotations</H3>
The member function <TT>SetToIdentity()</TT> will set the rotation object
to the identity (no rotation).

With a minor caveat, the Euler angles of the rotation may be set using
<TT>SetXEulerAngles()</TT> or individually set with <TT>SetXPhi()</TT>,
<TT>SetXTheta()</TT>, and <TT>SetXPsi()</TT>.  These routines set the Euler
angles using the X-convention which is defined by a rotation about the Z-axis,
about the new X-axis, and about the new Z-axis.  This is the convention used
in Landau and Lifshitz, Goldstein and other common physics texts.  The
Y-convention euler angles can be set with <TT>SetYEulerAngles()</TT>,
<TT>SetYPhi()</TT>, <TT>SetYTheta()</TT>, and <TT>SetYPsi()</TT>.  The caveat
is that Euler angles usually define the rotation of the new coordinate system
with respect to the original system, however, the TRotation class specifies
the rotation of the object in the original system (an active rotation).  To
recover the usual Euler rotations (ie. rotate the system not the object), you
must take the inverse of the rotation.

The member functions <TT>SetXAxis()</TT>, <TT>SetYAxis()</TT>, and
<TT>SetZAxis()</TT> will create a rotation which rotates the requested axis
of the object to be parallel to a vector.  If used with one argument, the
rotation about that axis is arbitrary.  If used with two arguments, the
second variable defines the <TT>XY</TT>, <TT>YZ</TT>, or <TT>ZX</TT>
respectively.

<H3>
Inverse rotation</H3>
<TT>&nbsp; TRotation a,b;</TT>
<BR><TT>&nbsp; ...</TT>
<BR><TT>&nbsp; b = a.Inverse();&nbsp; // b is inverse of a, a is unchanged</TT>
<BR><TT>&nbsp; b = a.Invert();&nbsp;&nbsp; // invert a and set b = a</TT>
<H3>
Compound Rotations</H3>
The <TT>operator *</TT> has been implemented in a way that follows the
mathematical notation of a product of the two matrices which describe the
two consecutive rotations. Therefore the second rotation should be placed
first:

<P><TT>&nbsp; r = r2 * r1;</TT>
<H3>
Rotation of TVector3</H3>
The TRotation class provides an <TT>operator *</TT> which allows to express
a rotation of a <TT>TVector3</TT> analog to the mathematical notation

<P><TT>&nbsp; | x' |&nbsp;&nbsp; | xx xy xz | | x |</TT>
<BR><TT>&nbsp; | y' | = | yx yy yz | | y |</TT>
<BR><TT>&nbsp; | z' |&nbsp;&nbsp; | zx zy zz | | z |</TT><TT></TT>

<P>e.g.:

<P><TT>&nbsp; TVector3 v(1,1,1);</TT>
<BR><TT>&nbsp; v = r * v;</TT><TT></TT>

<P>You can also use the <TT>Transform()</TT> member function or the o<TT>perator
*=</TT> of the
<BR>TVector3 class:<TT></TT>

<P><TT>&nbsp; TVector3 v;</TT>
<BR><TT>&nbsp; TRotation r;</TT>
<BR><TT>&nbsp; v.Transform(r);</TT>
<BR><TT>&nbsp; v *= r;&nbsp; //Attention v = r * v</TT>
<!--*/
// -->END_HTML
//

#include "TRotation.h"
#include "TMath.h"
#include "TQuaternion.h"
#include "TError.h"

ClassImp(TRotation)

#define TOLERANCE (1.0E-6)

TRotation::TRotation()
: fxx(1.0), fxy(0.0), fxz(0.0), fyx(0.0), fyy(1.0), fyz(0.0),
  fzx(0.0), fzy(0.0), fzz(1.0) {}

TRotation::TRotation(const TRotation & m) : TObject(m),
  fxx(m.fxx), fxy(m.fxy), fxz(m.fxz), fyx(m.fyx), fyy(m.fyy), fyz(m.fyz),
  fzx(m.fzx), fzy(m.fzy), fzz(m.fzz) {}

TRotation::TRotation(Double_t mxx, Double_t mxy, Double_t mxz,
                         Double_t myx, Double_t myy, Double_t myz,
                         Double_t mzx, Double_t mzy, Double_t mzz)
: fxx(mxx), fxy(mxy), fxz(mxz), fyx(myx), fyy(myy), fyz(myz),
  fzx(mzx), fzy(mzy), fzz(mzz) {}


Double_t TRotation::operator() (int i, int j) const {
   //dereferencing operator const
   if (i == 0) {
      if (j == 0) { return fxx; }
      if (j == 1) { return fxy; }
      if (j == 2) { return fxz; }
   } else if (i == 1) {
      if (j == 0) { return fyx; }
      if (j == 1) { return fyy; }
      if (j == 2) { return fyz; }
   } else if (i == 2) {
      if (j == 0) { return fzx; }
      if (j == 1) { return fzy; }
      if (j == 2) { return fzz; }
   }

   Warning("operator()(i,j)", "bad indices (%d , %d)",i,j);

   return 0.0;
}

TRotation TRotation::operator* (const TRotation & b) const {
   //multiplication operator
   return TRotation(fxx*b.fxx + fxy*b.fyx + fxz*b.fzx,
                    fxx*b.fxy + fxy*b.fyy + fxz*b.fzy,
                    fxx*b.fxz + fxy*b.fyz + fxz*b.fzz,
                    fyx*b.fxx + fyy*b.fyx + fyz*b.fzx,
                    fyx*b.fxy + fyy*b.fyy + fyz*b.fzy,
                    fyx*b.fxz + fyy*b.fyz + fyz*b.fzz,
                    fzx*b.fxx + fzy*b.fyx + fzz*b.fzx,
                    fzx*b.fxy + fzy*b.fyy + fzz*b.fzy,
                    fzx*b.fxz + fzy*b.fyz + fzz*b.fzz);
}

//_____________________________________
TRotation::TRotation(const TQuaternion & Q) {
   // Constructor for a rotation based on a Quaternion
   // if magnitude of quaternion is null, creates identity rotation
   // if quaternion is non-unit, creates rotation corresponding to the normalized (unit) quaternion


   double two_r2 = 2 * Q.fRealPart * Q.fRealPart;
   double two_x2 = 2 * Q.fVectorPart.X() * Q.fVectorPart.X();
   double two_y2 = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Y();
   double two_z2 = 2 * Q.fVectorPart.Z() * Q.fVectorPart.Z();
   double two_xy = 2 * Q.fVectorPart.X() * Q.fVectorPart.Y();
   double two_xz = 2 * Q.fVectorPart.X() * Q.fVectorPart.Z();
   double two_xr = 2 * Q.fVectorPart.X() * Q.fRealPart;
   double two_yz = 2 * Q.fVectorPart.Y() * Q.fVectorPart.Z();
   double two_yr = 2 * Q.fVectorPart.Y() * Q.fRealPart;
   double two_zr = 2 * Q.fVectorPart.Z() * Q.fRealPart;

   // protect agains zero quaternion
   double mag2 = Q.QMag2();
   if (mag2 > 0) {

      // diago + identity
      fxx = two_r2 + two_x2;
      fyy = two_r2 + two_y2;
      fzz = two_r2 + two_z2;

      //        line 0 column 1 and conjugate
      fxy = two_xy - two_zr;
      fyx = two_xy + two_zr;

      //        line 0 column 2 and conjugate
      fxz = two_xz + two_yr;
      fzx = two_xz - two_yr;

      //        line 1 column 2 and conjugate
      fyz = two_yz - two_xr;
      fzy = two_yz + two_xr;

      // protect agains non-unit quaternion
      if (TMath::Abs(mag2-1) > 1e-10) {
         fxx /= mag2;
         fyy /= mag2;
         fzz /= mag2;
         fxy /= mag2;
         fyx /= mag2;
         fxz /= mag2;
         fzx /= mag2;
         fyz /= mag2;
         fzy /= mag2;
      }

      // diago : remove identity
      fxx -= 1;
      fyy -= 1;
      fzz -= 1;


   } else {
      // Identity

      fxx = fyy = fzz = 1;
      fxy = fyx = fxz = fzx = fyz = fzy = 0;

   }

}

TRotation & TRotation::Rotate(Double_t a, const TVector3& axis) {
   //rotate along an axis
   if (a != 0.0) {
      Double_t ll = axis.Mag();
      if (ll == 0.0) {
         Warning("Rotate(angle,axis)"," zero axis");
      } else {
         Double_t sa = TMath::Sin(a), ca = TMath::Cos(a);
         Double_t dx = axis.X()/ll, dy = axis.Y()/ll, dz = axis.Z()/ll;
         TRotation m(
             ca+(1-ca)*dx*dx,          (1-ca)*dx*dy-sa*dz,    (1-ca)*dx*dz+sa*dy,
             (1-ca)*dy*dx+sa*dz, ca+(1-ca)*dy*dy,          (1-ca)*dy*dz-sa*dx,
             (1-ca)*dz*dx-sa*dy,    (1-ca)*dz*dy+sa*dx, ca+(1-ca)*dz*dz );
         Transform(m);
      }
   }
   return *this;
}

TRotation & TRotation::RotateX(Double_t a) {
   //rotate around x
   Double_t c = TMath::Cos(a);
   Double_t s = TMath::Sin(a);
   Double_t x = fyx, y = fyy, z = fyz;
   fyx = c*x - s*fzx;
   fyy = c*y - s*fzy;
   fyz = c*z - s*fzz;
   fzx = s*x + c*fzx;
   fzy = s*y + c*fzy;
   fzz = s*z + c*fzz;
   return *this;
}

TRotation & TRotation::RotateY(Double_t a){
   //rotate around y
   Double_t c = TMath::Cos(a);
   Double_t s = TMath::Sin(a);
   Double_t x = fzx, y = fzy, z = fzz;
   fzx = c*x - s*fxx;
   fzy = c*y - s*fxy;
   fzz = c*z - s*fxz;
   fxx = s*x + c*fxx;
   fxy = s*y + c*fxy;
   fxz = s*z + c*fxz;
   return *this;
}

TRotation & TRotation::RotateZ(Double_t a) {
   //rotate around z
   Double_t c = TMath::Cos(a);
   Double_t s = TMath::Sin(a);
   Double_t x = fxx, y = fxy, z = fxz;
   fxx = c*x - s*fyx;
   fxy = c*y - s*fyy;
   fxz = c*z - s*fyz;
   fyx = s*x + c*fyx;
   fyy = s*y + c*fyy;
   fyz = s*z + c*fyz;
   return *this;
}

TRotation & TRotation::RotateAxes(const TVector3 &newX,
                                  const TVector3 &newY,
                                  const TVector3 &newZ) {
   //rotate axes
   Double_t del = 0.001;
   TVector3 w = newX.Cross(newY);

   if (TMath::Abs(newZ.X()-w.X()) > del ||
       TMath::Abs(newZ.Y()-w.Y()) > del ||
       TMath::Abs(newZ.Z()-w.Z()) > del ||
       TMath::Abs(newX.Mag2()-1.) > del ||
       TMath::Abs(newY.Mag2()-1.) > del ||
       TMath::Abs(newZ.Mag2()-1.) > del ||
       TMath::Abs(newX.Dot(newY)) > del ||
       TMath::Abs(newY.Dot(newZ)) > del ||
       TMath::Abs(newZ.Dot(newX)) > del) {
      Warning("RotateAxes","bad axis vectors");
      return *this;
   } else {
      return Transform(TRotation(newX.X(), newY.X(), newZ.X(),
                                 newX.Y(), newY.Y(), newZ.Y(),
                                 newX.Z(), newY.Z(), newZ.Z()));
   }
}

Double_t TRotation::PhiX() const {
   //return Phi
   return (fyx == 0.0 && fxx == 0.0) ? 0.0 : TMath::ATan2(fyx,fxx);
}

Double_t TRotation::PhiY() const {
   //return Phi
   return (fyy == 0.0 && fxy == 0.0) ? 0.0 : TMath::ATan2(fyy,fxy);
}

Double_t TRotation::PhiZ() const {
   //return Phi
   return (fyz == 0.0 && fxz == 0.0) ? 0.0 : TMath::ATan2(fyz,fxz);
}

Double_t TRotation::ThetaX() const {
   //return Phi
   return TMath::ACos(fzx);
}

Double_t TRotation::ThetaY() const {
   //return Theta
   return TMath::ACos(fzy);
}

Double_t TRotation::ThetaZ() const {
   //return Theta
   return TMath::ACos(fzz);
}

void TRotation::AngleAxis(Double_t &angle, TVector3 &axis) const {
   //rotation defined by an angle and a vector
   Double_t cosa  = 0.5*(fxx+fyy+fzz-1);
   Double_t cosa1 = 1-cosa;
   if (cosa1 <= 0) {
      angle = 0;
      axis  = TVector3(0,0,1);
   } else {
      Double_t x=0, y=0, z=0;
      if (fxx > cosa) x = TMath::Sqrt((fxx-cosa)/cosa1);
      if (fyy > cosa) y = TMath::Sqrt((fyy-cosa)/cosa1);
      if (fzz > cosa) z = TMath::Sqrt((fzz-cosa)/cosa1);
      if (fzy < fyz)  x = -x;
      if (fxz < fzx)  y = -y;
      if (fyx < fxy)  z = -z;
      angle = TMath::ACos(cosa);
      axis  = TVector3(x,y,z);
   }
}

TRotation & TRotation::SetXEulerAngles(Double_t phi,
                                      Double_t theta,
                                      Double_t psi) {
   // Rotate using the x-convention (Landau and Lifshitz, Goldstein, &c) by
   // doing the explicit rotations.  This is slightly less efficient than
   // directly applying the rotation, but makes the code much clearer.  My
   // presumption is that this code is not going to be a speed bottle neck.

   SetToIdentity();
   RotateZ(phi);
   RotateX(theta);
   RotateZ(psi);

   return *this;
}

TRotation & TRotation::SetYEulerAngles(Double_t phi,
                                       Double_t theta,
                                       Double_t psi) {
   // Rotate using the y-convention.

   SetToIdentity();
   RotateZ(phi);
   RotateY(theta);
   RotateZ(psi);
   return *this;
}

TRotation & TRotation::RotateXEulerAngles(Double_t phi,
                                         Double_t theta,
                                         Double_t psi) {
   // Rotate using the x-convention.
   TRotation euler;
   euler.SetXEulerAngles(phi,theta,psi);
   return Transform(euler);
}

TRotation & TRotation::RotateYEulerAngles(Double_t phi,
                                          Double_t theta,
                                          Double_t psi) {
   // Rotate using the y-convention.
   TRotation euler;
   euler.SetYEulerAngles(phi,theta,psi);
   return Transform(euler);
}

void TRotation::SetXPhi(Double_t phi) {
   //set XPhi
   SetXEulerAngles(phi,GetXTheta(),GetXPsi());
}

void TRotation::SetXTheta(Double_t theta) {
   //set XTheta
   SetXEulerAngles(GetXPhi(),theta,GetXPsi());
}

void TRotation::SetXPsi(Double_t psi) {
   //set XPsi
   SetXEulerAngles(GetXPhi(),GetXTheta(),psi);
}

void TRotation::SetYPhi(Double_t phi) {
   //set YPhi
   SetYEulerAngles(phi,GetYTheta(),GetYPsi());
}

void TRotation::SetYTheta(Double_t theta) {
   //set YTheta
   SetYEulerAngles(GetYPhi(),theta,GetYPsi());
}

void TRotation::SetYPsi(Double_t psi) {
   //set YPsi
   SetYEulerAngles(GetYPhi(),GetYTheta(),psi);
}

Double_t TRotation::GetXPhi(void) const {
   //return phi angle
   Double_t finalPhi;

   Double_t s2 =  1.0 - fzz*fzz;
   if (s2 < 0) {
      Warning("GetPhi()"," |fzz| > 1 ");
      s2 = 0;
   }
   const Double_t sinTheta = TMath::Sqrt(s2);

   if (sinTheta != 0) {
      const Double_t cscTheta = 1/sinTheta;
      Double_t cosAbsPhi =  fzy * cscTheta;
      if ( TMath::Abs(cosAbsPhi) > 1 ) {        // NaN-proofing
         Warning("GetPhi()","finds | cos phi | > 1");
         cosAbsPhi = 1;
      }
      const Double_t absPhi = TMath::ACos(cosAbsPhi);
      if (fzx > 0) {
         finalPhi = absPhi;
      } else if (fzx < 0) {
         finalPhi = -absPhi;
      } else if (fzy > 0) {
         finalPhi = 0.0;
      } else {
         finalPhi = TMath::Pi();
      }
   } else {              // sinTheta == 0 so |Fzz| = 1
      const Double_t absPhi = .5 * TMath::ACos (fxx);
      if (fxy > 0) {
         finalPhi =  -absPhi;
      } else if (fxy < 0) {
         finalPhi =   absPhi;
      } else if (fxx>0) {
         finalPhi = 0.0;
      } else {
         finalPhi = fzz * TMath::PiOver2();
      }
   }
   return finalPhi;
}

Double_t TRotation::GetYPhi(void) const {
   //return YPhi
   return GetXPhi() + TMath::Pi()/2.0;
}

Double_t TRotation::GetXTheta(void) const {
   //return XTheta
   return  ThetaZ();
}

Double_t TRotation::GetYTheta(void) const {
   //return YTheta
   return  ThetaZ();
}

Double_t TRotation::GetXPsi(void) const {
   //Get psi angle
   double finalPsi = 0.0;

   Double_t s2 =  1.0 - fzz*fzz;
   if (s2 < 0) {
      Warning("GetPsi()"," |fzz| > 1 ");
      s2 = 0;
   }
   const Double_t sinTheta = TMath::Sqrt(s2);

   if (sinTheta != 0) {
      const Double_t cscTheta = 1/sinTheta;
      Double_t cosAbsPsi =  - fyz * cscTheta;
      if ( TMath::Abs(cosAbsPsi) > 1 ) {        // NaN-proofing
         Warning("GetPsi()","| cos psi | > 1 ");
         cosAbsPsi = 1;
      }
      const Double_t absPsi = TMath::ACos(cosAbsPsi);
      if (fxz > 0) {
         finalPsi = absPsi;
      } else if (fxz < 0) {
         finalPsi = -absPsi;
      } else {
         finalPsi = (fyz < 0) ? 0 : TMath::Pi();
      }
   } else {              // sinTheta == 0 so |Fzz| = 1
      Double_t absPsi = fxx;
      if ( TMath::Abs(fxx) > 1 ) {        // NaN-proofing
         Warning("GetPsi()","| fxx | > 1 ");
         absPsi = 1;
      }
      absPsi = .5 * TMath::ACos (absPsi);
      if (fyx > 0) {
         finalPsi = absPsi;
      } else if (fyx < 0) {
         finalPsi = -absPsi;
      } else {
         finalPsi = (fxx > 0) ? 0 : TMath::PiOver2();
      }
   }
   return finalPsi;
}

Double_t TRotation::GetYPsi(void) const {
   //return YPsi
   return GetXPsi() - TMath::Pi()/2;
}

TRotation & TRotation::SetXAxis(const TVector3& axis,
                                const TVector3& xyPlane) {
   //set X axis
   TVector3 xAxis(xyPlane);
   TVector3 yAxis;
   TVector3 zAxis(axis);
   MakeBasis(xAxis,yAxis,zAxis);
   fxx = zAxis.X();  fyx = zAxis.Y();  fzx = zAxis.Z();
   fxy = xAxis.X();  fyy = xAxis.Y();  fzy = xAxis.Z();
   fxz = yAxis.X();  fyz = yAxis.Y();  fzz = yAxis.Z();
   return *this;
}

TRotation & TRotation::SetXAxis(const TVector3& axis) {
   //set X axis
   TVector3 xyPlane(0.0,1.0,0.0);
   return SetXAxis(axis,xyPlane);
}

TRotation & TRotation::SetYAxis(const TVector3& axis,
                                const TVector3& yzPlane) {
   //set Y axis
   TVector3 xAxis(yzPlane);
   TVector3 yAxis;
   TVector3 zAxis(axis);
   MakeBasis(xAxis,yAxis,zAxis);
   fxx = yAxis.X();  fyx = yAxis.Y();  fzx = yAxis.Z();
   fxy = zAxis.X();  fyy = zAxis.Y();  fzy = zAxis.Z();
   fxz = xAxis.X();  fyz = xAxis.Y();  fzz = xAxis.Z();
   return *this;
}

TRotation & TRotation::SetYAxis(const TVector3& axis) {
   //set Y axis
   TVector3 yzPlane(0.0,0.0,1.0);
   return SetYAxis(axis,yzPlane);
}

TRotation & TRotation::SetZAxis(const TVector3& axis,
                                const TVector3& zxPlane) {
   //set Z axis
   TVector3 xAxis(zxPlane);
   TVector3 yAxis;
   TVector3 zAxis(axis);
   MakeBasis(xAxis,yAxis,zAxis);
   fxx = xAxis.X();  fyx = xAxis.Y();  fzx = xAxis.Z();
   fxy = yAxis.X();  fyy = yAxis.Y();  fzy = yAxis.Z();
   fxz = zAxis.X();  fyz = zAxis.Y();  fzz = zAxis.Z();
   return *this;
}

TRotation & TRotation::SetZAxis(const TVector3& axis) {
   //set Z axis
   TVector3 zxPlane(1.0,0.0,0.0);
   return SetZAxis(axis,zxPlane);
}

void TRotation::MakeBasis(TVector3& xAxis,
                          TVector3& yAxis,
                          TVector3& zAxis) const {
   // Make the Z axis into a unit variable.
   Double_t zmag = zAxis.Mag();
   if (zmag<TOLERANCE) {
      Warning("MakeBasis(X,Y,Z)","non-zero Z Axis is required");
   }
   zAxis *= (1.0/zmag);

   Double_t xmag = xAxis.Mag();
   if (xmag<TOLERANCE*zmag) {
      xAxis = zAxis.Orthogonal();
      xmag = 1.0;
   }

   // Find the Y axis
   yAxis = zAxis.Cross(xAxis)*(1.0/xmag);
   Double_t ymag = yAxis.Mag();
   if (ymag<TOLERANCE*zmag) {
      yAxis = zAxis.Orthogonal();
   } else {
      yAxis *= (1.0/ymag);
   }

   xAxis = yAxis.Cross(zAxis);
}
 TRotation.cxx:1
 TRotation.cxx:2
 TRotation.cxx:3
 TRotation.cxx:4
 TRotation.cxx:5
 TRotation.cxx:6
 TRotation.cxx:7
 TRotation.cxx:8
 TRotation.cxx:9
 TRotation.cxx:10
 TRotation.cxx:11
 TRotation.cxx:12
 TRotation.cxx:13
 TRotation.cxx:14
 TRotation.cxx:15
 TRotation.cxx:16
 TRotation.cxx:17
 TRotation.cxx:18
 TRotation.cxx:19
 TRotation.cxx:20
 TRotation.cxx:21
 TRotation.cxx:22
 TRotation.cxx:23
 TRotation.cxx:24
 TRotation.cxx:25
 TRotation.cxx:26
 TRotation.cxx:27
 TRotation.cxx:28
 TRotation.cxx:29
 TRotation.cxx:30
 TRotation.cxx:31
 TRotation.cxx:32
 TRotation.cxx:33
 TRotation.cxx:34
 TRotation.cxx:35
 TRotation.cxx:36
 TRotation.cxx:37
 TRotation.cxx:38
 TRotation.cxx:39
 TRotation.cxx:40
 TRotation.cxx:41
 TRotation.cxx:42
 TRotation.cxx:43
 TRotation.cxx:44
 TRotation.cxx:45
 TRotation.cxx:46
 TRotation.cxx:47
 TRotation.cxx:48
 TRotation.cxx:49
 TRotation.cxx:50
 TRotation.cxx:51
 TRotation.cxx:52
 TRotation.cxx:53
 TRotation.cxx:54
 TRotation.cxx:55
 TRotation.cxx:56
 TRotation.cxx:57
 TRotation.cxx:58
 TRotation.cxx:59
 TRotation.cxx:60
 TRotation.cxx:61
 TRotation.cxx:62
 TRotation.cxx:63
 TRotation.cxx:64
 TRotation.cxx:65
 TRotation.cxx:66
 TRotation.cxx:67
 TRotation.cxx:68
 TRotation.cxx:69
 TRotation.cxx:70
 TRotation.cxx:71
 TRotation.cxx:72
 TRotation.cxx:73
 TRotation.cxx:74
 TRotation.cxx:75
 TRotation.cxx:76
 TRotation.cxx:77
 TRotation.cxx:78
 TRotation.cxx:79
 TRotation.cxx:80
 TRotation.cxx:81
 TRotation.cxx:82
 TRotation.cxx:83
 TRotation.cxx:84
 TRotation.cxx:85
 TRotation.cxx:86
 TRotation.cxx:87
 TRotation.cxx:88
 TRotation.cxx:89
 TRotation.cxx:90
 TRotation.cxx:91
 TRotation.cxx:92
 TRotation.cxx:93
 TRotation.cxx:94
 TRotation.cxx:95
 TRotation.cxx:96
 TRotation.cxx:97
 TRotation.cxx:98
 TRotation.cxx:99
 TRotation.cxx:100
 TRotation.cxx:101
 TRotation.cxx:102
 TRotation.cxx:103
 TRotation.cxx:104
 TRotation.cxx:105
 TRotation.cxx:106
 TRotation.cxx:107
 TRotation.cxx:108
 TRotation.cxx:109
 TRotation.cxx:110
 TRotation.cxx:111
 TRotation.cxx:112
 TRotation.cxx:113
 TRotation.cxx:114
 TRotation.cxx:115
 TRotation.cxx:116
 TRotation.cxx:117
 TRotation.cxx:118
 TRotation.cxx:119
 TRotation.cxx:120
 TRotation.cxx:121
 TRotation.cxx:122
 TRotation.cxx:123
 TRotation.cxx:124
 TRotation.cxx:125
 TRotation.cxx:126
 TRotation.cxx:127
 TRotation.cxx:128
 TRotation.cxx:129
 TRotation.cxx:130
 TRotation.cxx:131
 TRotation.cxx:132
 TRotation.cxx:133
 TRotation.cxx:134
 TRotation.cxx:135
 TRotation.cxx:136
 TRotation.cxx:137
 TRotation.cxx:138
 TRotation.cxx:139
 TRotation.cxx:140
 TRotation.cxx:141
 TRotation.cxx:142
 TRotation.cxx:143
 TRotation.cxx:144
 TRotation.cxx:145
 TRotation.cxx:146
 TRotation.cxx:147
 TRotation.cxx:148
 TRotation.cxx:149
 TRotation.cxx:150
 TRotation.cxx:151
 TRotation.cxx:152
 TRotation.cxx:153
 TRotation.cxx:154
 TRotation.cxx:155
 TRotation.cxx:156
 TRotation.cxx:157
 TRotation.cxx:158
 TRotation.cxx:159
 TRotation.cxx:160
 TRotation.cxx:161
 TRotation.cxx:162
 TRotation.cxx:163
 TRotation.cxx:164
 TRotation.cxx:165
 TRotation.cxx:166
 TRotation.cxx:167
 TRotation.cxx:168
 TRotation.cxx:169
 TRotation.cxx:170
 TRotation.cxx:171
 TRotation.cxx:172
 TRotation.cxx:173
 TRotation.cxx:174
 TRotation.cxx:175
 TRotation.cxx:176
 TRotation.cxx:177
 TRotation.cxx:178
 TRotation.cxx:179
 TRotation.cxx:180
 TRotation.cxx:181
 TRotation.cxx:182
 TRotation.cxx:183
 TRotation.cxx:184
 TRotation.cxx:185
 TRotation.cxx:186
 TRotation.cxx:187
 TRotation.cxx:188
 TRotation.cxx:189
 TRotation.cxx:190
 TRotation.cxx:191
 TRotation.cxx:192
 TRotation.cxx:193
 TRotation.cxx:194
 TRotation.cxx:195
 TRotation.cxx:196
 TRotation.cxx:197
 TRotation.cxx:198
 TRotation.cxx:199
 TRotation.cxx:200
 TRotation.cxx:201
 TRotation.cxx:202
 TRotation.cxx:203
 TRotation.cxx:204
 TRotation.cxx:205
 TRotation.cxx:206
 TRotation.cxx:207
 TRotation.cxx:208
 TRotation.cxx:209
 TRotation.cxx:210
 TRotation.cxx:211
 TRotation.cxx:212
 TRotation.cxx:213
 TRotation.cxx:214
 TRotation.cxx:215
 TRotation.cxx:216
 TRotation.cxx:217
 TRotation.cxx:218
 TRotation.cxx:219
 TRotation.cxx:220
 TRotation.cxx:221
 TRotation.cxx:222
 TRotation.cxx:223
 TRotation.cxx:224
 TRotation.cxx:225
 TRotation.cxx:226
 TRotation.cxx:227
 TRotation.cxx:228
 TRotation.cxx:229
 TRotation.cxx:230
 TRotation.cxx:231
 TRotation.cxx:232
 TRotation.cxx:233
 TRotation.cxx:234
 TRotation.cxx:235
 TRotation.cxx:236
 TRotation.cxx:237
 TRotation.cxx:238
 TRotation.cxx:239
 TRotation.cxx:240
 TRotation.cxx:241
 TRotation.cxx:242
 TRotation.cxx:243
 TRotation.cxx:244
 TRotation.cxx:245
 TRotation.cxx:246
 TRotation.cxx:247
 TRotation.cxx:248
 TRotation.cxx:249
 TRotation.cxx:250
 TRotation.cxx:251
 TRotation.cxx:252
 TRotation.cxx:253
 TRotation.cxx:254
 TRotation.cxx:255
 TRotation.cxx:256
 TRotation.cxx:257
 TRotation.cxx:258
 TRotation.cxx:259
 TRotation.cxx:260
 TRotation.cxx:261
 TRotation.cxx:262
 TRotation.cxx:263
 TRotation.cxx:264
 TRotation.cxx:265
 TRotation.cxx:266
 TRotation.cxx:267
 TRotation.cxx:268
 TRotation.cxx:269
 TRotation.cxx:270
 TRotation.cxx:271
 TRotation.cxx:272
 TRotation.cxx:273
 TRotation.cxx:274
 TRotation.cxx:275
 TRotation.cxx:276
 TRotation.cxx:277
 TRotation.cxx:278
 TRotation.cxx:279
 TRotation.cxx:280
 TRotation.cxx:281
 TRotation.cxx:282
 TRotation.cxx:283
 TRotation.cxx:284
 TRotation.cxx:285
 TRotation.cxx:286
 TRotation.cxx:287
 TRotation.cxx:288
 TRotation.cxx:289
 TRotation.cxx:290
 TRotation.cxx:291
 TRotation.cxx:292
 TRotation.cxx:293
 TRotation.cxx:294
 TRotation.cxx:295
 TRotation.cxx:296
 TRotation.cxx:297
 TRotation.cxx:298
 TRotation.cxx:299
 TRotation.cxx:300
 TRotation.cxx:301
 TRotation.cxx:302
 TRotation.cxx:303
 TRotation.cxx:304
 TRotation.cxx:305
 TRotation.cxx:306
 TRotation.cxx:307
 TRotation.cxx:308
 TRotation.cxx:309
 TRotation.cxx:310
 TRotation.cxx:311
 TRotation.cxx:312
 TRotation.cxx:313
 TRotation.cxx:314
 TRotation.cxx:315
 TRotation.cxx:316
 TRotation.cxx:317
 TRotation.cxx:318
 TRotation.cxx:319
 TRotation.cxx:320
 TRotation.cxx:321
 TRotation.cxx:322
 TRotation.cxx:323
 TRotation.cxx:324
 TRotation.cxx:325
 TRotation.cxx:326
 TRotation.cxx:327
 TRotation.cxx:328
 TRotation.cxx:329
 TRotation.cxx:330
 TRotation.cxx:331
 TRotation.cxx:332
 TRotation.cxx:333
 TRotation.cxx:334
 TRotation.cxx:335
 TRotation.cxx:336
 TRotation.cxx:337
 TRotation.cxx:338
 TRotation.cxx:339
 TRotation.cxx:340
 TRotation.cxx:341
 TRotation.cxx:342
 TRotation.cxx:343
 TRotation.cxx:344
 TRotation.cxx:345
 TRotation.cxx:346
 TRotation.cxx:347
 TRotation.cxx:348
 TRotation.cxx:349
 TRotation.cxx:350
 TRotation.cxx:351
 TRotation.cxx:352
 TRotation.cxx:353
 TRotation.cxx:354
 TRotation.cxx:355
 TRotation.cxx:356
 TRotation.cxx:357
 TRotation.cxx:358
 TRotation.cxx:359
 TRotation.cxx:360
 TRotation.cxx:361
 TRotation.cxx:362
 TRotation.cxx:363
 TRotation.cxx:364
 TRotation.cxx:365
 TRotation.cxx:366
 TRotation.cxx:367
 TRotation.cxx:368
 TRotation.cxx:369
 TRotation.cxx:370
 TRotation.cxx:371
 TRotation.cxx:372
 TRotation.cxx:373
 TRotation.cxx:374
 TRotation.cxx:375
 TRotation.cxx:376
 TRotation.cxx:377
 TRotation.cxx:378
 TRotation.cxx:379
 TRotation.cxx:380
 TRotation.cxx:381
 TRotation.cxx:382
 TRotation.cxx:383
 TRotation.cxx:384
 TRotation.cxx:385
 TRotation.cxx:386
 TRotation.cxx:387
 TRotation.cxx:388
 TRotation.cxx:389
 TRotation.cxx:390
 TRotation.cxx:391
 TRotation.cxx:392
 TRotation.cxx:393
 TRotation.cxx:394
 TRotation.cxx:395
 TRotation.cxx:396
 TRotation.cxx:397
 TRotation.cxx:398
 TRotation.cxx:399
 TRotation.cxx:400
 TRotation.cxx:401
 TRotation.cxx:402
 TRotation.cxx:403
 TRotation.cxx:404
 TRotation.cxx:405
 TRotation.cxx:406
 TRotation.cxx:407
 TRotation.cxx:408
 TRotation.cxx:409
 TRotation.cxx:410
 TRotation.cxx:411
 TRotation.cxx:412
 TRotation.cxx:413
 TRotation.cxx:414
 TRotation.cxx:415
 TRotation.cxx:416
 TRotation.cxx:417
 TRotation.cxx:418
 TRotation.cxx:419
 TRotation.cxx:420
 TRotation.cxx:421
 TRotation.cxx:422
 TRotation.cxx:423
 TRotation.cxx:424
 TRotation.cxx:425
 TRotation.cxx:426
 TRotation.cxx:427
 TRotation.cxx:428
 TRotation.cxx:429
 TRotation.cxx:430
 TRotation.cxx:431
 TRotation.cxx:432
 TRotation.cxx:433
 TRotation.cxx:434
 TRotation.cxx:435
 TRotation.cxx:436
 TRotation.cxx:437
 TRotation.cxx:438
 TRotation.cxx:439
 TRotation.cxx:440
 TRotation.cxx:441
 TRotation.cxx:442
 TRotation.cxx:443
 TRotation.cxx:444
 TRotation.cxx:445
 TRotation.cxx:446
 TRotation.cxx:447
 TRotation.cxx:448
 TRotation.cxx:449
 TRotation.cxx:450
 TRotation.cxx:451
 TRotation.cxx:452
 TRotation.cxx:453
 TRotation.cxx:454
 TRotation.cxx:455
 TRotation.cxx:456
 TRotation.cxx:457
 TRotation.cxx:458
 TRotation.cxx:459
 TRotation.cxx:460
 TRotation.cxx:461
 TRotation.cxx:462
 TRotation.cxx:463
 TRotation.cxx:464
 TRotation.cxx:465
 TRotation.cxx:466
 TRotation.cxx:467
 TRotation.cxx:468
 TRotation.cxx:469
 TRotation.cxx:470
 TRotation.cxx:471
 TRotation.cxx:472
 TRotation.cxx:473
 TRotation.cxx:474
 TRotation.cxx:475
 TRotation.cxx:476
 TRotation.cxx:477
 TRotation.cxx:478
 TRotation.cxx:479
 TRotation.cxx:480
 TRotation.cxx:481
 TRotation.cxx:482
 TRotation.cxx:483
 TRotation.cxx:484
 TRotation.cxx:485
 TRotation.cxx:486
 TRotation.cxx:487
 TRotation.cxx:488
 TRotation.cxx:489
 TRotation.cxx:490
 TRotation.cxx:491
 TRotation.cxx:492
 TRotation.cxx:493
 TRotation.cxx:494
 TRotation.cxx:495
 TRotation.cxx:496
 TRotation.cxx:497
 TRotation.cxx:498
 TRotation.cxx:499
 TRotation.cxx:500
 TRotation.cxx:501
 TRotation.cxx:502
 TRotation.cxx:503
 TRotation.cxx:504
 TRotation.cxx:505
 TRotation.cxx:506
 TRotation.cxx:507
 TRotation.cxx:508
 TRotation.cxx:509
 TRotation.cxx:510
 TRotation.cxx:511
 TRotation.cxx:512
 TRotation.cxx:513
 TRotation.cxx:514
 TRotation.cxx:515
 TRotation.cxx:516
 TRotation.cxx:517
 TRotation.cxx:518
 TRotation.cxx:519
 TRotation.cxx:520
 TRotation.cxx:521
 TRotation.cxx:522
 TRotation.cxx:523
 TRotation.cxx:524
 TRotation.cxx:525
 TRotation.cxx:526
 TRotation.cxx:527
 TRotation.cxx:528
 TRotation.cxx:529
 TRotation.cxx:530
 TRotation.cxx:531
 TRotation.cxx:532
 TRotation.cxx:533
 TRotation.cxx:534
 TRotation.cxx:535
 TRotation.cxx:536
 TRotation.cxx:537
 TRotation.cxx:538
 TRotation.cxx:539
 TRotation.cxx:540
 TRotation.cxx:541
 TRotation.cxx:542
 TRotation.cxx:543
 TRotation.cxx:544
 TRotation.cxx:545
 TRotation.cxx:546
 TRotation.cxx:547
 TRotation.cxx:548
 TRotation.cxx:549
 TRotation.cxx:550
 TRotation.cxx:551
 TRotation.cxx:552
 TRotation.cxx:553
 TRotation.cxx:554
 TRotation.cxx:555
 TRotation.cxx:556
 TRotation.cxx:557
 TRotation.cxx:558
 TRotation.cxx:559
 TRotation.cxx:560
 TRotation.cxx:561
 TRotation.cxx:562
 TRotation.cxx:563
 TRotation.cxx:564
 TRotation.cxx:565
 TRotation.cxx:566
 TRotation.cxx:567
 TRotation.cxx:568
 TRotation.cxx:569
 TRotation.cxx:570
 TRotation.cxx:571
 TRotation.cxx:572
 TRotation.cxx:573
 TRotation.cxx:574
 TRotation.cxx:575
 TRotation.cxx:576
 TRotation.cxx:577
 TRotation.cxx:578
 TRotation.cxx:579
 TRotation.cxx:580
 TRotation.cxx:581
 TRotation.cxx:582
 TRotation.cxx:583
 TRotation.cxx:584
 TRotation.cxx:585
 TRotation.cxx:586
 TRotation.cxx:587
 TRotation.cxx:588
 TRotation.cxx:589
 TRotation.cxx:590
 TRotation.cxx:591
 TRotation.cxx:592
 TRotation.cxx:593
 TRotation.cxx:594
 TRotation.cxx:595
 TRotation.cxx:596
 TRotation.cxx:597
 TRotation.cxx:598
 TRotation.cxx:599
 TRotation.cxx:600
 TRotation.cxx:601
 TRotation.cxx:602
 TRotation.cxx:603
 TRotation.cxx:604
 TRotation.cxx:605
 TRotation.cxx:606
 TRotation.cxx:607
 TRotation.cxx:608
 TRotation.cxx:609
 TRotation.cxx:610
 TRotation.cxx:611
 TRotation.cxx:612
 TRotation.cxx:613
 TRotation.cxx:614
 TRotation.cxx:615
 TRotation.cxx:616
 TRotation.cxx:617
 TRotation.cxx:618
 TRotation.cxx:619
 TRotation.cxx:620
 TRotation.cxx:621
 TRotation.cxx:622
 TRotation.cxx:623
 TRotation.cxx:624
 TRotation.cxx:625
 TRotation.cxx:626
 TRotation.cxx:627
 TRotation.cxx:628
 TRotation.cxx:629
 TRotation.cxx:630
 TRotation.cxx:631
 TRotation.cxx:632
 TRotation.cxx:633
 TRotation.cxx:634
 TRotation.cxx:635
 TRotation.cxx:636
 TRotation.cxx:637
 TRotation.cxx:638
 TRotation.cxx:639
 TRotation.cxx:640
 TRotation.cxx:641
 TRotation.cxx:642
 TRotation.cxx:643
 TRotation.cxx:644
 TRotation.cxx:645
 TRotation.cxx:646
 TRotation.cxx:647
 TRotation.cxx:648
 TRotation.cxx:649
 TRotation.cxx:650
 TRotation.cxx:651
 TRotation.cxx:652
 TRotation.cxx:653
 TRotation.cxx:654
 TRotation.cxx:655
 TRotation.cxx:656
 TRotation.cxx:657
 TRotation.cxx:658
 TRotation.cxx:659
 TRotation.cxx:660
 TRotation.cxx:661
 TRotation.cxx:662
 TRotation.cxx:663
 TRotation.cxx:664
 TRotation.cxx:665
 TRotation.cxx:666
 TRotation.cxx:667
 TRotation.cxx:668
 TRotation.cxx:669
 TRotation.cxx:670
 TRotation.cxx:671
 TRotation.cxx:672
 TRotation.cxx:673
 TRotation.cxx:674
 TRotation.cxx:675
 TRotation.cxx:676
 TRotation.cxx:677
 TRotation.cxx:678
 TRotation.cxx:679
 TRotation.cxx:680
 TRotation.cxx:681
 TRotation.cxx:682
 TRotation.cxx:683
 TRotation.cxx:684
 TRotation.cxx:685
 TRotation.cxx:686
 TRotation.cxx:687
 TRotation.cxx:688
 TRotation.cxx:689
 TRotation.cxx:690
 TRotation.cxx:691
 TRotation.cxx:692
 TRotation.cxx:693
 TRotation.cxx:694
 TRotation.cxx:695
 TRotation.cxx:696
 TRotation.cxx:697
 TRotation.cxx:698
 TRotation.cxx:699
 TRotation.cxx:700
 TRotation.cxx:701
 TRotation.cxx:702
 TRotation.cxx:703
 TRotation.cxx:704
 TRotation.cxx:705
 TRotation.cxx:706
 TRotation.cxx:707
 TRotation.cxx:708
 TRotation.cxx:709