ROOT logo
// $Id: ZTrans.cxx 2341 2010-01-24 01:28:32Z 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/.

//______________________________________________________________________
// ZTrans
//
// ZTrans 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.
//
// Cartan angles in mA[1-3] (+z, -y, +x) are stored for backward
// compatibility and will probably be removed soon.
//
// 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

#include "ZTrans.h"
#include <Glasses/ZNode.h>

#include <TMath.h>
#include <TClass.h>

#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

ClassImp(ZTrans);

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

ZTrans::ZTrans() { UnitTrans(); }

ZTrans::ZTrans(const ZTrans& z) { *this = z; }

ZTrans::ZTrans(const ZNode* n)  { *this = n->RefTrans(); }

ZTrans::ZTrans(const Double_t arr[16]) { SetFromArray(arr); }

ZTrans::ZTrans(const Float_t  arr[16]) { SetFromArray(arr); }

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

void ZTrans::UnitTrans()
{
  memset(M, 0, 16*sizeof(Double_t));
  M[F00] = M[F11] = M[F22] = M[F33] = 1;
  mA1 = mA2 = mA3 = 0;
  bAsOK = true;
}

void ZTrans::UnitRot()
{
  memset(M, 0, 12*sizeof(Double_t));
  M[F00] = M[F11] = M[F22] = 1;
  mA1 = mA2 = mA3 = 0;
  bAsOK = true;
}

void ZTrans::SetTrans(const ZTrans& t)
{
  memcpy(M, t.M, sizeof(M));
  bAsOK = false;
}

void ZTrans::SetFromArray(const Double_t arr[16])
{
  for(Int_t i=0; i<16; ++i) M[i] = arr[i];
  bAsOK = false;
}

void ZTrans::SetFromArray(const Float_t  arr[16])
{
  for(Int_t i=0; i<16; ++i) M[i] = arr[i];
  bAsOK = false;
}

void ZTrans::SetupRotation(Int_t i, Int_t j, Double_t 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;
  ZTrans& M = *this;
  M(i,i) = M(j,j) = TMath::Cos(f);
  Double_t s = TMath::Sin(f);
  M(i,j) = -s; M(j,i) = s;
  bAsOK = false;
}

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

// OrtoNorm3 and Invert are near the bottom.

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

void ZTrans::MultLeft(const ZTrans& t)
{
  Double_t  B[4];
  Double_t* C = M;
  for(int c=0; c<4; ++c, C+=4) {
    const Double_t* 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];
  }
  bAsOK = false;
}

void ZTrans::MultRight(const ZTrans& t)
{
  Double_t  B[4];
  Double_t* C = M;
  for(int r=0; r<4; ++r, ++C) {
    const Double_t* 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];
  }
  bAsOK = false;
}

ZTrans ZTrans::operator*(const ZTrans& t)
{
  ZTrans b(*this);
  b.MultRight(t);
  return b;
}

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

void ZTrans::TransposeRotationPart()
{
  Double_t 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;
  bAsOK = false;
}

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

void ZTrans::MoveLF(Int_t ai, Double_t amount)
{
  const Double_t *C = M + 4*--ai;
  M[F03] += amount*C[0]; M[F13] += amount*C[1]; M[F23] += amount*C[2];
}

void ZTrans::Move3LF(Double_t x, Double_t y, Double_t 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];
}

void ZTrans::RotateLF(Int_t i1, Int_t i2, Double_t amount)
{
  // Rotate in local frame. Does optimised version of MultRight.

  if(i1 == i2) return;
  // Algorithm: ZTrans a; a.SetupRotation(i1, i2, amount); MultRight(a);
  // Optimized version:
  const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
  Double_t  b1, b2;
  Double_t* 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;
  }
  bAsOK = false;
}

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

void ZTrans::MovePF(Int_t ai, Double_t amount)
{
  M[F03 + --ai] += amount;
}

void ZTrans::Move3PF(Double_t x, Double_t y, Double_t z)
{
  M[F03] += x;
  M[F13] += y;
  M[F23] += z;
}

