/* Copyright (c) 2005-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "common/test.h" #include "common/utils.h" #include "common/utils_assert.h" #include "common/utils_concurrency_limit.h" #include "oneapi/tbb/blocked_range3d.h" #include "oneapi/tbb/parallel_for.h" #include "oneapi/tbb/global_control.h" #include //! \file conformance_blocked_range3d.cpp //! \brief Test for [algorithms.blocked_range3d] specification template class AbstractValueType { AbstractValueType() {} int value; public: template friend AbstractValueType MakeAbstractValueType( int i ); template friend int GetValueOf( const AbstractValueType& v ) ; }; template AbstractValueType MakeAbstractValueType( int i ) { AbstractValueType x; x.value = i; return x; } template int GetValueOf( const AbstractValueType& v ) {return v.value;} template bool operator<( const AbstractValueType& u, const AbstractValueType& v ) { return GetValueOf(u) std::size_t operator-( const AbstractValueType& u, const AbstractValueType& v ) { return GetValueOf(u)-GetValueOf(v); } template AbstractValueType operator+( const AbstractValueType& u, std::size_t offset ) { return MakeAbstractValueType(GetValueOf(u)+int(offset)); } struct PageTag {}; struct RowTag {}; struct ColTag {}; static void SerialTest() { typedef AbstractValueType page_type; typedef AbstractValueType row_type; typedef AbstractValueType col_type; typedef oneapi::tbb::blocked_range3d range_type; for( int page_x=-4; page_x<4; ++page_x ) { for( int page_y=page_x; page_y<4; ++page_y ) { page_type page_i = MakeAbstractValueType(page_x); page_type page_j = MakeAbstractValueType(page_y); for( int page_grain=1; page_grain<4; ++page_grain ) { for( int row_x=-4; row_x<4; ++row_x ) { for( int row_y=row_x; row_y<4; ++row_y ) { row_type row_i = MakeAbstractValueType(row_x); row_type row_j = MakeAbstractValueType(row_y); for( int row_grain=1; row_grain<4; ++row_grain ) { for( int col_x=-4; col_x<4; ++col_x ) { for( int col_y=col_x; col_y<4; ++col_y ) { col_type col_i = MakeAbstractValueType(col_x); col_type col_j = MakeAbstractValueType(col_y); for( int col_grain=1; col_grain<4; ++col_grain ) { range_type r( page_i, page_j, page_grain, row_i, row_j, row_grain, col_i, col_j, col_grain ); utils::AssertSameType( r.is_divisible(), true ); utils::AssertSameType( r.empty(), true ); utils::AssertSameType( static_cast(0), static_cast(0) ); utils::AssertSameType( static_cast(0), static_cast(0) ); utils::AssertSameType( static_cast(0), static_cast(0) ); utils::AssertSameType( r.pages(), oneapi::tbb::blocked_range( page_i, page_j, 1 )); utils::AssertSameType( r.rows(), oneapi::tbb::blocked_range( row_i, row_j, 1 )); utils::AssertSameType( r.cols(), oneapi::tbb::blocked_range( col_i, col_j, 1 )); REQUIRE( r.empty()==(page_x==page_y||row_x==row_y||col_x==col_y) ); REQUIRE( r.is_divisible()==(page_y-page_x>page_grain||row_y-row_x>row_grain||col_y-col_x>col_grain) ); if( r.is_divisible() ) { range_type r2(r,oneapi::tbb::split()); if( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin())) ) { REQUIRE( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()) ); REQUIRE( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()) ); REQUIRE( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()) ); } else { if ( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.cols().begin())==GetValueOf(r.cols().begin())) ) { REQUIRE( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()) ); REQUIRE( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()) ); REQUIRE( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()) ); } else { REQUIRE( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()) ); REQUIRE( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()) ); REQUIRE( GetValueOf(r2.pages().begin())==GetValueOf(r.pages().end()) ); } } } } } } } } } } } } } const int N = 1<<5; unsigned char Array[N][N][N]; struct Striker { // Note: we use here instead of in order to test for problems similar to Quad 407676 void operator()( const oneapi::tbb::blocked_range3d& r ) const { for( oneapi::tbb::blocked_range::const_iterator i=r.pages().begin(); i!=r.pages().end(); ++i ) for( oneapi::tbb::blocked_range::const_iterator j=r.rows().begin(); j!=r.rows().end(); ++j ) for( oneapi::tbb::blocked_range::const_iterator k=r.cols().begin(); k!=r.cols().end(); ++k ) ++Array[i][j][k]; } }; void ParallelTest() { for( int i=0; i r( 0, i, 5, 0, j, 3, 0, k, 1 ); oneapi::tbb::parallel_for( r, Striker() ); for( int l=0; l original(0, 100, 0, 100, 0, 100); oneapi::tbb::blocked_range3d first(original); oneapi::tbb::proportional_split ps(3, 1); oneapi::tbb::blocked_range3d second(first, ps); int expected_first_end = static_cast( original.rows().begin() + ps.left() * (original.rows().end() - original.rows().begin()) / (ps.left() + ps.right()) ); if (first.rows().size() == second.rows().size()) { if (first.cols().size() == second.cols().size()) { // Splitting was made by pages utils::check_range_bounds_after_splitting(original.pages(), first.pages(), second.pages(), expected_first_end); } else { // Splitting was made by cols utils::check_range_bounds_after_splitting(original.cols(), first.cols(), second.cols(), expected_first_end); } } else { // Splitting was made by rows utils::check_range_bounds_after_splitting(original.rows(), first.rows(), second.rows(), expected_first_end); } } #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT //! Testing blocked_range3d deduction guides //! \brief \ref interface TEST_CASE("Deduction guides") { std::vector v; std::vector v2; std::vector> v3; // check blocked_range2d(PageValue, PageValue, size_t, RowValue, RowValue, size_t, ColValue, ColValue, size_t) oneapi::tbb::blocked_range3d r1(v.begin(), v.end(), 2, v2.begin(), v2.end(), 2, v3.begin(), v3.end(), 6); static_assert(std::is_same>::value); // check blocked_range2d(blocked_range3d &) oneapi::tbb::blocked_range3d r2(r1); static_assert(std::is_same::value); // check blocked_range2d(blocked_range3d &&) oneapi::tbb::blocked_range3d r3(std::move(r1)); static_assert(std::is_same::value); } #endif