Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:51

0001 /*
0002     Copyright (c) 2017-2020 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
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 // tbb::blocked_rangeNd requires C++11 support
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     The blocked_rangeNd_impl uses make_index_sequence<N> to automatically generate a ctor with
0042     exactly N arguments of the type tbb::blocked_range<Value>. Such ctor provides an opportunity
0043     to use braced-init-list parameters to initialize each dimension.
0044     Use of parameters, whose representation is a braced-init-list, but they're not
0045     std::initializer_list or a reference to one, produces a non-deduced context
0046     within template argument deduction.
0047 
0048     NOTE: blocked_rangeNd must be exactly a templated alias to the blocked_rangeNd_impl
0049     (and not e.g. a derived class), otherwise it would need to declare its own ctor
0050     facing the same problem that the impl class solves.
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     //! Type of a value.
0060     using value_type = Value;
0061 
0062 private:
0063 
0064     //! Helper type to construct range with N tbb::blocked_range<value_type> objects.
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     //! Constructs N-dimensional range over N half-open intervals each represented as tbb::blocked_range<Value>.
0072     blocked_rangeNd_impl(const dim_type_helper<Is>&... args) : my_dims{ {args...} } {}
0073 
0074     //! Dimensionality of a range.
0075     static constexpr unsigned int ndims() { return N; }
0076 
0077     //! Range in certain dimension.
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     // Methods that implement Range concept
0085     //------------------------------------------------------------------------
0086 
0087     //! True if at least one dimension is empty.
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     //! True if at least one dimension is divisible.
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     //! Static field to support proportional split.
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     //! Ranges in each dimension.
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         // (!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin)) equals to
0136         // (my_it->my_begin == r_it->my_end), but we can't use operator== due to Value concept
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 } // namespace internal
0143 
0144 template<typename Value, unsigned int N>
0145 using blocked_rangeNd = internal::blocked_rangeNd_impl<Value, N>;
0146 
0147 } // namespace tbb
0148 
0149 #endif /* __TBB_CPP11_PRESENT && __TBB_CPP11_ARRAY_PRESENT && __TBB_CPP11_TEMPLATE_ALIASES_PRESENT */
0150 #endif /* __TBB_blocked_rangeNd_H */