ROOT logo
// $Id: HTrans.cxx 2370 2010-04-25 18:13:50Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "HTrans.h"
#include <Gled/GledTypes.h>

#include <iomanip>


//==============================================================================
// HPoint
//==============================================================================

template<typename TT>
TT HPoint<TT>::Eta() const
{
  static const Exc_t _eh("HPoint<TT>::Eta ");

  TT cosTheta = CosTheta();
  if (cosTheta*cosTheta < 1) return -0.5* TMath::Log( (1.0-cosTheta)/(1.0+cosTheta) );
  ISwarn(_eh + "transverse momentum = 0, returning +/- 1e10");
  return (z >= 0) ? 1e10 : -1e10;
}

template<typename TT>
TT HPoint<TT>::Normalize(TT length)
{
   // Normalize the vector to length if current length is non-zero.
   // Returns the old magnitude.

   TT m = Mag();
   if (m != 0)
   {
      length /= m;
      x *= length; y *= length; z *= length;
   }
   return m;
}

template<typename TT>
HPoint<TT> HPoint<TT>::Orthogonal() const
{
   // Returns an orthogonal vector (not normalized).

   Float_t xx = x < 0 ? -x : x;
   Float_t yy = y < 0 ? -y : y;
   Float_t zz = z < 0 ? -z : z;
   if (xx < yy) {
      return xx < zz ? HPoint<TT>(0,z,-y) : HPoint<TT>(y,-x,0);
   } else {
      return yy < zz ? HPoint<TT>(-z,0,x) : HPoint<TT>(y,-x,0);
   }
}

template<typename TT>
void HPoint<TT>::OrthoNormBase(HPoint<TT>& a, HPoint<TT>& b) const
{
   // Set vectors a and b to be normal to this and among themselves,
   // both of length 1.

   a = Orthogonal();
   b.Cross(*this, a);
   a.Normalize();
   b.Normalize();
}

//==============================================================================

template<class TT>
void HPoint<TT>::Print() const
{
  printf("%8.3lf %8.3lf %8.3lf\n", x, y, z);
}

template<class TT>
std::ostream& operator<<(std::ostream& s, const HPoint<TT>& t)
{
  s.setf(ios::fixed, ios::floatfield); s.precision(3);
  s << t.x <<"\t"<< t.y <<"\t"<< t.z <<"\n";
  return s;
}


//==============================================================================
// HTrans
//==============================================================================

//______________________________________________________________________
//
// HTrans is a 4x4 transformation matrix for homogeneous coordinates
// stored internaly in a column-major order to allow direct usage by
// GL. The element type is Double32_t as statically the floats would
// be precise enough but continuous operations on the matrix must
// retain precision of column vectors.
//
// Direct  element access (first two should be used with care):
// operator[i]    direct access to elements,   i:0->15
// CM(i,j)        element 4*j + i;           i,j:0->3    { CM ~ c-matrix }
// operator(i,j)  element 4*(j-1) + i - 1    i,j:1->4
//
// Column-vector access:
// USet Get/SetBaseVec(), Get/SetPos() and Arr[XYZT]() methods.
//
// For all methods taking the matrix indices:
// 1->X, 2->Y, 3->Z; 4->Position (if applicable). 0 reserved for time.
//
// Shorthands in method-names:
// LF ~ LocalFrame; PF ~ ParentFrame; IP ~ InPlace

ClassImp(HTransF);
ClassImp(HTransD);

#define F00  0
#define F01  4
#define F02  8
#define F03 12

#define F10  1
#define F11  5
#define F12  9
#define F13 13

#define F20  2
#define F21  6
#define F22 10
#define F23 14

#define F30  3
#define F31  7
#define F32 11
#define F33 15

/**************************************************************************/

template<class TT>
HTrans<TT>::HTrans() { UnitTrans(); }

template<class TT>
HTrans<TT>::HTrans(const HTrans<TT>& z) { SetTrans(z); }

template<class TT>
HTrans<TT>::HTrans(const Float_t* x)
{
  M[0]  = x[0];  M[1]  = x[1];  M[2]  = x[2];  M[3]  = x[3];
  M[4]  = x[4];  M[5]  = x[5];  M[6]  = x[6];  M[7]  = x[7];
  M[8]  = x[8];  M[9]  = x[9];  M[10] = x[10]; M[11] = x[11];
  M[12] = x[12]; M[13] = x[13]; M[14] = x[14]; M[15] = x[15];
}

template<class TT>
HTrans<TT>::HTrans(const Double_t* x)
{
  M[0]  = x[0];  M[1]  = x[1];  M[2]  = x[2];  M[3]  = x[3];
  M[4]  = x[4];  M[5]  = x[5];  M[6]  = x[6];  M[7]  = x[7];
  M[8]  = x[8];  M[9]  = x[9];  M[10] = x[10]; M[11] = x[11];
  M[12] = x[12]; M[13] = x[13]; M[14] = x[14]; M[15] = x[15];
}

/**************************************************************************/

template<class TT>
void HTrans<TT>::UnitTrans()
{
  M[0]  = 1; M[1]  = 0; M[2]  = 0; M[3]  = 0;
  M[4]  = 0; M[5]  = 1; M[6]  = 0; M[7]  = 0;
  M[8]  = 0; M[9]  = 0; M[10] = 1; M[11] = 0;
  M[12] = 0; M[13] = 0; M[14] = 0; M[15] = 1;
}

template<class TT>
void HTrans<TT>::UnitRot()
{
  M[0]  = 1; M[1]  = 0; M[2]  = 0;
  M[4]  = 0; M[5]  = 1; M[6]  = 0;
  M[8]  = 0; M[9]  = 0; M[10] = 1;
}

template<class TT>
void HTrans<TT>::SetTrans(const HTrans<TT>& t)
{
  const TT* const x = t.M;
  M[0]  = x[0];  M[1]  = x[1];  M[2]  = x[2];  M[3]  = x[3];
  M[4]  = x[4];  M[5]  = x[5];  M[6]  = x[6];  M[7]  = x[7];
  M[8]  = x[8];  M[9]  = x[9];  M[10] = x[10]; M[11] = x[11];
  M[12] = x[12]; M[13] = x[13]; M[14] = x[14]; M[15] = x[15];
}

template<class TT>
void HTrans<TT>::SetFromArray(const Double_t* arr)
{
  for (Int_t i=0; i<16; ++i) M[i] = arr[i];
}

template<class TT>
void HTrans<TT>::SetFromArray(const Float_t* arr)
{
  for (Int_t i=0; i<16; ++i) M[i] = arr[i];
}

template<class TT>
void HTrans<TT>::SetupRotation(Int_t i, Int_t j, TT f)
{
  // Setup the matrix as an elementary rotation.
  // Optimized versions of left/right multiplication with an elementary
  // rotation matrix are implemented in RotatePF/RotateLF.
  // Expects identity matrix.
  
  if(i == j) return;
  HTrans<TT>& M = *this;
  M(i,i) = M(j,j) = TMath::Cos(f);
  TT s = TMath::Sin(f);
  M(i,j) = -s; M(j,i) = s;
}

/**************************************************************************/
// OrtoNorm3 and Invert are near the bottom.
/**************************************************************************/

template<class TT>
void HTrans<TT>::MultLeft(const HTrans<TT>& t)
{
  TT  B[4];
  TT* C = M;
  for(int c=0; c<4; ++c, C+=4) {
    const TT* T = t.M;
    for(int r=0; r<4; ++r, ++T)
      B[r] = T[0]*C[0] + T[4]*C[1] + T[8]*C[2] + T[12]*C[3];
    C[0] = B[0]; C[1] = B[1]; C[2] = B[2]; C[3] = B[3];
  }
}

