ROOT logo
//*-- Author :    Ole Hansen, Jefferson Lab   06-Jun-2007

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// TreeSearch::MWDC                                                          //
//                                                                           //
// Reconstruction class for horizontal drift chambers used in BigBite.       //
// Tracking is done using a tree search algorithm (DellOrso et al.,          //
// NIM A 287, 436 (1990)), in essence a recursive template matching method.  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "MWDC.h"
#include "WirePlane.h"
#include "Projection.h"
#include "Hit.h"
#include "Road.h"
#include "Helper.h"

#include "THaDetMap.h"
#include "THaEvData.h"
#include "THaTrack.h"

#include "TString.h"
#include "TMath.h"
#include "THashTable.h"
#include "TVector2.h"
#include "TDecompChol.h"
#include "TSystem.h"
#include "TThread.h"
#include "TCondition.h"
#include "TMutex.h"

#include <iostream>
#include <algorithm>
#include <numeric>
#include <map>
#include <string>

#ifdef TESTCODE
#include "TStopwatch.h"
#endif

using namespace std;
typedef string::size_type ssiz_t;

namespace {

// Helper classes for describing a DAQ hardware module and using it with a
// THashTable. CSpair can be used to find elements in the THashTable w/o
// creating large dummy objects.
//TODO: replace in favor or retrieving the information from db_cratemap
class CSpair : public TObject {
public:
  CSpair( UShort_t crate, UShort_t slot ) : fCrate(crate), fSlot(slot) {}
  virtual ULong_t Hash() const {
    UInt_t cs = (static_cast<UInt_t>(fCrate)<<16) + static_cast<UInt_t>(fSlot);
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
    return TString::Hash( &cs, sizeof(cs) );
#else
    return TMath::Hash( &cs, sizeof(cs) );
#endif
  }
  virtual Bool_t IsEqual( const TObject* obj ) const {
    const CSpair* m;
    if( !obj or !(m = dynamic_cast<const CSpair*>(obj)) ) return kFALSE;
    return ( fCrate == m->fCrate and fSlot == m->fSlot );
  }
  UShort_t  fCrate;
  UShort_t  fSlot;
};
class DAQmodule : public CSpair {
public:
  DAQmodule( UShort_t crate, UShort_t slot, UInt_t model, Double_t res,
	     UInt_t nchan )
    : CSpair(crate, slot), fModel(model), fResolution(res), fNchan(nchan) {}
  virtual ~DAQmodule() {}
  virtual void Copy( TObject& obj ) const {
    TObject::Copy(obj);
    DAQmodule* m = dynamic_cast<DAQmodule*>(&obj);
    if( !m ) return;
    m->fCrate = fCrate; m->fSlot = fSlot; m->fModel = fModel;
    m->fResolution = fResolution, m->fNchan = fNchan;
  }
  virtual void Print( Option_t* ) const {
    cout << "DAQmodule: "
	 << " crate = " << fCrate
	 << " slot = "  << fSlot
	 << " model = " << fModel
	 << " res = "   << fResolution
	 << " nchan = "   << fNchan
	 << endl;
  }
  UInt_t    fModel;
  Double_t  fResolution;
  UInt_t    fNchan;
};

///////////////////////////////////////////////////////////////////////////////

} // end namespace

namespace TreeSearch {

typedef vector<WirePlane*>::size_type vwsiz_t;
typedef vector<WirePlane*>::iterator  vwiter_t;
typedef vector<Projection*>::size_type vpsiz_t;
typedef vector<vector<Int_t> >::iterator vviter_t;

// Global constant indicating invalid/uninitialized data
const Double_t kBig = 1e38;

#define ALL(c) (c).begin(), (c).end()

static void DoTrack( void* ptr );

//_____________________________________________________________________________
// Support classes for data-processing threads

struct TrackThread {
  Projection*  proj;    // Projection to be processed
  Int_t*       status;  // Return status (shared)
  Int_t*       running; // Bitfield indicating threads to wait for (shared)
  TMutex*      start_m; // Mutex for start condition
  TMutex*      done_m;  // Mutex for done condition
  TCondition*  start;   // Start condition of tracking threads
  TCondition*  done;    // Condition indicating all tracking threads done
  TThread*     thread;  // The actual thread running with these arguments
  TrackThread()
    : proj(0), status(0), running(0), start(0), done(0), thread(0) {}
  ~TrackThread() { 
    if( thread ) {
      TThread::Delete(thread);
      delete thread;
    }
  }
};
  
//_____________________________________________________________________________
class ThreadCtrl {
  //TODO: better encapsulation
  friend THaAnalysisObject::EStatus MWDC::Init(const TDatime&);
  friend Int_t MWDC::CoarseTrack(TClonesArray&);
public:
  ThreadCtrl() : fTrackStatus(0), fTrackToDo(0),
		 fTrackStartM(new TMutex), fTrackDoneM(new TMutex),
		 fTrackStart(new TCondition(fTrackStartM)),
		 fTrackDone(new TCondition(fTrackDoneM)) {}
  ~ThreadCtrl() {
    // Terminate tracking threads
    if( !fTrack.empty() ) {
      fTrackStartM->Lock();
      fTrackToDo = 0;
      for( vector<TrackThread>::iterator it = fTrack.begin(); it !=
	     fTrack.end(); ++it ) {
	TThread* th = (*it).thread;
	if( th and th->GetState() == TThread::kRunningState )
	  SETBIT(fTrackToDo, (*it).proj->GetType());
      }
      // negative sign is termination flag
      SETBIT(fTrackToDo, 31);
      fTrackStart->Broadcast();
      fTrackDoneM->Lock();
      fTrackStartM->UnLock();
      while( true ) {
	Int_t ret = fTrackDone->Wait();
	if( ret == 0 and fTrackToDo == BIT(31) )
	  break;
      }
      fTrackDoneM->UnLock();
    }
    // At this point, all threads should have released their condition
    // waits and mutexes, so clean up is safe
    delete fTrackDone;
    delete fTrackStart;
    delete fTrackDoneM;
    delete fTrackStartM;
  }
  TThread* AddTrackThread( Projection* proj ) {
    assert( proj );
    fTrack.push_back( TrackThread() );
    TrackThread* t = &fTrack.back();
    t->proj    = proj;
    t->status  = &fTrackStatus;
    t->running = &fTrackToDo;
    t->start_m = fTrackStartM;
    t->done_m  = fTrackDoneM;
    t->start   = fTrackStart;
    t->done    = fTrackDone;
    string tn;
    tn = "trk_"; tn.append( proj->GetName() );
    t->thread  = new TThread( tn.c_str(), DoTrack, (void*)t );
    return t->thread;
  }
private:
  vector<TrackThread>  fTrack;        // Tracking thread descriptors
  Int_t                fTrackStatus;  // Common status variable
  Int_t                fTrackToDo;    // Bitfield of projections to wait for
  TMutex*              fTrackStartM;  // Mutex for start condition
  TMutex*              fTrackDoneM;   // Mutex for done condition
  TCondition*          fTrackStart;   // Start condition
  TCondition*          fTrackDone;    // Finish condition
};

//_____________________________________________________________________________
MWDC::MWDC( const char* name, const char* desc, THaApparatus* app )
  : THaTrackingDetector(name,desc,app), fCrateMap(0),
    fMaxThreads(1), fThreads(0),
    f3dMatchvalScalefact(1), f3dMatchCut(0), fMinNdof(1),
    fFailNhits(0), fFailNpat(0)
#ifdef TESTCODE
  , fNcombos(0), fN3dFits(0), fEvNum(0)
#endif
{ 
  // Constructor

  fRefMap = new THaDetMap;

  // Set up the projection objects (describing wire planes of same type)
  fProj.resize( kTypeEnd, 0 );
  // Default plane angles and names. Angles can be overridden via the database
  Double_t p_angle[]   = { -60.0, 60.0, 0.0, 90.0 };
  //FIXME: the names should be part of the enum
  const char* p_name[] = { "u", "v", "x", "y" };
  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    Projection* proj = new Projection( type, 
				       p_name[type], 
				       p_angle[type]*TMath::DegToRad(),
				       this 
				       );
    if( !proj or proj->IsZombie() ) {
      // Urgh. Something very bad is going on
      Error( Here("MWDC"), "Error creating projection %s. Call expert.", 
	     p_name[type] );
      MakeZombie();
      return;
    }
    fProj[type] = proj;
  }
}

//_____________________________________________________________________________
MWDC::~MWDC()
{
  // Destructor. Delete objects & subdetectors and unregister variables
  if (fIsSetup)
    RemoveVariables();
  
  delete fThreads;
  if( fMaxThreads > 1 )
    gSystem->Unload("libThread");

  DeleteContainer( fPlanes );
  DeleteContainer( fProj );
  delete fRefMap;
}

//_____________________________________________________________________________
void MWDC::Clear( Option_t* opt )
{
  // Clear event-by-event data, including those of wire planes and projections
  THaTrackingDetector::Clear(opt);
  
  // Clear the planes and projections, but only if we're not called from Init()
  if( !opt or *opt != 'I' ) {
    for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane )
      fPlanes[iplane]->Clear(opt);

    for( EProjType type = kTypeBegin; type < kTypeEnd; ++type )
      fProj[type]->Clear(opt);

    if( fRefMap->GetSize() > 0 )
      fRefTime.assign( fRefMap->GetSize(), kBig );  // not strictly necessary
  }
  fFailNpat = fFailNhits = 0;
#ifdef TESTCODE
  size_t nbytes = (char*)&t_coarse - (char*)&fNcombos + sizeof(t_coarse);
  memset( &fNcombos, 0, nbytes );
#endif
}

//_____________________________________________________________________________
Int_t MWDC::Decode( const THaEvData& evdata )
{
  // Decode all planes and fill hitpatterns per projection
  
  static const char* const here = "Decode";

#ifdef TESTCODE
  // Save current event number for diagnostics
  fEvNum = evdata.GetEvNum();
#endif

#ifdef VERBOSE
  if( fDebug > 0 ) {
    cout << "============== Event ";
#ifdef TESTCODE
    cout << "# " << fEvNum << " ";
#endif
    cout << "==============" << endl;
  }
#endif

  // Decode reference channels of the VME readout (if any)
  for( Int_t imod = 0; imod < fRefMap->GetSize(); ++imod ) {
    THaDetMap::Module* d = fRefMap->GetModule(imod);
    // By construction, this map has one channel per module
    Int_t chan = d->lo;
    UInt_t nhits = evdata.GetNumHits( d->crate, d->slot, chan );
    if( nhits > 0 ) {
      Int_t data = evdata.GetData( d->crate, d->slot, chan, nhits-1 );
      if( nhits > 1 ) {
	Warning( Here(here), "%d hits on reference channel %d module %d", 
		 nhits, chan, imod );
      }
      fRefTime[imod] = d->resolution * data;
    } else {
      // TODO: At this point, one could look for backup reference channels
      // to recover the data. Left for later, if needed.
      Warning( Here(here), "No hits on reference channel %d module %d.",
	       chan, imod );
      fRefTime[imod] = kBig;
    }
  }   // modules

  // Decode the planes, then fill the hitpatterns in the projections
  //TODO: multithread
  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    Int_t nhits = fProj[type]->Decode( evdata );
    // Sanity cut on overfull wire planes. nhits < 0 indicates overflow
    if( nhits < 0 ) {
      fFailNhits = 1;
      continue;
    }
    // No need to fill the hitpattern if no tracking requested
    if( TestBit(kDoCoarse) )
      fProj[type]->FillHitpattern();
  }

  return 0;
}

//_____________________________________________________________________________
class AddFitCoord
{
public:
  AddFitCoord() {}
  void operator() ( Road* rd, Road::Point* p, const vector<Double_t>& coef )
  {
    const Projection* proj = rd->GetProjection();
    Double_t slope2d  = rd->GetSlope();
    Double_t trkpos2d = rd->GetPos() + p->z * slope2d;
    Double_t cosa     = proj->GetCosAngle();
    Double_t sina     = proj->GetSinAngle();
    Double_t slope    = coef[1]*cosa + coef[3]*sina;
    Double_t pos      = coef[0]*cosa + coef[2]*sina + slope * p->z;
    p->hit->GetWirePlane()->AddFitCoord
      ( FitCoord( p->hit, rd, p->x, trkpos2d, slope2d, pos, slope ));
  }
};

//_____________________________________________________________________________
#ifdef VERBOSE
class PrintFitPoint
{
public:
  PrintFitPoint() {}
  void operator() ( Road*, Road::Point* p, const vector<Double_t>& )
  {
    cout << p->hit->GetWirePlane()->GetName() << " " 
	 << "z = " << p->z << " x = " << p->x << endl;
  }
};
#endif

//_____________________________________________________________________________
class FillFitMatrix
{
public:
  FillFitMatrix( TMatrixDSym& AtA, TVectorD& Aty ) 
    : fAtA(AtA), fAty(Aty), fNpoints(0) 
  {
    assert( fAtA.GetNrows() == 4 && fAty.GetNrows() == 4 );
  }

  void operator() ( Road* rd, Road::Point* p, const vector<Double_t>& )
  {
    const Projection* proj = rd->GetProjection();
    Double_t cosa = proj->GetCosAngle();
    Double_t sina = proj->GetSinAngle();
    Double_t Ai[4] = { cosa, cosa * p->z, sina, sina * p->z };
    Double_t s2 = 1.0/(p->res()*p->res());
    for( int j = 0; j<4; ++j ) {
      for( int k = j; k<4; ++k ) {
	fAtA(j,k) += Ai[j] * s2 * Ai[k];
      }
      fAty(j) += Ai[j] * s2 * p->x;
    }
    ++fNpoints;
  }
  Int_t GetNpoints() const { return fNpoints; }
private:
  TMatrixDSym& fAtA;
  TVectorD&    fAty;
  Int_t        fNpoints;
};

//_____________________________________________________________________________
class CalcChisquare
{
public:
  CalcChisquare() : fChi2(0) {}
  void operator() ( Road* rd, Road::Point* p, const vector<Double_t>& coef )
  {
    const Projection* proj = rd->GetProjection();
    Double_t cosa  = proj->GetCosAngle();
    Double_t sina  = proj->GetSinAngle();
    Double_t slope = coef[1]*cosa + coef[3]*sina;
    Double_t pos   = coef[0]*cosa + coef[2]*sina + slope*p->z;
    Double_t diff  = (pos - p->x) / p->res();
    fChi2 += diff*diff;
  }
  void     Clear() { fChi2 = 0; }
  Double_t GetResult() const { return fChi2; }
private:
  Double_t fChi2;
};

//_____________________________________________________________________________
template< typename Action >
Action MWDC::ForAllTrackPoints( const Rvec_t& roads, 
				const vector<Double_t>& coef, Action action )
{
  // Apply action to all points from roads and the track given by coef

  for( Rvec_t::const_iterator it = roads.begin(); it != roads.end(); ++it ) {
    Road* rd = *it;
    const Road::Pvec_t& points = rd->GetPoints();
    for( Road::Pvec_t::const_iterator it2 = points.begin();
	 it2 != points.end(); ++it2 ) {
      Road::Point* p = *it2;
      action( rd, p, coef );
    }
  }
  return action;
}

//_____________________________________________________________________________
void MWDC::FitErrPrint( Int_t err ) const
{
  static const char* const here = "FitTrack";

#ifdef TESTCODE
  Error( Here(here), "Event %d: Failure fitting 3D track, err = %d. "
	 "Should never happen. Call expert.", fEvNum, err );
#else
  Error( Here(here), "Failure fitting 3D track, err = %d. "
	 "Should never happen. Call expert.", err );
#endif
}

