1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 #ifndef __TBB_blocked_range3d_H
18 #define __TBB_blocked_range3d_H
19 
20 #include <cstddef>
21 
22 #include "detail/_config.h"
23 #include "detail/_namespace_injection.h"
24 
25 #include "blocked_range.h"
26 
27 namespace tbb {
28 namespace detail {
29 namespace d1 {
30 
31 //! A 3-dimensional range that models the Range concept.
32 /** @ingroup algorithms */
33 template<typename PageValue, typename RowValue = PageValue, typename ColValue = RowValue>
__TBB_requires(blocked_range_value<PageValue> && blocked_range_value<RowValue> && blocked_range_value<ColValue>)34     __TBB_requires(blocked_range_value<PageValue> &&
35                    blocked_range_value<RowValue> &&
36                    blocked_range_value<ColValue>)
37 class blocked_range3d {
38 public:
39     //! Type for size of an iteration range
40     using page_range_type = blocked_range<PageValue>;
41     using row_range_type = blocked_range<RowValue>;
42     using col_range_type = blocked_range<ColValue>;
43 
44 private:
45     page_range_type my_pages;
46     row_range_type  my_rows;
47     col_range_type  my_cols;
48 
49 public:
50 
51     blocked_range3d( PageValue page_begin, PageValue page_end,
52                      RowValue  row_begin,  RowValue row_end,
53                      ColValue  col_begin,  ColValue col_end ) :
54         my_pages(page_begin,page_end),
55         my_rows(row_begin,row_end),
56         my_cols(col_begin,col_end)
57     {}
58 
59     blocked_range3d( PageValue page_begin, PageValue page_end, typename page_range_type::size_type page_grainsize,
60                      RowValue  row_begin,  RowValue row_end,   typename row_range_type::size_type row_grainsize,
61                      ColValue  col_begin,  ColValue col_end,   typename col_range_type::size_type col_grainsize ) :
62         my_pages(page_begin,page_end,page_grainsize),
63         my_rows(row_begin,row_end,row_grainsize),
64         my_cols(col_begin,col_end,col_grainsize)
65     {}
66 
67     //! True if range is empty
68     bool empty() const {
69         // Range is empty if at least one dimension is empty.
70         return my_pages.empty() || my_rows.empty() || my_cols.empty();
71     }
72 
73     //! True if range is divisible into two pieces.
74     bool is_divisible() const {
75         return  my_pages.is_divisible() || my_rows.is_divisible() || my_cols.is_divisible();
76     }
77 
78     blocked_range3d( blocked_range3d& r, split split_obj ) :
79         my_pages(r.my_pages),
80         my_rows(r.my_rows),
81         my_cols(r.my_cols)
82     {
83         do_split(r, split_obj);
84     }
85 
86     blocked_range3d( blocked_range3d& r, proportional_split& proportion ) :
87         my_pages(r.my_pages),
88         my_rows(r.my_rows),
89         my_cols(r.my_cols)
90     {
91         do_split(r, proportion);
92     }
93 
94     //! The pages of the iteration space
95     const page_range_type& pages() const { return my_pages; }
96 
97     //! The rows of the iteration space
98     const row_range_type& rows() const { return my_rows; }
99 
100     //! The columns of the iteration space
101     const col_range_type& cols() const { return my_cols; }
102 
103 private:
104     template <typename Split>
105     void do_split( blocked_range3d& r, Split& split_obj) {
106         if ( my_pages.size()*double(my_rows.grainsize()) < my_rows.size()*double(my_pages.grainsize()) ) {
107             if ( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) {
108                 my_cols.my_begin = col_range_type::do_split(r.my_cols, split_obj);
109             } else {
110                 my_rows.my_begin = row_range_type::do_split(r.my_rows, split_obj);
111             }
112         } else {
113             if ( my_pages.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_pages.grainsize()) ) {
114                 my_cols.my_begin = col_range_type::do_split(r.my_cols, split_obj);
115             } else {
116                 my_pages.my_begin = page_range_type::do_split(r.my_pages, split_obj);
117             }
118         }
119     }
120 };
121 
122 } // namespace d1
123 } // namespace detail
124 
125 inline namespace v1 {
126 using detail::d1::blocked_range3d;
127 } // namespace v1
128 } // namespace tbb
129 
130 #endif /* __TBB_blocked_range3d_H */
131