1 /*
2 Copyright (c) 2005-2020 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
23 template<typename Tag>
24 class AbstractValueType {
AbstractValueType()25 AbstractValueType() {}
26 int value;
27 public:
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
35 template<typename Tag>
MakeAbstractValueType(int i)36 AbstractValueType<Tag> MakeAbstractValueType( int i ) {
37 AbstractValueType<Tag> x;
38 x.value = i;
39 return x;
40 }
41
42 template<typename Tag>
GetValueOf(const AbstractValueType<Tag> & v)43 int GetValueOf( const AbstractValueType<Tag>& v ) {return v.value;}
44
45 template<typename Tag>
operator <(const AbstractValueType<Tag> & u,const AbstractValueType<Tag> & v)46 bool operator<( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) {
47 return GetValueOf(u)<GetValueOf(v);
48 }
49
50 template<typename Tag>
operator -(const AbstractValueType<Tag> & u,const AbstractValueType<Tag> & v)51 std::size_t operator-( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) {
52 return GetValueOf(u)-GetValueOf(v);
53 }
54
55 template<typename Tag>
operator +(const AbstractValueType<Tag> & u,std::size_t offset)56 AbstractValueType<Tag> operator+( const AbstractValueType<Tag>& u, std::size_t offset ) {
57 return MakeAbstractValueType<Tag>(GetValueOf(u)+int(offset));
58 }
59
60 struct PageTag {};
61 struct RowTag {};
62 struct ColTag {};
63
SerialTest()64 static 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
133 const int N = 1<<5;
134
135 unsigned char Array[N][N][N];
136
137 struct Striker {
138 // Note: we use <int> here instead of <long> in order to test for problems similar to Quad 407676
operator ()Striker139 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
ParallelTest()147 void 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>
TestDeductionGuides()168 void 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
TestMain()190 int 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