//_____________________________________________________________________________
Int_t MWDC::FitTrack( const Rvec_t& roads, vector<Double_t>& coef,
		      Double_t& chi2, TMatrixDSym* coef_covar ) const
{
  // Linear minimization routine to fit a physical straight line track through
  // the hits registered in the different projection planes.
  //
  // This is a much streamlined version of ROOT's TLinearFitter that solves
  // the normal equations with weights, (At W A) a = (At W) y, using Cholesky
  // decomposition, TDecompChol. The model used is
  //   y_i = P_i * T_i
  //       = ( x + z_i * mx, y + z_i * my) * ( cos(a_i), sin(a_i) )
  // where
  //   y_i is the measured coordinate in the i-th wire plane at z_i
  //   P_i is the physical track intersection point with the z_i plane
  //   T_i is the axis unit vector of the i-th plane
  //   a_i is the angle of the coordinate axis of the i-th plane w.r.t. x
  //   x,mx,y,my are the track parameters to be fitted, origin x,y and
  //       slopes mx,my.
  //   
  // "roads" contains a set of Roads that successfully combine in 3-d, one
  // Road* per projection. Each road, in turn, contains a set of (y_i,z_i)
  // coordinates, at most one per wire plane of the projection type, that
  // give the best 2D track fit within the road.
  //
  // "coef" are the fitted track parameters, x, x'(=mx), y, y'(=my).
  // The reference system is the z=0 plane (usually the first chamber).
  //
  // "chi2" is the chi2 of the fit (not normalized).
  //
  // "coef_covar" is the covariance matrix of the fit results. Since it is
  // expensive to calculate, it is only filled if the argument is supplied.
  //
  // The return value is the number of degrees of freedom of the fit, i.e.
  // npoints-4 > 0, or negative if too few points or matrix inversion error

  // Fill the (At W A) matrix and (At W y) vector with the measured points
  TMatrixDSym AtA(4);
  TVectorD Aty(4);
  FillFitMatrix f = ForAllTrackPoints(roads, coef, FillFitMatrix(AtA, Aty));

  Int_t npoints = f.GetNpoints();
  assert( npoints > 4 );
  if( npoints <=4 ) return -1; // Meaningful fit not possible

  // FillFitMatrix only fills the upper triangle for efficiency
  //TODO: make a function of FillFitMatrix?
  for( int j = 0; j<4; ++j )
    for( int k = j+1; k<4; ++k )
      AtA(k,j) = AtA(j,k);

  // Invert the characteristic matrix and solve the normal equations.
  // As in ROOT's TLinearFitter, we use a Cholesky decomposition
  // to do this (since AtA is symmetric and positive-definite).
  // For more speed but less accuracy, one could use TMatrixDSymCramerInv.
  TDecompChol chol(AtA);
  Bool_t ok = chol.Solve(Aty);
  assert(ok);
  if( !ok ) return -2; //Urgh, decomposition failed. Should never happen

  // Copy results to output vector in order x, x', y, y'
  assert( Aty.GetNrows() == 4 );
  coef.assign( Aty.GetMatrixArray(), Aty.GetMatrixArray()+Aty.GetNrows() );

#ifdef VERBOSE
  if( fDebug > 2 ) {
    cout << "Points in 3D fit:" << endl;
    ForAllTrackPoints( roads, coef, PrintFitPoint() );
  }
#endif

  // Calculate chi2
  chi2 = ForAllTrackPoints(roads, coef, CalcChisquare()).GetResult();

  // Calculate covariance matrix of the parameters, if requested
  if( coef_covar ) {
    if( coef_covar->GetNrows() != 4 )
      coef_covar->ResizeTo(4,4);
    Bool_t ok = chol.Invert(*coef_covar);
    assert(ok);
    if( !ok ) return -3; // Urgh, inversion failed. Should never happen
  }

#ifdef VERBOSE
  if( fDebug > 1 ) 
    cout << "3D fit:  x/y = " << coef[0] << "/" << coef[2] << " "
	 << "mx/my = " << coef[1] << "/" << coef[3] << " "
	 << "ndof = " << npoints-4 << " rchi2 = " << chi2/(double)(npoints-4)
	 << endl;
#endif
  
  return npoints-4;
}

//_____________________________________________________________________________
void MWDC::FindNearestHits( WirePlane* wp, const THaTrack* track, 
			    const Rvec_t& roads ) const
{
  // For the given wire plane, find the hit nearest to the given track
  // and register it in the plane's fit coordinates array.
  // The given roads are the ones generating the given track.
  // This routine is used for efficiency and alignment studies and testing.

  assert( !roads.empty() );

  // Search for the hit with wire position closest to the track crossing
  // position in this plane. The hits are sorted by wire position, so
  // the search can be made fast.
  Double_t z     = wp->GetZ();
  Double_t cosa  = wp->GetProjection()->GetCosAngle();
  Double_t sina  = wp->GetProjection()->GetSinAngle();
  Double_t slope = track->GetTheta()*cosa + track->GetPhi()*sina;
  Double_t x     = track->GetX()*cosa + track->GetY()*sina + slope*z;
  Double_t dmin  = kBig;
  Double_t pmin  = kBig;
  Hit* hmin = 0;
  // Binary search the hits array for the track crossing position x, similar
  // to std::lower_bound(). This finds the first hit with wire position >= x.
  const TSeqCollection* hits = wp->GetHits();
  Int_t first = 0, last = hits->GetSize();
  // GetSize() is incorrect for TObjArrays and TClonesArrays
  const TObjArray* arr = dynamic_cast<const TObjArray*>(hits);
  if( arr )
    last = arr->GetLast()+1;
  Int_t len = last - first;
  Int_t half, middle;
  while( len > 0 ) {
    half = len >> 1;
    middle = first + half;
    if( static_cast<Hit*>(hits->At(middle))->GetWirePos() < x ) {
      first = middle + 1;
      len -= half + 1;
    } else
      len = half;
  }
  // Decide whether the wire >= x or the first one < x are closest.
  // If the track crosses between two adjacent wires, keep both.
  if( last > 0 ) {
    assert( first <= last );
    Hit *hnext = 0, *hprev = 0;
    if( first < last ) {
      hnext = static_cast<Hit*>(hits->At(first));
      assert( hnext->GetWirePos() >= x );
    }
    if( first > 0 ) {
      hprev = static_cast<Hit*>(hits->At(first-1));
      assert( hprev->GetWirePos() < x );
      if( hnext ) {
	assert( hprev->GetWireNum() < hnext->GetWireNum() );
	if( hprev->GetWireNum() + 1 < hnext->GetWireNum() ) {
	  if( x - hprev->GetWirePos() < hnext->GetWirePos() - x )
	    hnext = 0;
	  else
	    hprev = 0;
	}
      }
    }
    // Of the closest wire(s) found, find the closest drift distance.
    // If there are multiple hits one a wire, test all hits - without
    // making assumptions about the order of drift distances
    if( hnext ) {
      hmin = hnext;
      pmin = hnext->GetPosL();
      dmin = TMath::Abs(pmin-x);
      Int_t i = first;
      Hit* h;
      while( ++i < last and (h = static_cast<Hit*>(hits->At(i)))->GetWireNum()
	     == hnext->GetWireNum() ) {
	Double_t d = TMath::Abs(h->GetPosL()-x);
	if( d < dmin ) {
	  dmin = d;
	  hmin = h;
	  pmin = h->GetPosL();
	}
      }
    }
    if( hprev ) {
      Double_t d = TMath::Abs(hprev->GetPosR()-x);
      if( !hmin or d < dmin ) {
	dmin = d;
	hmin = hprev;
	pmin = hprev->GetPosR();
      }
      Int_t i = first-1;
      Hit* h;
      while( --i >= 0 and (h = static_cast<Hit*>(hits->At(i)))->GetWireNum()
	     == hprev->GetWireNum() ) {
	d = TMath::Abs(h->GetPosR()-x);
	if( d < dmin ) {
	  dmin = d;
	  hmin = h;
	  pmin = h->GetPosR();
	}
      }
    }
  }
  // The road vector does not necessarily contain all projections, so
  // search for the road of the type of this wire plane, taking advantage
  // of the fact that the road vector is sorted by type
  Road* rd = 0;
  Int_t k = min( roads.size(), (Rvec_t::size_type)wp->GetType() );
  do {
    if( roads[k]->GetProjection()->GetType() > wp->GetType() )
      --k;
    else {
      if( roads[k]->GetProjection() == wp->GetProjection() )
	rd = roads[k];
      break;
    }
  } while( k>=0 );
  Double_t slope2d = rd ? rd->GetSlope() : kBig;
  Double_t pos2d   = rd ? rd->GetPos() + z * slope2d  : kBig;

  // Finally, record the hit info in the wire plane
  wp->AddFitCoord( FitCoord(hmin, rd, pmin, pos2d, slope2d, x, slope) );
}

//_____________________________________________________________________________
THaTrack* MWDC::NewTrack( TClonesArray& tracks, const FitRes_t& fit_par )
{
  // Make new track with given parameters. Used by CoarseTrack to generate
  // all MWDC tracks

  Double_t x  = fit_par.coef[0];
  Double_t xp = fit_par.coef[1];
  Double_t y  = fit_par.coef[2];
  Double_t yp = fit_par.coef[3];

  THaTrack* newTrack = AddTrack( tracks, x, y, xp, yp );
  //TODO: make a TrackID?
  assert( newTrack );
  // The "detector" and "fp" TRANSPORT systems are the same for BigBite
  newTrack->SetD( x, y, xp, yp );
  newTrack->SetChi2( fit_par.chi2, fit_par.ndof );

  ForAllTrackPoints( *fit_par.roads, fit_par.coef, AddFitCoord() );
  for( Wpvec_t::const_iterator it = fCalibPlanes.begin(); it !=
	 fCalibPlanes.end(); ++it ) {
    FindNearestHits( (*it), newTrack, *fit_par.roads );
  }

  return newTrack;
}

//_____________________________________________________________________________
class CheckTypes : public unary_function<Road*,void>
{
  // Function object for testing the projection occupancy of roads.
  // Applied to a road, it saves the road's plane type (u,v,x..).
  // Testing the object returns true if all types specified in the 'req'
  // argument to the constructor have been seen in all the roads tested.
public:
  CheckTypes( UInt_t req ) : fReq(req), fActive(0) {}
  void operator() ( const Road* rd )
  { fActive |= 1U << rd->GetProjection()->GetType(); }
  operator bool()       const { return (fActive & fReq) == fReq; }
  bool     operator!()  const { return (fActive & fReq) != fReq; }
  UInt_t   GetTypes()   const { return fActive; }
private:
  UInt_t fReq;
  UInt_t fActive;
};

//_____________________________________________________________________________
class AnySharedHits : public unary_function<Road*,bool>
{
public:
  AnySharedHits() {}
  bool operator() ( const Road* rd )
  {
    const Hset_t& test_hits = rd->GetHits();
//     cout << "--- testing: " << endl;
//     PrintHits(test_hits);
    for( Hset_t::const_iterator it = test_hits.begin(); it != test_hits.end();
	 ++it ) {
      if( fHits.find(*it) != fHits.end() )
	return true;
    }
    return false;
  }
  const AnySharedHits& use( const Rset_t& tuple )
  {
    fHits.clear();
    for( Rset_t::const_iterator it = tuple.begin(); it != tuple.end(); ++it ) {
      const Road* rd = *it;
      fHits.insert( ALL(rd->GetHits()) );
    }
//     PrintHits(fHits);
    return *this;
  }
private:
  Hset_t fHits;
};

//_____________________________________________________________________________
class MWDC::TrackFitWeight
{
  // Object for sorting fits. The smaller a track's TrackFitWeight, the
  // "better" a track is considered to be.
public:
  TrackFitWeight( const MWDC::FitRes_t& fit_par ) :
    fNdof(fit_par.ndof), fChi2(fit_par.chi2) { assert(fNdof); }

  bool operator<( const TrackFitWeight& rhs ) const
  {
    // The "best" tracks have the largest number of hits and the smallest chi2
    //TODO: devalue tracks with very large chi2?
    if( fNdof > rhs.fNdof ) return true;
    if( fNdof < rhs.fNdof ) return false;
    return ( fChi2 < rhs.fChi2 );
  }
  operator double() const { return fChi2/(double)fNdof; }
private:
  UInt_t   fNdof;
  Double_t fChi2;
};

//_____________________________________________________________________________
template< typename Container, typename Weight, typename TestF,
	  typename QuitF > Double_t
OptimalN( const Container& choices, const multimap<Weight,Container>& weights,
	  vector<Container>& picks, TestF testf, QuitF quitf )
{
  // This is the second-level de-ghosting algorithm, operating on fitted
  // 3D tracks.  It selects the best set of tracks if multiple roads
  // combinations are present in one or more projection.
  //
  // Requirements:
  //  "Container": STL container (set or sorted vector) supporting begin(),
  //               insert(), end(), swap(), and containing "Element"s sorted
  //               by Element's operator<.  Here, Element = Road*
  //  "Weight":    sorting functor, supporting operator< and operator double()
  //  "TestF":     Functor for eliminating additional leftover elements,
  //               must support:
  //                  operator() (const Element&): test this element,
  //                                         eliminate if true
  //                  use(const Container&): test against elements in this 
  //                                         container
  //               (use() is in lieu of a constructor because the object
  //                is constructed by the caller (possibly with parameters)).
  //  "QuitF":     Functor for terminating search early. Applied to all 
  //               leftover elements. Must support
  //                  operator() (const Element&)
  //                  operator bool(): End search if false after running on
  //                                   all elements

  //TODO: how efficient? O(N^2)? (N iterations on include)

  picks.clear();
  Container choices_left(choices);

  //TODO: try minimizing chi2 sum
  double wsum = 0;
  typename multimap<Weight,Container>::const_iterator it = weights.begin();
  for( ; it != weights.end(); ++it ) {
    const Container& tuple = (*it).second;
    if( includes(ALL(choices_left), ALL(tuple)) ) {
      // Pick next set of still-available elements in order of ascending weight
      picks.push_back( tuple );
      // Sum of weights of chosen sets, converted to double
      wsum += (*it).first;
      // Remove chosen elements from the remaining choices
      Container choices_less_tuple;
      set_difference( ALL(choices_left), ALL(tuple),
		      inserter(choices_less_tuple, choices_less_tuple.end()) );
      // Test each remaining element against the chosen set of elements
      // and remove it if it compares true (=remove elems with common traits)
      Container new_choices_left;
      remove_copy_if( ALL(choices_less_tuple),
		      inserter(new_choices_left, new_choices_left.end()),
		      testf.use(tuple) );
      // Quit if the quit function, applied to each element still remaining
      // now, is no longer true
      if( !for_each(ALL(new_choices_left), quitf) )
	break;
      // Update the set of remaining elements
      choices_left.swap( new_choices_left );
    }
  }

  return wsum;
}

//_____________________________________________________________________________
inline
void MWDC::Add3dMatch( const Rvec_t& selected, Double_t matchval,
		  list< pair<Double_t,Rvec_t> >& combos_found,
		  Rset_t& unique_found ) const
{
  // Save road combination with good matchvalue

  combos_found.push_back( make_pair(matchval,selected) );

  // Since not all of the roads in 'roads' may make a match,
  // keep track of unique roads found for each projection type

  unique_found.insert( ALL(selected) );

#ifdef VERBOSE
  if( fDebug > 3 )
    cout << "ACCEPTED" << endl;
#endif
}

