ROOT logo
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// TreeSearch::TreeWalk                                                      //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "TreeWalk.h"
#include "TError.h"
#include <iomanip>

using namespace std;

ClassImp(TreeSearch::TreeWalk)

namespace TreeSearch {

//_____________________________________________________________________________
NodeVisitor::ETreeOp
TreeWalk::operator()( Link* link, NodeVisitor& action, Pattern* parent, 
		      UInt_t depth, UInt_t shift, Bool_t mirrored ) const
{
  // Traverse the tree and call function object "action" for each link. 
  // The return value from action determines the behavior:
  //  kRecurse: process child nodes until reaching maxdepth
  //  kRecurseUncond: process child nodes (regardless of depth)
  //  fSkipChildNodes: ignore child nodes
  //  kError: error, return immediately

  if( !link ) return NodeVisitor::kError;
  NodeVisitor::ETreeOp ret = 
    action(NodeDescriptor(link, parent, shift, mirrored, depth));
  if( ret == NodeVisitor::kRecurseUncond or 
      ( ret == NodeVisitor::kRecurse and depth+1 < fNlevels ) ) {
    Pattern* pat = link->GetPattern();
    Link* ln = pat->GetChild();
    while( ln ) {
      // Set up parameters of child pattern based on current position in the
      // tree. The mirroring flag for the child pattern is the pattern's
      // mirroring flag xor the mirror state of the parent (so that 
      // mirrored+mirrored = unmirrored). The shift corresponds either
      // to the pattern's left or right edge for unmirrored or mirrored
      // patterns, respectively.
      Bool_t new_mir = mirrored xor ln->Mirrored();
      ret = (*this)( ln, action, pat, depth+1, 
		     (shift << 1) + (new_mir xor ln->Shift()), new_mir );
      if( ret == NodeVisitor::kError ) return ret;
      // Continue along the linked list of child nodes
      ln = ln->Next();
    }
  }
  return ret;
}


//_____________________________________________________________________________
void NodeVisitor::SetLinkPattern( Link* link, Pattern* pattern ) {
  link->fPattern = pattern;
}

void NodeVisitor::SetLinkType( Link* link, Int_t type ) {
  link->fOp = type;
}

void NodeVisitor::SetLinkNext( Link* link, Link* next ) {
  link->fNext = next;
}

void NodeVisitor::SetPatternChild( Pattern* pat, Link* link ) {
  pat->fChild = link;
  // Explicitly set pointer is managed externally
  pat->fDelChld = false;
}
 
//_____________________________________________________________________________
WritePattern::WritePattern( const char* filename, size_t index_size )
  : os(0), fIdxSiz(index_size)
{
  static const char* here = "PatternGenerator::WritePattern";

  if( filename && *filename ) {
    os = new ofstream(filename, ios::out|ios::binary|ios::trunc);
    if( !os || !(*os) ) {
      ::Error( here, "Error opening treefile %s", filename );
      if( os )
	delete os;
      os = 0;
    }
  } else {
    ::Error( here, "Invalid file name" );
  }
  if( (fIdxSiz & (fIdxSiz-1)) != 0 ) {
    ::Warning( here, "Invalid index_size = %d. Must be a power of 2", fIdxSiz);
    fIdxSiz = sizeof(Int_t);
  }    
}

//_____________________________________________________________________________
template< typename T>
static inline
void swapped_binary_write( ostream& os, const T& data, size_t n = 1, 
			   size_t start = 0 )
{
  // Write "n" elements of "data" to "os" in binary big-endian (MSB) format.
  // "start" indicates an optional _byte_ skip count from the beginning of
  // the big-endian format data - designed to write only the non-trivial
  // part of scalar data for which the upper bytes are known to be always zero.
  size_t size = sizeof(T);
  const char* bytes = reinterpret_cast<const char*>( &data );
#ifdef R__BYTESWAP
  size_t k = size-1;
  for( size_t i = start; i < n * size; ++i )
    os.put( bytes[(i&~k)+((k-i)&k)] );
#else
  os.write( bytes+start, n*size-start );
#endif
}

//_____________________________________________________________________________
NodeVisitor::ETreeOp WritePattern::operator() ( const NodeDescriptor& nd )
{
  // Write the single pattern referenced by "nd" to the binary output stream.
  // In essence, this implements the serialization method for cyclical graphs
  // described in
  // http://www.parashift.com/c++-faq-lite/serialization.html#faq-36.11

  if( !os )
    return kError;
  Pattern* node = nd.link->GetPattern();
  map<Pattern*,Int_t>::iterator idx = fMap.find(node);
  if( idx == fMap.end() ) {
    map<Pattern*,Int_t>::size_type n = fMap.size();
    fMap[node] = n;
    // Header for new pattern: link type + 128 (=128-130)
    os->put( nd.link->Type() | 0x80 );
    if( os->fail() ) return kError;
    // Pattern data. NB: fBits[0] is always 0, so we can skip it
    swapped_binary_write( *os, node->GetBits()[1], node->GetNbits()-1 );
    // Child node count
    UShort_t nchild = node->GetNchildren();
    swapped_binary_write( *os, nchild );
    if( os->fail() ) return kError;
    // Write child nodes regardless of depth
    return kRecurseUncond;
  } else {
    // Reference pattern header: the plain link type (=0-2)
    os->put( nd.link->Type() );
    // Reference index
    swapped_binary_write( *os, idx->second, 1, sizeof(Int_t)-fIdxSiz );
    if( os->fail() ) return kError;
    // Don't write child nodes
    return kSkipChildNodes;
  }
}

//_____________________________________________________________________________
NodeVisitor::ETreeOp PrintPattern::operator() ( const NodeDescriptor& nd )
{
  // Print actual (shifted & mirrored) pattern described by "nd".

  ++fCount;
  if( fDump )
    os << setw(2) << nd.depth;

  UInt_t nplanes = nd.link->GetPattern()->GetNbits();
  for( UInt_t i = 0; i < nplanes; i++ ) {
    UInt_t v = nd[i];

    // In dump mode, write out one pattern n-tuple per line
    if( fDump )
      os << " " << setw(5) << v;

    // Otherwise draw a pretty ASCII picture of the pattern
    else {
      UInt_t op = (nd.mirrored ? 2 : 0) + nd.link->Shift();
      os << static_cast<UInt_t>(nd.depth) << "-" << op;
      for( UInt_t k = 0; k < nd.depth; ++k )
	os << " ";
      os << " |";
      for( UInt_t k = 0; k < v; ++k )
	os << ".";
      os << "O";
      for( UInt_t k = (1<<nd.depth)-1; k > v; --k )
	os << ".";
      os << "|" << endl;
    }
  }
  os << endl;

  // Process child nodes through maxdepth
  return kRecurse;
}

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

} // end namespace TreeSearch
 TreeWalk.cxx:1
 TreeWalk.cxx:2
 TreeWalk.cxx:3
 TreeWalk.cxx:4
 TreeWalk.cxx:5
 TreeWalk.cxx:6
 TreeWalk.cxx:7
 TreeWalk.cxx:8
 TreeWalk.cxx:9
 TreeWalk.cxx:10
 TreeWalk.cxx:11
 TreeWalk.cxx:12
 TreeWalk.cxx:13
 TreeWalk.cxx:14
 TreeWalk.cxx:15
 TreeWalk.cxx:16
 TreeWalk.cxx:17
 TreeWalk.cxx:18
 TreeWalk.cxx:19
 TreeWalk.cxx:20
 TreeWalk.cxx:21
 TreeWalk.cxx:22
 TreeWalk.cxx:23
 TreeWalk.cxx:24
 TreeWalk.cxx:25
 TreeWalk.cxx:26
 TreeWalk.cxx:27
 TreeWalk.cxx:28
 TreeWalk.cxx:29
 TreeWalk.cxx:30
 TreeWalk.cxx:31
 TreeWalk.cxx:32
 TreeWalk.cxx:33
 TreeWalk.cxx:34
 TreeWalk.cxx:35
 TreeWalk.cxx:36
 TreeWalk.cxx:37
 TreeWalk.cxx:38
 TreeWalk.cxx:39
 TreeWalk.cxx:40
 TreeWalk.cxx:41
 TreeWalk.cxx:42
 TreeWalk.cxx:43
 TreeWalk.cxx:44
 TreeWalk.cxx:45
 TreeWalk.cxx:46
 TreeWalk.cxx:47
 TreeWalk.cxx:48
 TreeWalk.cxx:49
 TreeWalk.cxx:50
 TreeWalk.cxx:51
 TreeWalk.cxx:52
 TreeWalk.cxx:53
 TreeWalk.cxx:54
 TreeWalk.cxx:55
 TreeWalk.cxx:56
 TreeWalk.cxx:57
 TreeWalk.cxx:58
 TreeWalk.cxx:59
 TreeWalk.cxx:60
 TreeWalk.cxx:61
 TreeWalk.cxx:62
 TreeWalk.cxx:63
 TreeWalk.cxx:64
 TreeWalk.cxx:65
 TreeWalk.cxx:66
 TreeWalk.cxx:67
 TreeWalk.cxx:68
 TreeWalk.cxx:69
 TreeWalk.cxx:70
 TreeWalk.cxx:71
 TreeWalk.cxx:72
 TreeWalk.cxx:73
 TreeWalk.cxx:74
 TreeWalk.cxx:75
 TreeWalk.cxx:76
 TreeWalk.cxx:77
 TreeWalk.cxx:78
 TreeWalk.cxx:79
 TreeWalk.cxx:80
 TreeWalk.cxx:81
 TreeWalk.cxx:82
 TreeWalk.cxx:83
 TreeWalk.cxx:84
 TreeWalk.cxx:85
 TreeWalk.cxx:86
 TreeWalk.cxx:87
 TreeWalk.cxx:88
 TreeWalk.cxx:89
 TreeWalk.cxx:90
 TreeWalk.cxx:91
 TreeWalk.cxx:92
 TreeWalk.cxx:93
 TreeWalk.cxx:94
 TreeWalk.cxx:95
 TreeWalk.cxx:96
 TreeWalk.cxx:97
 TreeWalk.cxx:98
 TreeWalk.cxx:99
 TreeWalk.cxx:100
 TreeWalk.cxx:101
 TreeWalk.cxx:102
 TreeWalk.cxx:103
 TreeWalk.cxx:104
 TreeWalk.cxx:105
 TreeWalk.cxx:106
 TreeWalk.cxx:107
 TreeWalk.cxx:108
 TreeWalk.cxx:109
 TreeWalk.cxx:110
 TreeWalk.cxx:111
 TreeWalk.cxx:112
 TreeWalk.cxx:113
 TreeWalk.cxx:114
 TreeWalk.cxx:115
 TreeWalk.cxx:116
 TreeWalk.cxx:117
 TreeWalk.cxx:118
 TreeWalk.cxx:119
 TreeWalk.cxx:120
 TreeWalk.cxx:121
 TreeWalk.cxx:122
 TreeWalk.cxx:123
 TreeWalk.cxx:124
 TreeWalk.cxx:125
 TreeWalk.cxx:126
 TreeWalk.cxx:127
 TreeWalk.cxx:128
 TreeWalk.cxx:129
 TreeWalk.cxx:130
 TreeWalk.cxx:131
 TreeWalk.cxx:132
 TreeWalk.cxx:133
 TreeWalk.cxx:134
 TreeWalk.cxx:135
 TreeWalk.cxx:136
 TreeWalk.cxx:137
 TreeWalk.cxx:138
 TreeWalk.cxx:139
 TreeWalk.cxx:140
 TreeWalk.cxx:141
 TreeWalk.cxx:142
 TreeWalk.cxx:143
 TreeWalk.cxx:144
 TreeWalk.cxx:145
 TreeWalk.cxx:146
 TreeWalk.cxx:147
 TreeWalk.cxx:148
 TreeWalk.cxx:149
 TreeWalk.cxx:150
 TreeWalk.cxx:151
 TreeWalk.cxx:152
 TreeWalk.cxx:153
 TreeWalk.cxx:154
 TreeWalk.cxx:155
 TreeWalk.cxx:156
 TreeWalk.cxx:157
 TreeWalk.cxx:158
 TreeWalk.cxx:159
 TreeWalk.cxx:160
 TreeWalk.cxx:161
 TreeWalk.cxx:162
 TreeWalk.cxx:163
 TreeWalk.cxx:164
 TreeWalk.cxx:165
 TreeWalk.cxx:166
 TreeWalk.cxx:167
 TreeWalk.cxx:168
 TreeWalk.cxx:169
 TreeWalk.cxx:170
 TreeWalk.cxx:171
 TreeWalk.cxx:172
 TreeWalk.cxx:173
 TreeWalk.cxx:174
 TreeWalk.cxx:175
 TreeWalk.cxx:176
 TreeWalk.cxx:177
 TreeWalk.cxx:178
 TreeWalk.cxx:179
 TreeWalk.cxx:180
 TreeWalk.cxx:181
 TreeWalk.cxx:182
 TreeWalk.cxx:183
 TreeWalk.cxx:184
 TreeWalk.cxx:185
 TreeWalk.cxx:186
 TreeWalk.cxx:187
 TreeWalk.cxx:188
 TreeWalk.cxx:189
 TreeWalk.cxx:190
 TreeWalk.cxx:191
 TreeWalk.cxx:192
 TreeWalk.cxx:193
 TreeWalk.cxx:194
 TreeWalk.cxx:195