diff --git a/CHANGES b/CHANGES index 847db89a4fd..16b87522afa 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,22 @@ ------------------------------------------------------------------------ The list of most significant changes made over time in Parallel STL. +Parallel STL 20180619 release +PSTL_VERSION == 106 + +Features / APIs: + +- More algorithms support parallel and vector execution policies: + adjacent_difference, partition, reverse, reverse_copy, rotate_copy, + stable_partition. +- More algorithms support parallel execution policies: + inplace_merge, partial_sort_copy. +- Split algorithm declarations and implementation by files. + (by Thomas Rodgers). +- CMake support - Preview Feature + (by Amit Prakash Ambasta and Henry Schreiner) + +------------------------------------------------------------------------ Parallel STL release within Intel(R) Parallel Studio XE 2018 Update 3 PSTL_VERSION == 105 @@ -83,7 +99,7 @@ Features / APIs: - Aligned the implementation with the draft N4659 of the C++ standard. In particular, inner_product no longer supports execution policies. -- reduce and transform_reduce support unseq and par_unseq execution +- reduce and transform_reduce support unseq and par_unseq execution policies if std::plus<> is used for reduction. - Added counting_iterator and zip_iterator to support advanced use cases. To use, include pstl/iterators.h header file. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000..75d15ecdb4d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +# Copyright (c) 2018 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. +# +# +# +# + +cmake_minimum_required(VERSION 3.1) + +set(PARALLELSTL_VERSION_FILE "include/pstl/internal/pstl_config.h") +file(STRINGS "${PARALLELSTL_VERSION_FILE}" PARALLELSTL_VERSION_SOURCE REGEX "#define PSTL_VERSION .*$") +string(REGEX MATCH "#define PSTL_VERSION (.*)$" PARALLELSTL_VERSION_SOURCE "${PARALLELSTL_VERSION_SOURCE}") +math(EXPR VERSION_MAJOR "${PARALLELSTL_VERSION_SOURCE} / 100") +math(EXPR VERSION_MINOR "${PARALLELSTL_VERSION_SOURCE} % 100") + +project(ParallelSTL VERSION ${VERSION_MAJOR}.${VERSION_MINOR} LANGUAGES CXX) + +option(PARALLELSTL_USE_PARALLEL_POLICIES "Enable parallel policies" ON) +set(PARALLELSTL_BACKEND "tbb" CACHE STRING "Threading backend; defaults to TBB") + +include(CMakePackageConfigHelpers) + +add_library(ParallelSTL INTERFACE) +add_library(pstl::ParallelSTL ALIAS ParallelSTL) + +if (PARALLELSTL_USE_PARALLEL_POLICIES) + if (PARALLELSTL_BACKEND STREQUAL "tbb") + find_package(TBB 2018 REQUIRED tbb) + message(STATUS "Parallel STL uses TBB ${TBB_VERSION} (interface version: ${TBB_INTERFACE_VERSION})") + target_link_libraries(ParallelSTL INTERFACE TBB::tbb) + else() + if (TARGET ${PARALLELSTL_BACKEND}) + target_link_libraries(ParallelSTL INTERFACE ${PARALLELSTL_BACKEND}) + else() + find_package(${PARALLELSTL_BACKEND} REQUIRED) + target_link_libraries(ParallelSTL INTERFACE ${${PARALLELSTL_BACKEND}_IMPORTED_TARGETS}) + endif() + endif() +else() + target_add_definitions(ParallelSTL INTERFACE PSTL_USE_PARALLEL_POLICIES=0) +endif() + +target_include_directories(ParallelSTL + INTERFACE + $ + $) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/ParallelSTLConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion) + +configure_file( + ParallelSTLConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/ParallelSTLConfig.cmake + @ONLY) + +export(TARGETS ParallelSTL NAMESPACE pstl:: FILE ParallelSTLTargets.cmake) +export(PACKAGE ParallelSTL) diff --git a/ParallelSTLConfig.cmake.in b/ParallelSTLConfig.cmake.in new file mode 100644 index 00000000000..d0cf5011853 --- /dev/null +++ b/ParallelSTLConfig.cmake.in @@ -0,0 +1,27 @@ +# Copyright (c) 2018 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(CMakeFindDependencyMacro) + +set(PARALLELSTL_BACKEND "@PARALLELSTL_BACKEND@") + +if(PARALLELSTL_BACKEND STREQUAL "tbb") + find_dependency(TBB 2018 REQUIRED tbb) +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/ParallelSTLTargets.cmake") diff --git a/README.md b/README.md index 209f1a4947a..eaf79072eb9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Parallel STL -[![Stable release](https://img.shields.io/badge/version-20180529-green.svg)](https://github.com/intel/parallelstl/releases/tag/20180529) +[![Stable release](https://img.shields.io/badge/version-20180619-green.svg)](https://github.com/intel/parallelstl/releases/tag/20180619) [![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE) Parallel STL is an implementation of the C++ standard library algorithms with support for execution policies, diff --git a/include/pstl/algorithm b/include/pstl/algorithm index 859c5621ab5..68878169038 100644 --- a/include/pstl/algorithm +++ b/include/pstl/algorithm @@ -21,913 +21,15 @@ #ifndef __PSTL_algorithm #define __PSTL_algorithm -#include - #include "internal/pstl_config.h" -#include "internal/utils.h" -#include "internal/algorithm_impl.h" -#include "internal/numeric_impl.h" /* count and count_if use pattern_transform_reduce */ - -namespace std { - -// [alg.any_of] - -template -pstl::internal::enable_if_execution_policy -any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { - using namespace pstl::internal; - return pattern_any_of( first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.all_of] - -template -pstl::internal::enable_if_execution_policy -all_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Pred pred) { - return !any_of(std::forward(exec), first, last, pstl::internal::not_pred(pred)); -} - -// [alg.none_of] - -template -pstl::internal::enable_if_execution_policy -none_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { - return !any_of( std::forward(exec), first, last, pred ); -} - -// [alg.foreach] - -template -pstl::internal::enable_if_execution_policy -for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f) { - using namespace pstl::internal; - pattern_walk1( - first, last, f, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -for_each_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Function f) { - using namespace pstl::internal; - return pattern_walk1_n(first, n, f, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.find] - -template -pstl::internal::enable_if_execution_policy -find_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { - using namespace pstl::internal; - return pattern_find_if( first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -find_if_not(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, -Predicate pred) { - return find_if(std::forward(exec), first, last, pstl::internal::not_pred(pred)); -} - -template -pstl::internal::enable_if_execution_policy -find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, -const T& value) { - return find_if(std::forward(exec), first, last, pstl::internal::equal_value(value)); -} - -// [alg.find.end] -template -pstl::internal::enable_if_execution_policy -find_end(ExecutionPolicy &&exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_find_end(first, last, s_first, s_last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -find_end(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { - return find_end(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); -} - -// [alg.find_first_of] -template -pstl::internal::enable_if_execution_policy -find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_find_first_of(first, last, s_first, s_last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { - return find_first_of(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); -} - -// [alg.adjacent_find] -template< class ExecutionPolicy, class ForwardIterator > -pstl::internal::enable_if_execution_policy -adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - using namespace pstl::internal; - return pattern_adjacent_find(first, last, pstl::internal::pstl_equal(), - is_parallelization_preferred(exec), - is_vectorization_preferred(exec), /*first_semantic*/ false); -} - -template< class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> -pstl::internal::enable_if_execution_policy -adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_adjacent_find(first, last, pred, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec), /*first_semantic*/ false); -} - -// [alg.count] - -// Implementation note: count and count_if call the pattern directly instead of calling std::transform_reduce -// so that we do not have to include . - -template -pstl::internal::enable_if_execution_policy::difference_type> -count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { - typedef typename iterator_traits::reference value_type; - using namespace pstl::internal; - return pattern_count(first, last, [&value](const value_type x) {return value==x;}, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy::difference_type> -count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { - using namespace pstl::internal; - return pattern_count(first, last, pred, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -// [alg.search] - -template -pstl::internal::enable_if_execution_policy -search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_search(first, last, s_first, s_last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { - return search(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); -} - -template -pstl::internal::enable_if_execution_policy -search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_search_n(first, last, count, value, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value) { - return search_n(std::forward(exec), first, last, count, value, pstl::internal::pstl_equal()); -} - -// [alg.copy] - -template -pstl::internal::enable_if_execution_policy -copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { - using namespace pstl::internal; - const auto is_vector = is_vectorization_preferred(exec); - - return pattern_walk2_brick(first, last, result, [is_vector](ForwardIterator1 begin, ForwardIterator1 end, ForwardIterator2 res){ - return brick_copy(begin, end, res, is_vector); - }, is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -copy_n(ExecutionPolicy&& exec, ForwardIterator1 first, Size n, ForwardIterator2 result) { - using namespace pstl::internal; - const auto is_vector = is_vectorization_preferred(exec); - - return pattern_walk2_brick_n(first, n, result, [is_vector](ForwardIterator1 begin, Size sz, ForwardIterator2 res){ - return brick_copy_n(begin, sz, res, is_vector); - }, is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -copy_if(ExecutionPolicy&& exec, - ForwardIterator1 first, ForwardIterator1 last, - ForwardIterator2 result, Predicate pred) { - using namespace pstl::internal; - return pattern_copy_if( - first, last, result, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.swap] - -template -pstl::internal::enable_if_execution_policy -swap_ranges(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { - using namespace pstl::internal; - typedef typename iterator_traits::reference reference_type1; - typedef typename iterator_traits::reference reference_type2; - return pattern_walk2(first1, last1, first2, - [](reference_type1 x, reference_type2 y) { - using std::swap; - swap(x, y); - }, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.transform] - -template -pstl::internal::enable_if_execution_policy -transform( ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryOperation op ) { - typedef typename iterator_traits::reference input_type; - typedef typename iterator_traits::reference output_type; - using namespace pstl::internal; - return pattern_walk2(first, last, result, - [op](input_type x, output_type y ) mutable { y = op(x);}, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -transform( ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation op ) { - typedef typename iterator_traits::reference input1_type; - typedef typename iterator_traits::reference input2_type; - typedef typename iterator_traits::reference output_type; - using namespace pstl::internal; - return pattern_walk3(first1, last1, first2, result, [op](input1_type x, input2_type y, output_type z) mutable {z = op(x,y);}, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.replace] - -template -pstl::internal::enable_if_execution_policy -replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred, const T& new_value) { - using namespace pstl::internal; - typedef typename iterator_traits::reference element_type; - pattern_walk1(first, last, [&pred, &new_value] (element_type elem) { - if (pred(elem)) { - elem = new_value; - } - }, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) { - replace_if(std::forward(exec), first, last, pstl::internal::equal_value(old_value), new_value); -} - -template -pstl::internal::enable_if_execution_policy -replace_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryPredicate pred, const T& new_value) { - typedef typename iterator_traits::reference input_type; - typedef typename iterator_traits::reference output_type; - using namespace pstl::internal; - return pattern_walk2( - first, last, result, - [pred, &new_value](input_type x, output_type y) mutable { y = pred(x) ? new_value : x; }, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -replace_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value) { - return replace_copy_if(std::forward(exec), first, last, result, pstl::internal::equal_value(old_value), new_value); -} - -// [alg.fill] - -template -pstl::internal::enable_if_execution_policy -fill( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value ) { - using namespace pstl::internal; - pattern_fill(first, last, value, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator, class Size, class T> -pstl::internal::enable_if_execution_policy -fill_n( ExecutionPolicy&& exec, ForwardIterator first, Size count, const T& value ) { - if(count <= 0) - return first; - - using namespace pstl::internal; - return pattern_fill_n(first, count, value, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -// [alg.generate] -template< class ExecutionPolicy, class ForwardIterator, class Generator> -pstl::internal::enable_if_execution_policy -generate( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Generator g ) { - using namespace pstl::internal; - pattern_generate(first, last, g, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -template< class ExecutionPolicy, class OutputIterator, class Size, class Generator> -pstl::internal::enable_if_execution_policy -generate_n( ExecutionPolicy&& exec, OutputIterator first, Size count, Generator g ) { - if(count <= 0) - return first; - - using namespace pstl::internal; - return pattern_generate_n(first, count, g, - is_parallelization_preferred(exec), - is_vectorization_preferred(exec)); -} - -// [alg.remove] - -template -pstl::internal::enable_if_execution_policy -remove_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred) { - return copy_if( std::forward(exec), first, last, result, pstl::internal::not_pred(pred)); -} - -template -pstl::internal::enable_if_execution_policy -remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value) { - return copy_if( std::forward(exec), first, last, result, pstl::internal::not_equal_value(value)); -} - -template -pstl::internal::enable_if_execution_policy -remove_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { - using namespace pstl::internal; - return pattern_remove_if(first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { - return remove_if(std::forward(exec), first, last, pstl::internal::equal_value(value)); -} - -// [alg.unique] - -template -pstl::internal::enable_if_execution_policy -unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_unique(first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - return unique(std::forward(exec), first, last, pstl::internal::pstl_equal()); -} - -template -pstl::internal::enable_if_execution_policy -unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_unique_copy(first, last, result, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { - return unique_copy(std::forward(exec), first, last, result, pstl::internal::pstl_equal() ); -} - -// [alg.reverse] - -template -pstl::internal::enable_if_execution_policy -reverse(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last) { - using namespace pstl::internal; - pattern_reverse(first, last, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -reverse_copy(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first) { - using namespace pstl::internal; - return pattern_reverse_copy(first, last, d_first, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.rotate] - -template -pstl::internal::enable_if_execution_policy -rotate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator middle, ForwardIterator last) { - using namespace pstl::internal; - return pattern_rotate(first, middle, last, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -rotate_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result) { - using namespace pstl::internal; - return pattern_rotate_copy(first, middle, last, result, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.partitions] - -template -pstl::internal::enable_if_execution_policy -is_partitioned(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { - using namespace pstl::internal; - return pattern_is_partitioned(first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -partition(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { - using namespace pstl::internal; - return pattern_partition(first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -stable_partition(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred) { - using namespace pstl::internal; - return pattern_stable_partition(first, last, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy> -partition_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, UnaryPredicate pred) { - using namespace pstl::internal; - return pattern_partition_copy(first, last, out_true, out_false, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [alg.sort] - -template -pstl::internal::enable_if_execution_policy -sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - typedef typename iterator_traits::value_type input_type; - using namespace pstl::internal; - return pattern_sort(first, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec), - typename std::is_move_constructible::type()); -} - -template -pstl::internal::enable_if_execution_policy -sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - sort(std::forward(exec), first, last, std::less()); -} - -// [stable.sort] - -template -pstl::internal::enable_if_execution_policy -stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_stable_sort(first, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - stable_sort(std::forward(exec), first, last, std::less()); -} - -// [mismatch] - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > -pstl::internal::enable_if_execution_policy> -mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred) { - using namespace pstl::internal; - return pattern_mismatch(first1, last1, first2, last2, pred, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > -pstl::internal::enable_if_execution_policy> -mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred) { - return mismatch(std::forward(exec), first1, last1, first2, std::next(first2, std::distance(first1, last1)), pred); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > -pstl::internal::enable_if_execution_policy> -mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { - return mismatch(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_equal()); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > -pstl::internal::enable_if_execution_policy> -mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { - return mismatch(std::forward(exec), first1, last1, first2, std::next(first2, std::distance(first1, last1))); -} - -// [alg.equal] - -template -pstl::internal::enable_if_execution_policy -equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate p) { - using namespace pstl::internal; - return pattern_equal(first1, last1, first2, p, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec) - ); -} - -template -pstl::internal::enable_if_execution_policy -equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { - return equal(std::forward(exec), first1, last1, first2, pstl::internal::pstl_equal()); -} - -template -pstl::internal::enable_if_execution_policy -equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate p) { - if ( std::distance(first1, last1) == std::distance(first2, last2) ) - return std::equal(std::forward(exec), first1, last1, first2, p); - else - return false; -} - -template -pstl::internal::enable_if_execution_policy -equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { - return equal(std::forward(exec), first1, last1, first2, pstl::internal::pstl_equal()); -} - -// [alg.move] -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > -pstl::internal::enable_if_execution_policy -move(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first) { - using namespace pstl::internal; - const auto is_vector = is_vectorization_preferred(exec); - - return pattern_walk2_brick(first, last, d_first, [is_vector](ForwardIterator1 begin, ForwardIterator1 end, ForwardIterator2 res) { - return brick_move(begin, end, res, is_vector); - }, is_parallelization_preferred(exec)); -} - -// [partial.sort] - -template -pstl::internal::enable_if_execution_policy -partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp) { - using namespace pstl::internal; - pattern_partial_sort(first, middle, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - partial_sort(exec, first, middle, last, std::less()); -} - -// [partial.sort.copy] - -template -pstl::internal::enable_if_execution_policy -partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp) { - using namespace pstl::internal; - return pattern_partial_sort_copy(first, last, d_first, d_last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last) { - return partial_sort_copy(std::forward(exec), first, last, d_first, d_last, pstl::internal::pstl_less()); -} - -// [is.sorted] -template -pstl::internal::enable_if_execution_policy -is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { - using namespace pstl::internal; - const ForwardIterator res = pattern_adjacent_find(first, last, pstl::internal::reorder_pred(comp), - is_parallelization_preferred(exec), - is_vectorization_preferred(exec), /*first_semantic*/ false); - return res==last ? last : std::next(res); -} - -template -pstl::internal::enable_if_execution_policy -is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type input_type; - return is_sorted_until(exec, first, last, std::less()); -} - -template -pstl::internal::enable_if_execution_policy -is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_adjacent_find(first, last, reorder_pred(comp), - is_parallelization_preferred(exec), - is_vectorization_preferred(exec), /*or_semantic*/ true)==last; -} - -template -pstl::internal::enable_if_execution_policy -is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type input_type; - return is_sorted(exec, first, last, std::less()); -} - -// [alg.nth.element] - -template -pstl::internal::enable_if_execution_policy -nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp) { - using namespace pstl::internal; - pattern_nth_element(first, nth, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - nth_element(exec, first, nth, last, std::less()); -} - -// [alg.merge] -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> -pstl::internal::enable_if_execution_policy -merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator d_first, Compare comp) { - using namespace pstl::internal; - return pattern_merge(first1, last1, first2, last2, d_first, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> -pstl::internal::enable_if_execution_policy -merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator d_first) { - return merge(std::forward(exec), first1, last1, first2, last2, d_first, pstl::internal::pstl_less()); -} - -template< class ExecutionPolicy, class BidirectionalIterator, class Compare> -pstl::internal::enable_if_execution_policy -inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp) { - using namespace pstl::internal; - pattern_inplace_merge(first, middle, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class BidirectionalIterator> -pstl::internal::enable_if_execution_policy -inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { - typedef typename iterator_traits::value_type input_type; - inplace_merge(exec, first, middle, last, std::less()); -} - -// [includes] - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> -pstl::internal::enable_if_execution_policy -includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp) { - using namespace pstl::internal; - return pattern_includes(first1, last1, first2, last2, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> -pstl::internal::enable_if_execution_policy -includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { - return includes(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_less()); -} - -// [set.union] - -template -pstl::internal::enable_if_execution_policy -set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { - using namespace pstl::internal; - return pattern_set_union(first1, last1, first2, last2, result, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, - ForwardIterator2 last2, ForwardIterator result) { - return set_union(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); -} - -// [set.intersection] - -template -pstl::internal::enable_if_execution_policy -set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { - using namespace pstl::internal; - return pattern_set_intersection(first1, last1, first2, last2, result, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { - return set_intersection(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); -} - -// [set.difference] - -template -pstl::internal::enable_if_execution_policy -set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { - using namespace pstl::internal; - return pattern_set_difference(first1, last1, first2, last2, result, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { - return set_difference(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); -} - -// [set.symmetric.difference] - -template -pstl::internal::enable_if_execution_policy -set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { - using namespace pstl::internal; - return pattern_set_symmetric_difference(first1, last1, first2, last2, result, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { - return set_symmetric_difference(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); -} - -// [is.heap] -template< class ExecutionPolicy, class RandomAccessIterator, class Compare > -pstl::internal::enable_if_execution_policy -is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_is_heap_until(first, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class RandomAccessIterator > -pstl::internal::enable_if_execution_policy -is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - return is_heap_until(std::forward(exec), first, last, std::less()); -} - -template< class ExecutionPolicy, class RandomAccessIterator, class Compare > -pstl::internal::enable_if_execution_policy -is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { - return is_heap_until(std::forward(exec), first, last, comp) == last; -} - -template< class ExecutionPolicy, class RandomAccessIterator > -pstl::internal::enable_if_execution_policy -is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { - typedef typename iterator_traits::value_type input_type; - return is_heap(std::forward(exec), first, last, std::less()); -} - -// [alg.min.max] - -template< class ExecutionPolicy, class ForwardIterator, class Compare > -pstl::internal::enable_if_execution_policy -min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_min_element(first, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator > -pstl::internal::enable_if_execution_policy -min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type input_type; - return min_element(std::forward(exec), first, last, std::less()); -} - -template< class ExecutionPolicy, class ForwardIterator, class Compare > -pstl::internal::enable_if_execution_policy -max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_min_element(first, last, pstl::internal::reorder_pred(comp), - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator > -pstl::internal::enable_if_execution_policy -max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type input_type; - return min_element(std::forward(exec), first, last, pstl::internal::reorder_pred >(std::less())); -} - -template< class ExecutionPolicy, class ForwardIterator, class Compare > -pstl::internal::enable_if_execution_policy> -minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { - using namespace pstl::internal; - return pattern_minmax_element(first, last, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator > -pstl::internal::enable_if_execution_policy> -minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type value_type; - return minmax_element(std::forward(exec), first, last, std::less()); -} - -// [alg.lex.comparison] - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare > -pstl::internal::enable_if_execution_policy -lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp) { - using namespace pstl::internal; - return pattern_lexicographical_compare(first1, last1, first2, last2, comp, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > -pstl::internal::enable_if_execution_policy -lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { - return lexicographical_compare(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_less()); -} -} // namespace std +#if __PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +#include "internal/glue_algorithm_impl.h" +#else +// Otherwise just pull in forward declarations +#include "internal/glue_algorithm_defs.h" +#define __PSTL_ALGORITHM_FORWARD_DECLARED 1 +#endif #endif /* __PSTL_algorithm */ diff --git a/include/pstl/execution b/include/pstl/execution index 3917d85bbaa..e99423e7c8f 100644 --- a/include/pstl/execution +++ b/include/pstl/execution @@ -21,112 +21,28 @@ #ifndef __PSTL_execution #define __PSTL_execution -#include #include "internal/pstl_config.h" +#include "internal/execution_defs.h" -namespace pstl { -namespace execution { -inline namespace v1 { +#define __PSTL_EXECUTION_POLICIES_DEFINED 1 -// 2.4, Sequential execution policy -class sequenced_policy { -public: - // For internal use only - static constexpr std::false_type __allow_unsequenced() {return std::false_type{};} - static constexpr std::false_type __allow_vector() {return std::false_type{};} - static constexpr std::false_type __allow_parallel() {return std::false_type{};} -}; - -#if __PSTL_USE_PAR_POLICIES -// 2.5, Parallel execution policy -class parallel_policy { -public: - // For internal use only - static constexpr std::false_type __allow_unsequenced() {return std::false_type{};} - static constexpr std::false_type __allow_vector() {return std::false_type{};} - static constexpr std::true_type __allow_parallel() {return std::true_type{};} -}; - -// 2.6, Parallel+Vector execution policy -class parallel_unsequenced_policy { -public: - // For internal use only - static constexpr std::true_type __allow_unsequenced() {return std::true_type{};} - static constexpr std::true_type __allow_vector() {return std::true_type{};} - static constexpr std::true_type __allow_parallel() {return std::true_type{};} -}; +#if __PSTL_ALGORITHM_FORWARD_DECLARED + #include "internal/glue_algorithm_impl.h" #endif -class unsequenced_policy { -public: - // For internal use only - static constexpr std::true_type __allow_unsequenced() {return std::true_type{};} - static constexpr std::true_type __allow_vector() {return std::true_type{};} - static constexpr std::false_type __allow_parallel() {return std::false_type{};} -}; - - -// 2.8, Execution policy objects -constexpr sequenced_policy seq{}; -#if __PSTL_USE_PAR_POLICIES -constexpr parallel_policy par{}; -constexpr parallel_unsequenced_policy par_unseq{}; -#endif -constexpr unsequenced_policy unseq{}; - -// 2.3, Execution policy type trait -template struct is_execution_policy: std::false_type {}; - -template<> struct is_execution_policy: std::true_type {}; -#if __PSTL_USE_PAR_POLICIES -template<> struct is_execution_policy: std::true_type {}; -template<> struct is_execution_policy: std::true_type {}; +#if __PSTL_MEMORY_FORWARD_DECLARED + #include "internal/glue_memory_impl.h" #endif -template<> struct is_execution_policy: std::true_type {}; -#if __PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT -template constexpr bool is_execution_policy_v = is_execution_policy::value; +#if __PSTL_NUMERIC_FORWARD_DECLARED + #include "internal/glue_numeric_impl.h" #endif -} //namespace v1 -} //namespace execution -} //namespace pstl - #if __PSTL_CPP17_EXECUTION_POLICIES_PRESENT -__PSTL_PRAGMA_MESSAGE_POLICIES("The execution policies are defined in the namespace pstl::execution") -#else -namespace std { - // Type trait - using pstl::execution::is_execution_policy; -#if __PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT -#if __INTEL_COMPILER - template constexpr bool is_execution_policy_v = is_execution_policy::value; + __PSTL_PRAGMA_MESSAGE_POLICIES("The execution policies are defined in the namespace pstl::execution") #else - using pstl::execution::is_execution_policy_v; -#endif -#endif - - namespace execution { - // Standard C++ policy classes - using pstl::execution::sequenced_policy; -#if __PSTL_USE_PAR_POLICIES - using pstl::execution::parallel_policy; - using pstl::execution::parallel_unsequenced_policy; -#endif - // Standard predefined policy instances - using pstl::execution::seq; -#if __PSTL_USE_PAR_POLICIES - using pstl::execution::par; - using pstl::execution::par_unseq; -#endif - // Implementation-defined names - // Unsequenced policy is not yet standard, but for consistency - // we include it into namespace std::execution as well - using pstl::execution::unseq; - using pstl::execution::unsequenced_policy; - } -} -__PSTL_PRAGMA_MESSAGE_POLICIES("The execution policies are injected into the standard namespace std::execution") + #include "internal/glue_execution_defs.h" + __PSTL_PRAGMA_MESSAGE_POLICIES("The execution policies are injected into the standard namespace std::execution") #endif #endif /* __PSTL_execution */ diff --git a/include/pstl/internal/algorithm_impl.h b/include/pstl/internal/algorithm_impl.h index 5aa23b78c01..efef90b1d4b 100644 --- a/include/pstl/internal/algorithm_impl.h +++ b/include/pstl/internal/algorithm_impl.h @@ -28,7 +28,9 @@ #include #include "execution_impl.h" +#include "memory_impl.h" #include "unseq_backend_simd.h" +#include "bricks_impl.h" #if __PSTL_USE_PAR_POLICIES #include "parallel_backend.h" @@ -315,30 +317,6 @@ Iterator2 pattern_walk2_brick_n( Iterator1 first1, Size n, Iterator2 first2, Bri // // it_walk2 evaluates f(it1, it2) for iterators (it1, it2) drawn from [first1,last1) and [first2,...) //------------------------------------------------------------------------ -template -Iterator2 brick_it_walk2( Iterator1 first1, Iterator1 last1, Iterator2 first2, Function f, /*vector=*/std::false_type ) noexcept { - for(; first1!=last1; ++first1, ++first2 ) - f(first1, first2); - return first2; -} - -template -Iterator2 brick_it_walk2( Iterator1 first1, Iterator1 last1, Iterator2 first2, Function f, /*vector=*/std::true_type) noexcept { - return unseq_backend::simd_it_walk_2(first1, last1-first1, first2, f); -} - -template -Iterator2 brick_it_walk2_n( Iterator1 first1, Size n, Iterator2 first2, Function f, /*vector=*/std::false_type ) noexcept { - for(; n > 0; --n, ++first1, ++first2 ) - f(first1, first2); - return first2; -} - -template -Iterator2 brick_it_walk2_n(Iterator1 first1, Size n, Iterator2 first2, Function f, /*vector=*/std::true_type) noexcept { - return unseq_backend::simd_it_walk_2(first1, n, first2, f); -} - template Iterator2 pattern_it_walk2( Iterator1 first1, Iterator1 last1, Iterator2 first2, Function f, IsVector is_vector, /*parallel=*/std::false_type ) noexcept { return brick_it_walk2(first1,last1,first2,f,is_vector); @@ -682,7 +660,7 @@ OutputIterator brick_copy_n(InputIterator first, Size n, OutputIterator result, template OutputIterator brick_copy_n(InputIterator first, Size n, OutputIterator result, /*vector=*/std::true_type) noexcept { - return unseq_backend::simd_copy_move(first, n, result, + return unseq_backend::simd_assign(first, n, result, [](InputIterator first, OutputIterator result) { *result = *first; }); @@ -698,7 +676,7 @@ OutputIterator brick_copy(InputIterator first, InputIterator last, OutputIterato template OutputIterator brick_copy(InputIterator first, InputIterator last, OutputIterator result, /*vector=*/std::true_type) noexcept { - return unseq_backend::simd_copy_move(first, last - first, result, + return unseq_backend::simd_assign(first, last - first, result, [](InputIterator first, OutputIterator result) { *result = *first; }); @@ -714,10 +692,23 @@ OutputIterator brick_move(InputIterator first, InputIterator last, OutputIterato template OutputIterator brick_move(InputIterator first, InputIterator last, OutputIterator result, /*vector=*/std::true_type) noexcept { - return unseq_backend::simd_copy_move(first, last - first, result, + return unseq_backend::simd_assign(first, last - first, result, [](InputIterator first, OutputIterator result) { - *result = std::move(*first); - }); + *result = std::move(*first); + }); +} + +//------------------------------------------------------------------------ +// swap_ranges +//------------------------------------------------------------------------ +template +OutputIterator brick_swap_ranges(InputIterator first, InputIterator last, OutputIterator result, /*vector=*/std::false_type) noexcept { + return std::swap_ranges(first, last, result); +} + +template +OutputIterator brick_swap_ranges(InputIterator first, InputIterator last, OutputIterator result, /*vector=*/std::true_type) noexcept { + return unseq_backend::simd_assign(first, last - first, result, std::iter_swap); } //------------------------------------------------------------------------ @@ -958,14 +949,37 @@ OutputIterator pattern_unique_copy(InputIterator first, InputIterator last, Outp //------------------------------------------------------------------------ template -void brick_reverse(BidirectionalIterator first, BidirectionalIterator last,/*is_vector=*/std::false_type) noexcept { +void brick_reverse(BidirectionalIterator first, BidirectionalIterator last, /*is_vector=*/std::false_type) noexcept { std::reverse(first, last); } template -void brick_reverse(BidirectionalIterator first, BidirectionalIterator last,/*is_vector=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); - brick_reverse(first, last, std::false_type()); +void brick_reverse(BidirectionalIterator first, BidirectionalIterator last, /*is_vector=*/std::true_type) noexcept { + const auto n = (last - first) - 1; + unseq_backend::simd_it_walk_1(first, (last - first) / 2, [n, first](BidirectionalIterator in) { + using std::swap; + std::iter_swap(in, first + (n - (in - first))); + }); +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template +void brick_reverse(BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator d_first, /*is_vector=*/std::false_type) noexcept { + using std::swap; + for (; first != last; --last, ++d_first) { + std::iter_swap(last - 1, d_first); + } +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template +void brick_reverse(BidirectionalIterator first, BidirectionalIterator last, +BidirectionalIterator d_first, /*is_vector=*/std::true_type) noexcept { + const auto n = (last - first) - 1; + unseq_backend::simd_it_walk_1(first, last - first, [n, first, d_first](BidirectionalIterator in) { + using std::swap; + std::iter_swap(in, d_first + (n - (in - first))); + }); } template @@ -974,35 +988,41 @@ void pattern_reverse(BidirectionalIterator first, BidirectionalIterator last, Is } template -void pattern_reverse(BidirectionalIterator first, BidirectionalIterator last, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - brick_reverse(first, last, is_vector); +void pattern_reverse(BidirectionalIterator first, BidirectionalIterator last, IsVector is_vector, /*is_parallel=*/std::true_type) { + par_backend::parallel_for(first, first + (last - first) / 2, [is_vector, first, last](BidirectionalIterator inner_first, BidirectionalIterator inner_last) { + brick_reverse(inner_first, inner_last, last - (inner_last - first), is_vector); + }); } //------------------------------------------------------------------------ // reverse_copy //------------------------------------------------------------------------ -template -OutputIterator brick_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator d_first, /*is_vector=*/std::false_type) noexcept { +template +ForwardIterator brick_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first, /*is_vector=*/std::false_type) noexcept { return std::reverse_copy(first, last, d_first); } -template -OutputIterator brick_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator d_first, /*is_vector=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); - return brick_reverse_copy(first, last, d_first, std::false_type()); +template +ForwardIterator brick_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first, /*is_vector=*/std::true_type) noexcept { + unseq_backend::simd_it_walk_2(first, last - first, d_first, [first, last](BidirectionalIterator in, ForwardIterator out) { + *out = *(last - ((in - first) + 1)); + }); + return d_first + (last - first); } -template -OutputIterator pattern_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator d_first, IsVector is_vector, /*is_parallel=*/std::false_type) noexcept { - return brick_reverse_copy(first, last, d_first, is_vector); +template +ForwardIterator pattern_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first, IsVector is_vector, /*is_parallel=*/std::false_type) noexcept { + return brick_reverse_copy(first, last, d_first, is_vector); } -template -OutputIterator pattern_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator d_first, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - return brick_reverse_copy(first, last, d_first, is_vector); +template +ForwardIterator pattern_reverse_copy(BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { + auto len = last - first; + par_backend::parallel_for(first, last, [is_vector, first, len, d_first] (BidirectionalIterator inner_first, BidirectionalIterator inner_last) { + brick_reverse_copy(inner_first, inner_last, d_first + (len - (inner_last - first)), is_vector); + }); + return d_first + len; } //------------------------------------------------------------------------ @@ -1046,8 +1066,8 @@ OutputIterator brick_rotate_copy(ForwardIterator first, ForwardIterator middle, template OutputIterator brick_rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result, /*is_vector=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); - return std::rotate_copy(first, middle, last, result); + OutputIterator temp = brick_copy(middle, last, result, std::true_type()); + return brick_copy(first, middle, temp, std::true_type()); } template @@ -1056,9 +1076,23 @@ OutputIterator pattern_rotate_copy(ForwardIterator first, ForwardIterator middle } template -OutputIterator pattern_rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - return brick_rotate_copy(first, middle, last, result, is_vector); +OutputIterator pattern_rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result, IsVector is_vector, /*is_parallel=*/std::true_type) { + par_backend::parallel_for(first, last, [first, last, middle, result, is_vector](ForwardIterator b, ForwardIterator e) { + if (b > middle) { + brick_copy(b, e, result + (b - middle), is_vector); + } + else { + OutputIterator new_result = result + ((last - middle) + (b - first)); + if (e < middle) { + brick_copy(b, e, new_result, is_vector); + } + else { + brick_copy(b, middle, new_result, is_vector); + brick_copy(middle, e, result, is_vector); + } + } + }); + return result + (last - first); } //------------------------------------------------------------------------ @@ -1192,8 +1226,64 @@ ForwardIterator pattern_partition(ForwardIterator first, ForwardIterator last, U template ForwardIterator pattern_partition(ForwardIterator first, ForwardIterator last, UnaryPredicate pred, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - return brick_partition(first, last, pred, is_vector); + + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct PartitionRange { + ForwardIterator begin; + ForwardIterator pivot; + ForwardIterator end; + }; + + return except_handler([=]() { + PartitionRange init{ last, last, last }; + + // lambda for merging two partitioned ranges to one partitioned range + auto reductor = [first, is_vector](PartitionRange val1, PartitionRange val2)->PartitionRange { + ForwardIterator new_pivot; + auto size1 = val1.end - val1.pivot; + auto size2 = val2.pivot - val2.begin; + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (val1.end == val1.pivot) { + new_pivot = val2.pivot; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else if (size2 > size1) { + par_backend::parallel_for( + val1.pivot, val1.pivot + size1, + [val1, val2, size1, is_vector](ForwardIterator i, ForwardIterator j) { + brick_swap_ranges(i, j, (val2.pivot - size1) + (i - val1.pivot), is_vector); + } + ); + new_pivot = val2.pivot - size1; + } + // else we should swap the first part of false part of left range and true part of right range + else { + par_backend::parallel_for( + val1.pivot, val1.pivot + size2, + [val1, val2, is_vector](ForwardIterator i, ForwardIterator j) { + brick_swap_ranges(i, j, val2.begin + (i - val1.pivot), is_vector); + } + ); + new_pivot = val1.pivot + size2; + } + return { val2.begin - (val1.end - val1.begin), new_pivot, val2.end }; + }; + + PartitionRange result = par_backend::parallel_reduce(first, last, init, + [first, &pred, is_vector, reductor](ForwardIterator i, ForwardIterator j, PartitionRange value)->PartitionRange { + //1. serial partition + ForwardIterator pivot = brick_partition(i, j, pred, is_vector); + + // 2. merging of two ranges (left and right respectively) + return reductor(value, { i, pivot, j }); + }, + reductor + ); + return result.pivot; + }); } //------------------------------------------------------------------------ @@ -1218,8 +1308,48 @@ BidirectionalIterator pattern_stable_partition(BidirectionalIterator first, Bidi template BidirectionalIterator pattern_stable_partition(BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred, IsVector is_vector, /*is_parallelization=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - return brick_stable_partition(first, last, pred, is_vector); + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct PartitionRange { + BidirectionalIterator begin; + BidirectionalIterator pivot; + BidirectionalIterator end; + }; + typedef typename std::iterator_traits::value_type T; + + return except_handler([=]() { + PartitionRange init{ last, last, last }; + + // lambda for merging two partitioned ranges to one partitioned range + auto reductor = [first, is_vector, pred](PartitionRange val1, PartitionRange val2)->PartitionRange { + BidirectionalIterator new_pivot; + auto size1 = val1.end - val1.pivot; + auto size2 = val2.pivot - val2.begin; + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (val1.end == val1.pivot) { + new_pivot = val2.pivot; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else { + brick_rotate(val1.pivot, val2.begin, val2.pivot, is_vector); + new_pivot = val2.pivot - size1; + } + return { val2.begin - (val1.end - val1.begin), new_pivot, val2.end }; + }; + + PartitionRange result = par_backend::parallel_reduce(first, last, init, + [first, &pred, is_vector, reductor](BidirectionalIterator i, BidirectionalIterator j, PartitionRange value)->PartitionRange { + //1. serial stable_partition + BidirectionalIterator pivot = brick_stable_partition(i, j, pred, is_vector); + + // 2. merging of two ranges (left and right respectively) + return reductor(value, { i, pivot, j }); + }, + reductor); + return result.pivot; + }); } //------------------------------------------------------------------------ @@ -1267,18 +1397,19 @@ pattern_partition_copy(InputIterator first, InputIterator last, OutputIterator1 mask + i, pred, is_vector); - }, + }, [](const return_type& x, const return_type& y)-> return_type { - return std::make_pair(x.first + y.first, x.second + y.second); - }, // Combine + return std::make_pair(x.first + y.first, x.second + y.second); + }, // Combine [=](difference_type i, difference_type len, return_type initial) { // Scan - brick_partition_by_mask(first + i, first + (i + len), - out_true + initial.first, - out_false + initial.second, - mask + i, - is_vector); - }, - [&m](return_type total) {m = total; }); + brick_partition_by_mask(first + i, first + (i + len), + out_true + initial.first, + out_false + initial.second, + mask + i, + is_vector); + }, + [&m](const return_type& total) {m = total;} + ); return std::make_pair(out_true + m.first, out_false + m.second); }); } @@ -1355,26 +1486,71 @@ void pattern_partial_sort(RandomAccessIterator first, RandomAccessIterator middl // partial_sort_copy //------------------------------------------------------------------------ -template -RandomAccessIterator brick_partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, /*is_vector*/std::false_type) noexcept { - return std::partial_sort_copy(first, last, d_first, d_last, comp); -} - -template -RandomAccessIterator brick_partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, /*is_vector*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); +template +RandomAccessIterator pattern_partial_sort_copy(ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, IsVector, /*is_parallel=*/std::false_type) noexcept { return std::partial_sort_copy(first, last, d_first, d_last, comp); } -template -RandomAccessIterator pattern_partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, IsVector is_vector, /*is_parallel=*/std::false_type) noexcept { - return brick_partial_sort_copy(first, last, d_first, d_last, comp, is_vector); -} +template +RandomAccessIterator pattern_partial_sort_copy(ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { + if (last == first || d_last == d_first) { + return d_first; + } + auto n1 = last - first; + auto n2 = d_last - d_first; + return except_handler([=]() { + if (n2 >= n1) { + par_backend::parallel_stable_sort(d_first, d_first + n1, comp, + [n1, first, d_first, is_vector](RandomAccessIterator i, RandomAccessIterator j, Compare comp) { + ForwardIterator i1 = first + (i - d_first); + ForwardIterator j1 = first + (j - d_first); + + // 1. Copy elements from input to output +#if !__PSTL_ICC_18_OMP_SIMD_BROKEN + brick_copy(i1, j1, i, is_vector); +#else + std::copy(i1, j1, i); +#endif + // 2. Sort elements in output sequence + std::sort(i, j, comp); + }, + n1); + return d_first + n1; + } + else { + typedef typename std::iterator_traits::value_type T1; + typedef typename std::iterator_traits::value_type T2; + par_backend::buffer buf(n1); + if (buf) { + T1* r = buf.get(); + + par_backend::parallel_stable_sort(r, r+n1, comp, + [n2, first, r](T1* i, T1* j, Compare comp) { + ForwardIterator it = first + (i - r); + + // 1. Copy elements from input to raw memory + for (T1* k=i; k != j; ++k, ++it) { + ::new (k) T2(*it); + } -template -RandomAccessIterator pattern_partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - return brick_partial_sort_copy(first, last, d_first, d_last, comp, is_vector); + // 2. Sort elements in temporary buffer + if (n2 < j - i) + std::partial_sort(i, i + n2, j, comp); + else + std::sort(i, j, comp); + }, + n2); + + // 3. Move elements from temporary buffer to output + par_backend::parallel_for(r, r + n2, + [r, d_first, is_vector](T1* i, T1* j) { + brick_move(i, j, d_first + (i - r), is_vector); + }); + return d_first + n2; + } + return std::partial_sort_copy(first, last, d_first, d_last, comp); + } + }); } //------------------------------------------------------------------------ @@ -1632,14 +1808,17 @@ OutputIterator pattern_merge(InputIterator1 first1, InputIterator1 last1, InputI template OutputIterator pattern_merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator d_first, Compare comp, IsVector is_vector, /* is_parallel = */ std::true_type) noexcept { - par_backend::parallel_merge(first1, last1, first2, last2, d_first, comp, - [is_vector](InputIterator1 f1, InputIterator1 l1, InputIterator2 f2, InputIterator2 l2, OutputIterator f3, Compare comp) {return brick_merge(f1, l1, f2, l2, f3, comp, is_vector); }); + except_handler([=]() { + par_backend::parallel_merge(first1, last1, first2, last2, d_first, comp, + [is_vector](InputIterator1 f1, InputIterator1 l1, InputIterator2 f2, InputIterator2 l2, OutputIterator f3, Compare comp) {return brick_merge(f1, l1, f2, l2, f3, comp, is_vector); }); + }); return d_first + (last1 - first1) + (last2 - first2); } //------------------------------------------------------------------------ // inplace_merge //------------------------------------------------------------------------ + template void brick_inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp, /* is_vector = */ std::false_type) noexcept { std::inplace_merge(first, middle, last, comp); @@ -1648,7 +1827,7 @@ void brick_inplace_merge(BidirectionalIterator first, BidirectionalIterator midd template void brick_inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp, /* is_vector = */ std::true_type) noexcept { __PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial") - std::inplace_merge(first, middle, last, comp); + std::inplace_merge(first, middle, last, comp); } template @@ -1658,8 +1837,39 @@ void pattern_inplace_merge(BidirectionalIterator first, BidirectionalIterator mi template void pattern_inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp, IsVector is_vector, /*is_parallel=*/std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, redirected to serial"); - brick_inplace_merge(first, middle, last, comp, is_vector); + if (first == last || first == middle || middle == last) { + return; + } + typedef typename std::iterator_traits::value_type T; + auto n = last - first; + par_backend::buffer buf(n); + if (buf) { + T* r = buf.get(); + except_handler([=]() { + auto move_values = [](BidirectionalIterator x, T* z) {invoke_if_else(std::is_trivial(), + [&]() {*z = std::move(*x); }, + [&]() {::new (internal::reduce_to_ptr(z)) T(std::move(*x)); } + ); }; + + auto move_sequences = [](BidirectionalIterator first1, BidirectionalIterator last1, T* first2) { + return brick_uninitialized_move(first1, last1, first2, IsVector()); }; + + par_backend::parallel_merge(first, middle, middle, last, r, comp, + [n, comp, move_values, move_sequences](BidirectionalIterator f1, BidirectionalIterator l1, BidirectionalIterator f2, BidirectionalIterator l2, T* f3, + Compare comp) { + auto func = par_backend::serial_move_merge(n, move_values, move_sequences); + func(f1, l1, f2, l2, f3, comp); + return f3 + (l1 - f1) + (l2 - f2); + }); + par_backend::parallel_for(r, r + n, + [r, first, is_vector](T* i, T* j) { + brick_move(i, j, first + (i - r), is_vector); + }); + }); + } + else { + std::inplace_merge(first, middle, last, comp); + } } //------------------------------------------------------------------------ diff --git a/include/pstl/internal/bricks_impl.h b/include/pstl/internal/bricks_impl.h new file mode 100644 index 00000000000..938f44271e0 --- /dev/null +++ b/include/pstl/internal/bricks_impl.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_bricks_impl_H +#define __PSTL_bricks_impl_H + +namespace pstl { +namespace internal { + +template +Iterator2 brick_it_walk2(Iterator1 first1, Iterator1 last1, Iterator2 first2, Function f, /*vector=*/std::false_type) noexcept { + for (; first1 != last1; ++first1, ++first2) + f(first1, first2); + return first2; +} + +template +Iterator2 brick_it_walk2(Iterator1 first1, Iterator1 last1, Iterator2 first2, Function f, /*vector=*/std::true_type) noexcept { + return unseq_backend::simd_it_walk_2(first1, last1 - first1, first2, f); +} + +template +Iterator2 brick_it_walk2_n(Iterator1 first1, Size n, Iterator2 first2, Function f, /*vector=*/std::false_type) noexcept { + for (; n > 0; --n, ++first1, ++first2) + f(first1, first2); + return first2; +} + +template +Iterator2 brick_it_walk2_n(Iterator1 first1, Size n, Iterator2 first2, Function f, /*vector=*/std::true_type) noexcept { + return unseq_backend::simd_it_walk_2(first1, n, first2, f); +} + +} // namespace internal +} // namespace pstl + +#endif /* __PSTL_bricks_impl_H */ diff --git a/include/pstl/internal/execution_defs.h b/include/pstl/internal/execution_defs.h new file mode 100644 index 00000000000..661d48c72fe --- /dev/null +++ b/include/pstl/internal/execution_defs.h @@ -0,0 +1,100 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_execution_policy_defs_H +#define __PSTL_execution_policy_defs_H + +#include + +namespace pstl { +namespace execution { +inline namespace v1 { + +// 2.4, Sequential execution policy +class sequenced_policy { +public: + // For internal use only + static constexpr std::false_type __allow_unsequenced() {return std::false_type{};} + static constexpr std::false_type __allow_vector() {return std::false_type{};} + static constexpr std::false_type __allow_parallel() {return std::false_type{};} +}; + +#if __PSTL_USE_PAR_POLICIES +// 2.5, Parallel execution policy +class parallel_policy { +public: + // For internal use only + static constexpr std::false_type __allow_unsequenced() {return std::false_type{};} + static constexpr std::false_type __allow_vector() {return std::false_type{};} + static constexpr std::true_type __allow_parallel() {return std::true_type{};} +}; + +// 2.6, Parallel+Vector execution policy +class parallel_unsequenced_policy { +public: + // For internal use only + static constexpr std::true_type __allow_unsequenced() {return std::true_type{};} + static constexpr std::true_type __allow_vector() {return std::true_type{};} + static constexpr std::true_type __allow_parallel() {return std::true_type{};} +}; +#endif + +class unsequenced_policy { +public: + // For internal use only + static constexpr std::true_type __allow_unsequenced() {return std::true_type{};} + static constexpr std::true_type __allow_vector() {return std::true_type{};} + static constexpr std::false_type __allow_parallel() {return std::false_type{};} +}; + + +// 2.8, Execution policy objects +constexpr sequenced_policy seq{}; +#if __PSTL_USE_PAR_POLICIES +constexpr parallel_policy par{}; +constexpr parallel_unsequenced_policy par_unseq{}; +#endif +constexpr unsequenced_policy unseq{}; + +// 2.3, Execution policy type trait +template struct is_execution_policy: std::false_type {}; + +template<> struct is_execution_policy: std::true_type {}; +#if __PSTL_USE_PAR_POLICIES +template<> struct is_execution_policy: std::true_type {}; +template<> struct is_execution_policy: std::true_type {}; +#endif +template<> struct is_execution_policy: std::true_type {}; + +#if __PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT +template constexpr bool is_execution_policy_v = is_execution_policy::value; +#endif + +} // namespace v1 +} // namespace execution + +namespace internal { + template using enable_if_execution_policy = typename std::enable_if< + pstl::execution::is_execution_policy::type>::value, T>::type; +} // namespace internal + +} // namespace pstl + +#endif /* __PSTL_execution_policy_defs_H */ diff --git a/include/pstl/internal/execution_impl.h b/include/pstl/internal/execution_impl.h index 712e3e0efe1..893ea5229cf 100644 --- a/include/pstl/internal/execution_impl.h +++ b/include/pstl/internal/execution_impl.h @@ -24,10 +24,11 @@ #include #include -#include "../execution" +#include "execution_defs.h" namespace pstl { namespace internal { + using namespace pstl::execution; /* predicate */ @@ -59,7 +60,6 @@ struct is_random_access_iterator std::random_access_iterator_tag> { }; - /* policy */ template struct policy_traits {}; @@ -78,10 +78,9 @@ struct policy_traits { typedef std::true_type allow_vector; }; -template <> - #if __PSTL_USE_PAR_POLICIES +template <> struct policy_traits { typedef std::true_type allow_parallel; typedef std::false_type allow_unsequenced; @@ -96,9 +95,6 @@ struct policy_traits { }; #endif -template using enable_if_execution_policy = typename std::enable_if< - is_execution_policy::type>::value, T>::type; - template using collector_t = typename policy_traits::type>::collector_type; @@ -139,6 +135,7 @@ struct prefer_parallel_tag { allow_parallel::value && is_random_access_iterator::value; typedef std::integral_constant type; }; + } // namespace internal } // namespace pstl diff --git a/include/pstl/internal/glue_algorithm_defs.h b/include/pstl/internal/glue_algorithm_defs.h new file mode 100644 index 00000000000..917cf725add --- /dev/null +++ b/include/pstl/internal/glue_algorithm_defs.h @@ -0,0 +1,523 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_algorithm_defs_H +#define __PSTL_glue_algorithm_defs_H + +#include + +#include "execution_defs.h" + +namespace std { + +// [alg.any_of] + +template +pstl::internal::enable_if_execution_policy +any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); + +// [alg.all_of] + +template +pstl::internal::enable_if_execution_policy +all_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Pred pred); + +// [alg.none_of] + +template +pstl::internal::enable_if_execution_policy +none_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); + +// [alg.foreach] + +template +pstl::internal::enable_if_execution_policy +for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f); + +template +pstl::internal::enable_if_execution_policy +for_each_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Function f); + +// [alg.find] + +template +pstl::internal::enable_if_execution_policy +find_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); + +template +pstl::internal::enable_if_execution_policy +find_if_not(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); + +template +pstl::internal::enable_if_execution_policy +find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); + +// [alg.find.end] + +template +pstl::internal::enable_if_execution_policy +find_end(ExecutionPolicy &&exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, + BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +find_end(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last); + +// [alg.find_first_of] + +template +pstl::internal::enable_if_execution_policy +find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, + BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last); + +// [alg.adjacent_find] + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template< class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> +pstl::internal::enable_if_execution_policy +adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred); + +// [alg.count] + +template +pstl::internal::enable_if_execution_policy::difference_type> +count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); + +template +pstl::internal::enable_if_execution_policy::difference_type> +count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); + +// [alg.search] + +template +pstl::internal::enable_if_execution_policy +search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, + BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last); + +template +pstl::internal::enable_if_execution_policy +search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value); + +// [alg.copy] + +template +pstl::internal::enable_if_execution_policy +copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); + +template +pstl::internal::enable_if_execution_policy +copy_n(ExecutionPolicy&& exec, ForwardIterator1 first, Size n, ForwardIterator2 result); + +template +pstl::internal::enable_if_execution_policy +copy_if(ExecutionPolicy&& exec, + ForwardIterator1 first, ForwardIterator1 last, + ForwardIterator2 result, Predicate pred); + +// [alg.swap] + +template +pstl::internal::enable_if_execution_policy +swap_ranges(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); + +// [alg.transform] + +template +pstl::internal::enable_if_execution_policy +transform( ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryOperation op ); + +template +pstl::internal::enable_if_execution_policy +transform(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, + BinaryOperation op); + +// [alg.replace] + +template +pstl::internal::enable_if_execution_policy +replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred, const T& new_value); + +template +pstl::internal::enable_if_execution_policy +replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); + +template +pstl::internal::enable_if_execution_policy +replace_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryPredicate pred, + const T& new_value); + +template +pstl::internal::enable_if_execution_policy +replace_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, + const T& new_value); + +// [alg.fill] + +template +pstl::internal::enable_if_execution_policy +fill( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value ); + +template< class ExecutionPolicy, class ForwardIterator, class Size, class T> +pstl::internal::enable_if_execution_policy +fill_n( ExecutionPolicy&& exec, ForwardIterator first, Size count, const T& value ); + +// [alg.generate] +template< class ExecutionPolicy, class ForwardIterator, class Generator> +pstl::internal::enable_if_execution_policy +generate( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Generator g ); + +template< class ExecutionPolicy, class ForwardIterator, class Size, class Generator> +pstl::internal::enable_if_execution_policy +generate_n( ExecutionPolicy&& exec, ForwardIterator first, Size count, Generator g ); + +// [alg.remove] + +template +pstl::internal::enable_if_execution_policy +remove_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); + +template +pstl::internal::enable_if_execution_policy +remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value); + +template +pstl::internal::enable_if_execution_policy +remove_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); + +// [alg.unique] + +template +pstl::internal::enable_if_execution_policy +unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); + +// [alg.reverse] + +template +pstl::internal::enable_if_execution_policy +reverse(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last); + +template +pstl::internal::enable_if_execution_policy +reverse_copy(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first); + +// [alg.rotate] + +template +pstl::internal::enable_if_execution_policy +rotate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator middle, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +rotate_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result); + +// [alg.partitions] + +template +pstl::internal::enable_if_execution_policy +is_partitioned(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +partition(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy +stable_partition(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred); + +template +pstl::internal::enable_if_execution_policy> +partition_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, + UnaryPredicate pred); + +// [alg.sort] + +template +pstl::internal::enable_if_execution_policy +sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); + +// [stable.sort] + +template +pstl::internal::enable_if_execution_policy +stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); + +// [mismatch] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); + +// [alg.equal] + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate p); + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate p); + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); + +// [alg.move] +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy +move(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first); + +// [partial.sort] + +template +pstl::internal::enable_if_execution_policy +partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); + +// [partial.sort.copy] + +template +pstl::internal::enable_if_execution_policy +partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, + Compare comp); + +template +pstl::internal::enable_if_execution_policy +partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last); + +// [is.sorted] +template +pstl::internal::enable_if_execution_policy +is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +// [alg.nth.element] + +template +pstl::internal::enable_if_execution_policy +nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); + +template +pstl::internal::enable_if_execution_policy +nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); + +// [alg.merge] +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> +pstl::internal::enable_if_execution_policy +merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator d_first, Compare comp); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> +pstl::internal::enable_if_execution_policy +merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator d_first); + +template< class ExecutionPolicy, class BidirectionalIterator, class Compare> +pstl::internal::enable_if_execution_policy +inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); + +template< class ExecutionPolicy, class BidirectionalIterator> +pstl::internal::enable_if_execution_policy +inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); + +// [includes] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> +pstl::internal::enable_if_execution_policy +includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> +pstl::internal::enable_if_execution_policy +includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); + +// [set.union] + +template +pstl::internal::enable_if_execution_policy +set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result, Compare comp); + +template +pstl::internal::enable_if_execution_policy +set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, + ForwardIterator2 last2, ForwardIterator result); + +// [set.intersection] + +template +pstl::internal::enable_if_execution_policy +set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result, Compare comp); + +template +pstl::internal::enable_if_execution_policy +set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result); + +// [set.difference] + +template +pstl::internal::enable_if_execution_policy +set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result, Compare comp); + +template +pstl::internal::enable_if_execution_policy +set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result); + +// [set.symmetric.difference] + +template +pstl::internal::enable_if_execution_policy +set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result, Compare comp); + +template +pstl::internal::enable_if_execution_policy +set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + ForwardIterator result); + +// [is.heap] +template< class ExecutionPolicy, class RandomAccessIterator, class Compare > +pstl::internal::enable_if_execution_policy +is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); + +template< class ExecutionPolicy, class RandomAccessIterator > +pstl::internal::enable_if_execution_policy +is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); + +template< class ExecutionPolicy, class RandomAccessIterator, class Compare > +pstl::internal::enable_if_execution_policy +is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); + +template< class ExecutionPolicy, class RandomAccessIterator > +pstl::internal::enable_if_execution_policy +is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); + +// [alg.min.max] + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy +min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy +max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy> +minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy> +minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +// [alg.lex.comparison] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare > +pstl::internal::enable_if_execution_policy +lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, + Compare comp); + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy +lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); + +} // namespace std + +#endif /* __PSTL_glue_algorithm_defs_H */ diff --git a/include/pstl/internal/glue_algorithm_impl.h b/include/pstl/internal/glue_algorithm_impl.h new file mode 100644 index 00000000000..c9c58afac95 --- /dev/null +++ b/include/pstl/internal/glue_algorithm_impl.h @@ -0,0 +1,933 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_algorithm_impl_H +#define __PSTL_glue_algorithm_impl_H + +#include + +#include "execution_defs.h" +#include "utils.h" +#include "algorithm_impl.h" +#include "numeric_impl.h" /* count and count_if use pattern_transform_reduce */ + +namespace std { + +// [alg.any_of] + +template +pstl::internal::enable_if_execution_policy +any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { + using namespace pstl::internal; + return pattern_any_of( first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.all_of] + +template +pstl::internal::enable_if_execution_policy +all_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Pred pred) { + return !any_of(std::forward(exec), first, last, pstl::internal::not_pred(pred)); +} + +// [alg.none_of] + +template +pstl::internal::enable_if_execution_policy +none_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { + return !any_of( std::forward(exec), first, last, pred ); +} + +// [alg.foreach] + +template +pstl::internal::enable_if_execution_policy +for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f) { + using namespace pstl::internal; + pattern_walk1( + first, last, f, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +for_each_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Function f) { + using namespace pstl::internal; + return pattern_walk1_n(first, n, f, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.find] + +template +pstl::internal::enable_if_execution_policy +find_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { + using namespace pstl::internal; + return pattern_find_if( first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +find_if_not(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, +Predicate pred) { + return find_if(std::forward(exec), first, last, pstl::internal::not_pred(pred)); +} + +template +pstl::internal::enable_if_execution_policy +find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, +const T& value) { + return find_if(std::forward(exec), first, last, pstl::internal::equal_value(value)); +} + +// [alg.find.end] +template +pstl::internal::enable_if_execution_policy +find_end(ExecutionPolicy &&exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_find_end(first, last, s_first, s_last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +find_end(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { + return find_end(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); +} + +// [alg.find_first_of] +template +pstl::internal::enable_if_execution_policy +find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_find_first_of(first, last, s_first, s_last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { + return find_first_of(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); +} + +// [alg.adjacent_find] +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + using namespace pstl::internal; + return pattern_adjacent_find(first, last, pstl::internal::pstl_equal(), + is_parallelization_preferred(exec), + is_vectorization_preferred(exec), /*first_semantic*/ false); +} + +template< class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> +pstl::internal::enable_if_execution_policy +adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_adjacent_find(first, last, pred, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec), /*first_semantic*/ false); +} + +// [alg.count] + +// Implementation note: count and count_if call the pattern directly instead of calling std::transform_reduce +// so that we do not have to include . + +template +pstl::internal::enable_if_execution_policy::difference_type> +count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { + typedef typename iterator_traits::reference value_type; + using namespace pstl::internal; + return pattern_count(first, last, [&value](const value_type x) {return value==x;}, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy::difference_type> +count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred) { + using namespace pstl::internal; + return pattern_count(first, last, pred, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +// [alg.search] + +template +pstl::internal::enable_if_execution_policy +search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_search(first, last, s_first, s_last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +search(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 s_first, ForwardIterator2 s_last) { + return search(std::forward(exec), first, last, s_first, s_last, pstl::internal::pstl_equal()); +} + +template +pstl::internal::enable_if_execution_policy +search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_search_n(first, last, count, value, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value) { + return search_n(std::forward(exec), first, last, count, value, pstl::internal::pstl_equal()); +} + +// [alg.copy] + +template +pstl::internal::enable_if_execution_policy +copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { + using namespace pstl::internal; + const auto is_vector = is_vectorization_preferred(exec); + + return pattern_walk2_brick(first, last, result, [is_vector](ForwardIterator1 begin, ForwardIterator1 end, ForwardIterator2 res){ + return brick_copy(begin, end, res, is_vector); + }, is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +copy_n(ExecutionPolicy&& exec, ForwardIterator1 first, Size n, ForwardIterator2 result) { + using namespace pstl::internal; + const auto is_vector = is_vectorization_preferred(exec); + + return pattern_walk2_brick_n(first, n, result, [is_vector](ForwardIterator1 begin, Size sz, ForwardIterator2 res){ + return brick_copy_n(begin, sz, res, is_vector); + }, is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +copy_if(ExecutionPolicy&& exec, + ForwardIterator1 first, ForwardIterator1 last, + ForwardIterator2 result, Predicate pred) { + using namespace pstl::internal; + return pattern_copy_if( + first, last, result, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.swap] + +template +pstl::internal::enable_if_execution_policy +swap_ranges(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { + using namespace pstl::internal; + typedef typename iterator_traits::reference reference_type1; + typedef typename iterator_traits::reference reference_type2; + return pattern_walk2(first1, last1, first2, + [](reference_type1 x, reference_type2 y) { + using std::swap; + swap(x, y); + }, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.transform] + +template +pstl::internal::enable_if_execution_policy +transform( ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryOperation op ) { + typedef typename iterator_traits::reference input_type; + typedef typename iterator_traits::reference output_type; + using namespace pstl::internal; + return pattern_walk2(first, last, result, + [op](input_type x, output_type y ) mutable { y = op(x);}, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +transform( ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation op ) { + typedef typename iterator_traits::reference input1_type; + typedef typename iterator_traits::reference input2_type; + typedef typename iterator_traits::reference output_type; + using namespace pstl::internal; + return pattern_walk3(first1, last1, first2, result, [op](input1_type x, input2_type y, output_type z) mutable {z = op(x,y);}, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.replace] + +template +pstl::internal::enable_if_execution_policy +replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred, const T& new_value) { + using namespace pstl::internal; + typedef typename iterator_traits::reference element_type; + pattern_walk1(first, last, [&pred, &new_value] (element_type elem) { + if (pred(elem)) { + elem = new_value; + } + }, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) { + replace_if(std::forward(exec), first, last, pstl::internal::equal_value(old_value), new_value); +} + +template +pstl::internal::enable_if_execution_policy +replace_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, UnaryPredicate pred, const T& new_value) { + typedef typename iterator_traits::reference input_type; + typedef typename iterator_traits::reference output_type; + using namespace pstl::internal; + return pattern_walk2( + first, last, result, + [pred, &new_value](input_type x, output_type y) mutable { y = pred(x) ? new_value : x; }, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +replace_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value) { + return replace_copy_if(std::forward(exec), first, last, result, pstl::internal::equal_value(old_value), new_value); +} + +// [alg.fill] + +template +pstl::internal::enable_if_execution_policy +fill( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value ) { + using namespace pstl::internal; + pattern_fill(first, last, value, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator, class Size, class T> +pstl::internal::enable_if_execution_policy +fill_n( ExecutionPolicy&& exec, ForwardIterator first, Size count, const T& value ) { + if(count <= 0) + return first; + + using namespace pstl::internal; + return pattern_fill_n(first, count, value, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +// [alg.generate] +template< class ExecutionPolicy, class ForwardIterator, class Generator> +pstl::internal::enable_if_execution_policy +generate( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Generator g ) { + using namespace pstl::internal; + pattern_generate(first, last, g, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator, class Size, class Generator> +pstl::internal::enable_if_execution_policy +generate_n( ExecutionPolicy&& exec, ForwardIterator first, Size count, Generator g ) { + if(count <= 0) + return first; + + using namespace pstl::internal; + return pattern_generate_n(first, count, g, + is_parallelization_preferred(exec), + is_vectorization_preferred(exec)); +} + +// [alg.remove] + +template +pstl::internal::enable_if_execution_policy +remove_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred) { + return copy_if( std::forward(exec), first, last, result, pstl::internal::not_pred(pred)); +} + +template +pstl::internal::enable_if_execution_policy +remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value) { + return copy_if( std::forward(exec), first, last, result, pstl::internal::not_equal_value(value)); +} + +template +pstl::internal::enable_if_execution_policy +remove_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { + using namespace pstl::internal; + return pattern_remove_if(first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { + return remove_if(std::forward(exec), first, last, pstl::internal::equal_value(value)); +} + +// [alg.unique] + +template +pstl::internal::enable_if_execution_policy +unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_unique(first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + return unique(std::forward(exec), first, last, pstl::internal::pstl_equal()); +} + +template +pstl::internal::enable_if_execution_policy +unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_unique_copy(first, last, result, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { + return unique_copy(std::forward(exec), first, last, result, pstl::internal::pstl_equal() ); +} + +// [alg.reverse] + +template +pstl::internal::enable_if_execution_policy +reverse(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last) { + using namespace pstl::internal; + pattern_reverse(first, last, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +reverse_copy(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, ForwardIterator d_first) { + using namespace pstl::internal; + return pattern_reverse_copy(first, last, d_first, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.rotate] + +template +pstl::internal::enable_if_execution_policy +rotate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator middle, ForwardIterator last) { + using namespace pstl::internal; + return pattern_rotate(first, middle, last, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +rotate_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result) { + using namespace pstl::internal; + return pattern_rotate_copy(first, middle, last, result, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.partitions] + +template +pstl::internal::enable_if_execution_policy +is_partitioned(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { + using namespace pstl::internal; + return pattern_is_partitioned(first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +partition(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, UnaryPredicate pred) { + using namespace pstl::internal; + return pattern_partition(first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +stable_partition(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred) { + using namespace pstl::internal; + return pattern_stable_partition(first, last, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy> +partition_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, UnaryPredicate pred) { + using namespace pstl::internal; + return pattern_partition_copy(first, last, out_true, out_false, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [alg.sort] + +template +pstl::internal::enable_if_execution_policy +sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + typedef typename iterator_traits::value_type input_type; + using namespace pstl::internal; + return pattern_sort(first, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec), + typename std::is_move_constructible::type()); +} + +template +pstl::internal::enable_if_execution_policy +sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + sort(std::forward(exec), first, last, std::less()); +} + +// [stable.sort] + +template +pstl::internal::enable_if_execution_policy +stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_stable_sort(first, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + stable_sort(std::forward(exec), first, last, std::less()); +} + +// [mismatch] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred) { + using namespace pstl::internal; + return pattern_mismatch(first1, last1, first2, last2, pred, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred) { + return mismatch(std::forward(exec), first1, last1, first2, std::next(first2, std::distance(first1, last1)), pred); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { + return mismatch(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_equal()); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy> +mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { + return mismatch(std::forward(exec), first1, last1, first2, std::next(first2, std::distance(first1, last1))); +} + +// [alg.equal] + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate p) { + using namespace pstl::internal; + return pattern_equal(first1, last1, first2, p, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec) + ); +} + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) { + return equal(std::forward(exec), first1, last1, first2, pstl::internal::pstl_equal()); +} + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate p) { + if ( std::distance(first1, last1) == std::distance(first2, last2) ) + return std::equal(std::forward(exec), first1, last1, first2, p); + else + return false; +} + +template +pstl::internal::enable_if_execution_policy +equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { + return equal(std::forward(exec), first1, last1, first2, pstl::internal::pstl_equal()); +} + +// [alg.move] +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy +move(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first) { + using namespace pstl::internal; + const auto is_vector = is_vectorization_preferred(exec); + + return pattern_walk2_brick(first, last, d_first, [is_vector](ForwardIterator1 begin, ForwardIterator1 end, ForwardIterator2 res) { + return brick_move(begin, end, res, is_vector); + }, is_parallelization_preferred(exec)); +} + +// [partial.sort] + +template +pstl::internal::enable_if_execution_policy +partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp) { + using namespace pstl::internal; + pattern_partial_sort(first, middle, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + partial_sort(exec, first, middle, last, std::less()); +} + +// [partial.sort.copy] + +template +pstl::internal::enable_if_execution_policy +partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last, Compare comp) { + using namespace pstl::internal; + return pattern_partial_sort_copy(first, last, d_first, d_last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator d_first, RandomAccessIterator d_last) { + return partial_sort_copy(std::forward(exec), first, last, d_first, d_last, pstl::internal::pstl_less()); +} + +// [is.sorted] +template +pstl::internal::enable_if_execution_policy +is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { + using namespace pstl::internal; + const ForwardIterator res = pattern_adjacent_find(first, last, pstl::internal::reorder_pred(comp), + is_parallelization_preferred(exec), + is_vectorization_preferred(exec), /*first_semantic*/ false); + return res==last ? last : std::next(res); +} + +template +pstl::internal::enable_if_execution_policy +is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type input_type; + return is_sorted_until(exec, first, last, std::less()); +} + +template +pstl::internal::enable_if_execution_policy +is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_adjacent_find(first, last, reorder_pred(comp), + is_parallelization_preferred(exec), + is_vectorization_preferred(exec), /*or_semantic*/ true)==last; +} + +template +pstl::internal::enable_if_execution_policy +is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type input_type; + return is_sorted(exec, first, last, std::less()); +} + +// [alg.nth.element] + +template +pstl::internal::enable_if_execution_policy +nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp) { + using namespace pstl::internal; + pattern_nth_element(first, nth, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + nth_element(exec, first, nth, last, std::less()); +} + +// [alg.merge] +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> +pstl::internal::enable_if_execution_policy +merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator d_first, Compare comp) { + using namespace pstl::internal; + return pattern_merge(first1, last1, first2, last2, d_first, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> +pstl::internal::enable_if_execution_policy +merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator d_first) { + return merge(std::forward(exec), first1, last1, first2, last2, d_first, pstl::internal::pstl_less()); +} + +template< class ExecutionPolicy, class BidirectionalIterator, class Compare> +pstl::internal::enable_if_execution_policy +inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp) { + using namespace pstl::internal; + pattern_inplace_merge(first, middle, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class BidirectionalIterator> +pstl::internal::enable_if_execution_policy +inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last) { + typedef typename iterator_traits::value_type input_type; + inplace_merge(exec, first, middle, last, std::less()); +} + +// [includes] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> +pstl::internal::enable_if_execution_policy +includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp) { + using namespace pstl::internal; + return pattern_includes(first1, last1, first2, last2, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> +pstl::internal::enable_if_execution_policy +includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { + return includes(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_less()); +} + +// [set.union] + +template +pstl::internal::enable_if_execution_policy +set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { + using namespace pstl::internal; + return pattern_set_union(first1, last1, first2, last2, result, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, + ForwardIterator2 last2, ForwardIterator result) { + return set_union(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); +} + +// [set.intersection] + +template +pstl::internal::enable_if_execution_policy +set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { + using namespace pstl::internal; + return pattern_set_intersection(first1, last1, first2, last2, result, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { + return set_intersection(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); +} + +// [set.difference] + +template +pstl::internal::enable_if_execution_policy +set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { + using namespace pstl::internal; + return pattern_set_difference(first1, last1, first2, last2, result, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { + return set_difference(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); +} + +// [set.symmetric.difference] + +template +pstl::internal::enable_if_execution_policy +set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp) { + using namespace pstl::internal; + return pattern_set_symmetric_difference(first1, last1, first2, last2, result, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result) { + return set_symmetric_difference(std::forward(exec), first1, last1, first2, last2, result, pstl::internal::pstl_less()); +} + +// [is.heap] +template< class ExecutionPolicy, class RandomAccessIterator, class Compare > +pstl::internal::enable_if_execution_policy +is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_is_heap_until(first, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class RandomAccessIterator > +pstl::internal::enable_if_execution_policy +is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + return is_heap_until(std::forward(exec), first, last, std::less()); +} + +template< class ExecutionPolicy, class RandomAccessIterator, class Compare > +pstl::internal::enable_if_execution_policy +is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp) { + return is_heap_until(std::forward(exec), first, last, comp) == last; +} + +template< class ExecutionPolicy, class RandomAccessIterator > +pstl::internal::enable_if_execution_policy +is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last) { + typedef typename iterator_traits::value_type input_type; + return is_heap(std::forward(exec), first, last, std::less()); +} + +// [alg.min.max] + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy +min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_min_element(first, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type input_type; + return min_element(std::forward(exec), first, last, std::less()); +} + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy +max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_min_element(first, last, pstl::internal::reorder_pred(comp), + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy +max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type input_type; + return min_element(std::forward(exec), first, last, pstl::internal::reorder_pred >(std::less())); +} + +template< class ExecutionPolicy, class ForwardIterator, class Compare > +pstl::internal::enable_if_execution_policy> +minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp) { + using namespace pstl::internal; + return pattern_minmax_element(first, last, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator > +pstl::internal::enable_if_execution_policy> +minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type value_type; + return minmax_element(std::forward(exec), first, last, std::less()); +} + +// [alg.lex.comparison] + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare > +pstl::internal::enable_if_execution_policy +lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp) { + using namespace pstl::internal; + return pattern_lexicographical_compare(first1, last1, first2, last2, comp, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template< class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2 > +pstl::internal::enable_if_execution_policy +lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) { + return lexicographical_compare(std::forward(exec), first1, last1, first2, last2, pstl::internal::pstl_less()); +} + +} // namespace std + +#endif /* __PSTL_glue_algorithm_impl_H */ diff --git a/include/pstl/internal/glue_execution_defs.h b/include/pstl/internal/glue_execution_defs.h new file mode 100644 index 00000000000..4aecc0f433b --- /dev/null +++ b/include/pstl/internal/glue_execution_defs.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_execution_defs_H +#define __PSTL_glue_execution_defs_H + +#include + +#include "execution_defs.h" + +namespace std { + // Type trait + using pstl::execution::is_execution_policy; +#if __PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT +#if __INTEL_COMPILER + template constexpr bool is_execution_policy_v = is_execution_policy::value; +#else + using pstl::execution::is_execution_policy_v; +#endif +#endif + + namespace execution { + // Standard C++ policy classes + using pstl::execution::sequenced_policy; +#if __PSTL_USE_PAR_POLICIES + using pstl::execution::parallel_policy; + using pstl::execution::parallel_unsequenced_policy; +#endif + // Standard predefined policy instances + using pstl::execution::seq; +#if __PSTL_USE_PAR_POLICIES + using pstl::execution::par; + using pstl::execution::par_unseq; +#endif + // Implementation-defined names + // Unsequenced policy is not yet standard, but for consistency + // we include it into namespace std::execution as well + using pstl::execution::unseq; + using pstl::execution::unsequenced_policy; + } // namespace execution +} // namespace std + +#endif /* __PSTL_glue_execution_defs_H */ diff --git a/include/pstl/internal/glue_memory_defs.h b/include/pstl/internal/glue_memory_defs.h new file mode 100644 index 00000000000..672c5c8b1f4 --- /dev/null +++ b/include/pstl/internal/glue_memory_defs.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_memory_defs_H +#define __PSTL_glue_memory_defs_H + +#include "execution_defs.h" + +namespace std { + +// [uninitialized.copy] + +template +pstl::internal::enable_if_execution_policy +uninitialized_copy(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result); + +template +pstl::internal::enable_if_execution_policy +uninitialized_copy_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result); + +// [uninitialized.move] + +template +pstl::internal::enable_if_execution_policy +uninitialized_move(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result); + +template +pstl::internal::enable_if_execution_policy +uninitialized_move_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result); + +// [uninitialized.fill] + +template +pstl::internal::enable_if_execution_policy +uninitialized_fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); + +template +pstl::internal::enable_if_execution_policy +uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value); + +// [specialized.destroy] + +template +pstl::internal::enable_if_execution_policy +destroy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); + +// [uninitialized.construct.default] + +template +pstl::internal::enable_if_execution_policy +uninitialized_default_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); + +// [uninitialized.construct.value] + +template +pstl::internal::enable_if_execution_policy +uninitialized_value_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); + +} // namespace std + +#endif /* __PSTL_glue_memory_defs_H */ diff --git a/include/pstl/internal/glue_memory_impl.h b/include/pstl/internal/glue_memory_impl.h new file mode 100644 index 00000000000..11a36243d7f --- /dev/null +++ b/include/pstl/internal/glue_memory_impl.h @@ -0,0 +1,241 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_memory_impl_H +#define __PSTL_glue_memory_impl_H + +#include "utils.h" +#include "algorithm_impl.h" + +namespace std { + +// [uninitialized.copy] + +template +pstl::internal::enable_if_execution_policy +uninitialized_copy(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result) { + typedef typename iterator_traits::value_type value_type1; + typedef typename iterator_traits::value_type value_type2; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), + [&]() { return pattern_walk2_brick(first, last, result, [is_vector](InputIterator begin, InputIterator end, ForwardIterator res) + { return brick_copy(begin, end, res, is_vector); }, is_parallel); }, + [&]() { return pattern_it_walk2(first, last, result, [](InputIterator it1, ForwardIterator it2) + { ::new (reduce_to_ptr(it2)) value_type2(*it1); }, is_vector, is_parallel); } + ); +} + +template +pstl::internal::enable_if_execution_policy +uninitialized_copy_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result) { + typedef typename iterator_traits::value_type value_type1; + typedef typename iterator_traits::value_type value_type2; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), + [&]() { return pattern_walk2_brick_n(first, n, result, [is_vector](InputIterator begin, Size sz, ForwardIterator res) + { return brick_copy_n(begin, sz, res, is_vector); }, is_parallel); }, + [&]() { return pattern_it_walk2_n(first, n, result, [](InputIterator it1, ForwardIterator it2) + { ::new (reduce_to_ptr(it2)) value_type2(*it1); }, is_vector, is_parallel); } + ); +} + +// [uninitialized.move] + +template +pstl::internal::enable_if_execution_policy +uninitialized_move(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result) { + typedef typename iterator_traits::value_type value_type1; + typedef typename iterator_traits::value_type value_type2; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), + [&]() { return pattern_walk2_brick(first, last, result, [is_vector](InputIterator begin, InputIterator end, ForwardIterator res) + { return brick_copy(begin, end, res, is_vector);}, is_parallel); }, + [&]() { return pattern_it_walk2(first, last, result, [](InputIterator it1, ForwardIterator it2) + { ::new (reduce_to_ptr(it2)) value_type2(std::move(*it1)); }, is_vector, is_parallel); } + ); +} + +template +pstl::internal::enable_if_execution_policy +uninitialized_move_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result) { + typedef typename iterator_traits::value_type value_type1; + typedef typename iterator_traits::value_type value_type2; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), + [&]() { return pattern_walk2_brick_n(first, n, result, [is_vector](InputIterator begin, Size sz, ForwardIterator res) + { return brick_copy_n(begin, sz, res, is_vector);}, is_parallel); }, + [&]() { return pattern_it_walk2_n(first, n, result, [](InputIterator it1, ForwardIterator it2) + { ::new (reduce_to_ptr(it2)) value_type2(std::move(*it1)); }, is_vector, is_parallel); } + ); +} + +// [uninitialized.fill] + +template +pstl::internal::enable_if_execution_policy +uninitialized_fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + invoke_if_else(std::is_arithmetic(), + [&]() { pattern_walk_brick(first, last, [&value, &is_vector](ForwardIterator begin, ForwardIterator end) + { brick_fill(begin, end, value_type(value), is_vector);}, is_parallel); }, + [&]() { pattern_it_walk1(first, last, [&value](ForwardIterator it) + { ::new (reduce_to_ptr(it)) value_type(value); }, is_vector, is_parallel); } + ); +} + +template +pstl::internal::enable_if_execution_policy +uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::is_arithmetic(), + [&]() { return pattern_walk_brick_n(first, n, [&value, &is_vector](ForwardIterator begin, Size count) + { return brick_fill_n(begin, count, value_type(value), is_vector);}, is_parallel); }, + [&]() { return pattern_it_walk1_n(first, n, [&value](ForwardIterator it) + { ::new (reduce_to_ptr(it)) value_type(value); }, is_vector, is_parallel); } + ); +} + +// [specialized.destroy] + +template +pstl::internal::enable_if_execution_policy +destroy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + invoke_if_not(std::is_trivially_destructible(), + [&]() { pattern_it_walk1(first, last, [](ForwardIterator it){ (*it).~value_type(); }, is_vector, is_parallel); } + ); +} + +template +pstl::internal::enable_if_execution_policy +destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::is_trivially_destructible(), + [&]() { return std::next(first, n);}, + [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it){ (*it).~value_type(); }, is_vector, is_parallel); } + ); +} + +// [uninitialized.construct.default] + +template +pstl::internal::enable_if_execution_policy +uninitialized_default_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + invoke_if_not(std::is_trivial(), + [&]() { pattern_it_walk1(first, last, [](ForwardIterator it) { ::new (reduce_to_ptr(it)) value_type; }, is_vector, is_parallel); }); +} + +template +pstl::internal::enable_if_execution_policy +uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::is_trivial(), + [&]() { return std::next(first, n);}, + [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it) + { ::new (reduce_to_ptr(it)) value_type; }, is_vector, is_parallel); } + ); +} + +// [uninitialized.construct.value] + +template +pstl::internal::enable_if_execution_policy +uninitialized_value_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + invoke_if_else(std::is_trivial(), + [&]() { pattern_walk_brick(first, last, [is_vector](ForwardIterator begin, ForwardIterator end) + { brick_fill(begin, end, value_type(), is_vector);}, is_parallel); }, + [&]() { pattern_it_walk1(first, last, [](ForwardIterator it) + { ::new (reduce_to_ptr(it)) value_type(); }, is_vector, is_parallel); } + ); +} + +template +pstl::internal::enable_if_execution_policy +uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { + typedef typename iterator_traits::value_type value_type; + using namespace pstl::internal; + + const auto is_parallel = is_parallelization_preferred(exec); + const auto is_vector = is_vectorization_preferred(exec); + + return invoke_if_else(std::is_trivial(), + [&]() { return pattern_walk_brick_n(first, n, [is_vector](ForwardIterator begin, Size count) + { return brick_fill_n(begin, count, value_type(), is_vector);}, is_parallel); }, + [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it) + { ::new (reduce_to_ptr(it)) value_type(); }, is_vector, is_parallel); } + ); +} + +} // namespace std + +#endif /* __PSTL_glue_memory_imple_H */ diff --git a/include/pstl/internal/glue_numeric_defs.h b/include/pstl/internal/glue_numeric_defs.h new file mode 100644 index 00000000000..315d337a9f5 --- /dev/null +++ b/include/pstl/internal/glue_numeric_defs.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_numeric_defs_H +#define __PSTL_glue_numeric_defs_H + +#include "execution_defs.h" + +namespace std { + +// [reduce] + +template +pstl::internal::enable_if_execution_policy +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op); + +template +pstl::internal::enable_if_execution_policy +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init); + +template +pstl::internal::enable_if_execution_policy::value_type> +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init); + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, + BinaryOperation2 binary_op2); + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op); + +// [exclusive.scan] + +template +pstl::internal::enable_if_execution_policy +exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init); + +template +ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, + BinaryOperation binary_op); + +// [inclusive.scan] + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init); + +// [transform.exclusive.scan] + +template +pstl::internal::enable_if_execution_policy +transform_exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, + BinaryOperation binary_op, UnaryOperation unary_op); + +// [transform.inclusive.scan] + +template +pstl::internal::enable_if_execution_policy +transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, + UnaryOperation unary_op, T init); + +template +pstl::internal::enable_if_execution_policy +transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, + UnaryOperation unary_op); + +// [adjacent.difference] + +template +pstl::internal::enable_if_execution_policy +adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op); + +template +pstl::internal::enable_if_execution_policy +adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first); + +} // namespace std + +#endif /* __PSTL_glue_numeric_defs_H */ diff --git a/include/pstl/internal/glue_numeric_impl.h b/include/pstl/internal/glue_numeric_impl.h new file mode 100644 index 00000000000..128634979fe --- /dev/null +++ b/include/pstl/internal/glue_numeric_impl.h @@ -0,0 +1,178 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_glue_numeric_impl_H +#define __PSTL_glue_numeric_impl_H + +#include + +#include "utils.h" +#include "numeric_impl.h" + +namespace std { + +// [reduce] + +template +pstl::internal::enable_if_execution_policy +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op) { + return transform_reduce(std::forward(exec), first, last, init, binary_op, pstl::internal::no_op()); +} + +template +pstl::internal::enable_if_execution_policy +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init) { + return transform_reduce(std::forward(exec), first, last, init, std::plus(), pstl::internal::no_op()); +} + +template +pstl::internal::enable_if_execution_policy::value_type> +reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { + typedef typename iterator_traits::value_type T; + return transform_reduce(std::forward(exec), first, last, T{}, std::plus(), pstl::internal::no_op()); +} + +// [transform.reduce] + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init) { + typedef typename iterator_traits::value_type input_type; + using namespace pstl::internal; + return pattern_transform_reduce(first1, last1, first2, init, std::plus(), std::multiplies(), + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2) { + using namespace pstl::internal; + return pattern_transform_reduce(first1, last1, first2, init, binary_op1, binary_op2, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +transform_reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op) { + using namespace pstl::internal; + return pattern_transform_reduce(first, last, init, binary_op, unary_op, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [exclusive.scan] + +template +pstl::internal::enable_if_execution_policy +exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init) { + return transform_exclusive_scan(std::forward(exec), first, last, result, init, std::plus(), pstl::internal::no_op()); +} + +template +ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op) { + return transform_exclusive_scan(std::forward(exec), first, last, result, init, binary_op, pstl::internal::no_op()); +} + +// [inclusive.scan] + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { + typedef typename iterator_traits::value_type input_type; + return transform_inclusive_scan(std::forward(exec), first, last, result, std::plus(), pstl::internal::no_op()); +} + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op) { + return transform_inclusive_scan(std::forward(exec), first, last, result, binary_op, pstl::internal::no_op()); +} + +template +pstl::internal::enable_if_execution_policy +inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init) { + return transform_inclusive_scan(std::forward(exec), first, last, result, binary_op, pstl::internal::no_op(), init); +} + +// [transform.exclusive.scan] + +template +pstl::internal::enable_if_execution_policy +transform_exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op, UnaryOperation unary_op) { + using namespace pstl::internal; + return pattern_transform_scan( + first, last, result, unary_op, init, binary_op, + /*inclusive=*/std::false_type(), + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +// [transform.inclusive.scan] + +template +pstl::internal::enable_if_execution_policy +transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init) { + using namespace pstl::internal; + return pattern_transform_scan( + first, last, result, unary_op, init, binary_op, + /*inclusive=*/std::true_type(), + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op) { + if( first!=last ) { + auto tmp = unary_op(*first); + *result = tmp; + return transform_inclusive_scan(std::forward(exec), ++first, last, ++result, binary_op, unary_op, tmp); + } else { + return result; + } +} + +// [adjacent.difference] + +template +pstl::internal::enable_if_execution_policy +adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op) { + using namespace pstl::internal; + + if (first == last) + return d_first; + + return pattern_adjacent_difference(first, last, d_first, op, + is_vectorization_preferred(exec), + is_parallelization_preferred(exec)); +} + +template +pstl::internal::enable_if_execution_policy +adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first) { + typedef typename iterator_traits::value_type value_type; + return adjacent_difference(std::forward(exec), first, last, d_first, std::minus()); +} + +} // namespace std + +#endif /* __PSTL_glue_numeric_impl_H_ */ diff --git a/include/pstl/internal/memory_impl.h b/include/pstl/internal/memory_impl.h new file mode 100644 index 00000000000..d3635b95cb8 --- /dev/null +++ b/include/pstl/internal/memory_impl.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +#ifndef __PSTL_memory_impl_H +#define __PSTL_memory_impl_H + +#include + +#include "unseq_backend_simd.h" + +namespace pstl { +namespace internal { + +//------------------------------------------------------------------------ +// uninitialized_move +//------------------------------------------------------------------------ + +template +ForwardIterator brick_uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result, /*vector=*/std::false_type) noexcept { + typedef typename std::iterator_traits::value_type value_type2; + for (; first != last; ++first, ++result) { + ::new (reduce_to_ptr(result)) value_type2(std::move(*first)); + } + return result; +} + +template +ForwardIterator brick_uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result, /*vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits::value_type value_type2; + return unseq_backend::simd_it_walk_2(first, last - first, result, + [](InputIterator first1, ForwardIterator first2) {::new (reduce_to_ptr(first2)) value_type2(std::move(*first1)); + }); +} + +} // namespace internal +} // namespace pstl + +#endif /* __PSTL_memory_impl_H */ diff --git a/include/pstl/internal/numeric_impl.h b/include/pstl/internal/numeric_impl.h index f44b0c31592..53fe346e818 100644 --- a/include/pstl/internal/numeric_impl.h +++ b/include/pstl/internal/numeric_impl.h @@ -28,6 +28,7 @@ #include "pstl_config.h" #include "execution_impl.h" #include "unseq_backend_simd.h" +#include "bricks_impl.h" #if __PSTL_USE_PAR_POLICIES #include "parallel_backend.h" @@ -35,6 +36,7 @@ namespace pstl { namespace internal { + //------------------------------------------------------------------------ // transform_reduce (version with two binary functions, according to draft N4659) //------------------------------------------------------------------------ @@ -222,26 +224,44 @@ __PSTL_PRAGMA_FORCEINLINE // adjacent_difference //------------------------------------------------------------------------ -template -OutputIterator brick_adjacent_difference(InputIterator first, InputIterator last, OutputIterator d_first, BinaryOperation op, /*is_vector*/ std::false_type) noexcept { +template +ForwardIterator2 brick_adjacent_difference(ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op, /*is_vector=*/std::false_type) noexcept { return std::adjacent_difference(first, last, d_first, op); } -template -OutputIterator brick_adjacent_difference(InputIterator first, InputIterator last, OutputIterator d_first, BinaryOperation op, /*is_vector*/ std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Vectorial algorithm unimplemented, referenced to serial"); - return std::adjacent_difference(first, last, d_first, op); +template +ForwardIterator2 brick_adjacent_difference(ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op, /*is_vector=*/std::true_type) noexcept { + assert(first != last); + typedef typename std::iterator_traits::value_type T; + T val(*first); + *d_first = val; + unseq_backend::simd_it_walk_2(first, (last - first) - 1, d_first + 1, + [&op](ForwardIterator1 in, ForwardIterator2 out) { + T val(op(*(in + 1), *in)); + *out = val; + }); + return d_first + (last - first); } -template -OutputIterator pattern_adjacent_difference(InputIterator first, InputIterator last, OutputIterator d_first, BinaryOperation op, IsVector is_vector, /*is_parallel*/ std::false_type) noexcept { +template +ForwardIterator2 pattern_adjacent_difference(ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op, IsVector is_vector, /*is_parallel=*/std::false_type) noexcept { return brick_adjacent_difference(first, last, d_first, op, is_vector); } -template -OutputIterator pattern_adjacent_difference(InputIterator first, InputIterator last, OutputIterator d_first, BinaryOperation op, IsVector is_vector, /*is_parallel*/ std::true_type) noexcept { - __PSTL_PRAGMA_MESSAGE("Parallel algorithm unimplemented, referenced to serial"); - return brick_adjacent_difference(first, last, d_first, op, is_vector); +template +ForwardIterator2 pattern_adjacent_difference(ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op, IsVector is_vector, /*is_parallel=*/std::true_type) { + assert(first != last); + typedef typename std::iterator_traits::value_type T; + T val(*first); + *d_first = val; + par_backend::parallel_for(first, last - 1, [&op, is_vector, d_first, first](ForwardIterator1 b, ForwardIterator1 e) { + ForwardIterator2 d_b = d_first + (b - first); + brick_it_walk2(b, e, d_b + 1, [&op](ForwardIterator1 in, ForwardIterator2 out) { + T val(op(*(in + 1), *in)); + *out = val; + }, is_vector); + }); + return d_first + (last - first); } } // namespace internal diff --git a/include/pstl/internal/parallel_backend_tbb.h b/include/pstl/internal/parallel_backend_tbb.h index 67e13c60a6b..2fdcdd946d8 100644 --- a/include/pstl/internal/parallel_backend_tbb.h +++ b/include/pstl/internal/parallel_backend_tbb.h @@ -32,6 +32,7 @@ #include #include #include +#include #if TBB_INTERFACE_VERSION < 10000 #error Intel(R) Threading Building Blocks 2018 is required; older versions are not supported. @@ -44,20 +45,23 @@ namespace par_backend { /** Some of our algorithms need to start with raw memory buffer, not an initialize array, because initialization/destruction would make the span be at least O(N). */ +// tbb::allocator can improve performance in some cases. template class buffer { + tbb::tbb_allocator allocator; T* ptr; + const std::size_t buf_size; buffer(const buffer&) = delete; void operator=(const buffer&) = delete; public: //! Try to obtain buffer of given size to store objects of T type - buffer(size_t n): ptr(static_cast(operator new(n*sizeof(T), std::nothrow))) {} + buffer(std::size_t n) : allocator(), ptr(allocator.allocate(n)), buf_size(n) {} //! True if buffer was successfully obtained, zero otherwise. operator bool() const { return ptr != NULL; } //! Return pointer to buffer, or NULL if buffer could not be obtained. T* get() const { return ptr; } //! Destroy buffer - ~buffer() { operator delete(ptr); } + ~buffer() { allocator.deallocate(ptr, buf_size); } }; // Wrapper for tbb::task @@ -445,12 +449,17 @@ tbb::task* stable_sort_task(zs, zm, zm, ze, xs, comp, serial_destroy(), serial_move_merge(nmerge)); + m = new (allocate_continuation()) merge_task>(zs, zm, zm, ze, xs, comp, serial_destroy(), serial_move_merge(nmerge, move_values, move_sequences)); else if (inplace) - m = new (allocate_continuation()) merge_task(zs, zm, zm, ze, xs, comp, binary_no_op(), serial_move_merge(nmerge)); - else - m = new (allocate_continuation()) merge_task(xs, xm, xm, xe, zs, comp, binary_no_op(), serial_move_merge(nmerge)); + m = new (allocate_continuation()) merge_task>(zs, zm, zm, ze, xs, comp, binary_no_op(), serial_move_merge(nmerge, move_values, move_sequences)); + else { + auto move_values = [](RandomAccessIterator1 x, RandomAccessIterator2 z) {*z = std::move(*x); }; + auto move_sequences = [](RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2) {return std::move(first1, last1, first2); }; + m = new (allocate_continuation()) merge_task>(xs, xm, xm, xe, zs, comp, binary_no_op(), serial_move_merge(nmerge, move_values, move_sequences)); + } m->set_ref_count(2); task* right = new(m->allocate_child()) stable_sort_task(xm, xe, zm, !inplace, comp, leaf_sort, nmerge); spawn(*right); diff --git a/include/pstl/internal/parallel_backend_utils.h b/include/pstl/internal/parallel_backend_utils.h index b0f0328bd11..d0be9e3e5eb 100644 --- a/include/pstl/internal/parallel_backend_utils.h +++ b/include/pstl/internal/parallel_backend_utils.h @@ -23,6 +23,7 @@ #include #include +#include "utils.h" namespace pstl { namespace par_backend { @@ -40,44 +41,53 @@ struct serial_destroy { }; //! Merge sequences [xs,xe) and [ys,ye) to output sequence [zs,(xe-xs)+(ye-ys)), using std::move +template struct serial_move_merge { const std::size_t my_nmerge; - serial_move_merge(std::size_t nmerge) : my_nmerge(nmerge) {} + MoveValues move_values; + MoveSequences move_sequences; + + explicit serial_move_merge(std::size_t nmerge, MoveValues move_values_, MoveSequences move_sequences_) + : my_nmerge(nmerge), move_values(move_values_), move_sequences(move_sequences_) {} template void operator()(RandomAccessIterator1 xs, RandomAccessIterator1 xe, RandomAccessIterator2 ys, RandomAccessIterator2 ye, RandomAccessIterator3 zs, Compare comp) { auto n = my_nmerge; assert(n > 0); if (xs != xe) { if (ys != ye) { - for (;;) + for (;;) { if (comp(*ys, *xs)) { - *zs = std::move(*ys); + move_values(ys, zs); ++zs, --n; - if (++ys == ye) + if (++ys == ye) { break; + } else if (n == 0) { - zs = std::move(ys, ye, zs); + zs = move_sequences(ys, ye, zs); break; } + else {} } else { - *zs = std::move(*xs); + move_values(xs, zs); ++zs, --n; if (++xs == xe) { - std::move(ys, ye, zs); + move_sequences(ys, ye, zs); return; } else if (n == 0) { - zs = std::move(xs, xe, zs); - std::move(ys, ye, zs); + zs = move_sequences(xs, xe, zs); + move_sequences(ys, ye, zs); return; } + else {} } + } } ys = xs; ye = xe; } - std::move(ys, ye, zs); + move_sequences(ys, ye, zs); } }; diff --git a/include/pstl/internal/pstl_config.h b/include/pstl/internal/pstl_config.h index 2adfaee6aec..1257e3c8228 100644 --- a/include/pstl/internal/pstl_config.h +++ b/include/pstl/internal/pstl_config.h @@ -21,7 +21,7 @@ #ifndef __PSTL_config_H #define __PSTL_config_H -#define PSTL_VERSION 105 +#define PSTL_VERSION 106 #define PSTL_VERSION_MAJOR (PSTL_VERSION/100) #define PSTL_VERSION_MINOR (PSTL_VERSION - PSTL_VERSION_MAJOR * 100) @@ -132,8 +132,8 @@ //Too many warnings in output, switched off #define __PSTL_PRAGMA_MESSAGE(x) -#if defined(__GLIBCXX__) -#define __PSTL_CPP11_STD_ROTATE_BROKEN (__PSTL_GCC_VERSION < 50100) //GCC 5.1 release -#endif +#define __PSTL_CPP11_STD_ROTATE_BROKEN ((__GLIBCXX__ && __GLIBCXX__ < 20150716) || (_MSC_VER && _MSC_VER < 1800)) + +#define __PSTL_ICC_18_OMP_SIMD_BROKEN (__INTEL_COMPILER == 1800) #endif /* __PSTL_config_H */ diff --git a/include/pstl/internal/unseq_backend_simd.h b/include/pstl/internal/unseq_backend_simd.h index bbd9cb828c1..8f12be2c3d7 100644 --- a/include/pstl/internal/unseq_backend_simd.h +++ b/include/pstl/internal/unseq_backend_simd.h @@ -220,7 +220,7 @@ __PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC(cnt:1) } template -OutputIterator simd_copy_move(InputIterator first, DifferenceType n, OutputIterator result, Assigner assigner) noexcept { +OutputIterator simd_assign(InputIterator first, DifferenceType n, OutputIterator result, Assigner assigner) noexcept { __PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED __PSTL_PRAGMA_SIMD for (DifferenceType i = 0; i < n; ++i) @@ -234,11 +234,11 @@ OutputIterator simd_copy_if(InputIterator first, DifferenceType n, OutputIterato __PSTL_PRAGMA_SIMD for(DifferenceType i = 0; i < n; ++i) { - __PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC(cnt:1) - if(pred(first[i])) { - result[cnt] = first[i]; - ++cnt; - } +__PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC(cnt:1) + if(pred(first[i])) { + result[cnt] = first[i]; + ++cnt; + } } return result + cnt; } diff --git a/include/pstl/memory b/include/pstl/memory index 921fc0d2a49..0b123818668 100644 --- a/include/pstl/memory +++ b/include/pstl/memory @@ -22,218 +22,14 @@ #define __PSTL_memory #include "internal/pstl_config.h" -#include "internal/utils.h" -#include "internal/algorithm_impl.h" -namespace std { +#if __PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +#include "internal/glue_memory_impl.h" +#else +// Otherwise just pull in forward declarations +#include "internal/glue_memory_defs.h" +#define __PSTL_MEMORY_FORWARD_DECLARED 1 +#endif -template -pstl::internal::enable_if_execution_policy -uninitialized_copy(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result) { - typedef typename iterator_traits::value_type value_type1; - typedef typename iterator_traits::value_type value_type2; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), - [&]() { return pattern_walk2_brick(first, last, result, [is_vector](InputIterator begin, InputIterator end, ForwardIterator res) - { return brick_copy(begin, end, res, is_vector); }, is_parallel); }, - [&]() { return pattern_it_walk2(first, last, result, [](InputIterator it1, ForwardIterator it2) - { ::new (reduce_to_ptr(it2)) value_type2(*it1); }, is_vector, is_parallel); } - ); -} - -template -pstl::internal::enable_if_execution_policy -uninitialized_copy_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result) { - typedef typename iterator_traits::value_type value_type1; - typedef typename iterator_traits::value_type value_type2; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), - [&]() { return pattern_walk2_brick_n(first, n, result, [is_vector](InputIterator begin, Size sz, ForwardIterator res) - { return brick_copy_n(begin, sz, res, is_vector); }, is_parallel); }, - [&]() { return pattern_it_walk2_n(first, n, result, [](InputIterator it1, ForwardIterator it2) - { ::new (reduce_to_ptr(it2)) value_type2(*it1); }, is_vector, is_parallel); } - ); -} - -// [uninitialized.move] - -template -pstl::internal::enable_if_execution_policy -uninitialized_move(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result) { - typedef typename iterator_traits::value_type value_type1; - typedef typename iterator_traits::value_type value_type2; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), - [&]() { return pattern_walk2_brick(first, last, result, [is_vector](InputIterator begin, InputIterator end, ForwardIterator res) - { return brick_copy(begin, end, res, is_vector);}, is_parallel); }, - [&]() { return pattern_it_walk2(first, last, result, [](InputIterator it1, ForwardIterator it2) - { ::new (reduce_to_ptr(it2)) value_type2(std::move(*it1)); }, is_vector, is_parallel); } - ); -} - -template -pstl::internal::enable_if_execution_policy -uninitialized_move_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result) { - typedef typename iterator_traits::value_type value_type1; - typedef typename iterator_traits::value_type value_type2; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::integral_constant::value && std::is_trivial::value>(), - [&]() { return pattern_walk2_brick_n(first, n, result, [is_vector](InputIterator begin, Size sz, ForwardIterator res) - { return brick_copy_n(begin, sz, res, is_vector);}, is_parallel); }, - [&]() { return pattern_it_walk2_n(first, n, result, [](InputIterator it1, ForwardIterator it2) - { ::new (reduce_to_ptr(it2)) value_type2(std::move(*it1)); }, is_vector, is_parallel); } - ); -} - -// [uninitialized.fill] - -template -pstl::internal::enable_if_execution_policy -uninitialized_fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - invoke_if_else(std::is_arithmetic(), - [&]() { pattern_walk_brick(first, last, [&value, &is_vector](ForwardIterator begin, ForwardIterator end) - { brick_fill(begin, end, value_type(value), is_vector);}, is_parallel); }, - [&]() { pattern_it_walk1(first, last, [&value](ForwardIterator it) - { ::new (reduce_to_ptr(it)) value_type(value); }, is_vector, is_parallel); } - ); -} - -template -pstl::internal::enable_if_execution_policy -uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::is_arithmetic(), - [&]() { return pattern_walk_brick_n(first, n, [&value, &is_vector](ForwardIterator begin, Size count) - { return brick_fill_n(begin, count, value_type(value), is_vector);}, is_parallel); }, - [&]() { return pattern_it_walk1_n(first, n, [&value](ForwardIterator it) - { ::new (reduce_to_ptr(it)) value_type(value); }, is_vector, is_parallel); } - ); -} - -// [specialized.destroy] - -template -pstl::internal::enable_if_execution_policy -destroy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - invoke_if_not(std::is_trivially_destructible(), - [&]() { pattern_it_walk1(first, last, [](ForwardIterator it){ (*it).~value_type(); }, is_vector, is_parallel); } - ); -} - -template -pstl::internal::enable_if_execution_policy -destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::is_trivially_destructible(), - [&]() { return std::next(first, n);}, - [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it){ (*it).~value_type(); }, is_vector, is_parallel); } - ); -} - -// [uninitialized.construct.default] - -template -pstl::internal::enable_if_execution_policy -uninitialized_default_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - invoke_if_not(std::is_trivial(), - [&]() { pattern_it_walk1(first, last, [](ForwardIterator it) { ::new (reduce_to_ptr(it)) value_type; }, is_vector, is_parallel); }); -} - -template -pstl::internal::enable_if_execution_policy -uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::is_trivial(), - [&]() { return std::next(first, n);}, - [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it) - { ::new (reduce_to_ptr(it)) value_type; }, is_vector, is_parallel); } - ); -} - -// [uninitialized.construct.value] - -template -pstl::internal::enable_if_execution_policy -uninitialized_value_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - invoke_if_else(std::is_trivial(), - [&]() { pattern_walk_brick(first, last, [is_vector](ForwardIterator begin, ForwardIterator end) - { brick_fill(begin, end, value_type(), is_vector);}, is_parallel); }, - [&]() { pattern_it_walk1(first, last, [](ForwardIterator it) - { ::new (reduce_to_ptr(it)) value_type(); }, is_vector, is_parallel); } - ); -} - -template -pstl::internal::enable_if_execution_policy -uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n) { - typedef typename iterator_traits::value_type value_type; - using namespace pstl::internal; - - const auto is_parallel = is_parallelization_preferred(exec); - const auto is_vector = is_vectorization_preferred(exec); - - return invoke_if_else(std::is_trivial(), - [&]() { return pattern_walk_brick_n(first, n, [is_vector](ForwardIterator begin, Size count) - { return brick_fill_n(begin, count, value_type(), is_vector);}, is_parallel); }, - [&]() { return pattern_it_walk1_n(first, n, [](ForwardIterator it) - { ::new (reduce_to_ptr(it)) value_type(); }, is_vector, is_parallel); } - ); -} - -} // namespace std -#endif /*__PSTL_memory */ +#endif /* __PSTL_memory */ diff --git a/include/pstl/numeric b/include/pstl/numeric index c3d68483ef2..1199079faae 100644 --- a/include/pstl/numeric +++ b/include/pstl/numeric @@ -21,155 +21,15 @@ #ifndef __PSTL_numeric #define __PSTL_numeric -#include - #include "internal/pstl_config.h" -#include "internal/utils.h" -#include "internal/numeric_impl.h" - -namespace std { - -// [reduce] - -template -pstl::internal::enable_if_execution_policy -reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op) { - return transform_reduce(std::forward(exec), first, last, init, binary_op, pstl::internal::no_op()); -} - -template -pstl::internal::enable_if_execution_policy -reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init) { - return transform_reduce(std::forward(exec), first, last, init, std::plus(), pstl::internal::no_op()); -} - -template -pstl::internal::enable_if_execution_policy::value_type> -reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { - typedef typename iterator_traits::value_type T; - return transform_reduce(std::forward(exec), first, last, T{}, std::plus(), pstl::internal::no_op()); -} - -// [transform.reduce] - -template -pstl::internal::enable_if_execution_policy -transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init) { - typedef typename iterator_traits::value_type input_type; - using namespace pstl::internal; - return pattern_transform_reduce(first1, last1, first2, init, std::plus(), std::multiplies(), - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2) { - using namespace pstl::internal; - return pattern_transform_reduce(first1, last1, first2, init, binary_op1, binary_op2, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -transform_reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op) { - using namespace pstl::internal; - return pattern_transform_reduce(first, last, init, binary_op, unary_op, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [exclusive.scan] - -template -pstl::internal::enable_if_execution_policy -exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init) { - return transform_exclusive_scan(std::forward(exec), first, last, result, init, std::plus(), pstl::internal::no_op()); -} - -template -ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op) { - return transform_exclusive_scan(std::forward(exec), first, last, result, init, binary_op, pstl::internal::no_op()); -} - -// [inclusive.scan] - -template -pstl::internal::enable_if_execution_policy -inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result) { - typedef typename iterator_traits::value_type input_type; - return transform_inclusive_scan(std::forward(exec), first, last, result, std::plus(), pstl::internal::no_op()); -} - -template -pstl::internal::enable_if_execution_policy -inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op) { - return transform_inclusive_scan(std::forward(exec), first, last, result, binary_op, pstl::internal::no_op()); -} - -template -pstl::internal::enable_if_execution_policy -inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init) { - return transform_inclusive_scan(std::forward(exec), first, last, result, binary_op, pstl::internal::no_op(), init); -} - -// [transform.exclusive.scan] - -template -pstl::internal::enable_if_execution_policy -transform_exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op, UnaryOperation unary_op) { - using namespace pstl::internal; - return pattern_transform_scan( - first, last, result, unary_op, init, binary_op, - /*inclusive=*/std::false_type(), - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -// [transform.inclusive.scan] - -template -pstl::internal::enable_if_execution_policy -transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init) { - using namespace pstl::internal; - return pattern_transform_scan( - first, last, result, unary_op, init, binary_op, - /*inclusive=*/std::true_type(), - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op) { - if( first!=last ) { - auto tmp = unary_op(*first); - *result = tmp; - return transform_inclusive_scan(std::forward(exec), ++first, last, ++result, binary_op, unary_op, tmp); - } else { - return result; - } -} - -// [adjacent.difference] - -template -pstl::internal::enable_if_execution_policy -adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first, BinaryOperation op) { - using namespace pstl::internal; - return pattern_adjacent_difference(first, last, d_first, op, - is_vectorization_preferred(exec), - is_parallelization_preferred(exec)); -} - -template -pstl::internal::enable_if_execution_policy -adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 d_first) { - typedef typename iterator_traits::value_type value_type; - return adjacent_difference(std::forward(exec), first, last, d_first, std::minus()); -} -} +#if __PSTL_EXECUTION_POLICIES_DEFINED +// If has already been included, pull in implementations +#include "internal/glue_numeric_impl.h" +#else +// Otherwise just pull in forward declarations +#include "internal/glue_numeric_defs.h" +#define __PSTL_NUMERIC_FORWARD_DECLARED 1 +#endif #endif /* __PSTL_numeric */ diff --git a/test/pstl_test_config.h b/test/pstl_test_config.h index baaa0dea9ce..71794f8ec7a 100644 --- a/test/pstl_test_config.h +++ b/test/pstl_test_config.h @@ -29,7 +29,8 @@ #define __PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN (!_DEBUG && __INTEL_COMPILER && (__INTEL_COMPILER < 1800 || (__INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1))) #define __PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN (__x86_64 && !_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1) #define __PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN (__i386__ && !_DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && __APPLE__) -#define __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && _MSC_VER == 1910) +#define __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN (!_DEBUG && __INTEL_COMPILER >= 1800 && __INTEL_COMPILER < 1900 && _MSC_VER == 1910) +#define __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && _MSC_VER >= 1910) #define __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1600 && __INTEL_COMPILER < 1700 && _MSC_VER == 1900) #define __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN (__PSTL_USE_PAR_POLICIES && _M_X64 && !_DEBUG && __INTEL_COMPILER < 1700 && _MSC_VER == 1900) #define __PSTL_ICC_16_17_TEST_64_TIMEOUT (__x86_64 && __INTEL_COMPILER && __INTEL_COMPILER < 1800 && !__APPLE__) diff --git a/test/test_adjacent_difference.cpp b/test/test_adjacent_difference.cpp new file mode 100644 index 00000000000..e363711b406 --- /dev/null +++ b/test/test_adjacent_difference.cpp @@ -0,0 +1,160 @@ +/* + Copyright (c) 2017-2018 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 "test/pstl_test_config.h" + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#include "pstl/numeric" +#include "test/utils.h" + +using namespace TestUtils; + +template +struct wrapper { + T t; + explicit wrapper(T t_) : t(t_) {} + template + wrapper(const wrapper& a) { + t = a.t; + } + template + void operator=(const wrapper& a) { + t = a.t; + } + wrapper operator-(const wrapper& a) const { + return wrapper(t - a.t); + } +}; + +template +bool compare(const T& a, const T& b) { + return a == b; +} + +template +bool compare(const wrapper& a, const wrapper& b) { + return a.t == b.t; +} + +template +typename std::enable_if::value, bool>::type +compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function f) { + using T2 = typename std::iterator_traits::value_type; + + if (first == last) + return true; + + T2 temp(*first); + if (!compare(temp, *d_first)) + return false; + Iterator1 second = std::next(first); + + ++d_first; + for (; second != last; ++first, ++second, ++d_first) { + T2 temp(f(*second, *first)); + if (!compare(temp, *d_first)) + return false; + } + + return true; +} + +// we don't want to check equality here +// because we can't be sure it will be strictly equal for floating point types +template +typename std::enable_if::value, bool>::type +compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function) { + return true; +} + +struct test_one_policy { +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, + Iterator2 actual_b, Iterator2 actual_e, T trash, Function f) { } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, + Iterator2 actual_b, Iterator2 actual_e, T trash, Function f) { } +#endif + + template + void operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, + Iterator2 actual_b, Iterator2 actual_e, T trash, Function f) { + using namespace std; + using T2 = typename std::iterator_traits::value_type; + + fill(actual_b, actual_e, trash); + + Iterator2 actual_return = adjacent_difference(exec, data_b, data_e, actual_b); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), std::minus()), "wrong effect of adjacent_difference"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference"); + + fill(actual_b, actual_e, trash); + + actual_return = adjacent_difference(exec, data_b, data_e, actual_b, f); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), f), "wrong effect of adjacent_difference with functor"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference with functor"); + } + +}; + + +template +void test(Pred pred) { + typedef typename Sequence::iterator iterator_type; + + const std::size_t max_len = 100000; + + const T2 value = T2(77); + const T1 trash = T1(31); + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [&value](std::size_t i) { + return i % 3 == 2 ? T2(i*i) : value; + }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) { + invoke_on_all_policies(test_one_policy(), + data.begin(), data.begin() + len, + actual.begin(), actual.begin() + len, + trash, pred); + invoke_on_all_policies(test_one_policy(), + data.cbegin(), data.cbegin() + len, + actual.begin(), actual.begin() + len, + trash, pred); + } +} + +int32_t main() { + test([](uint32_t a, uint32_t b) { return a - b; }); + test([](int64_t a, int64_t b) { return a / (b + 1); }); + test([](float32_t a, float32_t b) { return (a + b) / 2; }); + test, wrapper>( + [](const wrapper& a, const wrapper& b) { return a - b; }); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index 5f2ea96e90d..e844935e220 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -73,10 +73,12 @@ struct run_rnd { partial_sort(exec, b1, middle, e1, std::less()); partial_sort(exec, b1, b1, b1, non_const(std::less())); - //partial_sort_copy - partial_sort_copy(exec, b1, e1, b2, e2); - partial_sort_copy(exec, b1, e1, b2, e2, std::less()); - partial_sort_copy(exec, b1, b1, b2, b2, non_const(std::less())); + invoke_if(exec, [&]() { + //partial_sort_copy + partial_sort_copy(exec, b1, e1, b2, e2); + partial_sort_copy(exec, b1, e1, b2, e2, std::less()); + partial_sort_copy(exec, b1, b1, b2, b2, non_const(std::less())); + }); //sort sort(exec, b1, e1); @@ -105,21 +107,23 @@ struct run_rnd_bi { //usage of "non_const" adapter - we pass empty container due to just compilation checks - //inplace_merge - auto middle = next(b1, distance(b1, e1) / 2); - inplace_merge(exec, b1, middle, e1); - inplace_merge(exec, b1, middle, e1, std::less()); - inplace_merge(exec, b1, b1, b1, non_const(std::less())); + invoke_if(exec, [&]() { + //inplace_merge + auto middle = next(b1, distance(b1, e1) / 2); + inplace_merge(exec, b1, middle, e1); + inplace_merge(exec, b1, middle, e1, std::less()); + inplace_merge(exec, b1, b1, b1, non_const(std::less())); - //reverse - reverse(exec, b2, e2); + //reverse + reverse(exec, b2, e2); - //reverse_copy - reverse_copy(exec, b1, e1, b2); + //reverse_copy + reverse_copy(exec, b1, e1, b2); - //stable_partition - stable_partition(exec, b1, e1, is_even); - stable_partition(exec, b1, b1, non_const(is_even)); + //stable_partition + stable_partition(exec, b1, e1, is_even); + stable_partition(exec, b1, b1, non_const(is_even)); + }); } template @@ -290,9 +294,11 @@ struct run_rnd_fw { none_of(exec, b1, e1, is_even); none_of(exec, b1, b1, non_const(is_even)); - //partition - partition(exec, b1, e1, is_even); - partition(exec, b1, b1, non_const(is_even)); + invoke_if(exec, [&]() { + //partition + partition(exec, b1, e1, is_even); + partition(exec, b1, b1, non_const(is_even)); + }); //partition_copy partition_copy(exec, b1, e1, out, out, is_even); @@ -330,10 +336,10 @@ struct run_rnd_fw { //rotate rotate(exec, b1, b1, e1); - //rotate_copy - rotate_copy(exec, b1, b1, e1, out); - invoke_if(exec, [&]() { + //rotate_copy + rotate_copy(exec, b1, b1, e1, out); + //search search(exec, b1, e1, b2, e2); search(exec, b1, e1, b2, e2, std::equal_to()); diff --git a/test/test_inplace_merge.cpp b/test/test_inplace_merge.cpp new file mode 100644 index 00000000000..d70c880a5f2 --- /dev/null +++ b/test/test_inplace_merge.cpp @@ -0,0 +1,131 @@ +/* + Copyright (c) 2017-2018 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 "test/pstl_test_config.h" + +#include +#include "pstl/execution" +#include "pstl/algorithm" + +#include "test/utils.h" + +using namespace TestUtils; + +struct test_one_policy { +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, + BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {} + + template + void operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, + BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {} +#endif + + // inplace_merge works with bidirectional iterators at least + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, + BiDirIt1 first2, BiDirIt1 last2, + Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { + + using T = typename std::iterator_traits::value_type; + const BiDirIt1 mid1 = std::next(first1, m); + fill_data(first1, mid1, generator1); + fill_data(mid1, last1, generator2); + + const BiDirIt1 mid2 = std::next(first2, m); + fill_data(first2, mid2, generator1); + fill_data(mid2, last2, generator2); + + std::inplace_merge(first1, mid1, last1, comp); + std::inplace_merge(exec, first2, mid2, last2, comp); + EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, + BiDirIt1 first2, BiDirIt1 last2, + Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) {} +}; + +template +void test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) { + using namespace std; + size_t max_size = 100000; + Sequence in1(max_size, [](size_t v) {return T(v); }); + Sequence exp(max_size, [](size_t v) {return T(v); }); + size_t m; + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) { + m = 0; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, + exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp); + + m = n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, + exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp); + + m = 2 * n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, + exp.begin(), exp.begin() + n, n, m, generator1, generator2, comp); + } +} + +template +struct LocalWrapper { + explicit LocalWrapper(int32_t k) : my_val(k) { } + LocalWrapper(LocalWrapper&& input) { + my_val = std::move(input.my_val); + } + LocalWrapper& operator=(LocalWrapper&& input) { + my_val = std::move(input.my_val); + return *this; + } + bool operator<(const LocalWrapper& w) const { + return my_val < w.my_val; + } + friend bool operator==(const LocalWrapper& x, const LocalWrapper& y) { + return x.my_val == y.my_val; + } + friend std::ostream& operator<<(std::ostream& stream, const LocalWrapper& input) { + return stream << input.my_val; + } +private: + T my_val; +}; + +int32_t main( ) { + test_by_type([](int32_t i) {return -2 * i; }, + [](int32_t i) {return -(2 * i + 1); }, + [](const float64_t x, const float64_t y) {return x > y; }); + + test_by_type([](int32_t i) { return 10 * i; }, + [](int32_t i) { return i + 1; }, + std::less()); + + test_by_type>([](int32_t i) {return LocalWrapper(2*i+1); }, + [](int32_t i) {return LocalWrapper(2 * i); }, + std::less>()); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/test_iterators.cpp b/test/test_iterators.cpp index d118b9f3daf..b605ab6d0ee 100644 --- a/test/test_iterators.cpp +++ b/test/test_iterators.cpp @@ -21,6 +21,7 @@ #include #include +#include "pstl/execution" #include "pstl/algorithm" #include "pstl/iterators.h" #include "test/utils.h" diff --git a/test/test_numeric.cpp b/test/test_numeric.cpp index 48a9a733400..9dd804b03de 100644 --- a/test/test_numeric.cpp +++ b/test/test_numeric.cpp @@ -81,6 +81,16 @@ struct test_reduce { }; struct test_adjacent_difference { +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, InputIterator inBegin, InputIterator inEnd, OutputIterator outBegin) {} + + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator inBegin, InputIterator inEnd, OutputIterator outBegin) {} +#endif + template void operator()(Policy&& exec, InputIterator inBegin, InputIterator inEnd, OutputIterator outBegin) { typedef typename InputIterator::value_type T; diff --git a/test/test_partial_sort.cpp b/test/test_partial_sort.cpp index 34c430134e5..9577c243f5c 100644 --- a/test/test_partial_sort.cpp +++ b/test/test_partial_sort.cpp @@ -80,7 +80,12 @@ struct test_brick_partial_sort { #else auto p = 1; #endif - EXPECT_TRUE(count_comp < complex*p, "bad complexity"); + +#ifdef _DEBUG + if (count_comp > complex*p) { + std::cout << "complexity exceeded" << std::endl; + } +#endif } } } diff --git a/test/test_partial_sort_copy.cpp b/test/test_partial_sort_copy.cpp new file mode 100644 index 00000000000..38bd1cfcda9 --- /dev/null +++ b/test/test_partial_sort_copy.cpp @@ -0,0 +1,142 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +// Tests for partial_sort_copy + +#include +#include "test/pstl_test_config.h" + +#include "pstl/execution" +#include "pstl/algorithm" +#include "test/utils.h" + +using namespace TestUtils; + +template +struct Num { + T val; + + Num() : val(0) { } + Num(T v): val(v) { } + Num(const Num& v): val(v.val) { } + Num(Num&& v): val(v.val) { } + Num& operator=(const Num& v) { val = v.val; return *this; } + operator T() const { return val; } + bool operator<(const Num& v) const { + return val < v.val; + } +}; + +template +struct test_one_policy { + RandomAccessIterator d_first; + RandomAccessIterator d_last; + RandomAccessIterator exp_first; + RandomAccessIterator exp_last; + // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed) + test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, + RandomAccessIterator b2, RandomAccessIterator e2) : + d_first(b1), d_last(e1), exp_first(b2), exp_last(e2) {} +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) {} + + template + void operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) {} + + template + void operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) {} + + template + void operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) {} +#endif + + template + void operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate"); + } + + template + void operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate"); + } +private: + template + void prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash) { + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + std::generate(first, last, [n1]() {return T(rand() % (2 * n1 + 1)); }); + + std::fill(exp_first, exp_last, trash); + std::fill(d_first, d_last, trash); + } +}; + +template +void test_partial_sort_copy(Compare compare) { + + typedef typename Sequence::iterator iterator_type; + const std::size_t n_max = 100000; + Sequence in(n_max); + Sequence out(2 * n_max); + Sequence exp(2 * n_max); + std::size_t n1 = 0; + std::size_t n2; + T trash = T(-666); + for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) { + // If both sequences are equal + n2 = n1; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is greater than second + n2 = n1 / 3; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is less than second + n2 = 2 * n1; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash, compare); + } + // Test partial_sort_copy without predicate + n1 = n_max; + n2 = 2 * n1; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash); +} + +int32_t main() { + test_partial_sort_copy>([](Num x, Num y) {return x < y; }); + test_partial_sort_copy([](int32_t x, int32_t y) {return x > y; }); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/test_partition.cpp b/test/test_partition.cpp new file mode 100644 index 00000000000..71eac9c61b7 --- /dev/null +++ b/test/test_partition.cpp @@ -0,0 +1,121 @@ +/* + Copyright (c) 2017-2018 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. + + + + +*/ + +// Tests for stable_partition and partition +#include "test/pstl_test_config.h" + +#include "pstl/execution" +#include "pstl/algorithm" +#include "test/utils.h" + +#include +#include + +using namespace TestUtils; + +template +struct DataType { + explicit DataType(int32_t k) : my_val(k) { } + DataType(DataType&& input) { + my_val = std::move(input.my_val); + } + DataType& operator=(DataType&& input) { + my_val = std::move(input.my_val); + return *this; + } + T get_val()const { return my_val; } + + friend std::ostream& operator<<(std::ostream& stream, const DataType& input) { + return stream << input.my_val; + } +private: + T my_val; +}; + +template +typename std::enable_if::value_type>::value, bool>::type +is_equal(Iterator first, Iterator last, Iterator d_first) { return std::equal(first, last, d_first); } + +template +typename std::enable_if::value_type>::value, bool>::type +is_equal(Iterator first, Iterator last, Iterator d_first) { return true; } + +struct test_one_policy { +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void operator()(pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) {} + + template + void operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) {} +#endif + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) { + // partition + { + fill_data(first, last, generator); + BiDirIt actual_ret = std::partition(exec, first, last, unary_op); + EXPECT_TRUE(std::all_of(first, actual_ret, unary_op) && !std::any_of(actual_ret, last, unary_op), "wrong effect from partition"); + } + // stable_partition + { + fill_data(exp_first, exp_last, generator); + BiDirIt exp_ret = std::stable_partition(exp_first, exp_last, unary_op); + fill_data(first, last, generator); + BiDirIt actual_ret = std::stable_partition(exec, first, last, unary_op); + + EXPECT_TRUE(std::distance(first, actual_ret) == std::distance(exp_first, exp_ret), + "wrong result from stable_partition"); + EXPECT_TRUE((is_equal(exp_first, exp_last, first)), "wrong effect from stable_partition"); + } + } + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) { } +}; + +template +void test_by_type(Generator generator, UnaryPred pred) { + + using namespace std; + size_t max_size = 100000; + Sequence in(max_size, [](size_t v) {return T(v); }); + Sequence exp(max_size, [](size_t v) {return T(v); }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) { + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, n, pred, generator); + } +} + +int32_t main() { +#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test_by_type([](int32_t i) {return i; }, [](int32_t) {return true; }); +#endif + test_by_type([](int32_t i) {return -i; }, + [](const float64_t x) {return x < 0; }); + test_by_type([](int32_t i) { return i + 1; }, + [](int64_t x) {return x % 3 == 0; }); + test_by_type>([](int32_t i) {return DataType(2 * i + 1); }, + [](const DataType& x) {return x.get_val() < 0; }); + + std::cout << "done" << std::endl; + return 0; +} diff --git a/test/test_reverse.cpp b/test/test_reverse.cpp new file mode 100644 index 00000000000..0b573587c63 --- /dev/null +++ b/test/test_reverse.cpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2017-2018 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 "test/pstl_test_config.h" + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#include "test/utils.h" + +using namespace TestUtils; + +struct test_one_policy { +#if __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN || __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) { } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) { } +#endif + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) { + using namespace std; + + copy(data_b, data_e, actual_b); + + reverse(exec, actual_b, actual_e); + + bool check = equal(data_b, data_e, reverse_iterator(actual_e)); + + EXPECT_TRUE(check, "wrong result of reverse"); + } + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) {} +}; + +template +void test() { + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { + return T(i); + }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) { + invoke_on_all_policies(test_one_policy(), + data.begin(), data.begin() + len, + actual.begin(), actual.begin() + len); + } +} + +template +struct wrapper { + T t; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + bool operator==(const wrapper& a) const { + return t == a.t; + } +}; + +int32_t main() { + test(); + test(); + test(); + test>(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/test_reverse_copy.cpp b/test/test_reverse_copy.cpp new file mode 100644 index 00000000000..37b7430fa7c --- /dev/null +++ b/test/test_reverse_copy.cpp @@ -0,0 +1,124 @@ +/* + Copyright (c) 2017-2018 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 "test/pstl_test_config.h" + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#include "test/utils.h" + +using namespace TestUtils; + +template +struct wrapper { + T t; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + void operator=(const T& t_) { + t = t_; + } +}; + +template +bool eq(const wrapper& a, const wrapper& b) { + return a.t == b.t; +} + +template +bool eq(const T& a, const T& b) { + return a == b; +} + +// we need to save state here, because we need to test with different types of iterators +// due to the caller invoke_on_all_policies does forcing modification passed iterator type to cover additional usage cases. +template +struct test_one_policy { + Iterator data_b; + Iterator data_e; + test_one_policy(Iterator b, Iterator e): data_b(b), data_e(e) {} + +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) { } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) { } +#endif + + template + void operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e) { + using namespace std; + using T = typename iterator_traits::value_type; + + fill(actual_b, actual_e, T(-123)); + Iterator1 actual_return = reverse_copy(exec, data_b, data_e, actual_b); + + EXPECT_TRUE(actual_return == actual_e, "wrong result of reverse_copy"); + + if (actual_b != actual_e) { + T temp = *actual_b; + + // check effect of reverse_copy + while (actual_b != actual_e) { + --data_e; + temp = *data_e; + if (!eq(temp, *actual_b)) { + EXPECT_TRUE(false, "wrong effect of reverse_copy"); + break; + } + ++actual_b; + } + } + } +}; + +template +void test() { + typedef typename Sequence::iterator iterator_type; + typedef typename Sequence::const_bidirectional_iterator cbi_iterator_type; + + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { + return T1(i); + }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) { + invoke_on_all_policies(test_one_policy(data.begin(), data.begin() + len), + actual.begin(), actual.begin() + len); + invoke_on_all_policies(test_one_policy(data.cbibegin(), std::next(data.cbibegin(), len)), + actual.begin(), actual.begin() + len); + } +} + +int32_t main() { + test(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/test_rotate_copy.cpp b/test/test_rotate_copy.cpp new file mode 100644 index 00000000000..156588ebf04 --- /dev/null +++ b/test/test_rotate_copy.cpp @@ -0,0 +1,126 @@ +/* + Copyright (c) 2017-2018 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 "test/pstl_test_config.h" + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#include "test/utils.h" + +using namespace TestUtils; + +template +struct wrapper; + +template +bool compare(const wrapper& a, const wrapper& b) { + return a.t == b.t; +} + +template +bool compare(const T& a, const T& b) { + return a == b; +} + +template +struct wrapper { + explicit wrapper(T t_) : t(t_) {} + void operator=(const T& t_) { + t = t_; + } + friend bool compare(const wrapper& a, const wrapper& b); + private: + T t; +}; + +template +struct comparator { + using T1 = typename std::iterator_traits::value_type; + using T2 = typename std::iterator_traits::value_type; + bool operator()(T1 a, T2 b) { + T temp = a; + return compare(temp, b); + } +}; + +struct test_one_policy { + +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, std::size_t shift) { } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, std::size_t shift) { } +#endif + + template + void operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, std::size_t shift) { + using namespace std; + using T = typename iterator_traits::value_type; + Iterator1 data_m = std::next(data_b, shift); + + fill(actual_b, actual_e, T(-123)); + Iterator2 actual_return = rotate_copy(exec, data_b, data_m, data_e, actual_b); + + EXPECT_TRUE(actual_return == actual_e, "wrong result of rotate_copy"); + auto comparer = comparator(); + bool check = std::equal(data_m, data_e, actual_b, comparer); + check = check && std::equal(data_b, data_m, std::next(actual_b, std::distance(data_m, data_e)), comparer); + + EXPECT_TRUE(check, "wrong effect of rotate_copy"); + } +}; + +template +void test() { + + const std::size_t max_len = 100000; + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [](std::size_t i) { return T1(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) { + std::size_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; + for (std::size_t shift : shifts) { + if (shift > 0 && shift < len) { + invoke_on_all_policies(test_one_policy(), + data.begin(), data.begin() + len, + actual.begin(), actual.begin() + len, shift); + invoke_on_all_policies(test_one_policy(), + data.cbegin(), data.cbegin() + len, + actual.begin(), actual.begin() + len, shift); + } + } + } +} + +int32_t main() { + test(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} diff --git a/test/utils.h b/test/utils.h index 48722eb51e8..420c30b0195 100644 --- a/test/utils.h +++ b/test/utils.h @@ -182,6 +182,14 @@ class BidirectionalIterator : public ForwardIterator { } }; +template +void fill_data(Iterator first, Iterator last, F f) { + typedef typename std::iterator_traits::value_type T; + for (std::size_t i = 0; first != last; ++first, ++i) { + *first = T(f(i)); + } +} + // Sequence is a container of a sequence of T with lots of kinds of iterators. // Prefixes on begin/end mean: // c = "const" @@ -246,10 +254,7 @@ class Sequence { void print() const; template - void fill( Func f ) { - for (size_t i = 0; i < m_storage.size(); i++) - m_storage[i] = T(f(i)); - } + void fill( Func f ) { fill_data(m_storage.begin(), m_storage.end(), f); } }; template