//_____________________________________________________________________________
UInt_t MWDC::MatchRoads( vector<Rvec_t>& roads,
			 list< pair<Double_t,Rvec_t> >& combos_found,
			 Rset_t& unique_found )
{
  // Match roads from different projections that intersect in the front
  // and back plane of the detector

  // The number of projections that we work with (must be >= 3)
  vector<Rvec_t>::size_type nproj = roads.size();
  assert( nproj >= 2 );

  combos_found.clear();
  unique_found.clear();

  // Number of all possible combinations of the input roads
  //TODO: protect against overflow?
  UInt_t ncombos = accumulate( ALL(roads), (UInt_t)1, SizeMul<Rvec_t>() );
  UInt_t nfound  = 0;
  bool   fast_3d = TestBit(k3dFastMatch);

#ifdef VERBOSE
  if( fDebug > 0 ) {
    cout << "Matching ";
    for( vector<Rvec_t>::size_type i = 0; i < nproj; ++i ) {
      cout << roads[i].size();
      if( i+1 < nproj ) cout << "x";
    }
    cout << " track projections in 3D (";
    if( fast_3d ) cout << "fast";
    else          cout << "generic";
    cout << " algo, " << ncombos << " combinations):" << endl;
  }
#endif
#ifdef TESTCODE
  fNcombos = ncombos;
#endif

  if( ncombos == 0 )
    return 0;

  // TODO: separate code sections
  // Vector holding a combination of roads to test. One road from each 
  // projection 
  Rvec_t selected;
  selected.reserve(nproj);

  Double_t zback = fPlanes.back()->GetZ();
  if( fast_3d ) {
    // special case n==3 and symmetric angles of planes 0 and 1:
    //  - intersect first two proj in front and back
    //  - calc perp distances to 3rd, add in quadrature -> matchval
    assert( nproj == 3 && fProj.size() == 3 );

    // Fetch coefficients for coordinate transformations
    Prvec_t::iterator ip = fProj.begin();
    Double_t su = (*ip)->GetSinAngle();
    Double_t cu = (*ip)->GetCosAngle();
    ++ip;
    Double_t sv = (*ip)->GetSinAngle();
    Double_t cv = (*ip)->GetCosAngle();
    Double_t inv_denom = 1.0/(sv*cu-su*cv);
    // Only the scaled coefficients are needed (cf. Road::Intersect)
    su *= inv_denom; cu *= inv_denom; sv *= inv_denom; cv *= inv_denom;
    // Components of the 3rd projection's axis
    ++ip;
    Double_t xax_x = ((*ip)->GetAxis()).X();
    Double_t xax_y = ((*ip)->GetAxis()).Y();

    // The selected roads from each of the three projections
    Road* tuple[3];
    // Number of roads in u/v projections
    UInt_t nrd[2] = { roads[0].size(), roads[1].size() };
    // Indices of currently selected u/v pair
    UInt_t ird[2];
    WirePlane *front_plane = fPlanes.front(), *back_plane = fPlanes.back();

    // For fast access to the relevant position range, sort the 3rd projection
    // by ascending front position
    sort( ALL(roads[2]), Road::PosIsLess() );
    Road::PosIsNear pos_near( TMath::Sqrt(f3dMatchCut) );

    Double_t matchval = 0.0;
    // Time-critical loop, may run O(1e5) times per event with noisy input
    ird[0] = 0;
    while( ird[0] != nrd[0] ) {
      tuple[0] = roads[0][ird[0]];
      Double_t uf = tuple[0]->GetPos();
      Double_t ub = tuple[0]->GetPos(zback);
      Double_t usf = uf * sv;
      Double_t ucf = uf * cv;
      Double_t usb = ub * sv;
      Double_t ucb = ub * cv;
      ird[1] = 0;
      while( ird[1] != nrd[1] ) {
	tuple[1] = roads[1][ird[1]];
	Double_t v = tuple[1]->GetPos();
	Double_t xf = usf - v * su;
	Double_t yf = v * cu - ucf;
	if( front_plane->Contains(xf,yf) ) {
	  v = tuple[1]->GetPos(zback);
	  Double_t xb = usb - v * su;
	  Double_t yb = v * cu - ucb;
	  if( back_plane->Contains(xb,yb) ) {
	    Double_t pf = xf*xax_x + yf*xax_y; // front x from u/v
	    Double_t pb = xb*xax_x + yb*xax_y; // back x from u/v
	    // Find range of roads in 3rd projection near this front x
	    pair<Rvec_t::iterator,Rvec_t::iterator> range = 
	      equal_range( ALL(roads[2]), pf, pos_near );
	    // Test the candidate x-roads for complete matches
	    for( Rvec_t::iterator it=range.first; it != range.second; ++it ) {
	      tuple[2] = *it;
	      Double_t d1 = tuple[2]->GetPos()      - pf;
	      Double_t d2 = tuple[2]->GetPos(zback) - pb;
	      //TODO; weigh with uncertainties?
	      matchval = d1*d1 + d2*d2;
#ifdef VERBOSE
	      if( fDebug > 3 ) {
		if( matchval < f3dMatchCut || fDebug > 4 ) {
		  cout << tuple[0]->GetProjection()->GetName()
		       << tuple[1]->GetProjection()->GetName()
		       << " front = " << "(" << xf << "," << yf << ")" << endl;
		  cout << "front x  = (" << tuple[2]->GetPos() * xax_x << ","
		       << tuple[2]->GetPos() * xax_y << ")" << endl;
		  cout << "front dist = " << d1 << endl;
		  cout << tuple[0]->GetProjection()->GetName()
		       << tuple[1]->GetProjection()->GetName()
		       << " back = " << "(" << xb << "," << yb << ")" << endl;
		  cout << "back x =  (" 
		       << tuple[2]->GetPos(zback) * xax_x << ","
		       << tuple[2]->GetPos(zback) * xax_y << ")" << endl;
		  cout << "back dist = " << d2 << endl;
		  cout << "matchval = " << matchval*f3dMatchvalScalefact
		       << endl;
		}
	      }
#endif
	      // Check if match, if so then add
	      if( matchval < f3dMatchCut ) {
		++nfound;
		selected.assign( tuple, tuple+3 );
		Add3dMatch( selected, matchval, combos_found, unique_found );
	      }
	    }
	  }
	}
	++ird[1];
      }
      ++ird[0];
    }

  } else {
    // general algorithm:
    //  - find all front and back intersections [ n(n-1)/2 each ] 
    //  - compute weighted center of gravity of intersection points
    //  - sum dist^2 of points to center of gravity -> matchval

    vector<TVector2> fxpts, bxpts;
    fxpts.reserve( nproj*(nproj-1)/2 );
    bxpts.reserve( nproj*(nproj-1)/2 );

    for( UInt_t i = 0; i < ncombos; ++i ) {
      Double_t matchval = 0.0;

      NthCombination( i, roads, selected );
      assert( selected.size() == nproj );

      fxpts.clear();
      bxpts.clear();
      TVector2 fctr, bctr;
      for( Rvec_t::iterator it1 = selected.begin();
	   it1 != selected.end(); ++it1 ) {
	for( Rvec_t::iterator it2 = it1+1; it2 != selected.end(); ++it2 ) {
	  //TODO: weigh with uncertainties of coordinates?
	  fxpts.push_back( (*it1)->Intersect(*it2, 0.0) );
	  bxpts.push_back( (*it1)->Intersect(*it2, zback) );
	  fctr += fxpts.back();
	  bctr += bxpts.back();
#ifdef VERBOSE
	  if( fDebug > 3 ) {
	    cout << (*it1)->GetProjection()->GetName()
		 << (*it2)->GetProjection()->GetName()
		 << " front(" << fxpts.size() << ") = ";
	    fxpts.back().Print();
	    cout << (*it1)->GetProjection()->GetName()
		 << (*it2)->GetProjection()->GetName()
		 << " back (" << bxpts.size() << ") = ";
	    bxpts.back().Print();
	  }
#endif
	}
      }
      assert( fxpts.size() <= nproj*(nproj-1)/2 );
      assert( bxpts.size() == fxpts.size() );
      fctr /= static_cast<Double_t>( fxpts.size() );
      if( !fPlanes.front()->Contains(fctr) )
	continue;
      bctr /= static_cast<Double_t>( fxpts.size() );
      if( !fPlanes.back()->Contains(bctr) )
	continue;
      for( vector<TVector2>::size_type k = 0; k < fxpts.size(); ++k ) {
	matchval += (fxpts[k]-fctr).Mod2() + (bxpts[k]-bctr).Mod2();
      }
#ifdef VERBOSE
      if( fDebug > 3 ) {
	cout << "fctr = "; fctr.Print();
	cout << "bctr = "; bctr.Print();
	cout << "matchval = " << matchval << endl;
      }
#endif
      // We could just connect fctr and bctr here to get an approximate
      // 3D track. But the linear minimization below is the right way
      // to do this.

      if( matchval < f3dMatchCut ) {
	++nfound;
	Add3dMatch( selected, matchval, combos_found, unique_found );
      }
    } //for(ncombos)

  } //if(fast_3d) else

#ifdef VERBOSE
  if( fDebug > 0 ) {
    cout << nfound << " match";
    if( nfound != 1 )
      cout << "es";
    cout << " found" << endl;
  }
#endif
  return nfound;
}

//_____________________________________________________________________________
inline
Bool_t MWDC::PassTrackCuts( const FitRes_t& fit_par ) const
{
  // Test results of 3D track fit (in fit_par) against hard cuts from
  // database

  if( fit_par.ndof < fMinNdof )
    return false;

  pdbl_t chi2_interval = GetChisqLimits(fit_par.ndof);
  if( fit_par.chi2 < chi2_interval.first or
      fit_par.chi2 > chi2_interval.second )
    return false;

  return true;
}

//_____________________________________________________________________________
static void DoTrack( void* ptr )
{
  TrackThread* arg = reinterpret_cast<TrackThread*>(ptr);

  //  TThread::SetCancelOn();
  bool terminate = false;
  arg->start_m->Lock();
  while( !terminate ) {

    // Wait for start condition
    while( true ) {
      Int_t ret = arg->start->Wait();
      if( ret == 0 and TESTBIT(*arg->running, arg->proj->GetType()) )
	break;
    }
    terminate = TESTBIT(*arg->running, 31);
    arg->start_m->UnLock();

    Int_t nrd = 0;
    if( !terminate )
      // Process this event
      nrd = arg->proj->Track();

    // Set error flag, if necessary, and decrement run counter
    arg->done_m->Lock();
    if( nrd < 0 ) {
      *arg->status = 1;
    }
    // Clear the bit for this projection in the status bitfield
    assert( TESTBIT(*arg->running, arg->proj->GetType()) );
    CLRBIT( *arg->running, arg->proj->GetType() );
    // If all bits are zero, all threads have finished processing
    if( (*arg->running & ~BIT(31)) == 0 )
      arg->done->Signal();

    if( !terminate )
      // Ensure that we enter Wait() before the main thread can send the
      // next Broadcast()
      arg->start_m->Lock();  

    arg->done_m->UnLock();
  }
}

//_____________________________________________________________________________
Int_t MWDC::CoarseTrack( TClonesArray& tracks )
{
  // Find tracks from the hitpatterns, using the coarse hit drift times
  // uncorrected for track slope, timing offset, fringe field effects etc.

  //  static const char* const here = "CoarseTrack";

  if( fFailNhits )
    return -1;

  if( !TestBit(kDoCoarse) )
    return 0;

#ifdef TESTCODE
  TStopwatch timer, timer_tot;
#endif

  Int_t err = 0;

  bool do_thread = (fMaxThreads > 1);
  if( do_thread ) {
    // Wake the tracking threads
    fThreads->fTrackDoneM->Lock();
    fThreads->fTrackStatus = 0;
    Int_t all_todo = (BIT(kTypeEnd)-1) & ~(BIT(kTypeBegin)-1);
    Int_t max_todo = BIT(fMaxThreads)-1;
    Int_t start = kTypeBegin;
    while( start < kTypeEnd ) {
      Int_t now_todo = (max_todo << start) & all_todo;
      fThreads->fTrackStartM->Lock();
      fThreads->fTrackToDo = now_todo;
      fThreads->fTrackStart->Broadcast();
      fThreads->fTrackStartM->UnLock();
      // Wait for end of processing
      while( true ) {
	Int_t ret = fThreads->fTrackDone->Wait();
	if( ret == 0 and fThreads->fTrackToDo == 0 )
	  break;
      }
      start += fMaxThreads;
    }
    // Retrieve status
    err = fThreads->fTrackStatus;
    fThreads->fTrackDoneM->UnLock();
  } else {
    // Single-threaded execution: Track() each projection in turn
    for( Prvec_t::iterator it = fProj.begin(); it != fProj.end(); ++it ) {
      Int_t ret = (*it)->Track();
      if( ret < 0 )
	err = 1;
    }
  }

  // Abort on error (e.g. too many patterns)
  if( err != 0 ) {
    fFailNpat = 1;
    return -1;
  }
  // Copy pointers to roads from each projection into local 2D vector
  // (projections, roads).
  // NB: subsequent code assumes that the first index runs in order
  // of ascending projection type, so this can't easily be done in the 
  // tracking threads.
  vector<Rvec_t>::size_type nproj = 0;
  vector<Rvec_t> roads;
  roads.reserve( kTypeEnd-kTypeBegin );
  UInt_t found_types = 0;
  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    Projection* proj = fProj[type];

    Int_t nrd = proj->GetNgoodRoads();
    if( nrd > 0 ) {
      // Count number of projections with at least one road
      ++nproj;
      found_types |= 1U << type;
      // Add pointers to the good roads to the appropriate vector
      roads.push_back( Rvec_t() );
      roads.back().reserve(nrd);
      for( UInt_t i = 0; i < proj->GetNroads(); ++i ) {
	Road* rd = proj->GetRoad(i);
	assert(rd);
	if( rd->IsGood() )
	  roads.back().push_back(rd);
      }
    }
  }
  assert( roads.size() == nproj );
#ifdef TESTCODE
  t_track = 1e6*timer.RealTime();
  timer.Start();
#endif

  // Combine track projections to 3D tracks
  // The standard method requires at least 3 projections. This helps reject
  // noise and, if there is more than one u or v road, correlates u and v
  if( nproj >= 3 ) {
    // Vector holding the results (vectors of roads with good matchval)
    list< pair<Double_t,Rvec_t> > road_combos;
    // Set of the unique roads occurring in the road_combos elements
    Rset_t unique_found;

    // Find matching combinations of roads
    UInt_t nfits = MatchRoads( roads, road_combos, unique_found );

#ifdef TESTCODE
    t_3dmatch = 1e6*timer.RealTime();
    timer.Start();
#endif
    // Fit each set of matched roads using linear least squares, yielding 
    // the 3D track parameters, x, x'(=mx), y, y'(=my)
    FitRes_t fit_par;
    fit_par.coef.reserve(4);
    if( nfits == 1 ) {
      // If there is only one combo (typical case), life is simple:
      fit_par.matchval    = road_combos.front().first;
      Rvec_t& these_roads = road_combos.front().second;
      fit_par.roads       = &these_roads;
      fit_par.ndof = FitTrack( these_roads, fit_par.coef, fit_par.chi2 );
      if( fit_par.ndof > 0 ) {
	if( PassTrackCuts(fit_par) )
	  NewTrack( tracks, fit_par );
      }
      else
	FitErrPrint( fit_par.ndof );
    }
    else if( nfits > 0 ) {
      // For multiple road combinations, find the set of tracks with the
      // lowest chi2s that uses each road at most once
      roads.clear();
      typedef map<Rset_t, FitRes_t> FitResMap_t;
      FitResMap_t fit_results;
      multimap< TrackFitWeight, Rset_t > fit_chi2;
      // Fit all combinations and sort the results by ascending chi2
      for( list< pair<Double_t,Rvec_t> >::iterator it = road_combos.begin();
	   it != road_combos.end(); ++it ) {
	fit_par.matchval    = (*it).first;
	Rvec_t& these_roads = (*it).second;
	fit_par.roads       = &these_roads;
	fit_par.ndof = FitTrack( these_roads, fit_par.coef, fit_par.chi2 );
	if( fit_par.ndof > 0 ) {
	  if( PassTrackCuts(fit_par) ) {
	    Rset_t road_tuple( ALL(these_roads) );
	    pair<FitResMap_t::iterator,bool> ins =
	      fit_results.insert( make_pair(road_tuple, fit_par) );
	    assert( ins.second );
	    fit_chi2.insert( make_pair( TrackFitWeight(fit_par), road_tuple) );
	  }
	} else
	  FitErrPrint( fit_par.ndof );
      }

#ifdef VERBOSE
      if( fDebug > 2 ) {
	cout << "Track candidates:" << endl;
	for( multimap<TrackFitWeight,Rset_t>::iterator it = fit_chi2.begin();
	     it != fit_chi2.end(); ++it ) {
	  FitResMap_t::iterator found = fit_results.find((*it).second);
	  FitRes_t& r = (*found).second;
	  cout 	 << "ndof = " << r.ndof
		 << " rchi2 = " << r.chi2/(double)r.ndof
		 << " x/y = " << r.coef[0] << "/" << r.coef[2]
		 << " mx/my = " << r.coef[1] << "/" << r.coef[3]
		 << endl;
	}
      }
#endif
      // Select "optimal" set of roads, minimizing sum of chi2s
      vector<Rset_t> best_roads;
      OptimalN( unique_found, fit_chi2, best_roads, 
		AnySharedHits(), CheckTypes(found_types) );

      // Now each selected road tuple corresponds to a new track
      for( vector<Rset_t>::iterator it = best_roads.begin(); it !=
	     best_roads.end(); ++it ) {
	// Retrieve the fit results for this tuple
	FitResMap_t::iterator found = fit_results.find(*it);
	assert( found != fit_results.end() );
	NewTrack( tracks, (*found).second );
      }
    } //if(nfits)
#ifdef TESTCODE
    fN3dFits = nfits;
    t_3dfit = 1e6*timer.RealTime();
#endif
#ifdef VERBOSE
    if( fDebug > 0 ) {
      Int_t ntr = tracks.GetLast()+1;
      cout << ntr << " track";
      if( ntr != 1 ) cout << "s";
      if( nfits > 1 ) cout << " after chi2 optimization";
      if( fDebug > 1 and ntr > 0 ) {
	cout << ":" << endl;
	for( Int_t i = 0; i < ntr; ++i ) {
	  THaTrack* tr = (THaTrack*)tracks.UncheckedAt(i);
	  cout << "3D track:  x/y = " << tr->GetX() << "/" << tr->GetY() 
	       << " mx/my = " << tr->GetTheta() << "/" << tr->GetPhi()
	       << " ndof = "  << tr->GetNDoF()
	       << " rchi2 = " << tr->GetChi2()/(double)tr->GetNDoF()
	       << endl;
	}
      } else
	cout << endl;
    }
#endif
  }
  else if( nproj == 2 ) {
    // TODO: optional recovery code for missing projection

  } //if(nproj>=3)

#ifdef TESTCODE
    t_coarse = 1e6*timer_tot.RealTime();
#endif
  // Quit here to let detectors CoarseProcess() the approximate tracks,
  // so that they can determine the corrections that we need when we
  // continue in FineTrack
  return 0;
}