template<class TT>
void HTrans<TT>::MultRight(const HTrans<TT>& t)
{
  TT  B[4];
  TT* C = M;
  for(int r=0; r<4; ++r, ++C) {
    const TT* T = t.M;
    for(int c=0; c<4; ++c, T+=4)
      B[c] = C[0]*T[0] + C[4]*T[1] + C[8]*T[2] + C[12]*T[3];
    C[0] = B[0]; C[4] = B[1]; C[8] = B[2]; C[12] = B[3];
  }
}

template<class TT>
HTrans<TT> HTrans<TT>::operator*(const HTrans<TT>& t)
{
  HTrans<TT> b(*this);
  b.MultRight(t);
  return b;
}

template<class TT>
void HTrans<TT>::MultLeft3x3(const TT* m)
{
  // Multiply from left with a column-major 3x3 matrix.

  TT  B[3];
  TT* C = M;
  for(int c=0; c<3; ++c, C+=4) {
    const TT* T = m;
    for(int r=0; r<3; ++r, ++T)
      B[r] = T[0]*C[0] + T[3]*C[1] + T[6]*C[2];
    C[0] = B[0]; C[1] = B[1]; C[2] = B[2];
  }
}

template<class TT>
void HTrans<TT>::MultRight3x3(const TT* m)
{
  // Multiply from right with a column-major 3x3 matrix.

  TT  B[3];
  TT* C = M;
  for(int r=0; r<3; ++r, ++C) {
    const TT* T = m;
    for(int c=0; c<3; ++c, T+=3)
      B[c] = C[0]*T[0] + C[4]*T[1] + C[8]*T[2];
    C[0] = B[0]; C[4] = B[1]; C[8] = B[2];
  }
}

template<class TT>
void HTrans<TT>::MultLeft3x3transposed(const TT* m)
{
  // Multiply from left with the transpose of a column-major 3x3 matrix.
  // Alternatively - multiply from left with a row-major 3x3 matrix.

  TT  B[3];
  TT* C = M;
  for(int c=0; c<3; ++c, C+=4) {
    const TT* T = m;
    for(int r=0; r<3; ++r, T+=3)
      B[r] = T[0]*C[0] + T[1]*C[1] + T[2]*C[2];
    C[0] = B[0]; C[1] = B[1]; C[2] = B[2];
  }
}

template<class TT>
void HTrans<TT>::MultRight3x3transposed(const TT* m)
{
  // Multiply from right with the transpose of a column-major 3x3 matrix.
  // Alternatively - multiply from right with a row-major 3x3 matrix.

  TT  B[3];
  TT* C = M;
  for(int r=0; r<3; ++r, ++C) {
    const TT* T = m;
    for(int c=0; c<3; ++c, ++T)
      B[c] = C[0]*T[0] + C[4]*T[3] + C[8]*T[6];
    C[0] = B[0]; C[4] = B[1]; C[8] = B[2];
  }
}

/**************************************************************************/
// Move & Rotate
/**************************************************************************/

template<class TT>
void HTrans<TT>::MoveLF(Int_t ai, TT amount)
{
  const TT *C = M + 4*--ai;
  M[F03] += amount*C[0]; M[F13] += amount*C[1]; M[F23] += amount*C[2];
}

template<class TT>
void HTrans<TT>::Move3LF(TT x, TT y, TT z)
{
  M[F03] += x*M[0] + y*M[4] + z*M[8];
  M[F13] += x*M[1] + y*M[5] + z*M[9];
  M[F23] += x*M[2] + y*M[6] + z*M[10];
}

template<class TT>
void HTrans<TT>::RotateLF(Int_t i1, Int_t i2, TT amount)
{
  // Rotate in local frame. Does optimised version of MultRight.

  if(i1 == i2) return;
  // Algorithm: HTrans<TT> a; a.SetupRotation(i1, i2, amount); MultRight(a);
  // Optimized version:
  const TT cos = TMath::Cos(amount), sin = TMath::Sin(amount);
  TT  b1, b2;
  TT* C = M;
  --i1 <<= 2; --i2 <<= 2; // column major
  for(int r=0; r<4; ++r, ++C) {
    b1 = cos*C[i1] + sin*C[i2];
    b2 = cos*C[i2] - sin*C[i1];
    C[i1] = b1; C[i2] = b2;
  }
}

/**************************************************************************/

template<class TT>
void HTrans<TT>::MovePF(Int_t ai, TT amount)
{
  M[F03 + --ai] += amount;
}

template<class TT>
void HTrans<TT>::Move3PF(TT x, TT y, TT z)
{
  M[F03] += x;
  M[F13] += y;
  M[F23] += z;
}

template<class TT>
void HTrans<TT>::RotatePF(Int_t i1, Int_t i2, TT amount)
{
  // Rotate in parent frame. Does optimised version of MultLeft.

  if(i1 == i2) return;
  // Algorithm: HTrans<TT> a; a.SetupRotation(i1, i2, amount); MultLeft(a);

  // Optimized version:
  const TT cos = TMath::Cos(amount), sin = TMath::Sin(amount);
  TT  b1, b2;
  TT* C = M;
  --i1; --i2;
  for(int c=0; c<4; ++c, C+=4) {
    b1 = cos*C[i1] - sin*C[i2];
    b2 = cos*C[i2] + sin*C[i1];
    C[i1] = b1; C[i2] = b2;
  }
}

/**************************************************************************/

template<class TT>
void HTrans<TT>::Move(const HTrans<TT>& a, Int_t ai, TT amount)
{
  const TT* A = a.M + 4*--ai;
  M[F03] += amount*A[0];
  M[F13] += amount*A[1];
  M[F23] += amount*A[2];
}

template<class TT>
void HTrans<TT>::Move3(const HTrans<TT>& a, TT x, TT y, TT z)
{
  const TT* A = a.M;
  M[F03] += x*A[F00] + y*A[F01] + z*A[F02];
  M[F13] += x*A[F10] + y*A[F11] + z*A[F12];
  M[F23] += x*A[F20] + y*A[F21] + z*A[F22];
}

template<class TT>
void HTrans<TT>::Rotate(const HTrans<TT>& a, Int_t i1, Int_t i2, TT amount)
{
  if(i1 == i2) return;
  HTrans<TT> X(a);
  X.Invert();
  MultLeft(X);
  RotatePF(i1, i2, amount);
  MultLeft(a);
}


/**************************************************************************/
// Cardan angle interface
/**************************************************************************/

template<class TT>
void HTrans<TT>::SetRotByAngles(Float_t a1, Float_t a2, Float_t a3)
{
  // Sets Rotation part as given by angles:
  // a1 around z, -a2 around y, a3 around x

  TT A, B, C, D, E, F;
  A = TMath::Cos(a3); B = TMath::Sin(a3);
  C = TMath::Cos(a2); D = TMath::Sin(a2); // should be -sin(a2) for positive direction
  E = TMath::Cos(a1); F = TMath::Sin(a1);
  TT AD = A*D, BD = B*D;

  M[F00] = C*E; M[F01] = -BD*E - A*F; M[F02] = -AD*E + B*F;
  M[F10] = C*F; M[F11] = -BD*F + A*E; M[F12] = -AD*F - B*E;
  M[F20] = D;   M[F21] =  B*C;        M[F22] =  A*C;
}

template<class TT>
void HTrans<TT>::SetRotByAnyAngles(Float_t a1, Float_t a2, Float_t a3,
				   const Text_t* pat)
{
  // Sets Rotation part as given by angles a1, a1, a3 and pattern pat.
  // Pattern consists of "XxYyZz" characters.
  // eg: x means rotate about x axis, X means rotate in negative direction
  // xYz -> R_x(a3) * R_y(-a2) * R_z(a1); (standard Gled representation)
  // Note that angles and pattern elements have inversed order!
  //
  // Implements Eulerian/Cardanian angles in a uniform way.

  int n = strspn(pat, "XxYyZz"); if(n > 3) n = 3;
  // Build Trans ... assign ...
  Float_t a[] = { a3, a2, a1 };
  UnitRot();
  for(int i=0; i<n; i++) {
    if(isupper(pat[i])) a[i] = -a[i];
    switch(pat[i]) {
    case 'x': case 'X': RotateLF(2, 3, a[i]); break;
    case 'y': case 'Y': RotateLF(3, 1, a[i]); break;
    case 'z': case 'Z': RotateLF(1, 2, a[i]); break;
    }
  }
}

