OpenVDB  9.0.1
Range.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /*!
5  \file 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_RANGE_H_HAS_BEEN_INCLUDED
15 #define NANOVDB_RANGE_H_HAS_BEEN_INCLUDED
16 
17 #include <cassert>
18 
19 #ifdef NANOVDB_USE_TBB
20 #include <tbb/blocked_range.h>// for tbb::split
21 #endif
22 
23 namespace nanovdb {
24 
25 class Split {};// Dummy class used by split constructors
26 
27 template <int, typename>
28 class Range;
29 
33 
34 // template specialization for Rank = 1
35 template <typename T>
36 class Range<1, T>
37 {
38  T mBegin, mEnd;
39  size_t mGrainsize;
40  template<int, typename>
41  friend class Range;
42 public:
43  using const_iterator = T;
44  using size_type = size_t;
45  Range(const Range&) = default;
46  Range(T begin, T end, size_type grainsize = size_type(1))
47  : mBegin(begin), mEnd(end), mGrainsize(grainsize)
48  {
49  assert(grainsize > size_type(0));
50  }
51  /// @brief Split constructor: r[a,b[ -> r[a,b/2[ & this[b/2,b[
52  Range(Range &r, Split) : mBegin(r.mBegin), mEnd(r.mEnd), mGrainsize(r.mGrainsize) {
53  assert(r.is_divisible());
54  r.mEnd = mBegin = this->middle();
55  }
56 #ifdef NANOVDB_USE_TBB
57  Range(Range &r, tbb::split) : Range(r, Split()) {}
58 #endif
59  bool operator==(const Range& rhs) const { return mBegin == rhs.mBegin && mEnd == rhs.mEnd && mGrainsize == rhs.mGrainsize; }
60  T middle() const {return mBegin + (mEnd - mBegin) / T(2);}
61  size_type size() const { assert(!this->empty()); return size_type(mEnd - mBegin); }
62  bool empty() const { return !(mBegin < mEnd); }
63  size_type grainsize() const {return mGrainsize;}
64  bool is_divisible() const {return mGrainsize < this->size();}
65  const_iterator begin() const { return mBegin; }
66  const_iterator end() const { return mEnd; }
67 };// Range<1, T>
68 
69 // template specialization for Rank = 2
70 template <typename T>
71 class Range<2, T>
72 {
73  Range<1, T> mRange[2];
74 public:
76  Range(const Range<1, T> &rangeRow, const Range<1, T> &rangeCol) : mRange{ rangeRow, rangeCol } {}
77  Range(T beginRow, T endRow, size_type grainsizeRow, T beginCol, T endCol, size_type grainsizeCol)
78  : Range( Range<1,T>(beginRow, endRow, grainsizeRow), Range<1,T>(beginCol, endCol, grainsizeCol) )
79  {
80  }
81  Range(T beginRow, T endRow, T beginCol, T endCol) : Range(Range<1,T>(beginRow, endRow), Range<1,T>(beginCol, endCol) )
82  {
83  }
84  Range(Range &r, Split) : Range(r.mRange[0], r.mRange[1]) {
85  assert( r.is_divisible() );// at least one of the two dimensions must be divisible!
86  if( mRange[0].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[0].grainsize()) ) {
87  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
88  } else {
89  r.mRange[0].mEnd = mRange[0].mBegin = mRange[0].middle();
90  }
91  }
92 #ifdef NANOVDB_USE_TBB
93  Range(Range &r, tbb::split) : Range(r, Split()) {}
94 #endif
95  bool operator==(const Range& rhs) const {return mRange[0] == rhs[0] && mRange[1] == rhs[1]; }
96  bool empty() const { return mRange[0].empty() || mRange[1].empty(); }
97  bool is_divisible() const {return mRange[0].is_divisible() || mRange[1].is_divisible();}
98  const Range<1, T>& operator[](int i) const { assert(i==0 || i==1); return mRange[i]; }
99 };// Range<2, T>
100 
101 // template specialization for Rank = 3
102 template <typename T>
103 class Range<3, T>
104 {
105  Range<1, T> mRange[3];
106 public:
108  Range(const Range<1, T> &rangeX, const Range<1, T> &rangeY, const Range<1, T> &rangeZ) : mRange{ rangeX, rangeY, rangeZ } {}
109  Range(T beginX, T endX, size_type grainsizeX,
110  T beginY, T endY, size_type grainsizeY,
111  T beginZ, T endZ, size_type grainsizeZ)
112  : Range( Range<1,T>(beginX, endX, grainsizeX),
113  Range<1,T>(beginY, endY, grainsizeY),
114  Range<1,T>(beginZ, endZ, grainsizeZ) )
115  {
116  }
117  Range(T beginX, T endX, T beginY, T endY, T beginZ, T endZ)
118  : Range( Range<1,T>(beginX, endX), Range<1,T>(beginY, endY), Range<1,T>(beginZ, endZ) )
119  {
120  }
121  Range(Range &r, Split) : Range(r.mRange[0], r.mRange[1], r.mRange[2])
122  {
123  assert( r.is_divisible() );// at least one of the three dimensions must be divisible!
124  if ( mRange[2].size()*double(mRange[0].grainsize()) < mRange[0].size()*double(mRange[2].grainsize()) ) {
125  if ( mRange[0].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[0].grainsize()) ) {
126  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
127  } else {
128  r.mRange[0].mEnd = mRange[0].mBegin = mRange[0].middle();
129  }
130  } else {
131  if ( mRange[2].size()*double(mRange[1].grainsize()) < mRange[1].size()*double(mRange[2].grainsize()) ) {
132  r.mRange[1].mEnd = mRange[1].mBegin = mRange[1].middle();
133  } else {
134  r.mRange[2].mEnd = mRange[2].mBegin = mRange[2].middle();
135  }
136  }
137  }
138 #ifdef NANOVDB_USE_TBB
139  Range(Range &r, tbb::split) : Range(r, Split()) {}
140 #endif
141  bool operator==(const Range& rhs) const {return mRange[0] == rhs[0] && mRange[1] == rhs[1] && mRange[2] == rhs[2]; }
142  bool empty() const { return mRange[0].empty() || mRange[1].empty() || mRange[2].empty(); }
143  bool is_divisible() const {return mRange[0].is_divisible() || mRange[1].is_divisible() || mRange[2].is_divisible();}
144  const Range<1, T>& operator[](int i) const { assert(i==0 || i==1 || i==2); return mRange[i]; }
145 };// Range<3, T>
146 
147 }// namespace nanovdb
148 
149 #endif // NANOVDB_RANGE_H_HAS_BEEN_INCLUDED
const_iterator begin() const
Definition: Range.h:65
const Range< 1, T > & operator[](int i) const
Definition: Range.h:98
Range(const Range< 1, T > &rangeRow, const Range< 1, T > &rangeCol)
Definition: Range.h:76
typename Range< 1, T >::size_type size_type
Definition: Range.h:107
bool empty() const
Definition: Range.h:142
Definition: Range.h:36
const Range< 1, T > & operator[](int i) const
Definition: Range.h:144
Range(Range &r, Split)
Definition: Range.h:121
const_iterator end() const
Definition: Range.h:66
size_t size_type
Definition: Range.h:44
bool is_divisible() const
Definition: Range.h:97
size_type size() const
Definition: Range.h:61
Definition: NanoVDB.h:184
bool empty() const
Definition: Range.h:62
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:109
Range(Range &r, Split)
Definition: Range.h:84
Range(T beginX, T endX, T beginY, T endY, T beginZ, T endZ)
Definition: Range.h:117
T middle() const
Definition: Range.h:60
bool is_divisible() const
Definition: Range.h:143
Definition: Range.h:28
bool operator==(const Range &rhs) const
Definition: Range.h:59
Range(T beginRow, T endRow, T beginCol, T endCol)
Definition: Range.h:81
Range(T begin, T end, size_type grainsize=size_type(1))
Definition: Range.h:46
size_type grainsize() const
Definition: Range.h:63
T const_iterator
Definition: Range.h:43
bool operator==(const Range &rhs) const
Definition: Range.h:141
bool empty() const
Definition: Range.h:96
Range(const Range< 1, T > &rangeX, const Range< 1, T > &rangeY, const Range< 1, T > &rangeZ)
Definition: Range.h:108
Range(Range &r, Split)
Split constructor: r[a,b[ -> r[a,b/2[ & this[b/2,b[.
Definition: Range.h:52
bool is_divisible() const
Definition: Range.h:64
typename Range< 1, T >::size_type size_type
Definition: Range.h:75
Definition: Range.h:25
Range(T beginRow, T endRow, size_type grainsizeRow, T beginCol, T endCol, size_type grainsizeCol)
Definition: Range.h:77
bool operator==(const Range &rhs) const
Definition: Range.h:95