//_____________________________________________________________________________
Int_t MWDC::FineTrack( TClonesArray& tracks )
{
  // Second-level tracking, applying fine corrections.
  //
  // - Correct the hit drift distances using timing, track slope,
  //   track momentum, magnet fringe field, etc., as applicable.
  // - Re-collect hits of roads and re-fit roads
  // - Re-combine track projections in 3D and re-fit 3D track

  if( !TestBit(kDoFine) )
    return 0;

  // TODO

  return 0;;
}

//_____________________________________________________________________________
Int_t MWDC::DefineVariables( EMode mode )
{
  // Initialize global variables

  if( mode == kDefine and fIsSetup ) return kOK;
  fIsSetup = ( mode == kDefine );

  // Register variables in global list
  
  RVarDef vars[] = {
    { "fail.nhits", "Too many hits in wire plane(s)",  "fFailNhits" },
    { "fail.npat",  "Too many treesearch patterns",    "fFailNpat" },
#ifdef TESTCODE
    { "ncombos",    "Number of road combinations",     "fNcombos" },
    { "nfits",      "Number of 3D track fits done",    "fN3dFits" },
    { "t_track",    "Time in 1st stage tracking (us)", "t_track" },
    { "t_3dmatch",  "Time in MatchRoads (us)",         "t_3dmatch" },
    { "t_3dfit",    "Time fitting/selecting 3D tracks (us)", "t_3dfit" },
    { "t_coarse",   "Total time in CoarseTrack (us)",  "t_coarse" },
#endif
    { 0 }
  };
  DefineVarsFromList( vars, mode );
  return 0;
}

//_____________________________________________________________________________
THaAnalysisObject::EStatus MWDC::Init( const TDatime& date )
{
  // Initialize MWDC. Calls standard Init(), then initializes subdetectors.

  static const char* const here = "Init";

  fRefMap->Reset();
  fRefTime.clear();

  // The "cratemap" is only needed during Init of MWDC and WirePlane
  fCrateMap = new THashTable(100);
  fCrateMap->SetOwner();

  // Initialize ourselves. This calls our ReadDatabase() and DefineVariables()
  EStatus status = THaTrackingDetector::Init(date);

  // Initialize the wire planes
  if( !status ) {
    for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
      status = fPlanes[iplane]->Init(date);
      if( status )
	break;
    }
  }
  delete fCrateMap; fCrateMap = 0;
  if( status )
    return fStatus = status;

  // Automatically create a separate detector map for the reference channels
  // used by the data channels. By construction, each "module" in this map
  // has exactly one channel.
  // This map is decoded in our Decode() for efficiency.
  for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
    THaDetMap* planeMap = fPlanes[iplane]->GetDetMap();
    for( Int_t imod = 0; imod < planeMap->GetSize(); ++imod ) {
      THaDetMap::Module* d = planeMap->GetModule(imod);
      if( d->refchan < 0 ) continue;
      THaDetMap::Module* refmod = fRefMap->Find( d->crate, d->slot,
						 d->refchan );
      // To allow the data channels to look up their reference channel data
      // quickly, we save the index into the refmap in d->refindex.
      if( refmod ) {
	d->refindex = refmod->first;
      }	else {
	d->refindex = fRefMap->GetSize();
	fRefMap->AddModule( d->crate, d->slot, d->refchan, 
			    d->refchan, d->refindex, d->model );
	refmod = fRefMap->GetModule(d->refindex);
	if( !refmod ) {
	  Error( Here(here), "Error when adding reference channel cr/sl/ch="
		 "%u/%u/%u. Call expert.", d->crate, d->slot, d->refchan );
	  return fStatus = kInitError;
	}
	// The reference channel module's model and resolution have already
	// been determined when the plane's detector map was filled. Also,
	// refindex was checked to be a vaid channel number for this model.
	refmod->SetResolution( d->resolution );
	refmod->MakeTDC();
      }
    }
  }
  // Check if any reference channels are also defined as data channels
  for( Int_t imod = 0; imod < fRefMap->GetSize(); ++imod ) {
    THaDetMap::Module* r = fRefMap->GetModule(imod);
    for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
      THaDetMap* planeMap = fPlanes[iplane]->GetDetMap();
      if( planeMap->Find( r->crate, r->slot, r->lo ) ) {
	Error( Here(here), "Reference channel cr/sl/ch=%u/%u/%u also defined "
	       "as data channel in plane \"%s\". Fix database.", 
	       r->crate, r->slot, r->lo, fPlanes[iplane]->GetName() );
	return fStatus = kInitError;
      }
    }
  }
  // Reference map set up correctly and without conflicts
  fRefTime.assign( fRefMap->GetSize(), kBig );

  // Sort planes by increasing z-position
  sort( ALL(fPlanes), WirePlane::ZIsLess() );

  // Associate planes and partners (names identical except trailing "p")
  if( !TestBit(kNoPartner) ) {
    for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
      WirePlane* thePlane = fPlanes[iplane];
      TString name( thePlane->GetName() );
      if( name.EndsWith("p") ) {
	TString other = name.Chop();
	if( other.IsNull() )
	  continue;
	vwiter_t it = find_if( ALL(fPlanes),WirePlane::NameEquals( other ) );
	if( it != fPlanes.end() ) {
	  WirePlane* partner = *it;
	  // Partner planes must be of the same type!
	  if( thePlane->GetType() != partner->GetType() ) {
	    Error( Here(here), "Partner planes %s and %s have different types!"
		   " Fix database.", thePlane->GetName(), partner->GetName() );
	    return fStatus = kInitError;
	  }
	  if( fDebug > 0 )
	    Info( Here(here), "Partnering plane %s with %s",
		  thePlane->GetName(), partner->GetName() );
	  partner->SetPartner( thePlane );
	}
      }
    }
  }

  // Initialize the projections. This will read the database and set
  // the projections' angle and maxslope, which we need in the following
  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    status = fProj[type]->Init(date);
    if( status )
      return fStatus = status;
  }

  // Sanity checks of U and V angles which the projections just read via Init
  Double_t u_angle = fProj[kUPlane]->GetAngle()*TMath::RadToDeg();
  Double_t v_angle = fProj[kVPlane]->GetAngle()*TMath::RadToDeg();
  Int_t qu = TMath::FloorNint( u_angle/90.0 );
  Int_t qv = TMath::FloorNint( v_angle/90.0 );
  if( (qu&1) == (qv&1) ) {
    Error( Here(here), "Plane misconfiguration: uangle (%6.2lf) and vangle "
	   "(%6.2lf) are in equivalent quadrants. Fix database.",
	   u_angle, v_angle );
    return fStatus = kInitError;
  }
  Double_t du = u_angle - 90.0*qu;
  Double_t dv = v_angle - 90.0*qv;
  if( TMath::Abs(TMath::Abs(du)-45.0) > 44.0 or
      TMath::Abs(TMath::Abs(dv)-45.0) > 44.0 ) {
    Error( Here(here), "uangle (%6.2lf) or vangle (%6.2lf) too close "
	   "to 0 or 90 degrees. Fix database.", u_angle, v_angle );
    return fStatus = kInitError;
  }

  // Check if we can use the simplified 3D matching algorithm
  ResetBit(k3dFastMatch);
  if( fProj.size() == 3 ) {
    // This assumes that the first two planes are the rotated ones
    assert( kUPlane < 2 && kVPlane < 2 );
    // The abs(angle) of the two rotated planes should be (nearly) the same
    Double_t uang =
      TMath::Abs( TVector2::Phi_mpi_pi(fProj[kUPlane]->GetAngle()) );
    if( (TMath::Abs( TVector2::Phi_mpi_pi(fProj[kVPlane]->GetAngle()) )-uang )
	<  0.5*TMath::DegToRad() ) {
      SetBit(k3dFastMatch);
      Double_t tan = TMath::Tan( 0.5*TMath::Pi()-uang );
      // The scale factor converts the fast_3d matchvalue to the one computed
      // by the general algorithm
      f3dMatchvalScalefact = 2.0 * (1.0/3.0 + tan*tan );
      // Avoid scaling for every event
      f3dMatchCut /= f3dMatchvalScalefact;
    }
  }

  // Determine the width of and add the wire planes to the projections
  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    Projection* theProj = fProj[type];
    Double_t width = 0.0;
    // Associate planes with plane types
    for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
      WirePlane* thePlane = fPlanes[iplane];
      if( thePlane->GetType() == type ) {
	// Add planes not yet used to the corresponding projection
	if( !thePlane->GetProjection() ) {
	  WirePlane* partner = thePlane->GetPartner();
	  assert( !partner or partner->GetProjection() == 0 );
	  // AddPlane() sets the plane number, fProjection and fCoordOffset
	  // in the WirePlane objects
	  theProj->AddPlane( thePlane, partner );
	}
	// Determine the "width" of this projection plane (=width along the
	// projection coordinate).
	// The idea is that all possible hit positions in all planes of a 
	// given projection must fall within the range [-W/2,W/2]. It is normal
	// that some planes cover less than this width (e.g. because they are 
	// smaller or offset) - it is meant to be the enclosing range for all
	// planes. In this way, the tree search can use one fixed bin width.
	// The total width found here divided by the number of bins used in
	// tree search is the resolution of the roads.
	// Of course, this will become inefficient for grotesque geometries.
	Double_t s = thePlane->GetWireStart();
	Double_t d = thePlane->GetWireSpacing();
	Double_t n = static_cast<Double_t>( thePlane->GetNelem() );
	Double_t lo = s - 0.5*d;
	Double_t hi = s + (n-0.5)*d;
	Double_t w = max( TMath::Abs(hi), TMath::Abs(lo) );
	if( w > width )
	  width = w;
      }
    }
    UInt_t n = theProj->GetNplanes();
    // Require at least 3 planes per projection
    if( n < 3 ) {
      Error( Here(here), "Too few planes of type \"%s\" defined. "
	     "Need >= 3, have %u. Fix database.", theProj->GetName(), n );
      return fStatus = kInitError;
    }
    // Set width of this projection
    width *= 2.0;
    if( width > 0.01 )
      theProj->SetWidth( width );
    else {
      Error( Here(here), "Error calculating width of projection \"%s\". "
	     "Wire spacing too small? Fix database.", theProj->GetName() );
      return fStatus = kInitError;
    }
    // maxslope is the maximum expected track slope in the projection.
    // width/depth is the maximum geometrically possible slope. It may be
    // further limited by the trigger acceptance, optics, etc.
    Double_t dz = TMath::Abs(theProj->GetZsize());
    if( dz > 0.01 ) {
      Double_t maxslope = width/dz;
      if( theProj->GetMaxSlope() < 0.01 ) {  // Consider unset
	theProj->SetMaxSlope( maxslope );
      } else if( theProj->GetMaxSlope() > maxslope ) {
	if( fDebug > 0 ) {
	  Warning( Here(here), "For projection \"%s\", maxslope from "
		   "database = %lf exceeds geometric maximum = %lf. "
		   "Using smaller value.",
		   theProj->GetName(), theProj->GetMaxSlope(), maxslope );
	}
	theProj->SetMaxSlope( maxslope );
      }
    } else {
      Error( Here(here), "Error calculating geometric maxslope for plane "
	     "type \"%s\". z-range of planes too small. Fix database.",
	     theProj->GetName() );
	return fStatus = kInitError;
    }

    // Now that the projection's list of planes, width, and maxslope is know,
    // do the level-2 initialization of the projections - load the pattern
    // database and initialize the hitpattern
    status = fProj[type]->InitLevel2(date);
    if( status )
      return fStatus = status;

  }

  // If threading requested, load thread library and start up threads
  if( fMaxThreads > 1 ) {
    gSystem->Load("libThread");
    //FIXME: check for successful load, warn and degrade if not
    delete fThreads;
    fThreads = new ThreadCtrl;
    fThreads->fTrack.reserve( fProj.size() );
    fThreads->fTrackStartM->Lock();
    for( vpsiz_t k = 0; k < fProj.size(); ++k ) {
      TThread* t = fThreads->AddTrackThread( fProj[k] );
      t->Run();
    }
    fThreads->fTrackStartM->UnLock();
  }

  return fStatus = kOK;
}

//_____________________________________________________________________________
Int_t MWDC::ReadDatabase( const TDatime& date )
{
  // Read MWDC database

  static const char* const here = "ReadDatabase";

  fIsInit = kFALSE;
  for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane ) {
    delete fPlanes[iplane];
  }
  // Delete existing configuration (in case we are re-initializing)
  fPlanes.clear();
  fCalibPlanes.clear();

  FILE* file = OpenFile( date );
  if( !file ) return kFileError;

  // Read fOrigin (detector position) and fSize. fOrigin is the position of
  // the MWDC detector relative to some superior coordinate system
  // (typically the spectrometer detector stack reference frame). 
  // fOrigin will be added to all tracks generated; if fOrigin.Z() is not
  // zero, tracks will be projected into the z=0 plane.
  Int_t err = ReadGeometry( file, date );
  if( err )
    return err;

  // Putting this container on the stack may cause strange stack overflows!
  vector<vector<Int_t> > *cmap = new vector<vector<Int_t> >;

  string planeconfig, calibconfig;
  Int_t time_cut = 1, pairs_only = 0, mc_data = 0, nopartner = 0;
  f3dMatchCut = 1e-4;
  Int_t event_display = 0, disable_tracking = 0, disable_finetrack = 0;
  Int_t maxmiss = -1, maxthreads = -1;
  Double_t conf_level = 1e-9;
  DBRequest request[] = {
    { "planeconfig",       &planeconfig,       kString },
    { "cratemap",          cmap,               kIntM,   6 },
    { "timecut",           &time_cut,          kInt,    0, 1 },
    { "pairsonly",         &pairs_only,        kInt,    0, 1 },
    { "MCdata",            &mc_data,           kInt,    0, 1 },
    { "nopartner",         &nopartner,         kInt,    0, 1 },
    { "3d_matchcut",       &f3dMatchCut,       kDouble, 0, 1 },
    { "event_display",     &event_display,     kInt,    0, 1 },
    { "disable_tracking",  &disable_tracking,  kInt,    0, 1 },
    { "disable_finetrack", &disable_finetrack, kInt,    0, 1 },
    { "calibrate",         &calibconfig,       kString, 0, 1 },
    { "3d_maxmiss",        &maxmiss,           kInt,    0, 1 },
    { "3d_chi2_conflevel", &conf_level,        kDouble, 0, 1 },
    { "maxthreads",        &maxthreads,        kInt,    0, 1 },
    { 0 }
  };

  Int_t status = kInitError;
  err = LoadDB( file, date, request, fPrefix );
  fclose(file);

  if( !err ) {
    if( cmap->empty() ) {
      Error(Here(here), "No cratemap defined. Set \"cratemap\" in database.");
    } else {
      // Build the list of crate map elements
      for( vviter_t it = cmap->begin(); it != cmap->end(); ++it ) {
	vector<int>& row = *it;
	for( Int_t slot = row[1]; slot <= row[2]; ++slot ) {
	  DAQmodule* m =
	    new DAQmodule( row[0], slot, row[3], row[4]*1e-12, row[5] );
	  DAQmodule* found = static_cast<DAQmodule*>(fCrateMap->FindObject(m));
	  if( found ) { 
	    m->Copy(*found);  // Later entries override earlier ones
	    delete m;
	  }
	  else
	    fCrateMap->Add(m);
	}
      }
      status = kOK;
    }
  }
  delete cmap; cmap = 0;
  if( status != kOK )
    return status;

  // Set analysis control flags
  SetBit( kDoTimeCut,     time_cut );
  SetBit( kPairsOnly,     pairs_only );
  SetBit( kMCdata,        mc_data );
  SetBit( kNoPartner,     nopartner );
  SetBit( kEventDisplay,  event_display );
  SetBit( kDoCoarse,      !disable_tracking );
  SetBit( kDoFine,        !(disable_tracking or disable_finetrack) );

  vector<string> planes = vsplit(planeconfig);
  if( planes.empty() ) {
    Error( Here(here), "No planes defined. Set \"planeconfig\" in database." );
    return kInitError;
  }
  vector<string> calibplanes = vsplit(calibconfig);

  // Set up the wire planes
  for( ssiz_t i=0; i<planes.size(); ++i ) {
    assert( !planes[i].empty() );
    const char* name = planes[i].c_str();
    vwiter_t it = find_if( ALL(fPlanes), WirePlane::NameEquals( name ) );
    if( it != fPlanes.end() ) {
      Error( Here(here), "Duplicate plane name: %s. Fix database.", name );
      return kInitError;
    }
    WirePlane* newplane = new WirePlane( name, name, this );
    if( !newplane or newplane->IsZombie() ) {
      // Urgh. Something is very bad
      Error( Here(here), "Error creating wire plane %s. Call expert.", name );
      return kInitError;
    }
    fPlanes.push_back( newplane );
    newplane->SetDebug( fDebug );

    // Set calibration mode if requested for any planes
    if( !calibplanes.empty() ) {
      vector<string>::iterator its =
	find_if( ALL(calibplanes), bind2nd(equal_to<string>(), planes[i]) );
      if( its != calibplanes.end() ) {
	Info( Here(here), "Plane %s in calibration mode", name );
	newplane->EnableCalibration();
	fCalibPlanes.push_back( newplane );
	calibplanes.erase( its );
      }
    }
  }

  // Warn if any requested calibration plane(s) do not exist
  if( !calibplanes.empty() ) {
    string s("plane");
    if( calibplanes.size() > 1 )
      s.append("s");
    for( vector<string>::size_type i = 0; i < calibplanes.size(); ++i ) {
      s.append(" ");
      s.append(calibplanes[i]);
    }
    Warning( Here(here), "Requested calibration for undefined %s. "
	     "Typo in database?", s.c_str() );
  }

  UInt_t nplanes = fPlanes.size();
  if( fDebug > 0 )
    Info( Here(here), "Loaded %u planes", nplanes );

  // Convert maximum number of missing hits to ndof of fits
  if( maxmiss >= 0 )
    fMinNdof = nplanes - 4 - maxmiss;
  else
    fMinNdof = 1;

  // Determine Chi2 confidence interval limits for the selected CL and the
  // possible degrees of freedom of the 3D track fit
  if( conf_level < 0.0 or conf_level > 1.0 ) {
    Error( Here(here), "Illegal fit confidence level = %lf. "
	   "Must be 0-1. Fix database.", conf_level );
    return kInitError;
  }
  fChisqLimits.clear();
  fChisqLimits.resize( nplanes-3, make_pair<Double_t,Double_t>(0,0) );
  for( vec_pdbl_t::size_type dof = fMinNdof; dof < fChisqLimits.size();
       ++dof ) {
    fChisqLimits[dof].first  = TMath::ChisquareQuantile( conf_level, dof );
    fChisqLimits[dof].second = TMath::ChisquareQuantile( 1.0-conf_level, dof );
  }

  // If maxthreads set, use it
  if( maxthreads > 0 ) {
    fMaxThreads = max(maxthreads,1);
    if( fMaxThreads > 20 ) { // Sanity limit
      fMaxThreads = 20;
      Warning( Here(here), "Excessive value of maxthreads = %d, "
	       "limited to %u", maxthreads, fMaxThreads );
    }
  } else {
    // If maxthreads not given, automatically use the number of cpus reported
    SysInfo_t sysifo;
    gSystem->GetSysInfo( &sysifo );
    if( sysifo.fCpus > 0 )
      fMaxThreads = sysifo.fCpus;
    else
      fMaxThreads = 1;
  }
  
  fIsInit = kTRUE;
  return kOK;
}