template<class TT>
void HTrans<TT>::GetRotAngles(Float_t* x) const
{
  // Get Cardan rotation angles (pattern xYz above).
  // This only works if no scaling has been applied.

  TT d = M[F20];
  if (d>1) d=1; else if (d<-1) d=-1; // Fix numerical errors
  x[1] = TMath::ASin(d);
  TT C = TMath::Cos(x[1]);
  if (TMath::Abs(C) > 8.7e-6)
  {
    x[0] = TMath::ATan2(M[F10], M[F00]);      
    x[2] = TMath::ATan2(M[F21], M[F22]);
  }
  else
  {
    x[0] = TMath::ATan2(-M[F01], M[F11]);
    x[2] = 0;
  }
}

/**************************************************************************/
// Scaling
/**************************************************************************/

template<class TT>
void HTrans<TT>::Scale(TT sx, TT sy, TT sz)
{
  M[F00] *= sx; M[F10] *= sx; M[F20] *= sx;
  M[F01] *= sy; M[F11] *= sy; M[F21] *= sy;
  M[F02] *= sz; M[F12] *= sz; M[F22] *= sz;
}

template<class TT>
void HTrans<TT>::GetScale(TT& sx, TT& sy, TT& sz) const
{
  sx = TMath::Sqrt( M[F00]*M[F00] + M[F10]*M[F10] + M[F20]*M[F20] );
  sy = TMath::Sqrt( M[F01]*M[F01] + M[F11]*M[F11] + M[F21]*M[F21] );
  sz = TMath::Sqrt( M[F02]*M[F02] + M[F12]*M[F12] + M[F22]*M[F22] );
}

template<class TT>
void HTrans<TT>::Unscale(TT& sx, TT& sy, TT& sz)
{
  GetScale(sx, sy, sz);
  M[F00] /= sx; M[F10] /= sx; M[F20] /= sx;
  M[F01] /= sy; M[F11] /= sy; M[F21] /= sy;
  M[F02] /= sz; M[F12] /= sz; M[F22] /= sz;
}

template<class TT>
TT HTrans<TT>::Unscale()
{
  TT sx, sy, sz;
  Unscale(sx, sy, sz);
  return (sx + sy + sz)/3;
}

/**************************************************************************/
// Operations on vectors
/**************************************************************************/

template<class TT>
void HTrans<TT>::MultiplyIP(HPoint<TT>& v, TT w) const
{
  v.Set(M[F00]*v.x + M[F01]*v.y + M[F02]*v.z + M[F03]*w,
	M[F10]*v.x + M[F11]*v.y + M[F12]*v.z + M[F13]*w,
	M[F20]*v.x + M[F21]*v.y + M[F22]*v.z + M[F23]*w);
}

template<class TT>
void HTrans<TT>::RotateIP(HPoint<TT>& v) const
{
  v.Set(M[F00]*v.x + M[F01]*v.y + M[F02]*v.z,
	M[F10]*v.x + M[F11]*v.y + M[F12]*v.z,
	M[F20]*v.x + M[F21]*v.y + M[F22]*v.z);
}

template<class TT>
HPoint<TT> HTrans<TT>::Multiply(const HPoint<TT>& v, TT w) const
{
  return HPoint<TT>(M[F00]*v.x + M[F01]*v.y + M[F02]*v.z + M[F03]*w,
		    M[F10]*v.x + M[F11]*v.y + M[F12]*v.z + M[F13]*w,
		    M[F20]*v.x + M[F21]*v.y + M[F22]*v.z + M[F23]*w);
}

template<class TT>
HPoint<TT> HTrans<TT>::Rotate(const HPoint<TT>& v) const
{
  return HPoint<TT>(M[F00]*v.x + M[F01]*v.y + M[F02]*v.z,
		    M[F10]*v.x + M[F11]*v.y + M[F12]*v.z,
		    M[F20]*v.x + M[F21]*v.y + M[F22]*v.z);
}

/**************************************************************************/

template<class TT>
void HTrans<TT>::MultiplyVec3IP(TT* in, TT w) const
{
  TT out[3];
  out[0] = M[F00]*in[0] + M[F01]*in[1] + M[F02]*in[2] + M[F03]*w;
  out[1] = M[F10]*in[0] + M[F11]*in[1] + M[F12]*in[2] + M[F13]*w;
  out[2] = M[F20]*in[0] + M[F21]*in[1] + M[F22]*in[2] + M[F23]*w;
  in[0] = out[0]; in[1] = out[1]; in[2] = out[2];
}

template<class TT>
void HTrans<TT>::MultiplyVec3(const TT* in, TT w, TT* out) const
{
  out[0] = M[F00]*in[0] + M[F01]*in[1] + M[F02]*in[2] + M[F03]*w;
  out[1] = M[F10]*in[0] + M[F11]*in[1] + M[F12]*in[2] + M[F13]*w;
  out[2] = M[F20]*in[0] + M[F21]*in[1] + M[F22]*in[2] + M[F23]*w;
}

template<class TT>
void HTrans<TT>::RotateVec3IP(TT* in) const
{
  TT out[3];
  out[0] = M[F00]*in[0] + M[F01]*in[1] + M[F02]*in[2];
  out[1] = M[F10]*in[0] + M[F11]*in[1] + M[F12]*in[2];
  out[2] = M[F20]*in[0] + M[F21]*in[1] + M[F22]*in[2];
  in[0] = out[0]; in[1] = out[1]; in[2] = out[2];
}

template<class TT>
void HTrans<TT>::RotateVec3(const TT* in, TT* out) const
{
  out[0] = M[F00]*in[0] + M[F01]*in[1] + M[F02]*in[2];
  out[1] = M[F10]*in[0] + M[F11]*in[1] + M[F12]*in[2];
  out[2] = M[F20]*in[0] + M[F21]*in[1] + M[F22]*in[2];
}

template<class TT>
void HTrans<TT>::RotateBackVec3(const TT* in, TT* out) const
{
  // Rotate with transposed matrix. Note that this makes sense only if
  // the base vectors are orthonormal.

  out[0] = M[F00]*in[0] + M[F10]*in[1] + M[F20]*in[2];
  out[1] = M[F01]*in[0] + M[F11]*in[1] + M[F21]*in[2];
  out[2] = M[F02]*in[0] + M[F12]*in[1] + M[F22]*in[2];
}

/**************************************************************************/
// Normalization, ortogonalization
/**************************************************************************/

template<class TT>
TT HTrans<TT>::Norm3Column(Int_t col)
{
  TT* C = M + 4*--col;
  const TT l = 1.0/TMath::Sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
  C[0] *= l; C[1] *= l; C[2] *= l;
  return l;
}

template<class TT>
TT HTrans<TT>::Orto3Column(Int_t col, Int_t ref)
{
  TT* C = M + 4*--col;
  TT* R = M + 4*--ref;
  const TT dp = C[0]*R[0] + C[1]*R[1] + C[2]*R[2];
  C[0] -= R[0]*dp; C[1] -= R[1]*dp; C[2] -= R[2]*dp;
  return dp;
}

