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

#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>

#include <vect.hh>

using namespace std;



// This is a "full tree" data structure, i.e., a tree data structure
// which decomposes a cuboid domain into a set of non-overlapping
// cuboid subdomains.  It is an n-ary tree, i.e., each tree node can
// have arbitrarily many subtrees.  Each node splits a domain in
// exactly one direction.  Subdomains cannot be empty.

// All intervals are closed at the lower and open at the upper
// boundary.  This makes it possible to combine adjacent such
// intervals, obtaining again an interval with this property.  (In
// particular, if bboxes are stored, the upper bound of bboxes must be
// increased by the stride to arrive at such intervals.)


// Generic arithmetic search
template <typename T>
static
int asearch (T t, vector <T> const & ts);



// T: index space (usually integer, or maybe real)
// D: number of dimensions (rank)
// P: payload (e.g. region_t)
template <typename T, int D, typename P>
class fulltree {
  
public:
  
  // Short name for a small vector
  typedef vect <T, D> tvect;
  
private:
  
  enum tree_type_t { type_empty, type_branch, type_leaf } type;
  
  // Direction in which the node is split (0 <= dir < D)
  int dir;
  
  // If this is a branch:
  // n+1 bounds, splitting the domain
  vector <T> bounds;            // [n+1]
  // n pointers to subtrees
  vector <fulltree *> subtrees; // [n]
  
  // If this is a leaf:
  // just the payload
  P p;
  
public:
  
  // Create an empty tree
  fulltree ();
  
  // Create a tree branch from a list of bounds and subtrees
  fulltree (int dir_, vector <T> const & bounds_,
            vector <fulltree *> const & subtrees_);
  
  // Create a tree leaf from a payload
  fulltree (P const & p_);
  
  // Create a tree as copy from another tree
  fulltree (fulltree const & t);
  
  // Copy a tree
  fulltree & operator= (fulltree const & t);
  
  // Delete a tree (and its subtrees)
  ~fulltree ();
  
  // Inquire tree properties
  bool empty() const { return type == type_empty; }
  bool is_branch() const { return type == type_branch; }
  bool is_leaf() const { return type == type_leaf; }
  
  // Compare trees
  bool operator== (fulltree const & t) const;
  bool operator!= (fulltree const & t) const
  { return not (*this == t); }
  
  // Invariant
  bool invariant () const;
  
  // Access the payload
  P const & payload () const { assert (is_leaf()); return p; }
  P & payload () { assert (is_leaf()); return p; }
  
  // Find the leaf payload corresponding to a position
  P const * search (tvect const & ipos) const;
  P * search (tvect const & ipos);
  
  class const_iterator {
    fulltree const & f;
    size_t i;
    const_iterator * it;
  public:
    const_iterator (fulltree const & f_);
    const_iterator (fulltree const & f_, int);
    ~const_iterator ();
  private:
    const_iterator (const_iterator const &);
    const_iterator & operator= (const_iterator const &);
  public:
    fulltree const & operator* () const;
    bool operator== (const_iterator const & it2) const;
    bool operator!= (const_iterator const & it2) const
    { return not (*this == it2); }
    const_iterator & operator++ ();
    bool done () const;
  };
  
  class iterator {
    fulltree & f;
    size_t i;
    iterator * it;
  public:
    iterator (fulltree & f_);
    iterator (fulltree & f_, int);
    ~iterator ();
  private:
    iterator (iterator const &);
    iterator & operator= (iterator const &);
  public:
    fulltree & operator* () const;
    bool operator== (iterator const & it2) const;
    bool operator!= (iterator const & it2) const
    { return not (*this == it2); }
    iterator & operator++ ();
    bool done () const;
  };
  
#if 0
  // ES 2008-09-04:
  // It seems that PGI does not handle comparisons to end() correctly.
  // We therefore disable these; please use the iterators'
  // constructors and their done() methods instead.
  
  const_iterator begin() const
  { return const_iterator (*this); }
  
  const_iterator end() const
  { return const_iterator (*this, 0); }
  
  iterator begin()
  { return iterator (*this); }
  
  iterator end()
  { return iterator (*this, 0); }
#endif
  
  // Memory usage
  size_t memory () const;
  
  // Output helper
  void output (ostream & os) const;
};



// Memory usage
template <typename T, int D, typename P>
inline size_t memoryof (fulltree<T,D,P> const & f) { return f.memory(); }



// Output
template <typename T, int D, typename P>
ostream &
operator<< (ostream & os, fulltree<T,D,P> const & f)
{
  f.output (os);
  return os;
}



#endif  // #ifndef FULLTREE_HH