//_____________________________________________________________________________
void MWDC::Print(const Option_t* opt) const
{
  THaTrackingDetector::Print(opt);

  Int_t verbose = 0;
  if( opt ) {
    TString opt_s(opt);
    opt_s.ToLower();
    verbose = opt_s.CountChar('v');
  }

  for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane )
    fPlanes[iplane]->Print(opt);

  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
    if( type == kTypeBegin or verbose > 0 )
      cout << endl;
    fProj[type]->Print(opt);
  }

}


//_____________________________________________________________________________
void MWDC::SetDebug( Int_t level )
{
  // Set debug level of this detector, including all wire planes (subdetectors)
  // and projections

  THaTrackingDetector::SetDebug( level );

  for( vwsiz_t iplane = 0; iplane < fPlanes.size(); ++iplane )
    fPlanes[iplane]->SetDebug( level );

  for( EProjType type = kTypeBegin; type < kTypeEnd; ++type )
    fProj[type]->SetDebug( level );
}

//_____________________________________________________________________________
void MWDC::EnableEventDisplay( Bool_t b )
{
  // Enable event display support. Can only be called before initialization.

  if( !fIsInit ) {
    Error( Here("EnableEventDisplay"), "Cannot enable/disable event display "
	   "support after initialization." );
    return;
  }

  SetBit( kEventDisplay, b );
}

//_____________________________________________________________________________
EProjType MWDC::NameToType( const char* name )
{
  // Return the index corresponding to the given plane name.
  // The comparison is not case-sensitive.

  if( name and *name ) {
    TString s(name);
    s.ToLower();
    for( EProjType type = kTypeBegin; type < kTypeEnd; ++type ) {
      if( !fProj[type] )
	continue;
      TString ps( fProj[type]->GetName() );
      ps.ToLower();
      if( s == ps )
	return type;
    }
  }
  return kUndefinedType;
}


//_____________________________________________________________________________
inline
static DAQmodule* FindDAQmodule( UShort_t crate, UShort_t slot, 
				 const THashTable* table )
{
  if( !table ) return 0;
  CSpair m( crate, slot );
  return static_cast<DAQmodule*>( table->FindObject(&m) );
}

//_____________________________________________________________________________
UInt_t MWDC::LoadDAQmodel( THaDetMap::Module* mod ) const
{
  // Update detector map module 'mod' with the model number from the cratemap
  DAQmodule* found = FindDAQmodule( mod->crate, mod->slot, fCrateMap );
  UInt_t num = found ? found->fModel : 0;
  mod->SetModel( num );
  return num;
}

//_____________________________________________________________________________
Double_t MWDC::LoadDAQresolution( THaDetMap::Module* mod ) const
{
  // Update detector map module 'mod' with the resolution from the cratemap
  DAQmodule* found = FindDAQmodule( mod->crate, mod->slot, fCrateMap );
  Double_t res = found ? found->fResolution : 0.0;
  mod->SetResolution( res );
  return res;
}

//_____________________________________________________________________________
UInt_t MWDC::GetDAQnchan( THaDetMap::Module* mod ) const
{
  // Return number of channels for detector map module 'mod' from cratemap
  DAQmodule* found = FindDAQmodule( mod->crate, mod->slot, fCrateMap );
  return found ? found->fNchan : 0;
}

///////////////////////////////////////////////////////////////////////////////

} // end namespace TreeSearch