template<class TT>
TT HTrans<TT>::OrtoNorm3Column(Int_t col, Int_t ref)
{
  // Ortogonalize col wrt ref then normalize col.
  // Returns dot-product.
  //
  // Assumption that both vectors are normalized and doing the calculation
  // in a single step resulted in slow degradation of norms.
  // The idea was ... since i know the projection on a future orthogonal vector
  // i also know the length after subtraction: len = sqrt(1 - dp^2).

  TT* C = M + 4*--col;
  TT* R = M + 4*--ref;
  const TT dp = C[0]*R[0] + C[1]*R[1] + C[2]*R[2];
  C[0] -= R[0]*dp; C[1] -= R[1]*dp; C[2] -= R[2]*dp;
  const TT l = 1.0/TMath::Sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
  C[0] *= l; C[1] *= l; C[2] *= l;
  return dp;
}

template<class TT>
void HTrans<TT>::OrtoNorm3()
{
  Norm3Column(1);
  OrtoNorm3Column(2,1);
  M[F02] = M[F10]*M[F21] - M[F11]*M[F20];
  M[F12] = M[F20]*M[F01] - M[F21]*M[F00];
  M[F22] = M[F00]*M[F11] - M[F01]*M[F10];
  // cross-product faster.
  // Orto3Column(3,1); Orto3Column(3,2); Norm3Column(3);
}

template<class TT>
void HTrans<TT>::SetBaseVecViaCross(Int_t i)
{
  switch (i) {
  case 1:
    M[F00] = M[F11]*M[F22] - M[F12]*M[F21];
    M[F10] = M[F21]*M[F02] - M[F22]*M[F01];
    M[F20] = M[F01]*M[F12] - M[F02]*M[F11];
    break;
  case 2:
    M[F01] = M[F12]*M[F20] - M[F10]*M[F22];
    M[F11] = M[F22]*M[F00] - M[F20]*M[F02];
    M[F21] = M[F02]*M[F10] - M[F00]*M[F12];
    break;
  case 3:
    M[F02] = M[F10]*M[F21] - M[F11]*M[F20];
    M[F12] = M[F20]*M[F01] - M[F21]*M[F00];
    M[F22] = M[F00]*M[F11] - M[F01]*M[F10];
    break;
  default:
    break;
  }
}

/**************************************************************************/
// Transpose & Invert
/**************************************************************************/

template<class TT>
void HTrans<TT>::Transpose()
{
  TT x;
  x = M[F01]; M[F01] = M[F10]; M[F10] = x;
  x = M[F02]; M[F02] = M[F20]; M[F20] = x;
  x = M[F03]; M[F03] = M[F30]; M[F30] = x;
  x = M[F12]; M[F12] = M[F21]; M[F21] = x;
  x = M[F13]; M[F13] = M[F31]; M[F31] = x;
  x = M[F23]; M[F23] = M[F32]; M[F32] = x;  
}

/**************************************************************************/

template<class TT>
void  HTrans<TT>::TransposeRotationPart()
{
  TT x;
  x = M[F01]; M[F01] = M[F10]; M[F10] = x;
  x = M[F02]; M[F02] = M[F20]; M[F20] = x;
  x = M[F12]; M[F12] = M[F21]; M[F21] = x;
}

template<class TT>
TT HTrans<TT>::Invert()
{
  // Copied from ROOT's TMatrixFCramerInv.

  static const Exc_t _eh("HTransF::Invert ");

  // Find all NECESSARY 2x2 dets:  (18 of them)
  const TT det2_12_01 = M[F10]*M[F21] - M[F11]*M[F20];
  const TT det2_12_02 = M[F10]*M[F22] - M[F12]*M[F20];
  const TT det2_12_03 = M[F10]*M[F23] - M[F13]*M[F20];
  const TT det2_12_13 = M[F11]*M[F23] - M[F13]*M[F21];
  const TT det2_12_23 = M[F12]*M[F23] - M[F13]*M[F22];
  const TT det2_12_12 = M[F11]*M[F22] - M[F12]*M[F21];
  const TT det2_13_01 = M[F10]*M[F31] - M[F11]*M[F30];
  const TT det2_13_02 = M[F10]*M[F32] - M[F12]*M[F30];
  const TT det2_13_03 = M[F10]*M[F33] - M[F13]*M[F30];
  const TT det2_13_12 = M[F11]*M[F32] - M[F12]*M[F31];
  const TT det2_13_13 = M[F11]*M[F33] - M[F13]*M[F31];
  const TT det2_13_23 = M[F12]*M[F33] - M[F13]*M[F32];
  const TT det2_23_01 = M[F20]*M[F31] - M[F21]*M[F30];
  const TT det2_23_02 = M[F20]*M[F32] - M[F22]*M[F30];
  const TT det2_23_03 = M[F20]*M[F33] - M[F23]*M[F30];
  const TT det2_23_12 = M[F21]*M[F32] - M[F22]*M[F31];
  const TT det2_23_13 = M[F21]*M[F33] - M[F23]*M[F31];
  const TT det2_23_23 = M[F22]*M[F33] - M[F23]*M[F32];

  // Find all NECESSARY 3x3 dets:   (16 of them)
  const TT det3_012_012 = M[F00]*det2_12_12 - M[F01]*det2_12_02 + M[F02]*det2_12_01;
  const TT det3_012_013 = M[F00]*det2_12_13 - M[F01]*det2_12_03 + M[F03]*det2_12_01;
  const TT det3_012_023 = M[F00]*det2_12_23 - M[F02]*det2_12_03 + M[F03]*det2_12_02;
  const TT det3_012_123 = M[F01]*det2_12_23 - M[F02]*det2_12_13 + M[F03]*det2_12_12;
  const TT det3_013_012 = M[F00]*det2_13_12 - M[F01]*det2_13_02 + M[F02]*det2_13_01;
  const TT det3_013_013 = M[F00]*det2_13_13 - M[F01]*det2_13_03 + M[F03]*det2_13_01;
  const TT det3_013_023 = M[F00]*det2_13_23 - M[F02]*det2_13_03 + M[F03]*det2_13_02;
  const TT det3_013_123 = M[F01]*det2_13_23 - M[F02]*det2_13_13 + M[F03]*det2_13_12;
  const TT det3_023_012 = M[F00]*det2_23_12 - M[F01]*det2_23_02 + M[F02]*det2_23_01;
  const TT det3_023_013 = M[F00]*det2_23_13 - M[F01]*det2_23_03 + M[F03]*det2_23_01;
  const TT det3_023_023 = M[F00]*det2_23_23 - M[F02]*det2_23_03 + M[F03]*det2_23_02;
  const TT det3_023_123 = M[F01]*det2_23_23 - M[F02]*det2_23_13 + M[F03]*det2_23_12;
  const TT det3_123_012 = M[F10]*det2_23_12 - M[F11]*det2_23_02 + M[F12]*det2_23_01;
  const TT det3_123_013 = M[F10]*det2_23_13 - M[F11]*det2_23_03 + M[F13]*det2_23_01;
  const TT det3_123_023 = M[F10]*det2_23_23 - M[F12]*det2_23_03 + M[F13]*det2_23_02;
  const TT det3_123_123 = M[F11]*det2_23_23 - M[F12]*det2_23_13 + M[F13]*det2_23_12;

  // Find the 4x4 det:
  const TT det = M[F00]*det3_123_123 - M[F01]*det3_123_023 + 
                 M[F02]*det3_123_013 - M[F03]*det3_123_012;

  if(det == 0) throw(_eh + "matrix is singular.");

  const TT oneOverDet = 1.0/det;
  const TT mn1OverDet = - oneOverDet;

  M[F00] = det3_123_123 * oneOverDet;
  M[F01] = det3_023_123 * mn1OverDet;
  M[F02] = det3_013_123 * oneOverDet;
  M[F03] = det3_012_123 * mn1OverDet;

  M[F10] = det3_123_023 * mn1OverDet;
  M[F11] = det3_023_023 * oneOverDet;
  M[F12] = det3_013_023 * mn1OverDet;
  M[F13] = det3_012_023 * oneOverDet;

  M[F20] = det3_123_013 * oneOverDet;
  M[F21] = det3_023_013 * mn1OverDet;
  M[F22] = det3_013_013 * oneOverDet;
  M[F23] = det3_012_013 * mn1OverDet;

  M[F30] = det3_123_012 * mn1OverDet;
  M[F31] = det3_023_012 * oneOverDet;
  M[F32] = det3_013_012 * mn1OverDet;
  M[F33] = det3_012_012 * oneOverDet;

  return det;
}

