OpenVDB  12.0.0
Range.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /*!
5  \file nanovdb/util/Range.h
6 
7  \author Ken Museth
8 
9  \date August 28, 2020
10 
11  \brief Custom Range class that is compatible with the tbb::blocked_range classes
12 */
13 
14 #ifndef NANOVDB_UTIL_RANGE_H_HAS_BEEN_INCLUDED
15 #define NANOVDB_UTIL_RANGE_H_HAS_BEEN_INCLUDED
16 
17 #include <cassert>
18 #include <cstddef>// for size_t
19 
20 #ifdef NANOVDB_USE_TBB
21 #include <tbb/blocked_range.h>// for tbb::split
22 #endif
23 
24 namespace nanovdb {
25 
26 namespace util {
27 
28 class Split {};// Dummy class used by split constructors
29 
30 template <int, typename>
31 class Range;
32 
36 
37 // template specialization for Rank = 1
38 template <typename T>
39 class Range<1, T>
40 {
41  T mBegin, mEnd;
42  size_t mGrainsize;
43  template<int, typename>
44  friend class Range;
45 public:
46  using const_iterator = T;
47  using size_type = size_t;
48  Range(const Range&) = default;
49  Range(T begin, T end, size_type grainsize = size_type(1))
50  : mBegin(begin), mEnd(end), mGrainsize(grainsize)
51  {
52  assert(grainsize > size_type(0));
53  }
54  /// @brief Split constructor: r[a,b[ -> r[a,b/2[ & this[b/2,b[
55  Range(Range &r, Split) : mBegin(r.mBegin), mEnd(r.mEnd), mGrainsize(r.mGrainsize) {
56  assert(r.is_divisible());
57  r.mEnd = mBegin = this->middle();
58  }
59 #ifdef NANOVDB_USE_TBB
60  Range(Range &r, tbb::split) : Range(r, Split()) {}
61 #endif
62  bool operator==(const Range& rhs) const { return mBegin == rhs.mBegin && mEnd == rhs.mEnd && mGrainsize == rhs.mGrainsize; }
63  T middle() const {return mBegin + (mEnd - mBegin) / T(2);}
64  size_type size() const { assert(!this->empty()); return size_type(mEnd - mBegin); }
65  bool empty() const { return !(mBegin < mEnd); }
66  size_type grainsize() const {return mGrainsize;}
67  bool is_divisible() const {return mGrainsize < this->size();}
68  const_iterator begin() const { return mBegin; }
69  const_iterator end() const { return mEnd; }
70 };// Range<1, T>
71 
72 // template specialization for Rank = 2
73 template <typename T>
74 class Range<2, T>
75 {
76  Range<1, T> mRange[2];
77 public:
79  Range(const Range<1, T> &rangeRow, const Range<1, T> &rangeCol) : mRange{ rangeRow, rangeCol } {}
80  Range(T beginRow, T endRow, size_type grainsizeRow, T beginCol, T endCol, size_type grainsizeCol)
81  : Range( Range<1,T>(beginRow, endRow, grainsizeRow), Range<1,T>(beginCol, endCol, grainsizeCol) )
82  {
83  }
84  Range(T beginRow, T endRow, T beginCol, T endCol) : Range(Range<1,T>(beginRow, endRow), Range<1,T>(beginCol, endCol) )
85  {
86  }
87  Range(Range &r, Split) : Range(r.mRange[0], r.mRange[1]) {
88  assert( r.is_divisible() );// at least one of the two dimensions must be divisible!
89  if( mRange[0].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[0].grainsize()) ) {
90  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
91  } else {
92  r.mRange[0].mEnd = mRange[0].mBegin = mRange[0].middle();
93  }
94  }
95 #ifdef NANOVDB_USE_TBB
96  Range(Range &r, tbb::split) : Range(r, Split()) {}
97 #endif
98  bool operator==(const Range& rhs) const {return mRange[0] == rhs[0] && mRange[1] == rhs[1]; }
99  bool empty() const { return mRange[0].empty() || mRange[1].empty(); }
100  bool is_divisible() const {return mRange[0].is_divisible() || mRange[1].is_divisible();}
101  const Range<1, T>& operator[](int i) const { assert(i==0 || i==1); return mRange[i]; }
102 };// Range<2, T>
103 
104 // template specialization for Rank = 3
105 template <typename T>
106 class Range<3, T>
107 {
108  Range<1, T> mRange[3];
109 public:
111  Range(const Range<1, T> &rangeX, const Range<1, T> &rangeY, const Range<1, T> &rangeZ) : mRange{ rangeX, rangeY, rangeZ } {}
112  Range(T beginX, T endX, size_type grainsizeX,
113  T beginY, T endY, size_type grainsizeY,
114  T beginZ, T endZ, size_type grainsizeZ)
115  : Range( Range<1,T>(beginX, endX, grainsizeX),
116  Range<1,T>(beginY, endY, grainsizeY),
117  Range<1,T>(beginZ, endZ, grainsizeZ) )
118  {
119  }
120  Range(T beginX, T endX, T beginY, T endY, T beginZ, T endZ)
121  : Range( Range<1,T>(beginX, endX), Range<1,T>(beginY, endY), Range<1,T>(beginZ, endZ) )
122  {
123  }
124  Range(Range &r, Split) : Range(r.mRange[0], r.mRange[1], r.mRange[2])
125  {
126  assert( r.is_divisible() );// at least one of the three dimensions must be divisible!
127  if ( mRange[2].size()*double(mRange[0].grainsize()) < mRange[0].size()*double(mRange[2].grainsize()) ) {
128  if ( mRange[0].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[0].grainsize()) ) {
129  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
130  } else {
131  r.mRange[0].mEnd = mRange[0].mBegin = mRange[0].middle();
132  }
133  } else {
134  if ( mRange[2].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[2].grainsize()) ) {
135  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
136  } else {
137  r.mRange[2].mEnd = mRange[2].mBegin = mRange[2].middle();
138  }
139  }
140  }
141 #ifdef NANOVDB_USE_TBB
142  Range(Range &r, tbb::split) : Range(r, Split()) {}
143 #endif
144  bool operator==(const Range& rhs) const {return mRange[0] == rhs[0] && mRange[1] == rhs[1] && mRange[2] == rhs[2]; }
145  bool empty() const { return mRange[0].empty() || mRange[1].empty() || mRange[2].empty(); }
146  bool is_divisible() const {return mRange[0].is_divisible() || mRange[1].is_divisible() || mRange[2].is_divisible();}
147  const Range<1, T>& operator[](int i) const { assert(i==0 || i==1 || i==2); return mRange[i]; }
148 };// Range<3, T>
149 
150 }// namespace util
151 
152 using Range1D [[deprecated("Use nanovdb::util::Range1D instead")]] = util::Range<1, size_t>;
153 using Range2D [[deprecated("Use nanovdb::util::Range2D instead")]] = util::Range<2, size_t>;
154 using Range3D [[deprecated("Use nanovdb::util::Range3D instead")]] = util::Range<3, size_t>;
155 
156 }// namespace nanovdb
157 
158 #endif // NANOVDB_UTIL_RANGE_H_HAS_BEEN_INCLUDED
bool empty() const
Definition: Range.h:65
bool operator==(const Range &rhs) const
Definition: Range.h:62
T middle() const
Definition: Range.h:63
Range< 3, size_t > Range3D
Definition: Range.h:35
Definition: Range.h:28
typename Range< 1, T >::size_type size_type
Definition: Range.h:78
Range(T begin, T end, size_type grainsize=size_type(1))
Definition: Range.h:49
bool is_divisible() const
Definition: Range.h:100
Range(Range &r, Split)
Definition: Range.h:87
Range< 2, size_t > Range2D
Definition: Range.h:34
size_type size() const
Definition: Range.h:64
const_iterator begin() const
Definition: Range.h:68
Definition: GridHandle.h:27
Range< 1, size_t > Range1D
Definition: Range.h:33
Definition: Range.h:39
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
bool empty() const
Definition: Range.h:99
bool operator==(const Range &rhs) const
Definition: Range.h:98
const Range< 1, T > & operator[](int i) const
Definition: Range.h:147
typename Range< 1, T >::size_type size_type
Definition: Range.h:110
const_iterator end() const
Definition: Range.h:69
Range(const Range< 1, T > &rangeRow, const Range< 1, T > &rangeCol)
Definition: Range.h:79
size_type grainsize() const
Definition: Range.h:66
bool empty() const
Definition: Range.h:145
bool empty(const char *str)
tests if a c-string str is empty, that is its first value is &#39;\0&#39;
Definition: Util.h:144
bool operator==(const Range &rhs) const
Definition: Range.h:144
Range(T beginX, T endX, size_type grainsizeX, T beginY, T endY, size_type grainsizeY, T beginZ, T endZ, size_type grainsizeZ)
Definition: Range.h:112
const Range< 1, T > & operator[](int i) const
Definition: Range.h:101
Range(T beginRow, T endRow, T beginCol, T endCol)
Definition: Range.h:84
T const_iterator
Definition: Range.h:46
Range(Range &r, Split)
Split constructor: r[a,b[ -> r[a,b/2[ & this[b/2,b[.
Definition: Range.h:55
Range(Range &r, Split)
Definition: Range.h:124
Range(T beginX, T endX, T beginY, T endY, T beginZ, T endZ)
Definition: Range.h:120
bool is_divisible() const
Definition: Range.h:67
size_t size_type
Definition: Range.h:47
Range(T beginRow, T endRow, size_type grainsizeRow, T beginCol, T endCol, size_type grainsizeCol)
Definition: Range.h:80
bool is_divisible() const
Definition: Range.h:146
Definition: Range.h:31
Range(const Range< 1, T > &rangeX, const Range< 1, T > &rangeY, const Range< 1, T > &rangeZ)
Definition: Range.h:111