ClassImp(TreeSearch::MWDC)

 MWDC.cxx:1
 MWDC.cxx:2
 MWDC.cxx:3
 MWDC.cxx:4
 MWDC.cxx:5
 MWDC.cxx:6
 MWDC.cxx:7
 MWDC.cxx:8
 MWDC.cxx:9
 MWDC.cxx:10
 MWDC.cxx:11
 MWDC.cxx:12
 MWDC.cxx:13
 MWDC.cxx:14
 MWDC.cxx:15
 MWDC.cxx:16
 MWDC.cxx:17
 MWDC.cxx:18
 MWDC.cxx:19
 MWDC.cxx:20
 MWDC.cxx:21
 MWDC.cxx:22
 MWDC.cxx:23
 MWDC.cxx:24
 MWDC.cxx:25
 MWDC.cxx:26
 MWDC.cxx:27
 MWDC.cxx:28
 MWDC.cxx:29
 MWDC.cxx:30
 MWDC.cxx:31
 MWDC.cxx:32
 MWDC.cxx:33
 MWDC.cxx:34
 MWDC.cxx:35
 MWDC.cxx:36
 MWDC.cxx:37
 MWDC.cxx:38
 MWDC.cxx:39
 MWDC.cxx:40
 MWDC.cxx:41
 MWDC.cxx:42
 MWDC.cxx:43
 MWDC.cxx:44
 MWDC.cxx:45
 MWDC.cxx:46
 MWDC.cxx:47
 MWDC.cxx:48
 MWDC.cxx:49
 MWDC.cxx:50
 MWDC.cxx:51
 MWDC.cxx:52
 MWDC.cxx:53
 MWDC.cxx:54
 MWDC.cxx:55
 MWDC.cxx:56
 MWDC.cxx:57
 MWDC.cxx:58
 MWDC.cxx:59
 MWDC.cxx:60
 MWDC.cxx:61
 MWDC.cxx:62
 MWDC.cxx:63
 MWDC.cxx:64
 MWDC.cxx:65
 MWDC.cxx:66
 MWDC.cxx:67
 MWDC.cxx:68
 MWDC.cxx:69
 MWDC.cxx:70
 MWDC.cxx:71
 MWDC.cxx:72
 MWDC.cxx:73
 MWDC.cxx:74
 MWDC.cxx:75
 MWDC.cxx:76
 MWDC.cxx:77
 MWDC.cxx:78
 MWDC.cxx:79
 MWDC.cxx:80
 MWDC.cxx:81
 MWDC.cxx:82
 MWDC.cxx:83
 MWDC.cxx:84
 MWDC.cxx:85
 MWDC.cxx:86
 MWDC.cxx:87
 MWDC.cxx:88
 MWDC.cxx:89
 MWDC.cxx:90
 MWDC.cxx:91
 MWDC.cxx:92
 MWDC.cxx:93
 MWDC.cxx:94
 MWDC.cxx:95
 MWDC.cxx:96
 MWDC.cxx:97
 MWDC.cxx:98
 MWDC.cxx:99
 MWDC.cxx:100
 MWDC.cxx:101
 MWDC.cxx:102
 MWDC.cxx:103
 MWDC.cxx:104
 MWDC.cxx:105
 MWDC.cxx:106
 MWDC.cxx:107
 MWDC.cxx:108
 MWDC.cxx:109
 MWDC.cxx:110
 MWDC.cxx:111
 MWDC.cxx:112
 MWDC.cxx:113
 MWDC.cxx:114
 MWDC.cxx:115
 MWDC.cxx:116
 MWDC.cxx:117
 MWDC.cxx:118
 MWDC.cxx:119
 MWDC.cxx:120
 MWDC.cxx:121
 MWDC.cxx:122
 MWDC.cxx:123
 MWDC.cxx:124
 MWDC.cxx:125
 MWDC.cxx:126
 MWDC.cxx:127
 MWDC.cxx:128
 MWDC.cxx:129
 MWDC.cxx:130
 MWDC.cxx:131
 MWDC.cxx:132
 MWDC.cxx:133
 MWDC.cxx:134
 MWDC.cxx:135
 MWDC.cxx:136
 MWDC.cxx:137
 MWDC.cxx:138
 MWDC.cxx:139
 MWDC.cxx:140
 MWDC.cxx:141
 MWDC.cxx:142
 MWDC.cxx:143
 MWDC.cxx:144
 MWDC.cxx:145
 MWDC.cxx:146
 MWDC.cxx:147
 MWDC.cxx:148
 MWDC.cxx:149
 MWDC.cxx:150
 MWDC.cxx:151
 MWDC.cxx:152
 MWDC.cxx:153
 MWDC.cxx:154
 MWDC.cxx:155
 MWDC.cxx:156
 MWDC.cxx:157
 MWDC.cxx:158
 MWDC.cxx:159
 MWDC.cxx:160
 MWDC.cxx:161
 MWDC.cxx:162
 MWDC.cxx:163
 MWDC.cxx:164
 MWDC.cxx:165
 MWDC.cxx:166
 MWDC.cxx:167
 MWDC.cxx:168
 MWDC.cxx:169
 MWDC.cxx:170
 MWDC.cxx:171
 MWDC.cxx:172
 MWDC.cxx:173
 MWDC.cxx:174
 MWDC.cxx:175
 MWDC.cxx:176
 MWDC.cxx:177
 MWDC.cxx:178
 MWDC.cxx:179
 MWDC.cxx:180
 MWDC.cxx:181
 MWDC.cxx:182
 MWDC.cxx:183
 MWDC.cxx:184
 MWDC.cxx:185
 MWDC.cxx:186
 MWDC.cxx:187
 MWDC.cxx:188
 MWDC.cxx:189
 MWDC.cxx:190
 MWDC.cxx:191
 MWDC.cxx:192
 MWDC.cxx:193
 MWDC.cxx:194
 MWDC.cxx:195
 MWDC.cxx:196
 MWDC.cxx:197
 MWDC.cxx:198
 MWDC.cxx:199
 MWDC.cxx:200
 MWDC.cxx:201
 MWDC.cxx:202
 MWDC.cxx:203
 MWDC.cxx:204
 MWDC.cxx:205
 MWDC.cxx:206
 MWDC.cxx:207
 MWDC.cxx:208
 MWDC.cxx:209
 MWDC.cxx:210
 MWDC.cxx:211
 MWDC.cxx:212
 MWDC.cxx:213
 MWDC.cxx:214
 MWDC.cxx:215
 MWDC.cxx:216
 MWDC.cxx:217
 MWDC.cxx:218
 MWDC.cxx:219
 MWDC.cxx:220
 MWDC.cxx:221
 MWDC.cxx:222
 MWDC.cxx:223
 MWDC.cxx:224
 MWDC.cxx:225
 MWDC.cxx:226
 MWDC.cxx:227
 MWDC.cxx:228
 MWDC.cxx:229
 MWDC.cxx:230
 MWDC.cxx:231
 MWDC.cxx:232
 MWDC.cxx:233
 MWDC.cxx:234
 MWDC.cxx:235
 MWDC.cxx:236
 MWDC.cxx:237
 MWDC.cxx:238
 MWDC.cxx:239
 MWDC.cxx:240
 MWDC.cxx:241
 MWDC.cxx:242
 MWDC.cxx:243
 MWDC.cxx:244
 MWDC.cxx:245
 MWDC.cxx:246
 MWDC.cxx:247
 MWDC.cxx:248
 MWDC.cxx:249
 MWDC.cxx:250
 MWDC.cxx:251
 MWDC.cxx:252
 MWDC.cxx:253
 MWDC.cxx:254
 MWDC.cxx:255
 MWDC.cxx:256
 MWDC.cxx:257
 MWDC.cxx:258
 MWDC.cxx:259
 MWDC.cxx:260
 MWDC.cxx:261
 MWDC.cxx:262
 MWDC.cxx:263
 MWDC.cxx:264
 MWDC.cxx:265
 MWDC.cxx:266
 MWDC.cxx:267
 MWDC.cxx:268
 MWDC.cxx:269
 MWDC.cxx:270
 MWDC.cxx:271
 MWDC.cxx:272
 MWDC.cxx:273
 MWDC.cxx:274
 MWDC.cxx:275
 MWDC.cxx:276
 MWDC.cxx:277
 MWDC.cxx:278
 MWDC.cxx:279
 MWDC.cxx:280
 MWDC.cxx:281
 MWDC.cxx:282
 MWDC.cxx:283
 MWDC.cxx:284
 MWDC.cxx:285
 MWDC.cxx:286
 MWDC.cxx:287
 MWDC.cxx:288
 MWDC.cxx:289
 MWDC.cxx:290
 MWDC.cxx:291
 MWDC.cxx:292
 MWDC.cxx:293
 MWDC.cxx:294
 MWDC.cxx:295
 MWDC.cxx:296
 MWDC.cxx:297
 MWDC.cxx:298
 MWDC.cxx:299
 MWDC.cxx:300
 MWDC.cxx:301
 MWDC.cxx:302
 MWDC.cxx:303
 MWDC.cxx:304
 MWDC.cxx:305
 MWDC.cxx:306
 MWDC.cxx:307
 MWDC.cxx:308
 MWDC.cxx:309
 MWDC.cxx:310
 MWDC.cxx:311
 MWDC.cxx:312
 MWDC.cxx:313
 MWDC.cxx:314
 MWDC.cxx:315
 MWDC.cxx:316
 MWDC.cxx:317
 MWDC.cxx:318
 MWDC.cxx:319
 MWDC.cxx:320
 MWDC.cxx:321
 MWDC.cxx:322
 MWDC.cxx:323
 MWDC.cxx:324
 MWDC.cxx:325
 MWDC.cxx:326
 MWDC.cxx:327
 MWDC.cxx:328
 MWDC.cxx:329
 MWDC.cxx:330
 MWDC.cxx:331
 MWDC.cxx:332
 MWDC.cxx:333
 MWDC.cxx:334
 MWDC.cxx:335
 MWDC.cxx:336
 MWDC.cxx:337
 MWDC.cxx:338
 MWDC.cxx:339
 MWDC.cxx:340
 MWDC.cxx:341
 MWDC.cxx:342
 MWDC.cxx:343
 MWDC.cxx:344
 MWDC.cxx:345
 MWDC.cxx:346
 MWDC.cxx:347
 MWDC.cxx:348
 MWDC.cxx:349
 MWDC.cxx:350
 MWDC.cxx:351
 MWDC.cxx:352
 MWDC.cxx:353
 MWDC.cxx:354
 MWDC.cxx:355
 MWDC.cxx:356
 MWDC.cxx:357
 MWDC.cxx:358
 MWDC.cxx:359
 MWDC.cxx:360
 MWDC.cxx:361
 MWDC.cxx:362
 MWDC.cxx:363
 MWDC.cxx:364
 MWDC.cxx:365
 MWDC.cxx:366
 MWDC.cxx:367
 MWDC.cxx:368
 MWDC.cxx:369
 MWDC.cxx:370
 MWDC.cxx:371
 MWDC.cxx:372
 MWDC.cxx:373
 MWDC.cxx:374
 MWDC.cxx:375
 MWDC.cxx:376
 MWDC.cxx:377
 MWDC.cxx:378
 MWDC.cxx:379
 MWDC.cxx:380
 MWDC.cxx:381
 MWDC.cxx:382
 MWDC.cxx:383
 MWDC.cxx:384
 MWDC.cxx:385
 MWDC.cxx:386
 MWDC.cxx:387
 MWDC.cxx:388
 MWDC.cxx:389
 MWDC.cxx:390
 MWDC.cxx:391
 MWDC.cxx:392
 MWDC.cxx:393
 MWDC.cxx:394
 MWDC.cxx:395
 MWDC.cxx:396
 MWDC.cxx:397
 MWDC.cxx:398
 MWDC.cxx:399
 MWDC.cxx:400
 MWDC.cxx:401
 MWDC.cxx:402
 MWDC.cxx:403
 MWDC.cxx:404
 MWDC.cxx:405
 MWDC.cxx:406
 MWDC.cxx:407
 MWDC.cxx:408
 MWDC.cxx:409
 MWDC.cxx:410
 MWDC.cxx:411
 MWDC.cxx:412
 MWDC.cxx:413
 MWDC.cxx:414
 MWDC.cxx:415
 MWDC.cxx:416
 MWDC.cxx:417
 MWDC.cxx:418
 MWDC.cxx:419
 MWDC.cxx:420
 MWDC.cxx:421
 MWDC.cxx:422
 MWDC.cxx:423
 MWDC.cxx:424
 MWDC.cxx:425
 MWDC.cxx:426
 MWDC.cxx:427
 MWDC.cxx:428
 MWDC.cxx:429
 MWDC.cxx:430
 MWDC.cxx:431
 MWDC.cxx:432
 MWDC.cxx:433
 MWDC.cxx:434
 MWDC.cxx:435
 MWDC.cxx:436
 MWDC.cxx:437
 MWDC.cxx:438
 MWDC.cxx:439
 MWDC.cxx:440
 MWDC.cxx:441
 MWDC.cxx:442
 MWDC.cxx:443
 MWDC.cxx:444
 MWDC.cxx:445
 MWDC.cxx:446
 MWDC.cxx:447
 MWDC.cxx:448
 MWDC.cxx:449
 MWDC.cxx:450
 MWDC.cxx:451
 MWDC.cxx:452
 MWDC.cxx:453
 MWDC.cxx:454
 MWDC.cxx:455
 MWDC.cxx:456
 MWDC.cxx:457
 MWDC.cxx:458
 MWDC.cxx:459
 MWDC.cxx:460
 MWDC.cxx:461
 MWDC.cxx:462
 MWDC.cxx:463
 MWDC.cxx:464
 MWDC.cxx:465
 MWDC.cxx:466
 MWDC.cxx:467
 MWDC.cxx:468
 MWDC.cxx:469
 MWDC.cxx:470
 MWDC.cxx:471
 MWDC.cxx:472
 MWDC.cxx:473
 MWDC.cxx:474
 MWDC.cxx:475
 MWDC.cxx:476
 MWDC.cxx:477
 MWDC.cxx:478
 MWDC.cxx:479
 MWDC.cxx:480
 MWDC.cxx:481
 MWDC.cxx:482
 MWDC.cxx:483
 MWDC.cxx:484
 MWDC.cxx:485
 MWDC.cxx:486
 MWDC.cxx:487
 MWDC.cxx:488
 MWDC.cxx:489
 MWDC.cxx:490
 MWDC.cxx:491
 MWDC.cxx:492
 MWDC.cxx:493
 MWDC.cxx:494
 MWDC.cxx:495
 MWDC.cxx:496
 MWDC.cxx:497
 MWDC.cxx:498
 MWDC.cxx:499
 MWDC.cxx:500
 MWDC.cxx:501
 MWDC.cxx:502
 MWDC.cxx:503
 MWDC.cxx:504
 MWDC.cxx:505
 MWDC.cxx:506
 MWDC.cxx:507
 MWDC.cxx:508
 MWDC.cxx:509
 MWDC.cxx:510
 MWDC.cxx:511
 MWDC.cxx:512
 MWDC.cxx:513
 MWDC.cxx:514
 MWDC.cxx:515
 MWDC.cxx:516
 MWDC.cxx:517
 MWDC.cxx:518
 MWDC.cxx:519
 MWDC.cxx:520
 MWDC.cxx:521
 MWDC.cxx:522
 MWDC.cxx:523
 MWDC.cxx:524
 MWDC.cxx:525
 MWDC.cxx:526
 MWDC.cxx:527
 MWDC.cxx:528
 MWDC.cxx:529
 MWDC.cxx:530
 MWDC.cxx:531
 MWDC.cxx:532
 MWDC.cxx:533
 MWDC.cxx:534
 MWDC.cxx:535
 MWDC.cxx:536
 MWDC.cxx:537
 MWDC.cxx:538
 MWDC.cxx:539
 MWDC.cxx:540
 MWDC.cxx:541
 MWDC.cxx:542
 MWDC.cxx:543
 MWDC.cxx:544
 MWDC.cxx:545
 MWDC.cxx:546
 MWDC.cxx:547
 MWDC.cxx:548
 MWDC.cxx:549
 MWDC.cxx:550
 MWDC.cxx:551
 MWDC.cxx:552
 MWDC.cxx:553
 MWDC.cxx:554
 MWDC.cxx:555
 MWDC.cxx:556
 MWDC.cxx:557
 MWDC.cxx:558
 MWDC.cxx:559
 MWDC.cxx:560
 MWDC.cxx:561
 MWDC.cxx:562
 MWDC.cxx:563
 MWDC.cxx:564
 MWDC.cxx:565
 MWDC.cxx:566
 MWDC.cxx:567
 MWDC.cxx:568
 MWDC.cxx:569
 MWDC.cxx:570
 MWDC.cxx:571
 MWDC.cxx:572
 MWDC.cxx:573
 MWDC.cxx:574
 MWDC.cxx:575
 MWDC.cxx:576
 MWDC.cxx:577
 MWDC.cxx:578
 MWDC.cxx:579
 MWDC.cxx:580
 MWDC.cxx:581
 MWDC.cxx:582
 MWDC.cxx:583
 MWDC.cxx:584
 MWDC.cxx:585
 MWDC.cxx:586
 MWDC.cxx:587
 MWDC.cxx:588
 MWDC.cxx:589
 MWDC.cxx:590
 MWDC.cxx:591
 MWDC.cxx:592
 MWDC.cxx:593
 MWDC.cxx:594
 MWDC.cxx:595
 MWDC.cxx:596
 MWDC.cxx:597
 MWDC.cxx:598
 MWDC.cxx:599
 MWDC.cxx:600
 MWDC.cxx:601
 MWDC.cxx:602
 MWDC.cxx:603
 MWDC.cxx:604
 MWDC.cxx:605
 MWDC.cxx:606
 MWDC.cxx:607
 MWDC.cxx:608
 MWDC.cxx:609
 MWDC.cxx:610
 MWDC.cxx:611
 MWDC.cxx:612
 MWDC.cxx:613
 MWDC.cxx:614
 MWDC.cxx:615
 MWDC.cxx:616
 MWDC.cxx:617
 MWDC.cxx:618
 MWDC.cxx:619
 MWDC.cxx:620
 MWDC.cxx:621
 MWDC.cxx:622
 MWDC.cxx:623
 MWDC.cxx:624
 MWDC.cxx:625
 MWDC.cxx:626
 MWDC.cxx:627
 MWDC.cxx:628
 MWDC.cxx:629
 MWDC.cxx:630
 MWDC.cxx:631
 MWDC.cxx:632
 MWDC.cxx:633
 MWDC.cxx:634
 MWDC.cxx:635
 MWDC.cxx:636
 MWDC.cxx:637
 MWDC.cxx:638
 MWDC.cxx:639
 MWDC.cxx:640
 MWDC.cxx:641
 MWDC.cxx:642
 MWDC.cxx:643
 MWDC.cxx:644
 MWDC.cxx:645
 MWDC.cxx:646
 MWDC.cxx:647
 MWDC.cxx:648
 MWDC.cxx:649
 MWDC.cxx:650
 MWDC.cxx:651
 MWDC.cxx:652
 MWDC.cxx:653
 MWDC.cxx:654
 MWDC.cxx:655
 MWDC.cxx:656
 MWDC.cxx:657
 MWDC.cxx:658
 MWDC.cxx:659
 MWDC.cxx:660
 MWDC.cxx:661
 MWDC.cxx:662
 MWDC.cxx:663
 MWDC.cxx:664
 MWDC.cxx:665
 MWDC.cxx:666
 MWDC.cxx:667
 MWDC.cxx:668
 MWDC.cxx:669
 MWDC.cxx:670
 MWDC.cxx:671
 MWDC.cxx:672
 MWDC.cxx:673
 MWDC.cxx:674
 MWDC.cxx:675
 MWDC.cxx:676
 MWDC.cxx:677
 MWDC.cxx:678
 MWDC.cxx:679
 MWDC.cxx:680
 MWDC.cxx:681
 MWDC.cxx:682
 MWDC.cxx:683
 MWDC.cxx:684
 MWDC.cxx:685
 MWDC.cxx:686
 MWDC.cxx:687
 MWDC.cxx:688
 MWDC.cxx:689
 MWDC.cxx:690
 MWDC.cxx:691
 MWDC.cxx:692
 MWDC.cxx:693
 MWDC.cxx:694
 MWDC.cxx:695
 MWDC.cxx:696
 MWDC.cxx:697
 MWDC.cxx:698
 MWDC.cxx:699
 MWDC.cxx:700
 MWDC.cxx:701
 MWDC.cxx:702
 MWDC.cxx:703
 MWDC.cxx:704
 MWDC.cxx:705
 MWDC.cxx:706
 MWDC.cxx:707
 MWDC.cxx:708
 MWDC.cxx:709
 MWDC.cxx:710
 MWDC.cxx:711
 MWDC.cxx:712
 MWDC.cxx:713
 MWDC.cxx:714
 MWDC.cxx:715
 MWDC.cxx:716
 MWDC.cxx:717
 MWDC.cxx:718
 MWDC.cxx:719
 MWDC.cxx:720
 MWDC.cxx:721
 MWDC.cxx:722
 MWDC.cxx:723
 MWDC.cxx:724
 MWDC.cxx:725
 MWDC.cxx:726
 MWDC.cxx:727
 MWDC.cxx:728
 MWDC.cxx:729
 MWDC.cxx:730
 MWDC.cxx:731
 MWDC.cxx:732
 MWDC.cxx:733
 MWDC.cxx:734
 MWDC.cxx:735
 MWDC.cxx:736
 MWDC.cxx:737
 MWDC.cxx:738
 MWDC.cxx:739
 MWDC.cxx:740
 MWDC.cxx:741
 MWDC.cxx:742
 MWDC.cxx:743
 MWDC.cxx:744
 MWDC.cxx:745
 MWDC.cxx:746
 MWDC.cxx:747
 MWDC.cxx:748
 MWDC.cxx:749
 MWDC.cxx:750
 MWDC.cxx:751
 MWDC.cxx:752
 MWDC.cxx:753
 MWDC.cxx:754
 MWDC.cxx:755
 MWDC.cxx:756
 MWDC.cxx:757
 MWDC.cxx:758
 MWDC.cxx:759
 MWDC.cxx:760
 MWDC.cxx:761
 MWDC.cxx:762
 MWDC.cxx:763
 MWDC.cxx:764
 MWDC.cxx:765
 MWDC.cxx:766
 MWDC.cxx:767
 MWDC.cxx:768
 MWDC.cxx:769
 MWDC.cxx:770
 MWDC.cxx:771
 MWDC.cxx:772
 MWDC.cxx:773
 MWDC.cxx:774
 MWDC.cxx:775
 MWDC.cxx:776
 MWDC.cxx:777
 MWDC.cxx:778
 MWDC.cxx:779
 MWDC.cxx:780
 MWDC.cxx:781
 MWDC.cxx:782
 MWDC.cxx:783
 MWDC.cxx:784
 MWDC.cxx:785
 MWDC.cxx:786
 MWDC.cxx:787
 MWDC.cxx:788
 MWDC.cxx:789
 MWDC.cxx:790
 MWDC.cxx:791
 MWDC.cxx:792
 MWDC.cxx:793
 MWDC.cxx:794
 MWDC.cxx:795
 MWDC.cxx:796
 MWDC.cxx:797
 MWDC.cxx:798
 MWDC.cxx:799
 MWDC.cxx:800
 MWDC.cxx:801
 MWDC.cxx:802
 MWDC.cxx:803
 MWDC.cxx:804
 MWDC.cxx:805
 MWDC.cxx:806
 MWDC.cxx:807
 MWDC.cxx:808
 MWDC.cxx:809
 MWDC.cxx:810
 MWDC.cxx:811
 MWDC.cxx:812
 MWDC.cxx:813
 MWDC.cxx:814
 MWDC.cxx:815
 MWDC.cxx:816
 MWDC.cxx:817
 MWDC.cxx:818
 MWDC.cxx:819
 MWDC.cxx:820
 MWDC.cxx:821
 MWDC.cxx:822
 MWDC.cxx:823
 MWDC.cxx:824
 MWDC.cxx:825
 MWDC.cxx:826
 MWDC.cxx:827
 MWDC.cxx:828
 MWDC.cxx:829
 MWDC.cxx:830
 MWDC.cxx:831
 MWDC.cxx:832
 MWDC.cxx:833
 MWDC.cxx:834
 MWDC.cxx:835
 MWDC.cxx:836
 MWDC.cxx:837
 MWDC.cxx:838
 MWDC.cxx:839
 MWDC.cxx:840
 MWDC.cxx:841
 MWDC.cxx:842
 MWDC.cxx:843
 MWDC.cxx:844
 MWDC.cxx:845
 MWDC.cxx:846
 MWDC.cxx:847
 MWDC.cxx:848
 MWDC.cxx:849
 MWDC.cxx:850
 MWDC.cxx:851
 MWDC.cxx:852
 MWDC.cxx:853
 MWDC.cxx:854
 MWDC.cxx:855
 MWDC.cxx:856
 MWDC.cxx:857
 MWDC.cxx:858
 MWDC.cxx:859
 MWDC.cxx:860
 MWDC.cxx:861
 MWDC.cxx:862
 MWDC.cxx:863
 MWDC.cxx:864
 MWDC.cxx:865
 MWDC.cxx:866
 MWDC.cxx:867
 MWDC.cxx:868
 MWDC.cxx:869
 MWDC.cxx:870
 MWDC.cxx:871
 MWDC.cxx:872
 MWDC.cxx:873
 MWDC.cxx:874
 MWDC.cxx:875
 MWDC.cxx:876
 MWDC.cxx:877
 MWDC.cxx:878
 MWDC.cxx:879
 MWDC.cxx:880
 MWDC.cxx:881
 MWDC.cxx:882
 MWDC.cxx:883
 MWDC.cxx:884
 MWDC.cxx:885
 MWDC.cxx:886
 MWDC.cxx:887
 MWDC.cxx:888
 MWDC.cxx:889
 MWDC.cxx:890
 MWDC.cxx:891
 MWDC.cxx:892
 MWDC.cxx:893
 MWDC.cxx:894
 MWDC.cxx:895
 MWDC.cxx:896
 MWDC.cxx:897
 MWDC.cxx:898
 MWDC.cxx:899
 MWDC.cxx:900
 MWDC.cxx:901
 MWDC.cxx:902
 MWDC.cxx:903
 MWDC.cxx:904
 MWDC.cxx:905
 MWDC.cxx:906
 MWDC.cxx:907
 MWDC.cxx:908
 MWDC.cxx:909
 MWDC.cxx:910
 MWDC.cxx:911
 MWDC.cxx:912
 MWDC.cxx:913
 MWDC.cxx:914
 MWDC.cxx:915
 MWDC.cxx:916
 MWDC.cxx:917
 MWDC.cxx:918
 MWDC.cxx:919
 MWDC.cxx:920
 MWDC.cxx:921
 MWDC.cxx:922
 MWDC.cxx:923
 MWDC.cxx:924
 MWDC.cxx:925
 MWDC.cxx:926
 MWDC.cxx:927
 MWDC.cxx:928
 MWDC.cxx:929
 MWDC.cxx:930
 MWDC.cxx:931
 MWDC.cxx:932
 MWDC.cxx:933
 MWDC.cxx:934
 MWDC.cxx:935
 MWDC.cxx:936
 MWDC.cxx:937
 MWDC.cxx:938
 MWDC.cxx:939
 MWDC.cxx:940
 MWDC.cxx:941
 MWDC.cxx:942
 MWDC.cxx:943
 MWDC.cxx:944
 MWDC.cxx:945
 MWDC.cxx:946
 MWDC.cxx:947
 MWDC.cxx:948
 MWDC.cxx:949
 MWDC.cxx:950
 MWDC.cxx:951
 MWDC.cxx:952
 MWDC.cxx:953
 MWDC.cxx:954
 MWDC.cxx:955
 MWDC.cxx:956
 MWDC.cxx:957
 MWDC.cxx:958
 MWDC.cxx:959
 MWDC.cxx:960
 MWDC.cxx:961
 MWDC.cxx:962
 MWDC.cxx:963
 MWDC.cxx:964
 MWDC.cxx:965
 MWDC.cxx:966
 MWDC.cxx:967
 MWDC.cxx:968
 MWDC.cxx:969
 MWDC.cxx:970
 MWDC.cxx:971
 MWDC.cxx:972
 MWDC.cxx:973
 MWDC.cxx:974
 MWDC.cxx:975
 MWDC.cxx:976
 MWDC.cxx:977
 MWDC.cxx:978
 MWDC.cxx:979
 MWDC.cxx:980
 MWDC.cxx:981
 MWDC.cxx:982
 MWDC.cxx:983
 MWDC.cxx:984
 MWDC.cxx:985
 MWDC.cxx:986
 MWDC.cxx:987
 MWDC.cxx:988
 MWDC.cxx:989
 MWDC.cxx:990
 MWDC.cxx:991
 MWDC.cxx:992
 MWDC.cxx:993
 MWDC.cxx:994
 MWDC.cxx:995
 MWDC.cxx:996
 MWDC.cxx:997
 MWDC.cxx:998
 MWDC.cxx:999
 MWDC.cxx:1000
 MWDC.cxx:1001
 MWDC.cxx:1002
 MWDC.cxx:1003
 MWDC.cxx:1004
 MWDC.cxx:1005
 MWDC.cxx:1006
 MWDC.cxx:1007
 MWDC.cxx:1008
 MWDC.cxx:1009
 MWDC.cxx:1010
 MWDC.cxx:1011
 MWDC.cxx:1012
 MWDC.cxx:1013
 MWDC.cxx:1014
 MWDC.cxx:1015
 MWDC.cxx:1016
 MWDC.cxx:1017
 MWDC.cxx:1018
 MWDC.cxx:1019
 MWDC.cxx:1020
 MWDC.cxx:1021
 MWDC.cxx:1022
 MWDC.cxx:1023
 MWDC.cxx:1024
 MWDC.cxx:1025
 MWDC.cxx:1026
 MWDC.cxx:1027
 MWDC.cxx:1028
 MWDC.cxx:1029
 MWDC.cxx:1030
 MWDC.cxx:1031
 MWDC.cxx:1032
 MWDC.cxx:1033
 MWDC.cxx:1034
 MWDC.cxx:1035
 MWDC.cxx:1036
 MWDC.cxx:1037
 MWDC.cxx:1038
 MWDC.cxx:1039
 MWDC.cxx:1040
 MWDC.cxx:1041
 MWDC.cxx:1042
 MWDC.cxx:1043
 MWDC.cxx:1044
 MWDC.cxx:1045
 MWDC.cxx:1046
 MWDC.cxx:1047
 MWDC.cxx:1048
 MWDC.cxx:1049
 MWDC.cxx:1050
 MWDC.cxx:1051
 MWDC.cxx:1052
 MWDC.cxx:1053
 MWDC.cxx:1054
 MWDC.cxx:1055
 MWDC.cxx:1056
 MWDC.cxx:1057
 MWDC.cxx:1058
 MWDC.cxx:1059
 MWDC.cxx:1060
 MWDC.cxx:1061
 MWDC.cxx:1062
 MWDC.cxx:1063
 MWDC.cxx:1064
 MWDC.cxx:1065
 MWDC.cxx:1066
 MWDC.cxx:1067
 MWDC.cxx:1068
 MWDC.cxx:1069
 MWDC.cxx:1070
 MWDC.cxx:1071
 MWDC.cxx:1072
 MWDC.cxx:1073
 MWDC.cxx:1074
 MWDC.cxx:1075
 MWDC.cxx:1076
 MWDC.cxx:1077
 MWDC.cxx:1078
 MWDC.cxx:1079
 MWDC.cxx:1080
 MWDC.cxx:1081
 MWDC.cxx:1082
 MWDC.cxx:1083
 MWDC.cxx:1084
 MWDC.cxx:1085
 MWDC.cxx:1086
 MWDC.cxx:1087
 MWDC.cxx:1088
 MWDC.cxx:1089
 MWDC.cxx:1090
 MWDC.cxx:1091
 MWDC.cxx:1092
 MWDC.cxx:1093
 MWDC.cxx:1094
 MWDC.cxx:1095
 MWDC.cxx:1096
 MWDC.cxx:1097
 MWDC.cxx:1098
 MWDC.cxx:1099
 MWDC.cxx:1100
 MWDC.cxx:1101
 MWDC.cxx:1102
 MWDC.cxx:1103
 MWDC.cxx:1104
 MWDC.cxx:1105
 MWDC.cxx:1106
 MWDC.cxx:1107
 MWDC.cxx:1108
 MWDC.cxx:1109
 MWDC.cxx:1110
 MWDC.cxx:1111
 MWDC.cxx:1112
 MWDC.cxx:1113
 MWDC.cxx:1114
 MWDC.cxx:1115
 MWDC.cxx:1116
 MWDC.cxx:1117
 MWDC.cxx:1118
 MWDC.cxx:1119
 MWDC.cxx:1120
 MWDC.cxx:1121
 MWDC.cxx:1122
 MWDC.cxx:1123
 MWDC.cxx:1124
 MWDC.cxx:1125
 MWDC.cxx:1126
 MWDC.cxx:1127
 MWDC.cxx:1128
 MWDC.cxx:1129
 MWDC.cxx:1130
 MWDC.cxx:1131
 MWDC.cxx:1132
 MWDC.cxx:1133
 MWDC.cxx:1134
 MWDC.cxx:1135
 MWDC.cxx:1136
 MWDC.cxx:1137
 MWDC.cxx:1138
 MWDC.cxx:1139
 MWDC.cxx:1140
 MWDC.cxx:1141
 MWDC.cxx:1142
 MWDC.cxx:1143
 MWDC.cxx:1144
 MWDC.cxx:1145
 MWDC.cxx:1146
 MWDC.cxx:1147
 MWDC.cxx:1148
 MWDC.cxx:1149
 MWDC.cxx:1150
 MWDC.cxx:1151
 MWDC.cxx:1152
 MWDC.cxx:1153
 MWDC.cxx:1154
 MWDC.cxx:1155
 MWDC.cxx:1156
 MWDC.cxx:1157
 MWDC.cxx:1158
 MWDC.cxx:1159
 MWDC.cxx:1160
 MWDC.cxx:1161
 MWDC.cxx:1162
 MWDC.cxx:1163
 MWDC.cxx:1164
 MWDC.cxx:1165
 MWDC.cxx:1166
 MWDC.cxx:1167
 MWDC.cxx:1168
 MWDC.cxx:1169
 MWDC.cxx:1170
 MWDC.cxx:1171
 MWDC.cxx:1172
 MWDC.cxx:1173
 MWDC.cxx:1174
 MWDC.cxx:1175
 MWDC.cxx:1176
 MWDC.cxx:1177
 MWDC.cxx:1178
 MWDC.cxx:1179
 MWDC.cxx:1180
 MWDC.cxx:1181
 MWDC.cxx:1182
 MWDC.cxx:1183
 MWDC.cxx:1184
 MWDC.cxx:1185
 MWDC.cxx:1186
 MWDC.cxx:1187
 MWDC.cxx:1188
 MWDC.cxx:1189
 MWDC.cxx:1190
 MWDC.cxx:1191
 MWDC.cxx:1192
 MWDC.cxx:1193
 MWDC.cxx:1194
 MWDC.cxx:1195
 MWDC.cxx:1196
 MWDC.cxx:1197
 MWDC.cxx:1198
 MWDC.cxx:1199
 MWDC.cxx:1200
 MWDC.cxx:1201
 MWDC.cxx:1202
 MWDC.cxx:1203
 MWDC.cxx:1204
 MWDC.cxx:1205
 MWDC.cxx:1206
 MWDC.cxx:1207
 MWDC.cxx:1208
 MWDC.cxx:1209
 MWDC.cxx:1210
 MWDC.cxx:1211
 MWDC.cxx:1212
 MWDC.cxx:1213
 MWDC.cxx:1214
 MWDC.cxx:1215
 MWDC.cxx:1216
 MWDC.cxx:1217
 MWDC.cxx:1218
 MWDC.cxx:1219
 MWDC.cxx:1220
 MWDC.cxx:1221
 MWDC.cxx:1222
 MWDC.cxx:1223
 MWDC.cxx:1224
 MWDC.cxx:1225
 MWDC.cxx:1226
 MWDC.cxx:1227
 MWDC.cxx:1228
 MWDC.cxx:1229
 MWDC.cxx:1230
 MWDC.cxx:1231
 MWDC.cxx:1232
 MWDC.cxx:1233
 MWDC.cxx:1234
 MWDC.cxx:1235
 MWDC.cxx:1236
 MWDC.cxx:1237
 MWDC.cxx:1238
 MWDC.cxx:1239
 MWDC.cxx:1240
 MWDC.cxx:1241
 MWDC.cxx:1242
 MWDC.cxx:1243
 MWDC.cxx:1244
 MWDC.cxx:1245
 MWDC.cxx:1246
 MWDC.cxx:1247
 MWDC.cxx:1248
 MWDC.cxx:1249
 MWDC.cxx:1250
 MWDC.cxx:1251
 MWDC.cxx:1252
 MWDC.cxx:1253
 MWDC.cxx:1254
 MWDC.cxx:1255
 MWDC.cxx:1256
 MWDC.cxx:1257
 MWDC.cxx:1258
 MWDC.cxx:1259
 MWDC.cxx:1260
 MWDC.cxx:1261
 MWDC.cxx:1262
 MWDC.cxx:1263
 MWDC.cxx:1264
 MWDC.cxx:1265
 MWDC.cxx:1266
 MWDC.cxx:1267
 MWDC.cxx:1268
 MWDC.cxx:1269
 MWDC.cxx:1270
 MWDC.cxx:1271
 MWDC.cxx:1272
 MWDC.cxx:1273
 MWDC.cxx:1274
 MWDC.cxx:1275
 MWDC.cxx:1276
 MWDC.cxx:1277
 MWDC.cxx:1278
 MWDC.cxx:1279
 MWDC.cxx:1280
 MWDC.cxx:1281
 MWDC.cxx:1282
 MWDC.cxx:1283
 MWDC.cxx:1284
 MWDC.cxx:1285
 MWDC.cxx:1286
 MWDC.cxx:1287
 MWDC.cxx:1288
 MWDC.cxx:1289
 MWDC.cxx:1290
 MWDC.cxx:1291
 MWDC.cxx:1292
 MWDC.cxx:1293
 MWDC.cxx:1294
 MWDC.cxx:1295
 MWDC.cxx:1296
 MWDC.cxx:1297
 MWDC.cxx:1298
 MWDC.cxx:1299
 MWDC.cxx:1300
 MWDC.cxx:1301
 MWDC.cxx:1302
 MWDC.cxx:1303
 MWDC.cxx:1304
 MWDC.cxx:1305
 MWDC.cxx:1306
 MWDC.cxx:1307
 MWDC.cxx:1308
 MWDC.cxx:1309
 MWDC.cxx:1310
 MWDC.cxx:1311
 MWDC.cxx:1312
 MWDC.cxx:1313
 MWDC.cxx:1314
 MWDC.cxx:1315
 MWDC.cxx:1316
 MWDC.cxx:1317
 MWDC.cxx:1318
 MWDC.cxx:1319
 MWDC.cxx:1320
 MWDC.cxx:1321
 MWDC.cxx:1322
 MWDC.cxx:1323
 MWDC.cxx:1324
 MWDC.cxx:1325
 MWDC.cxx:1326
 MWDC.cxx:1327
 MWDC.cxx:1328
 MWDC.cxx:1329
 MWDC.cxx:1330
 MWDC.cxx:1331
 MWDC.cxx:1332
 MWDC.cxx:1333
 MWDC.cxx:1334
 MWDC.cxx:1335
 MWDC.cxx:1336
 MWDC.cxx:1337
 MWDC.cxx:1338
 MWDC.cxx:1339
 MWDC.cxx:1340
 MWDC.cxx:1341
 MWDC.cxx:1342
 MWDC.cxx:1343
 MWDC.cxx:1344
 MWDC.cxx:1345
 MWDC.cxx:1346
 MWDC.cxx:1347
 MWDC.cxx:1348
 MWDC.cxx:1349
 MWDC.cxx:1350
 MWDC.cxx:1351
 MWDC.cxx:1352
 MWDC.cxx:1353
 MWDC.cxx:1354
 MWDC.cxx:1355
 MWDC.cxx:1356
 MWDC.cxx:1357
 MWDC.cxx:1358
 MWDC.cxx:1359
 MWDC.cxx:1360
 MWDC.cxx:1361
 MWDC.cxx:1362
 MWDC.cxx:1363
 MWDC.cxx:1364
 MWDC.cxx:1365
 MWDC.cxx:1366
 MWDC.cxx:1367
 MWDC.cxx:1368
 MWDC.cxx:1369
 MWDC.cxx:1370
 MWDC.cxx:1371
 MWDC.cxx:1372
 MWDC.cxx:1373
 MWDC.cxx:1374
 MWDC.cxx:1375
 MWDC.cxx:1376
 MWDC.cxx:1377
 MWDC.cxx:1378
 MWDC.cxx:1379
 MWDC.cxx:1380
 MWDC.cxx:1381
 MWDC.cxx:1382
 MWDC.cxx:1383
 MWDC.cxx:1384
 MWDC.cxx:1385
 MWDC.cxx:1386
 MWDC.cxx:1387
 MWDC.cxx:1388
 MWDC.cxx:1389
 MWDC.cxx:1390
 MWDC.cxx:1391
 MWDC.cxx:1392
 MWDC.cxx:1393
 MWDC.cxx:1394
 MWDC.cxx:1395
 MWDC.cxx:1396
 MWDC.cxx:1397
 MWDC.cxx:1398
 MWDC.cxx:1399
 MWDC.cxx:1400
 MWDC.cxx:1401
 MWDC.cxx:1402
 MWDC.cxx:1403
 MWDC.cxx:1404
 MWDC.cxx:1405
 MWDC.cxx:1406
 MWDC.cxx:1407
 MWDC.cxx:1408
 MWDC.cxx:1409
 MWDC.cxx:1410
 MWDC.cxx:1411
 MWDC.cxx:1412
 MWDC.cxx:1413
 MWDC.cxx:1414
 MWDC.cxx:1415
 MWDC.cxx:1416
 MWDC.cxx:1417
 MWDC.cxx:1418
 MWDC.cxx:1419
 MWDC.cxx:1420
 MWDC.cxx:1421
 MWDC.cxx:1422
 MWDC.cxx:1423
 MWDC.cxx:1424
 MWDC.cxx:1425
 MWDC.cxx:1426
 MWDC.cxx:1427
 MWDC.cxx:1428
 MWDC.cxx:1429
 MWDC.cxx:1430
 MWDC.cxx:1431
 MWDC.cxx:1432
 MWDC.cxx:1433
 MWDC.cxx:1434
 MWDC.cxx:1435
 MWDC.cxx:1436
 MWDC.cxx:1437
 MWDC.cxx:1438
 MWDC.cxx:1439
 MWDC.cxx:1440
 MWDC.cxx:1441
 MWDC.cxx:1442
 MWDC.cxx:1443
 MWDC.cxx:1444
 MWDC.cxx:1445
 MWDC.cxx:1446
 MWDC.cxx:1447
 MWDC.cxx:1448
 MWDC.cxx:1449
 MWDC.cxx:1450
 MWDC.cxx:1451
 MWDC.cxx:1452
 MWDC.cxx:1453
 MWDC.cxx:1454
 MWDC.cxx:1455
 MWDC.cxx:1456
 MWDC.cxx:1457
 MWDC.cxx:1458
 MWDC.cxx:1459
 MWDC.cxx:1460
 MWDC.cxx:1461
 MWDC.cxx:1462
 MWDC.cxx:1463
 MWDC.cxx:1464
 MWDC.cxx:1465
 MWDC.cxx:1466
 MWDC.cxx:1467
 MWDC.cxx:1468
 MWDC.cxx:1469
 MWDC.cxx:1470
 MWDC.cxx:1471
 MWDC.cxx:1472
 MWDC.cxx:1473
 MWDC.cxx:1474
 MWDC.cxx:1475
 MWDC.cxx:1476
 MWDC.cxx:1477
 MWDC.cxx:1478
 MWDC.cxx:1479
 MWDC.cxx:1480
 MWDC.cxx:1481
 MWDC.cxx:1482
 MWDC.cxx:1483
 MWDC.cxx:1484
 MWDC.cxx:1485
 MWDC.cxx:1486
 MWDC.cxx:1487
 MWDC.cxx:1488
 MWDC.cxx:1489
 MWDC.cxx:1490
 MWDC.cxx:1491
 MWDC.cxx:1492
 MWDC.cxx:1493
 MWDC.cxx:1494
 MWDC.cxx:1495
 MWDC.cxx:1496
 MWDC.cxx:1497
 MWDC.cxx:1498
 MWDC.cxx:1499
 MWDC.cxx:1500
 MWDC.cxx:1501
 MWDC.cxx:1502
 MWDC.cxx:1503
 MWDC.cxx:1504
 MWDC.cxx:1505
 MWDC.cxx:1506
 MWDC.cxx:1507
 MWDC.cxx:1508
 MWDC.cxx:1509
 MWDC.cxx:1510
 MWDC.cxx:1511
 MWDC.cxx:1512
 MWDC.cxx:1513
 MWDC.cxx:1514
 MWDC.cxx:1515
 MWDC.cxx:1516
 MWDC.cxx:1517
 MWDC.cxx:1518
 MWDC.cxx:1519
 MWDC.cxx:1520
 MWDC.cxx:1521
 MWDC.cxx:1522
 MWDC.cxx:1523
 MWDC.cxx:1524
 MWDC.cxx:1525
 MWDC.cxx:1526
 MWDC.cxx:1527
 MWDC.cxx:1528
 MWDC.cxx:1529
 MWDC.cxx:1530
 MWDC.cxx:1531
 MWDC.cxx:1532
 MWDC.cxx:1533
 MWDC.cxx:1534
 MWDC.cxx:1535
 MWDC.cxx:1536
 MWDC.cxx:1537
 MWDC.cxx:1538
 MWDC.cxx:1539
 MWDC.cxx:1540
 MWDC.cxx:1541
 MWDC.cxx:1542
 MWDC.cxx:1543
 MWDC.cxx:1544
 MWDC.cxx:1545
 MWDC.cxx:1546
 MWDC.cxx:1547
 MWDC.cxx:1548
 MWDC.cxx:1549
 MWDC.cxx:1550
 MWDC.cxx:1551
 MWDC.cxx:1552
 MWDC.cxx:1553
 MWDC.cxx:1554
 MWDC.cxx:1555
 MWDC.cxx:1556
 MWDC.cxx:1557
 MWDC.cxx:1558
 MWDC.cxx:1559
 MWDC.cxx:1560
 MWDC.cxx:1561
 MWDC.cxx:1562
 MWDC.cxx:1563
 MWDC.cxx:1564
 MWDC.cxx:1565
 MWDC.cxx:1566
 MWDC.cxx:1567
 MWDC.cxx:1568
 MWDC.cxx:1569
 MWDC.cxx:1570
 MWDC.cxx:1571
 MWDC.cxx:1572
 MWDC.cxx:1573
 MWDC.cxx:1574
 MWDC.cxx:1575
 MWDC.cxx:1576
 MWDC.cxx:1577
 MWDC.cxx:1578
 MWDC.cxx:1579
 MWDC.cxx:1580
 MWDC.cxx:1581
 MWDC.cxx:1582
 MWDC.cxx:1583
 MWDC.cxx:1584
 MWDC.cxx:1585
 MWDC.cxx:1586
 MWDC.cxx:1587
 MWDC.cxx:1588
 MWDC.cxx:1589
 MWDC.cxx:1590
 MWDC.cxx:1591
 MWDC.cxx:1592
 MWDC.cxx:1593
 MWDC.cxx:1594
 MWDC.cxx:1595
 MWDC.cxx:1596
 MWDC.cxx:1597
 MWDC.cxx:1598
 MWDC.cxx:1599
 MWDC.cxx:1600
 MWDC.cxx:1601
 MWDC.cxx:1602
 MWDC.cxx:1603
 MWDC.cxx:1604
 MWDC.cxx:1605
 MWDC.cxx:1606
 MWDC.cxx:1607
 MWDC.cxx:1608
 MWDC.cxx:1609
 MWDC.cxx:1610
 MWDC.cxx:1611
 MWDC.cxx:1612
 MWDC.cxx:1613
 MWDC.cxx:1614
 MWDC.cxx:1615
 MWDC.cxx:1616
 MWDC.cxx:1617
 MWDC.cxx:1618
 MWDC.cxx:1619
 MWDC.cxx:1620
 MWDC.cxx:1621
 MWDC.cxx:1622
 MWDC.cxx:1623
 MWDC.cxx:1624
 MWDC.cxx:1625
 MWDC.cxx:1626
 MWDC.cxx:1627
 MWDC.cxx:1628
 MWDC.cxx:1629
 MWDC.cxx:1630
 MWDC.cxx:1631
 MWDC.cxx:1632
 MWDC.cxx:1633
 MWDC.cxx:1634
 MWDC.cxx:1635
 MWDC.cxx:1636
 MWDC.cxx:1637
 MWDC.cxx:1638
 MWDC.cxx:1639
 MWDC.cxx:1640
 MWDC.cxx:1641
 MWDC.cxx:1642
 MWDC.cxx:1643
 MWDC.cxx:1644
 MWDC.cxx:1645
 MWDC.cxx:1646
 MWDC.cxx:1647
 MWDC.cxx:1648
 MWDC.cxx:1649
 MWDC.cxx:1650
 MWDC.cxx:1651
 MWDC.cxx:1652
 MWDC.cxx:1653
 MWDC.cxx:1654
 MWDC.cxx:1655
 MWDC.cxx:1656
 MWDC.cxx:1657
 MWDC.cxx:1658
 MWDC.cxx:1659
 MWDC.cxx:1660
 MWDC.cxx:1661
 MWDC.cxx:1662
 MWDC.cxx:1663
 MWDC.cxx:1664
 MWDC.cxx:1665
 MWDC.cxx:1666
 MWDC.cxx:1667
 MWDC.cxx:1668
 MWDC.cxx:1669
 MWDC.cxx:1670
 MWDC.cxx:1671
 MWDC.cxx:1672
 MWDC.cxx:1673
 MWDC.cxx:1674
 MWDC.cxx:1675
 MWDC.cxx:1676
 MWDC.cxx:1677
 MWDC.cxx:1678
 MWDC.cxx:1679
 MWDC.cxx:1680
 MWDC.cxx:1681
 MWDC.cxx:1682
 MWDC.cxx:1683
 MWDC.cxx:1684
 MWDC.cxx:1685
 MWDC.cxx:1686
 MWDC.cxx:1687
 MWDC.cxx:1688
 MWDC.cxx:1689
 MWDC.cxx:1690
 MWDC.cxx:1691
 MWDC.cxx:1692
 MWDC.cxx:1693
 MWDC.cxx:1694
 MWDC.cxx:1695
 MWDC.cxx:1696
 MWDC.cxx:1697
 MWDC.cxx:1698
 MWDC.cxx:1699
 MWDC.cxx:1700
 MWDC.cxx:1701
 MWDC.cxx:1702
 MWDC.cxx:1703
 MWDC.cxx:1704
 MWDC.cxx:1705
 MWDC.cxx:1706
 MWDC.cxx:1707
 MWDC.cxx:1708
 MWDC.cxx:1709
 MWDC.cxx:1710
 MWDC.cxx:1711
 MWDC.cxx:1712
 MWDC.cxx:1713
 MWDC.cxx:1714
 MWDC.cxx:1715
 MWDC.cxx:1716
 MWDC.cxx:1717
 MWDC.cxx:1718
 MWDC.cxx:1719
 MWDC.cxx:1720
 MWDC.cxx:1721
 MWDC.cxx:1722
 MWDC.cxx:1723
 MWDC.cxx:1724
 MWDC.cxx:1725
 MWDC.cxx:1726
 MWDC.cxx:1727
 MWDC.cxx:1728
 MWDC.cxx:1729
 MWDC.cxx:1730
 MWDC.cxx:1731
 MWDC.cxx:1732
 MWDC.cxx:1733
 MWDC.cxx:1734
 MWDC.cxx:1735
 MWDC.cxx:1736
 MWDC.cxx:1737
 MWDC.cxx:1738
 MWDC.cxx:1739
 MWDC.cxx:1740
 MWDC.cxx:1741
 MWDC.cxx:1742
 MWDC.cxx:1743
 MWDC.cxx:1744
 MWDC.cxx:1745
 MWDC.cxx:1746
 MWDC.cxx:1747
 MWDC.cxx:1748
 MWDC.cxx:1749
 MWDC.cxx:1750
 MWDC.cxx:1751
 MWDC.cxx:1752
 MWDC.cxx:1753
 MWDC.cxx:1754
 MWDC.cxx:1755
 MWDC.cxx:1756
 MWDC.cxx:1757
 MWDC.cxx:1758
 MWDC.cxx:1759
 MWDC.cxx:1760
 MWDC.cxx:1761
 MWDC.cxx:1762
 MWDC.cxx:1763
 MWDC.cxx:1764
 MWDC.cxx:1765
 MWDC.cxx:1766
 MWDC.cxx:1767
 MWDC.cxx:1768
 MWDC.cxx:1769
 MWDC.cxx:1770
 MWDC.cxx:1771
 MWDC.cxx:1772
 MWDC.cxx:1773
 MWDC.cxx:1774
 MWDC.cxx:1775
 MWDC.cxx:1776
 MWDC.cxx:1777
 MWDC.cxx:1778
 MWDC.cxx:1779
 MWDC.cxx:1780
 MWDC.cxx:1781
 MWDC.cxx:1782
 MWDC.cxx:1783
 MWDC.cxx:1784
 MWDC.cxx:1785
 MWDC.cxx:1786
 MWDC.cxx:1787
 MWDC.cxx:1788
 MWDC.cxx:1789
 MWDC.cxx:1790
 MWDC.cxx:1791
 MWDC.cxx:1792
 MWDC.cxx:1793
 MWDC.cxx:1794
 MWDC.cxx:1795
 MWDC.cxx:1796
 MWDC.cxx:1797
 MWDC.cxx:1798
 MWDC.cxx:1799
 MWDC.cxx:1800
 MWDC.cxx:1801
 MWDC.cxx:1802
 MWDC.cxx:1803
 MWDC.cxx:1804
 MWDC.cxx:1805
 MWDC.cxx:1806
 MWDC.cxx:1807
 MWDC.cxx:1808
 MWDC.cxx:1809
 MWDC.cxx:1810
 MWDC.cxx:1811
 MWDC.cxx:1812
 MWDC.cxx:1813
 MWDC.cxx:1814
 MWDC.cxx:1815
 MWDC.cxx:1816
 MWDC.cxx:1817
 MWDC.cxx:1818
 MWDC.cxx:1819
 MWDC.cxx:1820
 MWDC.cxx:1821
 MWDC.cxx:1822
 MWDC.cxx:1823
 MWDC.cxx:1824
 MWDC.cxx:1825
 MWDC.cxx:1826
 MWDC.cxx:1827
 MWDC.cxx:1828
 MWDC.cxx:1829
 MWDC.cxx:1830
 MWDC.cxx:1831
 MWDC.cxx:1832
 MWDC.cxx:1833
 MWDC.cxx:1834
 MWDC.cxx:1835
 MWDC.cxx:1836
 MWDC.cxx:1837
 MWDC.cxx:1838
 MWDC.cxx:1839
 MWDC.cxx:1840
 MWDC.cxx:1841
 MWDC.cxx:1842
 MWDC.cxx:1843
 MWDC.cxx:1844
 MWDC.cxx:1845
 MWDC.cxx:1846
 MWDC.cxx:1847
 MWDC.cxx:1848
 MWDC.cxx:1849
 MWDC.cxx:1850
 MWDC.cxx:1851
 MWDC.cxx:1852
 MWDC.cxx:1853
 MWDC.cxx:1854
 MWDC.cxx:1855
 MWDC.cxx:1856
 MWDC.cxx:1857
 MWDC.cxx:1858
 MWDC.cxx:1859
 MWDC.cxx:1860
 MWDC.cxx:1861
 MWDC.cxx:1862
 MWDC.cxx:1863
 MWDC.cxx:1864
 MWDC.cxx:1865
 MWDC.cxx:1866
 MWDC.cxx:1867
 MWDC.cxx:1868
 MWDC.cxx:1869
 MWDC.cxx:1870
 MWDC.cxx:1871
 MWDC.cxx:1872
 MWDC.cxx:1873
 MWDC.cxx:1874
 MWDC.cxx:1875
 MWDC.cxx:1876
 MWDC.cxx:1877
 MWDC.cxx:1878
 MWDC.cxx:1879
 MWDC.cxx:1880
 MWDC.cxx:1881
 MWDC.cxx:1882
 MWDC.cxx:1883
 MWDC.cxx:1884
 MWDC.cxx:1885
 MWDC.cxx:1886
 MWDC.cxx:1887
 MWDC.cxx:1888
 MWDC.cxx:1889
 MWDC.cxx:1890
 MWDC.cxx:1891
 MWDC.cxx:1892
 MWDC.cxx:1893
 MWDC.cxx:1894
 MWDC.cxx:1895
 MWDC.cxx:1896
 MWDC.cxx:1897
 MWDC.cxx:1898
 MWDC.cxx:1899
 MWDC.cxx:1900
 MWDC.cxx:1901
 MWDC.cxx:1902
 MWDC.cxx:1903
 MWDC.cxx:1904
 MWDC.cxx:1905
 MWDC.cxx:1906
 MWDC.cxx:1907
 MWDC.cxx:1908
 MWDC.cxx:1909
 MWDC.cxx:1910
 MWDC.cxx:1911
 MWDC.cxx:1912
 MWDC.cxx:1913
 MWDC.cxx:1914
 MWDC.cxx:1915
 MWDC.cxx:1916
 MWDC.cxx:1917
 MWDC.cxx:1918
 MWDC.cxx:1919
 MWDC.cxx:1920
 MWDC.cxx:1921
 MWDC.cxx:1922
 MWDC.cxx:1923
 MWDC.cxx:1924
 MWDC.cxx:1925
 MWDC.cxx:1926
 MWDC.cxx:1927
 MWDC.cxx:1928
 MWDC.cxx:1929
 MWDC.cxx:1930
 MWDC.cxx:1931
 MWDC.cxx:1932
 MWDC.cxx:1933
 MWDC.cxx:1934
 MWDC.cxx:1935
 MWDC.cxx:1936
 MWDC.cxx:1937
 MWDC.cxx:1938
 MWDC.cxx:1939
 MWDC.cxx:1940
 MWDC.cxx:1941
 MWDC.cxx:1942
 MWDC.cxx:1943
 MWDC.cxx:1944
 MWDC.cxx:1945
 MWDC.cxx:1946
 MWDC.cxx:1947
 MWDC.cxx:1948
 MWDC.cxx:1949
 MWDC.cxx:1950
 MWDC.cxx:1951
 MWDC.cxx:1952
 MWDC.cxx:1953
 MWDC.cxx:1954
 MWDC.cxx:1955
 MWDC.cxx:1956
 MWDC.cxx:1957
 MWDC.cxx:1958
 MWDC.cxx:1959
 MWDC.cxx:1960
 MWDC.cxx:1961
 MWDC.cxx:1962
 MWDC.cxx:1963
 MWDC.cxx:1964
 MWDC.cxx:1965
 MWDC.cxx:1966
 MWDC.cxx:1967
 MWDC.cxx:1968
 MWDC.cxx:1969
 MWDC.cxx:1970
 MWDC.cxx:1971
 MWDC.cxx:1972
 MWDC.cxx:1973
 MWDC.cxx:1974
 MWDC.cxx:1975
 MWDC.cxx:1976
 MWDC.cxx:1977
 MWDC.cxx:1978
 MWDC.cxx:1979
 MWDC.cxx:1980
 MWDC.cxx:1981
 MWDC.cxx:1982
 MWDC.cxx:1983
 MWDC.cxx:1984
 MWDC.cxx:1985
 MWDC.cxx:1986
 MWDC.cxx:1987
 MWDC.cxx:1988
 MWDC.cxx:1989
 MWDC.cxx:1990
 MWDC.cxx:1991
 MWDC.cxx:1992
 MWDC.cxx:1993
 MWDC.cxx:1994
 MWDC.cxx:1995