template<class TT>
TT HTrans<TT>::InvertWithoutRow4()
{
  // Copied from ROOT's TMatrixFCramerInv.
  // Optimised for 4th row = (0, 0, 0, 1).

  static const Exc_t _eh("HTrans::InvertWithoutRow4 ");

  // Find all NECESSARY 2x2 dets:  (18 of them, now 6)
  const TT det2_12_01 = M[F10]*M[F21] - M[F11]*M[F20];
  const TT det2_12_02 = M[F10]*M[F22] - M[F12]*M[F20];
  const TT det2_12_03 = M[F10]*M[F23] - M[F13]*M[F20];
  const TT det2_12_13 = M[F11]*M[F23] - M[F13]*M[F21];
  const TT det2_12_23 = M[F12]*M[F23] - M[F13]*M[F22];
  const TT det2_12_12 = M[F11]*M[F22] - M[F12]*M[F21];

  // Find all NECESSARY 3x3 dets:   (16 of them, now 12)
  const TT det3_012_013 = M[F00]*det2_12_13 - M[F01]*det2_12_03 + M[F03]*det2_12_01;
  const TT det3_012_023 = M[F00]*det2_12_23 - M[F02]*det2_12_03 + M[F03]*det2_12_02;
  const TT det3_012_123 = M[F01]*det2_12_23 - M[F02]*det2_12_13 + M[F03]*det2_12_12;

  const TT det3_013_013 = M[F00]*M[F11] - M[F01]*M[F10];
  const TT det3_013_023 = M[F00]*M[F12] - M[F02]*M[F10];
  const TT det3_013_123 = M[F01]*M[F12] - M[F02]*M[F11];
  const TT det3_023_013 = M[F00]*M[F21] - M[F01]*M[F20];
  const TT det3_023_023 = M[F00]*M[F22] - M[F02]*M[F20];
  const TT det3_023_123 = M[F01]*M[F22] - M[F02]*M[F21];
  const TT det3_123_013 = M[F10]*M[F21] - M[F11]*M[F20];
  const TT det3_123_023 = M[F10]*M[F22] - M[F12]*M[F20];
  const TT det3_123_123 = M[F11]*M[F22] - M[F12]*M[F21];

  // Find the 4x4 det:
  const TT det = M[F00]*det3_123_123 - M[F01]*det3_123_023 + M[F02]*det3_123_013;

  if(det == 0) throw(_eh + "matrix is singular.");

  const TT oneOverDet = 1.0/det;
  const TT mn1OverDet = - oneOverDet;

  M[F00] = det3_123_123 * oneOverDet;
  M[F01] = det3_023_123 * mn1OverDet;
  M[F02] = det3_013_123 * oneOverDet;
  M[F03] = det3_012_123 * mn1OverDet;

  M[F10] = det3_123_023 * mn1OverDet;
  M[F11] = det3_023_023 * oneOverDet;
  M[F12] = det3_013_023 * mn1OverDet;
  M[F13] = det3_012_023 * oneOverDet;

  M[F20] = det3_123_013 * oneOverDet;
  M[F21] = det3_023_013 * mn1OverDet;
  M[F22] = det3_013_013 * oneOverDet;
  M[F23] = det3_012_013 * mn1OverDet;

  // M[F30], M[F31], M[F32], M[F33] assumed (0, 0, 0, 1).

  return det;
}

//==============================================================================

template<class TT>
void HTrans<TT>::Print() const
{
  const TT* C = M;
  for(Int_t i=0; i<4; ++i, ++C)
    printf("%8.3lf %8.3lf %8.3lf | %8.3lf\n", C[0], C[4], C[8], C[12]);
}


template<class TT>
std::ostream& operator<<(std::ostream& s, const HTrans<TT>& t)
{
  s.setf(ios::fixed, ios::floatfield); s.precision(3);
  for(Int_t i=1; i<=4; i++)
    for(Int_t j=1; j<=4; j++)
      s << t(i,j) << ((j==4) ? "\n" : "\t");
  return s;
}

//==============================================================================

template class HPoint<Float_t>;
template class HPoint<Double_t>;

