File indexing completed on 2025-01-18 10:12:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_blocked_rangeNd_H
0018 #define __TBB_blocked_rangeNd_H
0019
0020 #if ! TBB_PREVIEW_BLOCKED_RANGE_ND
0021 #error Set TBB_PREVIEW_BLOCKED_RANGE_ND to include blocked_rangeNd.h
0022 #endif
0023
0024 #include "tbb_config.h"
0025
0026
0027 #if __TBB_CPP11_PRESENT && __TBB_CPP11_ARRAY_PRESENT && __TBB_CPP11_TEMPLATE_ALIASES_PRESENT
0028
0029 #include "internal/_template_helpers.h" // index_sequence, make_index_sequence
0030
0031 #include <array>
0032 #include <algorithm> // std::any_of
0033 #include <type_traits> // std::is_same, std::enable_if
0034
0035 #include "tbb/blocked_range.h"
0036
0037 namespace tbb {
0038 namespace internal {
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 template<typename Value, unsigned int N, typename = make_index_sequence<N>>
0054 class blocked_rangeNd_impl;
0055
0056 template<typename Value, unsigned int N, std::size_t... Is>
0057 class blocked_rangeNd_impl<Value, N, index_sequence<Is...>> {
0058 public:
0059
0060 using value_type = Value;
0061
0062 private:
0063
0064
0065 template<std::size_t>
0066 using dim_type_helper = tbb::blocked_range<value_type>;
0067
0068 public:
0069 blocked_rangeNd_impl() = delete;
0070
0071
0072 blocked_rangeNd_impl(const dim_type_helper<Is>&... args) : my_dims{ {args...} } {}
0073
0074
0075 static constexpr unsigned int ndims() { return N; }
0076
0077
0078 const tbb::blocked_range<value_type>& dim(unsigned int dimension) const {
0079 __TBB_ASSERT(dimension < N, "out of bound");
0080 return my_dims[dimension];
0081 }
0082
0083
0084
0085
0086
0087
0088 bool empty() const {
0089 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
0090 return d.empty();
0091 });
0092 }
0093
0094
0095 bool is_divisible() const {
0096 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
0097 return d.is_divisible();
0098 });
0099 }
0100
0101 #if __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
0102
0103 static const bool is_splittable_in_proportion = true;
0104
0105 blocked_rangeNd_impl(blocked_rangeNd_impl& r, proportional_split proportion) : my_dims(r.my_dims) {
0106 do_split(r, proportion);
0107 }
0108 #endif
0109
0110 blocked_rangeNd_impl(blocked_rangeNd_impl& r, split proportion) : my_dims(r.my_dims) {
0111 do_split(r, proportion);
0112 }
0113
0114 private:
0115 __TBB_STATIC_ASSERT(N != 0, "zero dimensional blocked_rangeNd can't be constructed");
0116
0117
0118 std::array<tbb::blocked_range<value_type>, N> my_dims;
0119
0120 template<typename split_type>
0121 void do_split(blocked_rangeNd_impl& r, split_type proportion) {
0122 __TBB_STATIC_ASSERT((is_same_type<split_type, split>::value
0123 || is_same_type<split_type, proportional_split>::value),
0124 "type of split object is incorrect");
0125 __TBB_ASSERT(r.is_divisible(), "can't split not divisible range");
0126
0127 auto my_it = std::max_element(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& first, const tbb::blocked_range<value_type>& second) {
0128 return (first.size() * second.grainsize() < second.size() * first.grainsize());
0129 });
0130
0131 auto r_it = r.my_dims.begin() + (my_it - my_dims.begin());
0132
0133 my_it->my_begin = tbb::blocked_range<value_type>::do_split(*r_it, proportion);
0134
0135
0136
0137 __TBB_ASSERT(!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin),
0138 "blocked_range has been split incorrectly");
0139 }
0140 };
0141
0142 }
0143
0144 template<typename Value, unsigned int N>
0145 using blocked_rangeNd = internal::blocked_rangeNd_impl<Value, N>;
0146
0147 }
0148
0149 #endif
0150 #endif