carl  24.04
Computer ARithmetic Library
CompactTree.h
Go to the documentation of this file.
1 /**
2  * @file CompactTree.h
3  * This file has been extracted from mathic. It was deployed without license at:
4  * http://www.broune.com/papers/issac2012.html
5  * Currently, it is distributed under LGPL v2 from
6  * http://www.broune.com/papers/issac2012.html
7  */
8 
9 
10 #pragma once
11 
13 #include <cassert>
14 #include <ostream>
15 
16 CLANG_WARNING_DISABLE("-Wnull-pointer-arithmetic")
17 
18 namespace carl
19 {
20  /** This class packs a complete binary tree in a vector.
21 
22  The idea is to have the root at index 1, and then the left child of node n
23  will be at index 2n and the right child will be at index 2n + 1. The
24  corresponding formulas when indexes start at 0 take more computation, so
25  we need a 1-based array so we can't use std::vector.
26 
27  Also, when sizeof(Entry) is a power of 2 it is faster to keep track of
28  i * sizeof(Entry) than directly keeping track of an index i. This doesn't
29  work well when sizeof(Entry) is not a power of two. So we need both
30  possibilities. That is why this class never exposes indexes. Instead
31  you interact with Node objects that serve the role of an index, but the
32  precise value it stores is encapsulated. This way you can't do something
33  like _array[i * sizeof(Entry)] by accident. Client code also does not
34  need to (indeed, can't) be aware of how indexes are calculated, stored and
35  looked up.
36 
37  If FastIndex is false, then Nodes contain an index i. If FastIndex is
38  true, then Nodes contain the byte offset i * sizeof(Entry). FastIndex must
39  be false if sizeof(Entry) is not a power of two.
40  */
41  template<class Entry, bool FastIndex>
43  {
44  public:
45  class Node;
46  explicit CompactTree( std::size_t initialCapacity = 0 );
47  CompactTree( const CompactTree& tree, std::size_t minCapacity = 0 );
49  {
50  delete[] (_array + 1);
51  }
52 
53  Entry& operator []( Node n );
54  const Entry& operator []( Node n ) const;
55 
56  bool empty() const
57  {
58  return _lastLeaf == Node( 0 );
59  }
60 
61  std::size_t size() const
62  {
63  return _lastLeaf.getNormalIndex();
64  }
65 
66  std::size_t capacity() const
67  {
68  return _capacityEnd.getNormalIndex();
69  }
70 
71  Node lastLeaf() const
72  {
73  return _lastLeaf;
74  }
75 
76  void pushBack( const Entry& value );
77  void pushBackWithCapacity( const Entry& value );
78  void popBack();
79 
80  bool hasFreeCapacity( size_t extraCapacity ) const;
82  void swap( CompactTree& tree );
83 
84  class Node
85  {
86  public:
87  Node():
88  _index( fi ? S : 1 )
89  {} // the root node is the default
90 
91  Node parent() const;
92  Node left() const;
93  Node right() const;
94  Node sibling() const;
95  Node leftSibling() const;
96  Node next( size_t count = 1) const;
97  Node prev() const;
98 
100  {
101  *this = next();
102  return *this;
103  }
104 
105  bool isRoot() const
106  {
107  return *this == Node();
108  }
109 
110  bool isLeft() const
111  {
112  return fi ? !(_index & S) : !(_index & 1);
113  }
114 
115  bool isRight() const
116  {
117  return fi ? _index & S : _index & 1;
118  }
119 
120  bool operator <( Node node ) const
121  {
122  return _index < node._index;
123  }
124 
125  bool operator <=( Node node ) const
126  {
127  return _index <= node._index;
128  }
129 
130  bool operator >( Node node ) const
131  {
132  return _index > node._index;
133  }
134 
135  bool operator >=( Node node ) const
136  {
137  return _index >= node._index;
138  }
139 
140  bool operator ==( Node node ) const
141  {
142  return _index == node._index;
143  }
144 
145  bool operator !=( Node node ) const
146  {
147  return _index != node._index;
148  }
149 
150  //private:
151  friend class CompactTree<Entry, FastIndex>;
152  static const bool fi = FastIndex;
153  static const size_t S = sizeof(Entry);
154 
155  explicit Node( size_t i ):
156  _index( i )
157  {}
158  size_t getNormalIndex() const
159  {
160  return fi ? _index / S : _index;
161  }
162 
163  size_t _index;
164  };
165 
166  void print( std::ostream& out ) const;
167 
168  void clear();
169 
170  std::size_t getMemoryUse() const;
171 
172  bool isValid() const;
173 
174  std::vector<Entry> getCopy() const
175  {
176  Node it;
177  std::vector<Entry> ret;
178  while( it <= _lastLeaf )
179  {
180  ret.push_back( (*this)[it] );
181  }
182  return ret;
183  }
184 
185  private:
186  CompactTree& operator = ( const CompactTree& tree ) const = delete;
187 
188  Entry* _array;
191  };
192 
193  template<class E, bool FI>
195  {
196  _lastLeaf = Node( 0 );
197  }
198 
199  template<class E, bool FI>
201  {
202  return capacity() * sizeof(E);
203  }
204 
205  template<class E, bool FI>
206  std::ostream& operator <<( std::ostream& out, const CompactTree<E, FI>& tree )
207  {
208  tree.print( out );
209  return out;
210  }
211 
212  template<class E, bool FI>
213  CompactTree<E, FI>::CompactTree( size_t initialCapacity ):
214  _array( static_cast<E*>(nullptr) - 1 ),
215  _lastLeaf( 0 ),
216  _capacityEnd( Node( 0 ).next( initialCapacity ))
217  {
218  if( initialCapacity > 0 ) {
219  _array = new E[initialCapacity]-1;
220  }
221  assert( isValid() );
222  }
223 
224  template<class E, bool FI>
225  CompactTree<E, FI>::CompactTree( const CompactTree& tree, size_t minCapacity ):
226  _array( static_cast<E*>(0) - 1 ),
227  _lastLeaf( tree._lastLeaf )
228  {
229  if( tree.size() > minCapacity ) {
230  minCapacity = tree.size();
231  }
232  _capacityEnd = Node( 0 ).next( minCapacity );
233  if( minCapacity == 0 ) {
234  return;
235  }
236  _array = new E[minCapacity]-1;
237  for( Node i; i <= tree.lastLeaf(); ++i ) {
238  (*this)[i] = tree[i];
239  }
240  }
241 
242  template<class E, bool FI>
244  {
245  if( !FI ) {
246  return _array[n._index];
247  }
248  char* base = reinterpret_cast<char*>(_array);
249  E* element = reinterpret_cast<E*>(base + n._index);
250  assert( element == &(_array[n._index / sizeof(E)]) );
251  return *element;
252  }
253 
254  template<class E, bool FI>
256  {
257  return const_cast<CompactTree<E, FI>*>(this)->operator []( n );
258  }
259 
260  template<class E, bool FI>
261  void CompactTree<E, FI>::pushBack( const E& value )
262  {
263  if( _lastLeaf == _capacityEnd ) {
264  increaseCapacity();
265  }
266  _lastLeaf = _lastLeaf.next();
267  (*this)[lastLeaf()] = value;
268  }
269 
270  template<class E, bool FI>
272  {
273  assert( _lastLeaf != _capacityEnd );
274  _lastLeaf = _lastLeaf.next();
275  (*this)[lastLeaf()] = value;
276  }
277 
278  template<class E, bool FI>
280  {
281  assert( _lastLeaf >= Node() );
282  _lastLeaf = _lastLeaf.prev();
283  }
284 
285  template<class E, bool FI>
287  {
288  std::swap( _array, tree._array );
289  std::swap( _lastLeaf, tree._lastLeaf );
290  std::swap( _capacityEnd, tree._capacityEnd );
291  }
292 
293  template<class E, bool FI>
295  {
296  return fi ? Node( (_index / (2 * S)) * S ) : Node( _index / 2 );
297  }
298 
299  template<class E, bool FI>
301  {
302  return Node( 2 * _index );
303  }
304 
305  template<class E, bool FI>
307  {
308  return fi ? Node( 2 * _index + S ) : Node( 2 * _index + 1 );
309  }
310 
311  template<class E, bool FI>
313  {
314  return fi ? Node( _index ^ S ) : Node( _index ^ 1 );
315  }
316 
317  template<class E, bool FI>
319  {
320  return fi ? Node( _index & ~S ) : Node( _index & ~1 );
321  }
322 
323 
324  template<class E, bool FI>
326  {
327  return fi ? Node( _index + S * count ) : Node( _index + count );
328  }
329 
330  template<class E, bool FI>
332  {
333  return fi ? Node( _index - S ) : Node( _index - 1 );
334  }
335 
336  template<class E, bool FI>
337  void CompactTree<E, FI>::print( std::ostream& out ) const
338  {
339  Node last = lastLeaf();
340  for( Node i; i <= last; i = i.next() )
341  {
342  if( (i._index & (i._index - 1)) == 0 ) { // if i._index is a power of 2
343  out << "\n " << i._index << ':';
344  }
345  out << ' ' << (*this)[i] << " := ";
346  out.flush();
347  (*this)[i]->print( out );
348  }
349  out << "}\n";
350  }
351 
352  template<class E, bool FI>
354  {
355  // sizeof(Entry) must be a power of two if FastIndex is true.
356  assert( !FI || (sizeof(E) & (sizeof(E) - 1)) == 0 );
357  if( capacity() == 0 )
358  {
359  assert( _array == static_cast<E*>(nullptr) - 1 );
360  assert( _capacityEnd == Node( 0 ));
361  assert( _lastLeaf == Node( 0 ));
362  }
363  else
364  {
365  assert( _array != static_cast<E*>(nullptr) - 1 );
366  assert( _capacityEnd > Node( 0 ));
367  assert( _lastLeaf <= _capacityEnd );
368  }
369  return true;
370  }
371 
372  template<class E, bool FI>
373  bool CompactTree<E, FI>::hasFreeCapacity( size_t extraCapacity ) const
374  {
375  return Node( _capacityEnd._index - _lastLeaf._index ) >= Node( 0 ).next( extraCapacity );
376  }
377 
378  template<class E, bool FI>
380  {
381  CompactTree<E, FI> newTree( capacity() == 0 ? 16 : capacity() * 2 );
382  for( Node i; i <= lastLeaf(); i = i.next() ) {
383  newTree.pushBack( (*this)[i] );
384  }
385  std::swap( _array, newTree._array );
386  std::swap( _capacityEnd, newTree._capacityEnd );
387  assert( isValid() );
388  }
389 }
390 
391 CLANG_WARNING_RESET
std::ostream & operator<<(std::ostream &os, const GbBenchmark< C, O, P > &b)
carl is the main namespace for the library.
bool operator>(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
void swap(Variable &lhs, Variable &rhs)
Definition: Variables.h:202
bool operator<(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
bool operator!=(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
bool operator<=(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
bool operator==(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
bool operator>=(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
std::enable_if<!reverse, I >::type & operator++(BaseIterator< T, I, reverse > &it)
Definition: carlTree.h:126
void print(CaseDistinction< Poly > &_substitutionResults)
Prints the given disjunction of conjunction of constraints.
This class represents a tree.
Definition: carlTree.h:559
This class packs a complete binary tree in a vector.
Definition: CompactTree.h:43
void print(std::ostream &out) const
Definition: CompactTree.h:337
void pushBackWithCapacity(const Entry &value)
Definition: CompactTree.h:271
bool hasFreeCapacity(size_t extraCapacity) const
Definition: CompactTree.h:373
void swap(CompactTree &tree)
Definition: CompactTree.h:286
void increaseCapacity()
Definition: CompactTree.h:379
std::vector< Entry > getCopy() const
Definition: CompactTree.h:174
bool empty() const
Definition: CompactTree.h:56
CompactTree(std::size_t initialCapacity=0)
std::size_t size() const
Definition: CompactTree.h:61
Node lastLeaf() const
Definition: CompactTree.h:71
bool isValid() const
Definition: CompactTree.h:353
std::size_t getMemoryUse() const
Definition: CompactTree.h:200
CompactTree(const CompactTree &tree, std::size_t minCapacity=0)
std::size_t capacity() const
Definition: CompactTree.h:66
void pushBack(const Entry &value)
Definition: CompactTree.h:261
size_t getNormalIndex() const
Definition: CompactTree.h:158
Node next(size_t count=1) const
Definition: CompactTree.h:325