aboutsummaryrefslogtreecommitdiff
path: root/Carpet/CarpetLib/src/bbox.hh
blob: b2eb6de1f0722d38397dbf5bba987c03e890cd8e (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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#ifndef BBOX_HH
#define BBOX_HH

#include <cassert>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <limits>

#include "defs.hh"
#include "vect.hh"

using namespace std;



#ifdef CARPET_DEBUG
#  define ASSERT_BBOX(x) assert(x)
#else
#  define ASSERT_BBOX(x)
#endif



// Forward declaration
template<typename T, int D> class bbox;

// Input/Output
template<typename T, int D>
istream& operator>> (istream& is, bbox<T,D>& b);
template<typename T, int D>
ostream& operator<< (ostream& os, const bbox<T,D>& b);



/**
 * A bounding box, i.e., a rectangle with lower and upper bound and a
 * stride.
 */
template<typename T, int D>
class bbox {
  
  // Fields
  
  /** Bounding box bounds and stride.  The bounds are inclusive.  */
  
  // Consistency checks
  
  void assert_bbox_limits () const CCTK_MEMBER_ATTRIBUTE_PURE;
  
public:
  vect<T,D> _lower, _upper, _stride;
  
  // Constructors
  
  /** Construct an empty bbox.  */
  bbox ()
  : _lower(T(1)), _upper(T(0)), _stride(T(1))
  {
  }
  
  /** Copy constructor.  */
  bbox (const bbox& b)
    : _lower(b._lower), _upper(b._upper), _stride(b._stride)
  {
  }
  
  /** Assignment operator.  */
  bbox& operator= (const bbox& b)
  {
    _lower=b._lower; _upper=b._upper; _stride=b._stride;
    return *this;
  }
  
  /** Create a bbox from bounds and stride.  */
  bbox (const vect<T,D>& lower_,
        const vect<T,D>& upper_,
	const vect<T,D>& stride_)
    : _lower(lower_), _upper(upper_), _stride(stride_)
  {
#ifdef CARPET_DEBUG
    assert_bbox_limits();
#endif
  }
  
  // Poison
  static bbox poison () CCTK_ATTRIBUTE_PURE;
  
  bool is_poison () const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  // Accessors
  // (Don't return references; *this might be a temporary)
  
  /** Get lower bound.  */
  vect<T,D> lower () const { return _lower; }
  
  /** Get upper bound.  */
  vect<T,D> upper () const { return _upper; }
  
  /** Get bounds.  */
  vect<vect<T,D>,2> bounds () const
  { return vect<vect<T,D>,2> (_lower, _upper); }
  
  /** Get stride.  */
  vect<T,D> stride () const { return _stride; }
  
  /** Get offset.  */
  vect<T,D> offset () const { return imod(_lower, _stride); }
  
  /** Get the shape (or extent).  */
  vect<T,D> shape () const { return _upper - _lower + _stride; }
  
  /** Determine whether the bbox is empty.  */
  bool empty() const {
    return any(lower()>upper());
  }
  
  /** Return the size, which is the number of contained points.  */
  // T size () const;
  typedef long long int size_type;
  size_type size () const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  // Queries
  
  /** Find out whether the bbox contains the point x.  */
  bool contains (const vect<T,D>& x) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find out whether this bbox is contained in the bbox b.  */
  bool is_contained_in (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find out whether this bbox intersects the bbox b.  */
  bool intersects (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find out whether this bbox is aligned with the bbox b.
      ("aligned" means that both bboxes have the same stride and that
      their boundaries are commensurate.)  */
  bool is_aligned_with (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  // Operators
  bool operator== (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  bool operator!= (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  bool operator<= (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  bool operator>= (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  bool operator< (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  bool operator> (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Calculate the intersection (the set of common points) with the
      bbox b.  */
  bbox operator& (const bbox& b) const
  {
    ASSERT_BBOX (all(stride()==b.stride()));
    ASSERT_BBOX (is_aligned_with(b));
    vect<T,D> lo = max(lower(),b.lower());
    vect<T,D> up = min(upper(),b.upper());
    return bbox(lo,up,stride());
  }
  
  /** Expand (enlarge) the bbox by multiples of the stride.  */
  bbox expand (const vect<T,D>& lo, const vect<T,D>& hi) const
    CCTK_MEMBER_ATTRIBUTE_PURE;
  bbox expand (const vect<vect<T,D>,2>& lohi) const
  { return expand (lohi[0], lohi[1]); }
  
  /** Shift the bbox by multiples of the stride.  */
  bbox shift (const vect<T,D>& v) const
  { return expand (-v, v); }
  
  /** Expand (enlarge) the bbox by multiples of a fraction of the
      stride.  */
  bbox expand (const vect<T,D>& lo, const vect<T,D>& hi,
               const vect<T,D>& denom) const
    CCTK_MEMBER_ATTRIBUTE_PURE;
  bbox expand (const vect<vect<T,D>,2>& lohi, const vect<T,D>& denom) const
  { return expand (lohi[0], lohi[1], denom); }
  
  /** Shift the bbox by multiples of a fraction of the stride.  */
  bbox shift (const vect<T,D>& v, const vect<T,D>& denom) const
  { return expand (-v, v, denom); }
  
  /** Find the smallest b-compatible box around this bbox.
      ("compatible" means having the same stride.)  */
  bbox expanded_for (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find the largest b-compatible box inside this bbox.  */
  bbox contracted_for (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find the smallest open b-compatible box around *this */
  bbox anti_contracted_for (const bbox& b) const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  /** Find the smallest bbox containing both boxes.  */
  bbox expanded_containing (const bbox<T,D>& b) const
    CCTK_MEMBER_ATTRIBUTE_PURE;
  
  // Iterators
  
  /** An iterator over all points in a bbox.  */
  class iterator {
  protected:
    /** The bbox over which we iterate.  */
    const bbox& box;
    /** Current position.  */
    vect<T,D> pos;
  public:
    /** Constructor.  */
    iterator (const bbox& box, const vect<T,D>& pos);
    /** Accessor.  */
    const vect<T,D>& operator* () const { return pos; }
    /** Check whether the position is the same.  */
    bool operator!= (const iterator& i) const;
    /** Advance.  */
    iterator& operator++ ();
  };
  
  /** Create an iterator that points to the first point in a bbox.  */
  iterator begin () const CCTK_MEMBER_ATTRIBUTE_PURE;
  /** Create an iterator that points "after the last point" in a bbox,
      which means that it also points to the first point.  */
  iterator end () const CCTK_MEMBER_ATTRIBUTE_PURE;
  
  size_type index (const vect<T,D>& pos) const
  {
    assert (not empty());
    bbox const posbox (pos, pos, stride());
    assert (is_aligned_with (posbox));
    assert (contains(pos));
    size_type const i = ::index (shape(), (pos - lower()) / stride());
    assert (i>=0 and i<size());
    return i;
  }
  
  // Memory usage
  size_t memory () const
  {
    return memoryof (_lower) + memoryof (_upper) + memoryof (_stride);
  }
  
  // Input/Output helpers
  void input (istream& is);
  void output (ostream& os) const;
};



// Memory usage

template<typename T, int D>
inline size_t memoryof (bbox<T,D> const & b) { return b.memory(); }



// Input

/** Read a formatted bbox from a stream.  */
template<typename T,int D>
inline istream& operator>> (istream& is, bbox<T,D>& b) {
  b.input(is);
  return is;
}



// Output

/** Write a bbox formatted to a stream.  */
template<typename T,int D>
inline ostream& operator<< (ostream& os, const bbox<T,D>& b) {
  b.output(os);
  return os;
}



// Comparison

namespace std {
  // ==
  template<typename T, int D>
  struct equal_to<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const;
  };
  
  // <
  template<typename T, int D>
  struct less<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const;
  };
  
  // >
  template<typename T, int D>
  struct greater<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const
    {
      return less<bbox<T,D> >()(y, x);
    }
  };
  
  // >=
  template<typename T, int D>
  struct greater_equal<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const
    {
      return not less<bbox<T,D> >()(x, y);
    }
  };
  
  // <=
  template<typename T, int D>
  struct less_equal<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const
    {
      return not greater<bbox<T,D> >()(x, y);
    }
  };
  
  // !=
  template<typename T, int D>
  struct not_equal_to<bbox<T,D> >: binary_function<bbox<T,D>, bbox<T,D>, bool>
  {
    bool operator()(const bbox<T,D>& x, const bbox<T,D>& y) const
    {
      return not equal_to<bbox<T,D> >()(x, y);
    }
  };
}



#endif // BBOX_HH