xref: /oneTBB/test/tbb/test_blocked_range.cpp (revision 478de5b1)
151c0b2f7Stbbdev /*
2b15aabb3Stbbdev     Copyright (c) 2005-2021 Intel Corporation
351c0b2f7Stbbdev 
451c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev     you may not use this file except in compliance with the License.
651c0b2f7Stbbdev     You may obtain a copy of the License at
751c0b2f7Stbbdev 
851c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev 
1051c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev     See the License for the specific language governing permissions and
1451c0b2f7Stbbdev     limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev 
1751c0b2f7Stbbdev #include "common/test.h"
1851c0b2f7Stbbdev #include "common/utils.h"
1951c0b2f7Stbbdev #include "common/utils_report.h"
2051c0b2f7Stbbdev #include "common/range_based_for_support.h"
2151c0b2f7Stbbdev #include "common/config.h"
22*478de5b1Stbbdev #include "common/concepts_common.h"
2351c0b2f7Stbbdev 
2451c0b2f7Stbbdev #include "tbb/blocked_range.h"
25*478de5b1Stbbdev #include "tbb/blocked_range2d.h"
26*478de5b1Stbbdev #include "tbb/blocked_range3d.h"
27*478de5b1Stbbdev #define TBB_PREVIEW_BLOCKED_RANGE_ND 1
28*478de5b1Stbbdev #include "tbb/blocked_rangeNd.h"
2951c0b2f7Stbbdev 
3051c0b2f7Stbbdev //! \file test_blocked_range.cpp
3151c0b2f7Stbbdev //! \brief Test for [algorithms.blocked_range] specification
3251c0b2f7Stbbdev 
3351c0b2f7Stbbdev #include <utility> //for std::pair
3451c0b2f7Stbbdev #include <functional>
35*478de5b1Stbbdev #include <vector>
3651c0b2f7Stbbdev 
3751c0b2f7Stbbdev //! Testing blocked_range with range based for
3851c0b2f7Stbbdev //! \brief \ref interface
3951c0b2f7Stbbdev TEST_CASE("Range based for") {
4051c0b2f7Stbbdev     using namespace range_based_for_support_tests;
4151c0b2f7Stbbdev 
4251c0b2f7Stbbdev     const std::size_t sequence_length = 100;
4351c0b2f7Stbbdev     std::size_t int_array[sequence_length] = {0};
4451c0b2f7Stbbdev 
4551c0b2f7Stbbdev     for (std::size_t i = 0; i < sequence_length; ++i) {
4651c0b2f7Stbbdev         int_array[i] = i + 1;
4751c0b2f7Stbbdev     }
4851c0b2f7Stbbdev     const tbb::blocked_range<std::size_t*> r(int_array, int_array + sequence_length, 1);
4951c0b2f7Stbbdev 
5051c0b2f7Stbbdev     CHECK_MESSAGE(range_based_for_accumulate<std::size_t>(r, std::plus<std::size_t>(), std::size_t(0))
5151c0b2f7Stbbdev             == gauss_summ_of_int_sequence(sequence_length), "incorrect accumulated value generated via range based for ?");
5251c0b2f7Stbbdev }
5351c0b2f7Stbbdev 
5451c0b2f7Stbbdev //! Proportional split does not overflow with blocked range
5551c0b2f7Stbbdev //! \brief \ref error_guessing \ref boundary
5651c0b2f7Stbbdev TEST_CASE("Proportional split overflow") {
5751c0b2f7Stbbdev     using tbb::blocked_range;
5851c0b2f7Stbbdev     using tbb::proportional_split;
5951c0b2f7Stbbdev 
6051c0b2f7Stbbdev     blocked_range<std::size_t> r1(0, std::size_t(-1) / 2);
6151c0b2f7Stbbdev     std::size_t size = r1.size();
6251c0b2f7Stbbdev     std::size_t begin = r1.begin();
6351c0b2f7Stbbdev     std::size_t end = r1.end();
6451c0b2f7Stbbdev 
6551c0b2f7Stbbdev     proportional_split p(1, 3);
6651c0b2f7Stbbdev     blocked_range<std::size_t> r2(r1, p);
6751c0b2f7Stbbdev 
6851c0b2f7Stbbdev     // overflow-free computation
6951c0b2f7Stbbdev     std::size_t parts = p.left() + p.right();
7051c0b2f7Stbbdev     std::size_t int_part = size / parts;
7151c0b2f7Stbbdev     std::size_t fraction = size - int_part * parts; // fraction < parts
7251c0b2f7Stbbdev     std::size_t right_idx = int_part * p.right() + fraction * p.right() / parts + 1;
7351c0b2f7Stbbdev     std::size_t newRangeBegin = end - right_idx;
7451c0b2f7Stbbdev 
7551c0b2f7Stbbdev     // Division in 'right_idx' very likely is inexact also.
7651c0b2f7Stbbdev     std::size_t tolerance = 1;
7751c0b2f7Stbbdev     std::size_t diff = (r2.begin() < newRangeBegin) ? (newRangeBegin - r2.begin()) : (r2.begin() - newRangeBegin);
7851c0b2f7Stbbdev     bool is_split_correct = diff <= tolerance;
7951c0b2f7Stbbdev     bool test_passed = (r1.begin() == begin && r1.end() == r2.begin() && is_split_correct &&
8051c0b2f7Stbbdev                         r2.end() == end);
8151c0b2f7Stbbdev     if (!test_passed) {
8251c0b2f7Stbbdev         REPORT("Incorrect split of blocked range[%lu, %lu) into r1[%lu, %lu) and r2[%lu, %lu), "
8351c0b2f7Stbbdev                "must be r1[%lu, %lu) and r2[%lu, %lu)\n", begin, end, r1.begin(), r1.end(), r2.begin(), r2.end(), begin, newRangeBegin, newRangeBegin, end);
8451c0b2f7Stbbdev         CHECK(test_passed);
8551c0b2f7Stbbdev     }
8651c0b2f7Stbbdev }
8751c0b2f7Stbbdev 
88*478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
89*478de5b1Stbbdev 
90*478de5b1Stbbdev template <bool ExpectSatisfies, typename... Types>
91*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range, Types> == ExpectSatisfies))
test_blocked_range_constraint()92*478de5b1Stbbdev void test_blocked_range_constraint() {}
93*478de5b1Stbbdev 
94*478de5b1Stbbdev template <bool ExpectSatisfies, typename... Types>
95*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range2d, Types, Types> == ExpectSatisfies))
test_blocked_range2d_constraint()96*478de5b1Stbbdev void test_blocked_range2d_constraint() {}
97*478de5b1Stbbdev 
98*478de5b1Stbbdev template <typename... Types>
99*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range2d, Types, test_concepts::Dummy> == false))
test_blocked_range2d_col_invalid_constraint()100*478de5b1Stbbdev void test_blocked_range2d_col_invalid_constraint() {}
101*478de5b1Stbbdev 
102*478de5b1Stbbdev template <typename... Types>
103*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range2d, test_concepts::Dummy, Types> == false))
test_blocked_range2d_row_invalid_constraint()104*478de5b1Stbbdev void test_blocked_range2d_row_invalid_constraint() {}
105*478de5b1Stbbdev 
106*478de5b1Stbbdev template <bool ExpectSatisfies, typename... Types>
107*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range3d, Types, Types, Types> == ExpectSatisfies))
test_blocked_range3d_constraint()108*478de5b1Stbbdev void test_blocked_range3d_constraint() {}
109*478de5b1Stbbdev 
110*478de5b1Stbbdev template <typename... Types>
111*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range3d, test_concepts::Dummy, Types, Types> == false))
test_blocked_range3d_page_invalid_constraint()112*478de5b1Stbbdev void test_blocked_range3d_page_invalid_constraint() {}
113*478de5b1Stbbdev 
114*478de5b1Stbbdev template <typename... Types>
115*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range3d, Types, test_concepts::Dummy, Types> == false))
test_blocked_range3d_row_invalid_constraint()116*478de5b1Stbbdev void test_blocked_range3d_row_invalid_constraint() {}
117*478de5b1Stbbdev 
118*478de5b1Stbbdev template <typename... Types>
119*478de5b1Stbbdev     requires (... && (utils::well_formed_instantiation<tbb::blocked_range3d, Types, Types, test_concepts::Dummy> == false))
test_blocked_range3d_col_invalid_constraint()120*478de5b1Stbbdev void test_blocked_range3d_col_invalid_constraint() {}
121*478de5b1Stbbdev 
122*478de5b1Stbbdev template <typename T>
123*478de5b1Stbbdev concept well_formed_blocked_range_Nd_instantiation_basic = requires {
124*478de5b1Stbbdev     typename tbb::blocked_rangeNd<T, 1>;
125*478de5b1Stbbdev };
126*478de5b1Stbbdev 
127*478de5b1Stbbdev template <typename... Types>
128*478de5b1Stbbdev concept well_formed_blocked_range_Nd_instantiation = ( ... && well_formed_blocked_range_Nd_instantiation_basic<Types> );
129*478de5b1Stbbdev 
130*478de5b1Stbbdev //! \brief \ref error_guessing
131*478de5b1Stbbdev TEST_CASE("constraints for blocked_range value") {
132*478de5b1Stbbdev     using namespace test_concepts::blocked_range_value;
133*478de5b1Stbbdev     using const_iterator = typename std::vector<int>::const_iterator;
134*478de5b1Stbbdev 
135*478de5b1Stbbdev     test_blocked_range_constraint</*Expected = */true,
136*478de5b1Stbbdev                                   Correct, char, int, std::size_t, const_iterator>();
137*478de5b1Stbbdev 
138*478de5b1Stbbdev     test_blocked_range_constraint</*Expected = */false,
139*478de5b1Stbbdev                                   NonCopyable, NonCopyAssignable, NonDestructible,
140*478de5b1Stbbdev                                   NoOperatorLess, OperatorLessNonConst, WrongReturnOperatorLess,
141*478de5b1Stbbdev                                   NoOperatorMinus, OperatorMinusNonConst, WrongReturnOperatorMinus,
142*478de5b1Stbbdev                                   NoOperatorPlus, OperatorPlusNonConst, WrongReturnOperatorPlus>();
143*478de5b1Stbbdev }
144*478de5b1Stbbdev 
145*478de5b1Stbbdev //! \brief \ref error_guessing
146*478de5b1Stbbdev TEST_CASE("constraints for blocked_range2d value") {
147*478de5b1Stbbdev     using namespace test_concepts::blocked_range_value;
148*478de5b1Stbbdev     using const_iterator = typename std::vector<int>::const_iterator;
149*478de5b1Stbbdev 
150*478de5b1Stbbdev     test_blocked_range2d_constraint</*Expected = */true,
151*478de5b1Stbbdev                                     Correct, char, int, std::size_t, const_iterator>();
152*478de5b1Stbbdev 
153*478de5b1Stbbdev     test_blocked_range2d_constraint</*Expected = */false,
154*478de5b1Stbbdev                                     NonCopyable, NonCopyAssignable, NonDestructible,
155*478de5b1Stbbdev                                     NoOperatorLess, OperatorLessNonConst, WrongReturnOperatorLess,
156*478de5b1Stbbdev                                     NoOperatorMinus, OperatorMinusNonConst, WrongReturnOperatorMinus,
157*478de5b1Stbbdev                                     NoOperatorPlus, OperatorPlusNonConst, WrongReturnOperatorPlus>();
158*478de5b1Stbbdev 
159*478de5b1Stbbdev     test_blocked_range2d_row_invalid_constraint<Correct, char, int, std::size_t, const_iterator>();
160*478de5b1Stbbdev     test_blocked_range2d_col_invalid_constraint<Correct, char, int, std::size_t, const_iterator>();
161*478de5b1Stbbdev }
162*478de5b1Stbbdev 
163*478de5b1Stbbdev //! \brief \ref error_guessing
164*478de5b1Stbbdev TEST_CASE("constraints for blocked_range3d value") {
165*478de5b1Stbbdev     using namespace test_concepts::blocked_range_value;
166*478de5b1Stbbdev     using const_iterator = typename std::vector<int>::const_iterator;
167*478de5b1Stbbdev 
168*478de5b1Stbbdev     test_blocked_range3d_constraint</*Expected = */true,
169*478de5b1Stbbdev                                     Correct, char, int, std::size_t, const_iterator>();
170*478de5b1Stbbdev 
171*478de5b1Stbbdev     test_blocked_range3d_constraint</*Expected = */false,
172*478de5b1Stbbdev                                     NonCopyable, NonCopyAssignable, NonDestructible,
173*478de5b1Stbbdev                                     NoOperatorLess, OperatorLessNonConst, WrongReturnOperatorLess,
174*478de5b1Stbbdev                                     NoOperatorMinus, OperatorMinusNonConst, WrongReturnOperatorMinus,
175*478de5b1Stbbdev                                     NoOperatorPlus, OperatorPlusNonConst, WrongReturnOperatorPlus>();
176*478de5b1Stbbdev 
177*478de5b1Stbbdev     test_blocked_range3d_page_invalid_constraint<Correct, char, int, std::size_t, const_iterator>();
178*478de5b1Stbbdev     test_blocked_range3d_row_invalid_constraint<Correct, char, int, std::size_t, const_iterator>();
179*478de5b1Stbbdev     test_blocked_range3d_col_invalid_constraint<Correct, char, int, std::size_t, const_iterator>();
180*478de5b1Stbbdev }
181*478de5b1Stbbdev 
182*478de5b1Stbbdev //! \brief \ref error_guessing
183*478de5b1Stbbdev TEST_CASE("constraints for blocked_rangeNd value") {
184*478de5b1Stbbdev     using namespace test_concepts::blocked_range_value;
185*478de5b1Stbbdev     using const_iterator = typename std::vector<int>::const_iterator;
186*478de5b1Stbbdev 
187*478de5b1Stbbdev     static_assert(well_formed_blocked_range_Nd_instantiation<Correct, char, int, std::size_t, const_iterator>);
188*478de5b1Stbbdev 
189*478de5b1Stbbdev     static_assert(!well_formed_blocked_range_Nd_instantiation<NonCopyable, NonCopyAssignable, NonDestructible,
190*478de5b1Stbbdev                                                               NoOperatorLess, OperatorLessNonConst, WrongReturnOperatorLess,
191*478de5b1Stbbdev                                                               NoOperatorMinus, OperatorMinusNonConst, WrongReturnOperatorMinus,
192*478de5b1Stbbdev                                                               NoOperatorPlus, OperatorPlusNonConst, WrongReturnOperatorPlus>);
193*478de5b1Stbbdev }
194*478de5b1Stbbdev 
195*478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
196