OpenVDB: nanovdb/util/Range.h Source File

OpenVDB 12.1.0

Loading...
Searching...
No Matches
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
24namespace nanovdb {
25
26namespace util {
27
28 class Split {};// Dummy class used by split constructors
29
30template <int, typename>
31 class Range;
32
33 using Range1D = Range<1, size_t>;
34 using Range2D = Range<2, size_t>;
35 using Range3D = Range<3, size_t>;
36
37// template specialization for Rank = 1
38template <typename T>
39 class Range<1, T>
40{
41 T mBegin, mEnd;
42 size_t mGrainsize;
43 template<int, typename>
44 friend class Range;
45public:
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
73template <typename T>
74 class Range<2, T>
75{
76 Range<1, T> mRange[2];
77public:
78 using size_type = typename Range<1, T>::size_type;
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
105template <typename T>
106 class Range<3, T>
107{
108 Range<1, T> mRange[3];
109public:
110 using size_type = typename Range<1, T>::size_type;
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
152using Range1D [[deprecated("Use nanovdb::util::Range1D instead")]] = util::Range<1, size_t>;
153using Range2D [[deprecated("Use nanovdb::util::Range2D instead")]] = util::Range<2, size_t>;
154using 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
nanovdb::util::Range< 1, T >::Range
Range(T begin, T end, size_type grainsize=size_type(1))
Definition Range.h:49
nanovdb::util::Range< 1, T >::begin
const_iterator begin() const
Definition Range.h:68
nanovdb::util::Range< 1, T >::is_divisible
bool is_divisible() const
Definition Range.h:67
nanovdb::util::Range< 1, T >::Range
Range(const Range &)=default
nanovdb::util::Range< 1, T >::size
size_type size() const
Definition Range.h:64
nanovdb::util::Range< 1, T >::empty
bool empty() const
Definition Range.h:65
nanovdb::util::Range< 1, T >::size_type
size_t size_type
Definition Range.h:47
nanovdb::util::Range< 1, T >::grainsize
size_type grainsize() const
Definition Range.h:66
nanovdb::util::Range< 1, T >::operator==
bool operator==(const Range &rhs) const
Definition Range.h:62
nanovdb::util::Range< 1, T >::end
const_iterator end() const
Definition Range.h:69
nanovdb::util::Range< 1, T >::middle
T middle() const
Definition Range.h:63
nanovdb::util::Range< 1, T >::Range
Range(Range &r, Split)
Split constructor: r[a,b[ -> r[a,b/2[ & this[b/2,b[.
Definition Range.h:55
nanovdb::util::Range< 1, T >::Range
friend class Range
Definition Range.h:44
nanovdb::util::Range< 1, T >::const_iterator
T const_iterator
Definition Range.h:46
nanovdb::util::Range< 2, T >::operator[]
const Range< 1, T > & operator[](int i) const
Definition Range.h:101
nanovdb::util::Range< 2, T >::is_divisible
bool is_divisible() const
Definition Range.h:100
nanovdb::util::Range< 2, T >::Range
Range(const Range< 1, T > &rangeRow, const Range< 1, T > &rangeCol)
Definition Range.h:79
nanovdb::util::Range< 2, T >::Range
Range(T beginRow, T endRow, size_type grainsizeRow, T beginCol, T endCol, size_type grainsizeCol)
Definition Range.h:80
nanovdb::util::Range< 2, T >::size_type
typename Range< 1, T >::size_type size_type
Definition Range.h:78
nanovdb::util::Range< 2, T >::empty
bool empty() const
Definition Range.h:99
nanovdb::util::Range< 2, T >::Range
Range(T beginRow, T endRow, T beginCol, T endCol)
Definition Range.h:84
nanovdb::util::Range< 2, T >::operator==
bool operator==(const Range &rhs) const
Definition Range.h:98
nanovdb::util::Range< 2, T >::Range
Range(Range &r, Split)
Definition Range.h:87
nanovdb::util::Range< 3, T >::Range
Range(const Range< 1, T > &rangeX, const Range< 1, T > &rangeY, const Range< 1, T > &rangeZ)
Definition Range.h:111
nanovdb::util::Range< 3, T >::operator[]
const Range< 1, T > & operator[](int i) const
Definition Range.h:147
nanovdb::util::Range< 3, T >::is_divisible
bool is_divisible() const
Definition Range.h:146
nanovdb::util::Range< 3, T >::Range
Range(T beginX, T endX, T beginY, T endY, T beginZ, T endZ)
Definition Range.h:120
nanovdb::util::Range< 3, T >::size_type
typename Range< 1, T >::size_type size_type
Definition Range.h:110
nanovdb::util::Range< 3, T >::Range
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
nanovdb::util::Range< 3, T >::empty
bool empty() const
Definition Range.h:145
nanovdb::util::Range< 3, T >::operator==
bool operator==(const Range &rhs) const
Definition Range.h:144
nanovdb::util::Range< 3, T >::Range
Range(Range &r, Split)
Definition Range.h:124
nanovdb::util::Range
Definition Range.h:31
nanovdb::util::Split
Definition Range.h:28
nanovdb::util
Definition ForEach.h:29
nanovdb::util::Range3D
Range< 3, size_t > Range3D
Definition Range.h:35
nanovdb::util::empty
bool empty(const char *str)
tests if a c-string str is empty, that is its first value is '\0'
Definition Util.h:144
nanovdb::util::Range2D
Range< 2, size_t > Range2D
Definition Range.h:34
nanovdb::util::Range1D
Range< 1, size_t > Range1D
Definition Range.h:33
nanovdb
Definition GridHandle.h:27