void ZTrans::RotatePF(Int_t i1, Int_t i2, Double_t amount)
{
  // Rotate in parent frame. Does optimised version of MultLeft.

  if(i1 == i2) return;
  // Algorithm: ZTrans a; a.SetupRotation(i1, i2, amount); MultLeft(a);

  // Optimized version:
  const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
  Double_t  b1, b2;
  Double_t* 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;
  }
  bAsOK = false;
}

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

void ZTrans::Move(const ZTrans& a, Int_t ai, Double_t amount)
{
  const Double_t* A = a.M + 4*--ai;
  M[F03] += amount*A[0];
  M[F13] += amount*A[1];
  M[F23] += amount*A[2];
}

void ZTrans::Move3(const ZTrans& a, Double_t x, Double_t y, Double_t z)
{
  const Double_t* 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];
}

void ZTrans::Rotate(const ZTrans& a, Int_t i1, Int_t i2, Double_t amount)
{
  if(i1 == i2) return;
  ZTrans X(a);
  X.Invert();
  MultLeft(X);
  RotatePF(i1, i2, amount);
  MultLeft(a);
  bAsOK = false;
}

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

namespace {
  inline void clamp_angle(Float_t& a) {
    while(a < -TMath::TwoPi()) a += TMath::TwoPi();
    while(a >  TMath::TwoPi()) a -= TMath::TwoPi();
  }
}

void ZTrans::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
  clamp_angle(a1); clamp_angle(a2); clamp_angle(a3);

  Double_t 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);
  Double_t 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;

  mA1 = a1; mA2 = a2; mA3 = a3;
  bAsOK = true;
}

void ZTrans::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;
    }
  }
  bAsOK = false;
}

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

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

Bool_t ZTrans::CompareAngles(Float_t a1, Float_t a2, Float_t a3) const
{
  // Return true if angles currently used are the same as passed ones.
  // This will most likely only work correctly if SetRotByAngles() was and
  // will be used.

  return (bAsOK && mA1 == a1 && mA2 == a2 && mA3 == a3);
}

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

void ZTrans::Scale(Double_t sx, Double_t sy, Double_t 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;
}

void ZTrans::GetScale(Double_t& sx, Double_t& sy, Double_t& 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] );
}

void ZTrans::Unscale(Double_t& sx, Double_t& sy, Double_t& 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;
}

Double_t ZTrans::Unscale()
{
  Double_t sx, sy, sz;
  Unscale(sx, sy, sz);
  return (sx + sy + sz)/3;
}

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

void ZTrans::MultiplyIP(TVector3& v, Double_t w) const
{
  v.SetXYZ(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);
}

TVector3 ZTrans::Multiply(const TVector3& v, Double_t w) const
{
  return TVector3(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);
}

void ZTrans::RotateIP(TVector3& v) const
{
  v.SetXYZ(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());
}

TVector3 ZTrans::Rotate(const TVector3& v) const
{
  return TVector3(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());
}

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

Double_t ZTrans::Norm3Column(Int_t col)
{
  Double_t* C = M + 4*--col;
  const Double_t 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;
}

Double_t ZTrans::Orto3Column(Int_t col, Int_t ref)
{
  Double_t* C = M + 4*--col;
  Double_t* R = M + 4*--ref;
  const Double_t 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;
}

Double_t ZTrans::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).

  Double_t* C = M + 4*--col;
  Double_t* R = M + 4*--ref;
  const Double_t 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 Double_t  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;
}

void ZTrans::OrtoNorm3()
{
  Norm3Column(1);
  Orto3Column(2,1); Norm3Column(2);
  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);
}

void ZTrans::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;
  }
}

/**************************************************************************/
// Inversion
/**************************************************************************/

Double_t ZTrans::Invert()
{
  // Copied from ROOT's TMatrixFCramerInv.

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

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

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

  // Find the 4x4 det:
  const Double_t 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 Double_t oneOverDet = 1.0/det;
  const Double_t 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;

  bAsOK = false;
  return det;
}

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

void ZTrans::Streamer(TBuffer &R__b)
{
   // Stream an object of class ZTrans.

   if (R__b.IsReading()) {
      ZTrans::Class()->ReadBuffer(R__b, this);
      bAsOK = false;
   } else {
      ZTrans::Class()->WriteBuffer(R__b, this);
   }
}

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

void ZTrans::Print(Option_t* option) const
{
  const Double_t* 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]);
}

#include <iomanip>

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