Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/oneapi/tbb/blocked_rangeNd.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     Copyright (c) 2017-2021 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 <algorithm>    // std::any_of
0025 #include <array>
0026 #include <cstddef>
0027 #include <type_traits>  // std::is_same, std::enable_if
0028 
0029 #include "detail/_config.h"
0030 #include "detail/_template_helpers.h" // index_sequence, make_index_sequence
0031 #include "detail/_range_common.h"
0032 
0033 #include "blocked_range.h"
0034 
0035 namespace tbb {
0036 namespace detail {
0037 namespace d1 {
0038 
0039 /*
0040     The blocked_rangeNd_impl uses make_index_sequence<N> to automatically generate a ctor with
0041     exactly N arguments of the type tbb::blocked_range<Value>. Such ctor provides an opportunity
0042     to use braced-init-list parameters to initialize each dimension.
0043     Use of parameters, whose representation is a braced-init-list, but they're not
0044     std::initializer_list or a reference to one, produces a non-deduced context
0045     within template argument deduction.
0046 
0047     NOTE: blocked_rangeNd must be exactly a templated alias to the blocked_rangeNd_impl
0048     (and not e.g. a derived class), otherwise it would need to declare its own ctor
0049     facing the same problem that the impl class solves.
0050 */
0051 
0052 template<typename Value, unsigned int N, typename = detail::make_index_sequence<N>>
0053     __TBB_requires(blocked_range_value<Value>)
0054 class blocked_rangeNd_impl;
0055 
0056 template<typename Value, unsigned int N, std::size_t... Is>
0057     __TBB_requires(blocked_range_value<Value>)
0058 class blocked_rangeNd_impl<Value, N, detail::index_sequence<Is...>> {
0059 public:
0060     //! Type of a value.
0061     using value_type = Value;
0062 
0063 private:
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     blocked_rangeNd_impl(blocked_rangeNd_impl& r, proportional_split proportion) : my_dims(r.my_dims) {
0102         do_split(r, proportion);
0103     }
0104 
0105     blocked_rangeNd_impl(blocked_rangeNd_impl& r, split proportion) : my_dims(r.my_dims) {
0106         do_split(r, proportion);
0107     }
0108 
0109 private:
0110     static_assert(N != 0, "zero dimensional blocked_rangeNd can't be constructed");
0111 
0112     //! Ranges in each dimension.
0113     std::array<tbb::blocked_range<value_type>, N> my_dims;
0114 
0115     template<typename split_type>
0116     void do_split(blocked_rangeNd_impl& r, split_type proportion) {
0117         static_assert((std::is_same<split_type, split>::value || std::is_same<split_type, proportional_split>::value), "type of split object is incorrect");
0118         __TBB_ASSERT(r.is_divisible(), "can't split not divisible range");
0119 
0120         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) {
0121             return (first.size() * second.grainsize() < second.size() * first.grainsize());
0122         });
0123 
0124         auto r_it = r.my_dims.begin() + (my_it - my_dims.begin());
0125 
0126         my_it->my_begin = tbb::blocked_range<value_type>::do_split(*r_it, proportion);
0127 
0128         // (!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin)) equals to
0129         // (my_it->my_begin == r_it->my_end), but we can't use operator== due to Value concept
0130         __TBB_ASSERT(!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin),
0131                      "blocked_range has been split incorrectly");
0132     }
0133 };
0134 
0135 template<typename Value, unsigned int N>
0136 using blocked_rangeNd = blocked_rangeNd_impl<Value, N>;
0137 
0138 } // namespace d1
0139 } // namespace detail
0140 
0141 inline namespace v1 {
0142 using detail::d1::blocked_rangeNd;
0143 } // namespace v1
0144 } // namespace tbb
0145 
0146 #endif /* __TBB_blocked_rangeNd_H */
0147