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