#include "PatternTree.h"
#include "Pattern.h"
#include "TError.h"
#include <iostream>
#include <stdexcept>
using namespace std;
ClassImp(TreeSearch::PatternTree)
namespace TreeSearch {
PatternTree::PatternTree( const TreeParam_t& param, UInt_t nPatterns,
UInt_t nLinks )
try
: fParameters(param), fParamOK(false), fNpat(0), fNlnk(0), fNbit(0)
{
if( fParameters.Normalize() != 0 )
return;
fPatterns.resize( nPatterns );
fLinks.resize( nLinks );
fBits.resize( nPatterns * fParameters.zpos().size() );
fParamOK = true;
}
catch ( bad_alloc ) {
::Error( "PatternTree::PatternTree", "Out of memory trying to create "
"%u patterns, %u links. Tree not created.", nPatterns, nLinks );
throw;
}
PatternTree::~PatternTree()
{
}
PatternTree* PatternTree::Read( const char* filename, const TreeParam_t& tp )
{
try {
}
catch ( bad_alloc ) {
::Error( "PatternTree::Read", "Out of memory trying to read "
"%u patterns, %u links", 0,0 );
}
return 0;
}
Int_t TreeParam_t::Normalize()
{
static const char* const here = "TreeParam_t::Normalize";
if( fNormalized ) return 0;
if( fMaxdepth >= 16 ) {
::Error( here, "Illegal maxdepth = %u. Must be < 16", fMaxdepth );
return -1;
}
if( fWidth < 1e-2 ) {
::Error( here, "Illegal detector width %lf. Must be >= 0.01.",
fWidth );
return -2;
}
if( fZpos.size() < 3 || fZpos.size() > 16 ) {
::Error( here, "Illegal number of planes = %u. Must be between 3-16.",
fZpos.size() );
return -3;
}
if( fMaxslope < 0.0 )
fMaxslope = -fMaxslope;
for( vector<Double_t>::size_type i = 1; i < fZpos.size(); ++i ) {
if( fZpos[i] < fZpos[i-1] + 1e-3 ) {
::Error( here, "Array of z-positions not sorted or planes not "
"spaced by at least 0.001 at index = %u.", i );
return -4;
}
}
Double_t zsize = fZpos.back() - fZpos.front();
for( vector<Double_t>::size_type i = 1; i+1 < fZpos.size(); ++i ) {
fZpos[i] -= fZpos.front();
fZpos[i] /= zsize;
}
fZpos.back() = 1.0;
fZpos.front() = 0.0;
fMaxslope *= zsize / fWidth;
fNormalized = true;
return 0;
}
void PatternTree::Print( Option_t* opt, ostream& os )
{
TreeWalk walk( GetNlevels() );
if( *opt == 'P' or *opt == 'L' ) {
PrintPattern print(os, (*opt == 'L'));
walk( GetRoot(), print );
return;
}
if( *opt == 'C' ) {
CountPattern count;
walk( GetRoot(), count );
os << "Total pattern count = " << count.GetCount() << endl;
return;
}
}
Int_t PatternTree::Write( const char* filename )
{
size_t index_size = sizeof(Int_t);
vpsz_t npatt = fPatterns.size();
if( npatt < (1U<<8) )
index_size = 1;
else if( npatt < (1U<<16) )
index_size = 2;
WritePattern write(filename,index_size);
TreeWalk walk( GetNlevels() );
Int_t ret = walk( GetRoot(), write );
if( ret != kError )
ret = 0;
return ret;
}
void
PatternTree::CopyPattern::AddChild( Pattern* node, Pattern* child, Int_t type )
{
Link* ln = node->GetChild();
while( ln ) {
if( !ln->GetPattern() ) {
SetLinkPattern( ln, child );
SetLinkType( ln, type );
break;
}
assert( ln->GetPattern() != child or ln->Type() != type );
ln = ln->Next();
assert(ln);
}
}
NodeVisitor::ETreeOp
PatternTree::CopyPattern::operator() ( const NodeDescriptor& nd )
try {
map<Pattern*,Int_t>::iterator idx;
Pattern* copied_parent = 0;
if( nd.parent ) {
idx = fMap.find(nd.parent);
assert( idx != fMap.end() );
copied_parent = &(fTree->fPatterns.at( idx->second ));
}
Pattern* node = nd.link->GetPattern();
idx = fMap.find(node);
if( idx == fMap.end() ) {
map< Pattern*,Int_t>::size_type np = fMap.size();
fMap[node] = np;
assert( fTree->fNpat == np );
Pattern* cur_pat = &(fTree->fPatterns.at(fTree->fNpat));
*cur_pat = *node;
UShort_t* bitloc = &(fTree->fBits.at(fTree->fNbit));
cur_pat->SetBitloc( bitloc );
if( copied_parent ) {
AddChild( copied_parent, cur_pat, nd.link->Type() );
} else {
assert( fTree->fNlnk == 0 );
fTree->fLinks.at(fTree->fNlnk++) = Link(cur_pat, 0, nd.link->Type());
}
Int_t nchild = node->GetNchildren();
if( nchild > 0 ) {
PatternTree::vlsz_t lpos = fTree->fNlnk;
SetPatternChild( cur_pat, &(fTree->fLinks.at(lpos)) );
for( Int_t i = nchild-2; i >= 0; --i )
SetLinkNext( &(fTree->fLinks.at(lpos+i)),
&(fTree->fLinks.at(lpos+i+1)) );
}
fTree->fNpat++;
fTree->fNlnk += nchild;
fTree->fNbit += cur_pat->GetNbits();
return kRecurseUncond;
}
else {
Pattern* ref_node = &(fTree->fPatterns.at( idx->second ));
AddChild( copied_parent, ref_node, nd.link->Type() );
return kSkipChildNodes;
}
}
catch ( out_of_range ) {
::Error( "TreeSearch::CopyPattern", "Array index out of range at %u %u %u "
"(internal logic error). Tree not copied. Call expert.",
fTree->fNpat, fTree->fNlnk, fTree->fNbit );
return kError;
}
}