template class HTrans<Float_t>;
template class HTrans<Double_t>;
 HTrans.cxx:1
 HTrans.cxx:2
 HTrans.cxx:3
 HTrans.cxx:4
 HTrans.cxx:5
 HTrans.cxx:6
 HTrans.cxx:7
 HTrans.cxx:8
 HTrans.cxx:9
 HTrans.cxx:10
 HTrans.cxx:11
 HTrans.cxx:12
 HTrans.cxx:13
 HTrans.cxx:14
 HTrans.cxx:15
 HTrans.cxx:16
 HTrans.cxx:17
 HTrans.cxx:18
 HTrans.cxx:19
 HTrans.cxx:20
 HTrans.cxx:21
 HTrans.cxx:22
 HTrans.cxx:23
 HTrans.cxx:24
 HTrans.cxx:25
 HTrans.cxx:26
 HTrans.cxx:27
 HTrans.cxx:28
 HTrans.cxx:29
 HTrans.cxx:30
 HTrans.cxx:31
 HTrans.cxx:32
 HTrans.cxx:33
 HTrans.cxx:34
 HTrans.cxx:35
 HTrans.cxx:36
 HTrans.cxx:37
 HTrans.cxx:38
 HTrans.cxx:39
 HTrans.cxx:40
 HTrans.cxx:41
 HTrans.cxx:42
 HTrans.cxx:43
 HTrans.cxx:44
 HTrans.cxx:45
 HTrans.cxx:46
 HTrans.cxx:47
 HTrans.cxx:48
 HTrans.cxx:49
 HTrans.cxx:50
 HTrans.cxx:51
 HTrans.cxx:52
 HTrans.cxx:53
 HTrans.cxx:54
 HTrans.cxx:55
 HTrans.cxx:56
 HTrans.cxx:57
 HTrans.cxx:58
 HTrans.cxx:59
 HTrans.cxx:60
 HTrans.cxx:61
 HTrans.cxx:62
 HTrans.cxx:63
 HTrans.cxx:64
 HTrans.cxx:65
 HTrans.cxx:66
 HTrans.cxx:67
 HTrans.cxx:68
 HTrans.cxx:69
 HTrans.cxx:70
 HTrans.cxx:71
 HTrans.cxx:72
 HTrans.cxx:73
 HTrans.cxx:74
 HTrans.cxx:75
 HTrans.cxx:76
 HTrans.cxx:77
 HTrans.cxx:78
 HTrans.cxx:79
 HTrans.cxx:80
 HTrans.cxx:81
 HTrans.cxx:82
 HTrans.cxx:83
 HTrans.cxx:84
 HTrans.cxx:85
 HTrans.cxx:86
 HTrans.cxx:87
 HTrans.cxx:88
 HTrans.cxx:89
 HTrans.cxx:90
 HTrans.cxx:91
 HTrans.cxx:92
 HTrans.cxx:93
 HTrans.cxx:94
 HTrans.cxx:95
 HTrans.cxx:96
 HTrans.cxx:97
 HTrans.cxx:98
 HTrans.cxx:99
 HTrans.cxx:100
 HTrans.cxx:101
 HTrans.cxx:102
 HTrans.cxx:103
 HTrans.cxx:104
 HTrans.cxx:105
 HTrans.cxx:106
 HTrans.cxx:107
 HTrans.cxx:108
 HTrans.cxx:109
 HTrans.cxx:110
 HTrans.cxx:111
 HTrans.cxx:112
 HTrans.cxx:113
 HTrans.cxx:114
 HTrans.cxx:115
 HTrans.cxx:116
 HTrans.cxx:117
 HTrans.cxx:118
 HTrans.cxx:119
 HTrans.cxx:120
 HTrans.cxx:121
 HTrans.cxx:122
 HTrans.cxx:123
 HTrans.cxx:124
 HTrans.cxx:125
 HTrans.cxx:126
 HTrans.cxx:127
 HTrans.cxx:128
 HTrans.cxx:129
 HTrans.cxx:130
 HTrans.cxx:131
 HTrans.cxx:132
 HTrans.cxx:133
 HTrans.cxx:134
 HTrans.cxx:135
 HTrans.cxx:136
 HTrans.cxx:137
 HTrans.cxx:138
 HTrans.cxx:139
 HTrans.cxx:140
 HTrans.cxx:141
 HTrans.cxx:142
 HTrans.cxx:143
 HTrans.cxx:144
 HTrans.cxx:145
 HTrans.cxx:146
 HTrans.cxx:147
 HTrans.cxx:148
 HTrans.cxx:149
 HTrans.cxx:150
 HTrans.cxx:151
 HTrans.cxx:152
 HTrans.cxx:153
 HTrans.cxx:154
 HTrans.cxx:155
 HTrans.cxx:156
 HTrans.cxx:157
 HTrans.cxx:158
 HTrans.cxx:159
 HTrans.cxx:160
 HTrans.cxx:161
 HTrans.cxx:162
 HTrans.cxx:163
 HTrans.cxx:164
 HTrans.cxx:165
 HTrans.cxx:166
 HTrans.cxx:167
 HTrans.cxx:168
 HTrans.cxx:169
 HTrans.cxx:170
 HTrans.cxx:171
 HTrans.cxx:172
 HTrans.cxx:173
 HTrans.cxx:174
 HTrans.cxx:175
 HTrans.cxx:176
 HTrans.cxx:177
 HTrans.cxx:178
 HTrans.cxx:179
 HTrans.cxx:180
 HTrans.cxx:181
 HTrans.cxx:182
 HTrans.cxx:183
 HTrans.cxx:184
 HTrans.cxx:185
 HTrans.cxx:186
 HTrans.cxx:187
 HTrans.cxx:188
 HTrans.cxx:189
 HTrans.cxx:190
 HTrans.cxx:191
 HTrans.cxx:192
 HTrans.cxx:193
 HTrans.cxx:194
 HTrans.cxx:195
 HTrans.cxx:196
 HTrans.cxx:197
 HTrans.cxx:198
 HTrans.cxx:199
 HTrans.cxx:200
 HTrans.cxx:201
 HTrans.cxx:202
 HTrans.cxx:203
 HTrans.cxx:204
 HTrans.cxx:205
 HTrans.cxx:206
 HTrans.cxx:207
 HTrans.cxx:208
 HTrans.cxx:209
 HTrans.cxx:210
 HTrans.cxx:211
 HTrans.cxx:212
 HTrans.cxx:213
 HTrans.cxx:214
 HTrans.cxx:215
 HTrans.cxx:216
 HTrans.cxx:217
 HTrans.cxx:218
 HTrans.cxx:219
 HTrans.cxx:220
 HTrans.cxx:221
 HTrans.cxx:222
 HTrans.cxx:223
 HTrans.cxx:224
 HTrans.cxx:225
 HTrans.cxx:226
 HTrans.cxx:227
 HTrans.cxx:228
 HTrans.cxx:229
 HTrans.cxx:230
 HTrans.cxx:231
 HTrans.cxx:232
 HTrans.cxx:233
 HTrans.cxx:234
 HTrans.cxx:235
 HTrans.cxx:236
 HTrans.cxx:237
 HTrans.cxx:238
 HTrans.cxx:239
 HTrans.cxx:240
 HTrans.cxx:241
 HTrans.cxx:242
 HTrans.cxx:243
 HTrans.cxx:244
 HTrans.cxx:245
 HTrans.cxx:246
 HTrans.cxx:247
 HTrans.cxx:248
 HTrans.cxx:249
 HTrans.cxx:250
 HTrans.cxx:251
 HTrans.cxx:252
 HTrans.cxx:253
 HTrans.cxx:254
 HTrans.cxx:255
 HTrans.cxx:256
 HTrans.cxx:257
 HTrans.cxx:258
 HTrans.cxx:259
 HTrans.cxx:260
 HTrans.cxx:261
 HTrans.cxx:262
 HTrans.cxx:263
 HTrans.cxx:264
 HTrans.cxx:265
 HTrans.cxx:266
 HTrans.cxx:267
 HTrans.cxx:268
 HTrans.cxx:269
 HTrans.cxx:270
 HTrans.cxx:271
 HTrans.cxx:272
 HTrans.cxx:273
 HTrans.cxx:274
 HTrans.cxx:275
 HTrans.cxx:276
 HTrans.cxx:277
 HTrans.cxx:278
 HTrans.cxx:279
 HTrans.cxx:280
 HTrans.cxx:281
 HTrans.cxx:282
 HTrans.cxx:283
 HTrans.cxx:284
 HTrans.cxx:285
 HTrans.cxx:286
 HTrans.cxx:287
 HTrans.cxx:288
 HTrans.cxx:289
 HTrans.cxx:290
 HTrans.cxx:291
 HTrans.cxx:292
 HTrans.cxx:293
 HTrans.cxx:294
 HTrans.cxx:295
 HTrans.cxx:296
 HTrans.cxx:297
 HTrans.cxx:298
 HTrans.cxx:299
 HTrans.cxx:300
 HTrans.cxx:301
 HTrans.cxx:302
 HTrans.cxx:303
 HTrans.cxx:304
 HTrans.cxx:305
 HTrans.cxx:306
 HTrans.cxx:307
 HTrans.cxx:308
 HTrans.cxx:309
 HTrans.cxx:310
 HTrans.cxx:311
 HTrans.cxx:312
 HTrans.cxx:313
 HTrans.cxx:314
 HTrans.cxx:315
 HTrans.cxx:316
 HTrans.cxx:317
 HTrans.cxx:318
 HTrans.cxx:319
 HTrans.cxx:320
 HTrans.cxx:321
 HTrans.cxx:322
 HTrans.cxx:323
 HTrans.cxx:324
 HTrans.cxx:325
 HTrans.cxx:326
 HTrans.cxx:327
 HTrans.cxx:328
 HTrans.cxx:329
 HTrans.cxx:330
 HTrans.cxx:331
 HTrans.cxx:332
 HTrans.cxx:333
 HTrans.cxx:334
 HTrans.cxx:335
 HTrans.cxx:336
 HTrans.cxx:337
 HTrans.cxx:338
 HTrans.cxx:339
 HTrans.cxx:340
 HTrans.cxx:341
 HTrans.cxx:342
 HTrans.cxx:343
 HTrans.cxx:344
 HTrans.cxx:345
 HTrans.cxx:346
 HTrans.cxx:347
 HTrans.cxx:348
 HTrans.cxx:349
 HTrans.cxx:350
 HTrans.cxx:351
 HTrans.cxx:352
 HTrans.cxx:353
 HTrans.cxx:354
 HTrans.cxx:355
 HTrans.cxx:356
 HTrans.cxx:357
 HTrans.cxx:358
 HTrans.cxx:359
 HTrans.cxx:360
 HTrans.cxx:361
 HTrans.cxx:362
 HTrans.cxx:363
 HTrans.cxx:364
 HTrans.cxx:365
 HTrans.cxx:366
 HTrans.cxx:367
 HTrans.cxx:368
 HTrans.cxx:369
 HTrans.cxx:370
 HTrans.cxx:371
 HTrans.cxx:372
 HTrans.cxx:373
 HTrans.cxx:374
 HTrans.cxx:375
 HTrans.cxx:376
 HTrans.cxx:377
 HTrans.cxx:378
 HTrans.cxx:379
 HTrans.cxx:380
 HTrans.cxx:381
 HTrans.cxx:382
 HTrans.cxx:383
 HTrans.cxx:384
 HTrans.cxx:385
 HTrans.cxx:386
 HTrans.cxx:387
 HTrans.cxx:388
 HTrans.cxx:389
 HTrans.cxx:390
 HTrans.cxx:391
 HTrans.cxx:392
 HTrans.cxx:393
 HTrans.cxx:394
 HTrans.cxx:395
 HTrans.cxx:396
 HTrans.cxx:397
 HTrans.cxx:398
 HTrans.cxx:399
 HTrans.cxx:400
 HTrans.cxx:401
 HTrans.cxx:402
 HTrans.cxx:403
 HTrans.cxx:404
 HTrans.cxx:405
 HTrans.cxx:406
 HTrans.cxx:407
 HTrans.cxx:408
 HTrans.cxx:409
 HTrans.cxx:410
 HTrans.cxx:411
 HTrans.cxx:412
 HTrans.cxx:413
 HTrans.cxx:414
 HTrans.cxx:415
 HTrans.cxx:416
 HTrans.cxx:417
 HTrans.cxx:418
 HTrans.cxx:419
 HTrans.cxx:420
 HTrans.cxx:421
 HTrans.cxx:422
 HTrans.cxx:423
 HTrans.cxx:424
 HTrans.cxx:425
 HTrans.cxx:426
 HTrans.cxx:427
 HTrans.cxx:428
 HTrans.cxx:429
 HTrans.cxx:430
 HTrans.cxx:431
 HTrans.cxx:432
 HTrans.cxx:433
 HTrans.cxx:434
 HTrans.cxx:435
 HTrans.cxx:436
 HTrans.cxx:437
 HTrans.cxx:438
 HTrans.cxx:439
 HTrans.cxx:440
 HTrans.cxx:441
 HTrans.cxx:442
 HTrans.cxx:443
 HTrans.cxx:444
 HTrans.cxx:445
 HTrans.cxx:446
 HTrans.cxx:447
 HTrans.cxx:448
 HTrans.cxx:449
 HTrans.cxx:450
 HTrans.cxx:451
 HTrans.cxx:452
 HTrans.cxx:453
 HTrans.cxx:454
 HTrans.cxx:455
 HTrans.cxx:456
 HTrans.cxx:457
 HTrans.cxx:458
 HTrans.cxx:459
 HTrans.cxx:460
 HTrans.cxx:461
 HTrans.cxx:462
 HTrans.cxx:463
 HTrans.cxx:464
 HTrans.cxx:465
 HTrans.cxx:466
 HTrans.cxx:467
 HTrans.cxx:468
 HTrans.cxx:469
 HTrans.cxx:470
 HTrans.cxx:471
 HTrans.cxx:472
 HTrans.cxx:473
 HTrans.cxx:474
 HTrans.cxx:475
 HTrans.cxx:476
 HTrans.cxx:477
 HTrans.cxx:478
 HTrans.cxx:479
 HTrans.cxx:480
 HTrans.cxx:481
 HTrans.cxx:482
 HTrans.cxx:483
 HTrans.cxx:484
 HTrans.cxx:485
 HTrans.cxx:486
 HTrans.cxx:487
 HTrans.cxx:488
 HTrans.cxx:489
 HTrans.cxx:490
 HTrans.cxx:491
 HTrans.cxx:492
 HTrans.cxx:493
 HTrans.cxx:494
 HTrans.cxx:495
 HTrans.cxx:496
 HTrans.cxx:497
 HTrans.cxx:498
 HTrans.cxx:499
 HTrans.cxx:500
 HTrans.cxx:501
 HTrans.cxx:502
 HTrans.cxx:503
 HTrans.cxx:504
 HTrans.cxx:505
 HTrans.cxx:506
 HTrans.cxx:507
 HTrans.cxx:508
 HTrans.cxx:509
 HTrans.cxx:510
 HTrans.cxx:511
 HTrans.cxx:512
 HTrans.cxx:513
 HTrans.cxx:514
 HTrans.cxx:515
 HTrans.cxx:516
 HTrans.cxx:517
 HTrans.cxx:518
 HTrans.cxx:519
 HTrans.cxx:520
 HTrans.cxx:521
 HTrans.cxx:522
 HTrans.cxx:523
 HTrans.cxx:524
 HTrans.cxx:525
 HTrans.cxx:526
 HTrans.cxx:527
 HTrans.cxx:528
 HTrans.cxx:529
 HTrans.cxx:530
 HTrans.cxx:531
 HTrans.cxx:532
 HTrans.cxx:533
 HTrans.cxx:534
 HTrans.cxx:535
 HTrans.cxx:536
 HTrans.cxx:537
 HTrans.cxx:538
 HTrans.cxx:539
 HTrans.cxx:540
 HTrans.cxx:541
 HTrans.cxx:542
 HTrans.cxx:543
 HTrans.cxx:544
 HTrans.cxx:545
 HTrans.cxx:546
 HTrans.cxx:547
 HTrans.cxx:548
 HTrans.cxx:549
 HTrans.cxx:550
 HTrans.cxx:551
 HTrans.cxx:552
 HTrans.cxx:553
 HTrans.cxx:554
 HTrans.cxx:555
 HTrans.cxx:556
 HTrans.cxx:557
 HTrans.cxx:558
 HTrans.cxx:559
 HTrans.cxx:560
 HTrans.cxx:561
 HTrans.cxx:562
 HTrans.cxx:563
 HTrans.cxx:564
 HTrans.cxx:565
 HTrans.cxx:566
 HTrans.cxx:567
 HTrans.cxx:568
 HTrans.cxx:569
 HTrans.cxx:570
 HTrans.cxx:571
 HTrans.cxx:572
 HTrans.cxx:573
 HTrans.cxx:574
 HTrans.cxx:575
 HTrans.cxx:576
 HTrans.cxx:577
 HTrans.cxx:578
 HTrans.cxx:579
 HTrans.cxx:580
 HTrans.cxx:581
 HTrans.cxx:582
 HTrans.cxx:583
 HTrans.cxx:584
 HTrans.cxx:585
 HTrans.cxx:586
 HTrans.cxx:587
 HTrans.cxx:588
 HTrans.cxx:589
 HTrans.cxx:590
 HTrans.cxx:591
 HTrans.cxx:592
 HTrans.cxx:593
 HTrans.cxx:594
 HTrans.cxx:595
 HTrans.cxx:596
 HTrans.cxx:597
 HTrans.cxx:598
 HTrans.cxx:599
 HTrans.cxx:600
 HTrans.cxx:601
 HTrans.cxx:602
 HTrans.cxx:603
 HTrans.cxx:604
 HTrans.cxx:605
 HTrans.cxx:606
 HTrans.cxx:607
 HTrans.cxx:608
 HTrans.cxx:609
 HTrans.cxx:610
 HTrans.cxx:611
 HTrans.cxx:612
 HTrans.cxx:613
 HTrans.cxx:614
 HTrans.cxx:615
 HTrans.cxx:616
 HTrans.cxx:617
 HTrans.cxx:618
 HTrans.cxx:619
 HTrans.cxx:620
 HTrans.cxx:621
 HTrans.cxx:622
 HTrans.cxx:623
 HTrans.cxx:624
 HTrans.cxx:625
 HTrans.cxx:626
 HTrans.cxx:627
 HTrans.cxx:628
 HTrans.cxx:629
 HTrans.cxx:630
 HTrans.cxx:631
 HTrans.cxx:632
 HTrans.cxx:633
 HTrans.cxx:634
 HTrans.cxx:635
 HTrans.cxx:636
 HTrans.cxx:637
 HTrans.cxx:638
 HTrans.cxx:639
 HTrans.cxx:640
 HTrans.cxx:641
 HTrans.cxx:642
 HTrans.cxx:643
 HTrans.cxx:644
 HTrans.cxx:645
 HTrans.cxx:646
 HTrans.cxx:647
 HTrans.cxx:648
 HTrans.cxx:649
 HTrans.cxx:650
 HTrans.cxx:651
 HTrans.cxx:652
 HTrans.cxx:653
 HTrans.cxx:654
 HTrans.cxx:655
 HTrans.cxx:656
 HTrans.cxx:657
 HTrans.cxx:658
 HTrans.cxx:659
 HTrans.cxx:660
 HTrans.cxx:661
 HTrans.cxx:662
 HTrans.cxx:663
 HTrans.cxx:664
 HTrans.cxx:665
 HTrans.cxx:666
 HTrans.cxx:667
 HTrans.cxx:668
 HTrans.cxx:669
 HTrans.cxx:670
 HTrans.cxx:671
 HTrans.cxx:672
 HTrans.cxx:673
 HTrans.cxx:674
 HTrans.cxx:675
 HTrans.cxx:676
 HTrans.cxx:677
 HTrans.cxx:678
 HTrans.cxx:679
 HTrans.cxx:680
 HTrans.cxx:681
 HTrans.cxx:682
 HTrans.cxx:683
 HTrans.cxx:684
 HTrans.cxx:685
 HTrans.cxx:686
 HTrans.cxx:687
 HTrans.cxx:688
 HTrans.cxx:689
 HTrans.cxx:690
 HTrans.cxx:691
 HTrans.cxx:692
 HTrans.cxx:693
 HTrans.cxx:694
 HTrans.cxx:695
 HTrans.cxx:696
 HTrans.cxx:697
 HTrans.cxx:698
 HTrans.cxx:699
 HTrans.cxx:700
 HTrans.cxx:701
 HTrans.cxx:702
 HTrans.cxx:703
 HTrans.cxx:704
 HTrans.cxx:705
 HTrans.cxx:706
 HTrans.cxx:707
 HTrans.cxx:708
 HTrans.cxx:709
 HTrans.cxx:710
 HTrans.cxx:711
 HTrans.cxx:712
 HTrans.cxx:713
 HTrans.cxx:714
 HTrans.cxx:715
 HTrans.cxx:716
 HTrans.cxx:717
 HTrans.cxx:718
 HTrans.cxx:719
 HTrans.cxx:720
 HTrans.cxx:721
 HTrans.cxx:722
 HTrans.cxx:723
 HTrans.cxx:724
 HTrans.cxx:725
 HTrans.cxx:726
 HTrans.cxx:727
 HTrans.cxx:728
 HTrans.cxx:729
 HTrans.cxx:730
 HTrans.cxx:731
 HTrans.cxx:732
 HTrans.cxx:733
 HTrans.cxx:734
 HTrans.cxx:735
 HTrans.cxx:736
 HTrans.cxx:737
 HTrans.cxx:738
 HTrans.cxx:739
 HTrans.cxx:740
 HTrans.cxx:741
 HTrans.cxx:742
 HTrans.cxx:743
 HTrans.cxx:744
 HTrans.cxx:745
 HTrans.cxx:746
 HTrans.cxx:747
 HTrans.cxx:748
 HTrans.cxx:749
 HTrans.cxx:750
 HTrans.cxx:751
 HTrans.cxx:752
 HTrans.cxx:753
 HTrans.cxx:754
 HTrans.cxx:755
 HTrans.cxx:756
 HTrans.cxx:757
 HTrans.cxx:758
 HTrans.cxx:759
 HTrans.cxx:760
 HTrans.cxx:761
 HTrans.cxx:762
 HTrans.cxx:763
 HTrans.cxx:764
 HTrans.cxx:765
 HTrans.cxx:766
 HTrans.cxx:767
 HTrans.cxx:768
 HTrans.cxx:769
 HTrans.cxx:770
 HTrans.cxx:771
 HTrans.cxx:772
 HTrans.cxx:773
 HTrans.cxx:774
 HTrans.cxx:775
 HTrans.cxx:776
 HTrans.cxx:777
 HTrans.cxx:778
 HTrans.cxx:779
 HTrans.cxx:780
 HTrans.cxx:781
 HTrans.cxx:782
 HTrans.cxx:783
 HTrans.cxx:784
 HTrans.cxx:785
 HTrans.cxx:786
 HTrans.cxx:787
 HTrans.cxx:788
 HTrans.cxx:789
 HTrans.cxx:790
 HTrans.cxx:791
 HTrans.cxx:792
 HTrans.cxx:793
 HTrans.cxx:794
 HTrans.cxx:795
 HTrans.cxx:796
 HTrans.cxx:797
 HTrans.cxx:798
 HTrans.cxx:799
 HTrans.cxx:800
 HTrans.cxx:801
 HTrans.cxx:802
 HTrans.cxx:803
 HTrans.cxx:804
 HTrans.cxx:805
 HTrans.cxx:806
 HTrans.cxx:807
 HTrans.cxx:808
 HTrans.cxx:809
 HTrans.cxx:810
 HTrans.cxx:811
 HTrans.cxx:812
 HTrans.cxx:813
 HTrans.cxx:814
 HTrans.cxx:815
 HTrans.cxx:816
 HTrans.cxx:817
 HTrans.cxx:818
 HTrans.cxx:819
 HTrans.cxx:820
 HTrans.cxx:821
 HTrans.cxx:822
 HTrans.cxx:823
 HTrans.cxx:824
 HTrans.cxx:825
 HTrans.cxx:826
 HTrans.cxx:827
 HTrans.cxx:828
 HTrans.cxx:829
 HTrans.cxx:830
 HTrans.cxx:831
 HTrans.cxx:832
 HTrans.cxx:833
 HTrans.cxx:834
 HTrans.cxx:835
 HTrans.cxx:836
 HTrans.cxx:837
 HTrans.cxx:838
 HTrans.cxx:839
 HTrans.cxx:840
 HTrans.cxx:841
 HTrans.cxx:842
 HTrans.cxx:843
 HTrans.cxx:844
 HTrans.cxx:845
 HTrans.cxx:846
 HTrans.cxx:847
 HTrans.cxx:848
 HTrans.cxx:849
 HTrans.cxx:850
 HTrans.cxx:851
 HTrans.cxx:852
 HTrans.cxx:853
 HTrans.cxx:854
 HTrans.cxx:855
 HTrans.cxx:856
 HTrans.cxx:857
 HTrans.cxx:858
 HTrans.cxx:859
 HTrans.cxx:860
 HTrans.cxx:861
 HTrans.cxx:862
 HTrans.cxx:863
 HTrans.cxx:864
 HTrans.cxx:865
 HTrans.cxx:866
 HTrans.cxx:867
 HTrans.cxx:868
 HTrans.cxx:869
 HTrans.cxx:870
 HTrans.cxx:871
 HTrans.cxx:872
 HTrans.cxx:873
 HTrans.cxx:874
 HTrans.cxx:875
 HTrans.cxx:876
 HTrans.cxx:877
 HTrans.cxx:878
 HTrans.cxx:879
 HTrans.cxx:880
 HTrans.cxx:881
 HTrans.cxx:882
 HTrans.cxx:883
 HTrans.cxx:884