1/*
2 Copyright (c) 2005-2019 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#include "tbb/blocked_range3d.h"
18#include "harness_assert.h"
19
20// First test as much as we can without including other headers.
21// Doing so should catch problems arising from failing to include headers.
22
23template<typename Tag>
24class AbstractValueType {
25 AbstractValueType() {}
26 int value;
27public:
28 template<typename OtherTag>
29 friend AbstractValueType<OtherTag> MakeAbstractValueType( int i );
30
31 template<typename OtherTag>
32 friend int GetValueOf( const AbstractValueType<OtherTag>& v ) ;
33};
34
35template<typename Tag>
36AbstractValueType<Tag> MakeAbstractValueType( int i ) {
37 AbstractValueType<Tag> x;
38 x.value = i;
39 return x;
40}
41
42template<typename Tag>
43int GetValueOf( const AbstractValueType<Tag>& v ) {return v.value;}
44
45template<typename Tag>
46bool operator<( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) {
47 return GetValueOf(u)<GetValueOf(v);
48}
49
50template<typename Tag>
51std::size_t operator-( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) {
52 return GetValueOf(u)-GetValueOf(v);
53}
54
55template<typename Tag>
56AbstractValueType<Tag> operator+( const AbstractValueType<Tag>& u, std::size_t offset ) {
57 return MakeAbstractValueType<Tag>(GetValueOf(u)+int(offset));
58}
59
60struct PageTag {};
61struct RowTag {};
62struct ColTag {};
63
64static void SerialTest() {
65 typedef AbstractValueType<PageTag> page_type;
66 typedef AbstractValueType<RowTag> row_type;
67 typedef AbstractValueType<ColTag> col_type;
68 typedef tbb::blocked_range3d<page_type,row_type,col_type> range_type;
69 for( int page_x=-4; page_x<4; ++page_x ) {
70 for( int page_y=page_x; page_y<4; ++page_y ) {
71 page_type page_i = MakeAbstractValueType<PageTag>(page_x);
72 page_type page_j = MakeAbstractValueType<PageTag>(page_y);
73 for( int page_grain=1; page_grain<4; ++page_grain ) {
74 for( int row_x=-4; row_x<4; ++row_x ) {
75 for( int row_y=row_x; row_y<4; ++row_y ) {
76 row_type row_i = MakeAbstractValueType<RowTag>(row_x);
77 row_type row_j = MakeAbstractValueType<RowTag>(row_y);
78 for( int row_grain=1; row_grain<4; ++row_grain ) {
79 for( int col_x=-4; col_x<4; ++col_x ) {
80 for( int col_y=col_x; col_y<4; ++col_y ) {
81 col_type col_i = MakeAbstractValueType<ColTag>(col_x);
82 col_type col_j = MakeAbstractValueType<ColTag>(col_y);
83 for( int col_grain=1; col_grain<4; ++col_grain ) {
84 range_type r( page_i, page_j, page_grain, row_i, row_j, row_grain, col_i, col_j, col_grain );
85 AssertSameType( r.is_divisible(), true );
86
87 AssertSameType( r.empty(), true );
88
89 AssertSameType( static_cast<range_type::page_range_type::const_iterator*>(0), static_cast<page_type*>(0) );
90 AssertSameType( static_cast<range_type::row_range_type::const_iterator*>(0), static_cast<row_type*>(0) );
91 AssertSameType( static_cast<range_type::col_range_type::const_iterator*>(0), static_cast<col_type*>(0) );
92
93 AssertSameType( r.pages(), tbb::blocked_range<page_type>( page_i, page_j, 1 ));
94 AssertSameType( r.rows(), tbb::blocked_range<row_type>( row_i, row_j, 1 ));
95 AssertSameType( r.cols(), tbb::blocked_range<col_type>( col_i, col_j, 1 ));
96
97 ASSERT( r.empty()==(page_x==page_y||row_x==row_y||col_x==col_y), NULL );
98
99 ASSERT( r.is_divisible()==(page_y-page_x>page_grain||row_y-row_x>row_grain||col_y-col_x>col_grain), NULL );
100
101 if( r.is_divisible() ) {
102 range_type r2(r,tbb::split());
103 if( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin())) ) {
104 ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL );
105 ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL );
106 ASSERT( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()), NULL );
107 } else {
108 if ( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.cols().begin())==GetValueOf(r.cols().begin())) ) {
109 ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL );
110 ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL );
111 ASSERT( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()), NULL );
112 } else {
113 ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL );
114 ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL );
115 ASSERT( GetValueOf(r2.pages().begin())==GetValueOf(r.pages().end()), NULL );
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 }
124 }
125 }
126 }
127 }
128}
129
130#include "tbb/parallel_for.h"
131#include "harness.h"
132
133const int N = 1<<5;
134
135unsigned char Array[N][N][N];
136
137struct Striker {
138 // Note: we use <int> here instead of <long> in order to test for problems similar to Quad 407676
139 void operator()( const tbb::blocked_range3d<int>& r ) const {
140 for( tbb::blocked_range<int>::const_iterator i=r.pages().begin(); i!=r.pages().end(); ++i )
141 for( tbb::blocked_range<int>::const_iterator j=r.rows().begin(); j!=r.rows().end(); ++j )
142 for( tbb::blocked_range<int>::const_iterator k=r.cols().begin(); k!=r.cols().end(); ++k )
143 ++Array[i][j][k];
144 }
145};
146
147void ParallelTest() {
148 for( int i=0; i<N; i=i<3 ? i+1 : i*3 ) {
149 for( int j=0; j<N; j=j<3 ? j+1 : j*3 ) {
150 for( int k=0; k<N; k=k<3 ? k+1 : k*3 ) {
151 const tbb::blocked_range3d<int> r( 0, i, 5, 0, j, 3, 0, k, 1 );
152 tbb::parallel_for( r, Striker() );
153 for( int l=0; l<N; ++l ) {
154 for( int m=0; m<N; ++m ) {
155 for( int n=0; n<N; ++n ) {
156 ASSERT( Array[l][m][n]==(l<i && m<j && n<k), NULL );
157 Array[l][m][n] = 0;
158 }
159 }
160 }
161 }
162 }
163 }
164}
165
166#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
167#include <vector>
168void TestDeductionGuides() {
169 std::vector<const unsigned long *> v;
170 std::vector<double> v2;
171 std::vector<std::vector<int>> v3;
172
173 // check blocked_range2d(PageValue, PageValue, size_t, RowValue, RowValue, size_t, ColValue, ColValue, size_t)
174 tbb::blocked_range3d r1(v.begin(), v.end(), 2, v2.begin(), v2.end(), 2, v3.begin(), v3.end(), 6);
175 static_assert(std::is_same<decltype(r1),
176 tbb::blocked_range3d<decltype(v)::iterator, decltype(v2)::iterator, decltype(v3)::iterator>>::value);
177
178 // check blocked_range2d(blocked_range3d &)
179 tbb::blocked_range3d r2(r1);
180 static_assert(std::is_same<decltype(r2), decltype(r1)>::value);
181
182 // check blocked_range2d(blocked_range3d &&)
183 tbb::blocked_range3d r3(std::move(r1));
184 static_assert(std::is_same<decltype(r2), decltype(r1)>::value);
185}
186#endif
187
188#include "tbb/task_scheduler_init.h"
189
190int TestMain () {
191 SerialTest();
192 for( int p=MinThread; p<=MaxThread; ++p ) {
193 tbb::task_scheduler_init init(p);
194 ParallelTest();
195 }
196
197 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
198 TestDeductionGuides();
199 #endif
200 return Harness::Done;
201}
202