diff options
author | Thomas Rodgers <trodgers@redhat.com> | 2023-06-26 11:30:21 -0700 |
---|---|---|
committer | Thomas Rodgers <trodgers@redhat.com> | 2023-06-26 11:34:43 -0700 |
commit | 3162ca09dbdc2ea3ff1d4b752edf76955b6d94f9 (patch) | |
tree | f355082a2f63d30d1911cae7a45e8e78adbb7719 | |
parent | 3a39a31b8ae9c6465434aefa657f7fcc86f905c0 (diff) | |
download | gcc-3162ca09dbdc2ea3ff1d4b752edf76955b6d94f9.zip gcc-3162ca09dbdc2ea3ff1d4b752edf76955b6d94f9.tar.gz gcc-3162ca09dbdc2ea3ff1d4b752edf76955b6d94f9.tar.bz2 |
libstdc++: Synchronize PSTL with upstream
This patch rebases the C++17 parallel algorithms implementation (pstl)
against the current upstream version, commit 843c12d6a.
This version does not currently include the recently added OpenMP
backend, that will be considered for a future version.
libstdc++-v3/ChangeLog:
* include/pstl/algorithm_fwd.h: Synchronize with upstream.
* include/pstl/algorithm_impl.h: Likewise.
* include/pstl/execution_defs.h: Likewise.
* include/pstl/execution_impl.h: Likewise.
* include/pstl/glue_algorithm_impl.h: Likewise.
* include/pstl/glue_execution_defs.h: Likewise.
* include/pstl/glue_memory_impl.h: Likewise.
* include/pstl/glue_numeric_impl.h: Likewise.
* include/pstl/memory_impl.h: Likewise.
* include/pstl/numeric_fwd.h: Likewise.
* include/pstl/numeric_impl.h: Likewise.
* include/pstl/parallel_backend.h: Likewise.
* include/pstl/parallel_backend_serial.h: Likewise.
* include/pstl/parallel_backend_tbb.h: Likewise.
* include/pstl/parallel_impl.h: Likewise.
* include/pstl/pstl_config.h: Likewise.
* include/pstl/unseq_backend_simd.h: Likewise.
* include/pstl/utils.h: Likewise.
* testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_merge/merge.cc: Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/includes.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/set.cc:
Likewise.
* testsuite/25_algorithms/pstl/alg_sorting/sort.cc:
Likewise.
* testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc:
Likewise.
* testsuite/26_numerics/pstl/numeric_ops/reduce.cc:
Likewise.
* testsuite/26_numerics/pstl/numeric_ops/scan.cc:
Likewise.
* testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc:
Likewise.
* testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc:
Likewise.
* testsuite/util/pstl/test_utils.h:
Likewise.
72 files changed, 3334 insertions, 3286 deletions
diff --git a/libstdc++-v3/include/pstl/algorithm_fwd.h b/libstdc++-v3/include/pstl/algorithm_fwd.h index e85125c..1ba9555 100644 --- a/libstdc++-v3/include/pstl/algorithm_fwd.h +++ b/libstdc++-v3/include/pstl/algorithm_fwd.h @@ -10,6 +10,7 @@ #ifndef _PSTL_ALGORITHM_FWD_H #define _PSTL_ALGORITHM_FWD_H +#include <iterator> #include <type_traits> #include <utility> @@ -27,20 +28,18 @@ bool __brick_any_of(const _ForwardIterator, const _ForwardIterator, _Pred, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _Pred> +template <class _RandomAccessIterator, class _Pred> bool -__brick_any_of(const _ForwardIterator, const _ForwardIterator, _Pred, +__brick_any_of(const _RandomAccessIterator, const _RandomAccessIterator, _Pred, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Pred> bool -__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_any_of(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Pred> bool -__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred, _IsVector, - /*parallel=*/std::true_type); +__pattern_any_of(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Pred); //------------------------------------------------------------------------ // walk1 (pseudo) @@ -56,25 +55,22 @@ template <class _RandomAccessIterator, class _Function> void __brick_walk1(_RandomAccessIterator, _RandomAccessIterator, _Function, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function> void -__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function> void -__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function, _IsVector, - /*parallel=*/std::true_type); +__pattern_walk1(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Function); -template <class _ExecutionPolicy, class _ForwardIterator, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick> void -__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick, - /*parallel=*/std::false_type) noexcept; +__pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick> void -__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick, - /*parallel=*/std::true_type); +__pattern_walk_brick(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Brick); //------------------------------------------------------------------------ // walk1_n @@ -88,25 +84,21 @@ template <class _RandomAccessIterator, class _DifferenceType, class _Function> _RandomAccessIterator __brick_walk1_n(_RandomAccessIterator, _DifferenceType, _Function, /*vectorTag=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function> _ForwardIterator -__pattern_walk1_n(_ExecutionPolicy&&, _ForwardIterator, _Size, _Function, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Function) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function> _RandomAccessIterator -__pattern_walk1_n(_ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_walk1_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function); -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> _ForwardIterator -__pattern_walk_brick_n(_ExecutionPolicy&&, _ForwardIterator, _Size, _Brick, - /*is_parallel=*/std::false_type) noexcept; +__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Brick) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> _RandomAccessIterator -__pattern_walk_brick_n(_ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick, - /*is_parallel=*/std::true_type); +__pattern_walk_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick); //------------------------------------------------------------------------ // walk2 (pseudo) @@ -118,60 +110,60 @@ template <class _ForwardIterator1, class _ForwardIterator2, class _Function> _ForwardIterator2 __brick_walk2(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _Function> -_ForwardIterator2 __brick_walk2(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, - /*vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 __brick_walk2(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _Function, + /*vector=*/std::true_type) noexcept; template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function> _ForwardIterator2 __brick_walk2_n(_ForwardIterator1, _Size, _ForwardIterator2, _Function, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function> -_ForwardIterator2 __brick_walk2_n(_ForwardIterator1, _Size, _ForwardIterator2, _Function, - /*vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 __brick_walk2_n(_RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function, + /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function> _ForwardIterator2 -__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector> -_ForwardIterator2 -__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, _IsVector, - /*parallel=*/std::true_type); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 +__pattern_walk2(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _Function); -template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, + class _Function> _ForwardIterator2 -__pattern_walk2_n(_ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, - class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, + class _RandomAccessIterator2, class _Function> _RandomAccessIterator2 -__pattern_walk2_n(_ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function, _IsVector, - /*parallel=*/std::true_type); +__pattern_walk2_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, + _Function); -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> _ForwardIterator2 -__pattern_walk2_brick(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Brick, - /*parallel=*/std::false_type) noexcept; +__pattern_walk2_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _Brick) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Brick> _RandomAccessIterator2 -__pattern_walk2_brick(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _Brick, - /*parallel=*/std::true_type); +__pattern_walk2_brick(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _Brick); -template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, + class _Brick> _ForwardIterator2 -__pattern_walk2_brick_n(_ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick, - /*parallel=*/std::false_type) noexcept; +__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, + class _RandomAccessIterator2, class _Brick> _RandomAccessIterator2 -__pattern_walk2_brick_n(_ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Brick, - /*parallel=*/std::true_type); +__pattern_walk2_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, + _RandomAccessIterator2, _Brick); //------------------------------------------------------------------------ // walk3 (pseudo) @@ -188,18 +180,17 @@ _RandomAccessIterator3 __brick_walk3(_RandomAccessIterator1, _RandomAccessIterat _RandomAccessIterator3, _Function, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, - class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, + class _Function> _ForwardIterator3 -__pattern_walk3(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator3, - _Function, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_walk3(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator3, + _Function) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, - class _RandomAccessIterator3, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Function> _RandomAccessIterator3 -__pattern_walk3(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _RandomAccessIterator3, _Function, _IsVector, /*parallel=*/std::true_type); +__pattern_walk3(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator3, _Function); //------------------------------------------------------------------------ // equal @@ -213,17 +204,16 @@ template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Bin bool __brick_equal(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BinaryPredicate, /* is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _BinaryPredicate, - _IsVector, /* is_parallel = */ std::false_type) noexcept; +__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _BinaryPredicate, _IsVector, /* is_parallel = */ std::true_type); +__pattern_equal(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _BinaryPredicate); template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> bool __brick_equal(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate, @@ -233,17 +223,16 @@ template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Bin bool __brick_equal(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate, /* is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, /* is_parallel = */ std::false_type) noexcept; +__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _RandomAccessIterator2, _BinaryPredicate, _IsVector, /* is_parallel = */ std::true_type); +__pattern_equal(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate); //------------------------------------------------------------------------ // find_if @@ -257,15 +246,14 @@ template <class _RandomAccessIterator, class _Predicate> _RandomAccessIterator __brick_find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> _ForwardIterator -__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_find_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> -_ForwardIterator -__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, _IsVector, - /*is_parallel=*/std::true_type); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +_RandomAccessIterator +__pattern_find_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Predicate); //------------------------------------------------------------------------ // find_end @@ -276,24 +264,21 @@ _ForwardIterator1 __brick_find_end(_ForwardIterator1, _ForwardIterator1, _Forwar _BinaryPredicate, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 __brick_find_end(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, - /*__is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_end(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_find_end(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, - /*is_parallel=*/std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_find_end(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept; //------------------------------------------------------------------------ // find_first_of @@ -304,22 +289,21 @@ _ForwardIterator1 __brick_find_first_of(_ForwardIterator1, _ForwardIterator1, _F _BinaryPredicate, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 __brick_find_first_of(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, - /*__is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_first_of(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, /*is_parallel=*/std::false_type) noexcept; +__pattern_find_first_of(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, /*is_parallel=*/std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_find_first_of(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept; //------------------------------------------------------------------------ // search @@ -330,24 +314,21 @@ _ForwardIterator1 __brick_search(_ForwardIterator1, _ForwardIterator1, _ForwardI _BinaryPredicate, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 __brick_search(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, - /*vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_search(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _BinaryPredicate, + /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_search(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _BinaryPredicate, _IsVector, - /*is_parallel=*/std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_search(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept; //------------------------------------------------------------------------ // search_n @@ -358,24 +339,21 @@ _ForwardIterator __brick_search_n(_ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> -_ForwardIterator -__brick_search_n(_ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate, +template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate> +_RandomAccessIterator +__brick_search_n(_RandomAccessIterator, _RandomAccessIterator, _Size, const _Tp&, _BinaryPredicate, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> _ForwardIterator -__pattern_search_n(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate, - _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_search_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&, + _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, + class _BinaryPredicate> _RandomAccessIterator -__pattern_search_n(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Size, const _Tp&, - _BinaryPredicate, _IsVector, - /*is_parallel=*/std::true_type) noexcept; +__pattern_search_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Size, + const _Tp&, _BinaryPredicate) noexcept; //------------------------------------------------------------------------ // copy_n @@ -385,8 +363,8 @@ template <class _ForwardIterator, class _Size, class _OutputIterator> _OutputIterator __brick_copy_n(_ForwardIterator, _Size, _OutputIterator, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _Size, class _OutputIterator> -_OutputIterator __brick_copy_n(_ForwardIterator, _Size, _OutputIterator, +template <class _RandomAccessIterator, class _Size, class _OutputIterator> +_OutputIterator __brick_copy_n(_RandomAccessIterator, _Size, _OutputIterator, /*vector=*/std::true_type) noexcept; //------------------------------------------------------------------------ @@ -417,14 +395,12 @@ _OutputIterator __brick_move(_RandomAccessIterator, _RandomAccessIterator, _Outp // swap_ranges //------------------------------------------------------------------------ template <class _ForwardIterator, class _OutputIterator> -_OutputIterator -__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, - /*vector=*/std::false_type) noexcept; +_OutputIterator __brick_swap_ranges(_ForwardIterator, _ForwardIterator, _OutputIterator, + /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator> -_OutputIterator -__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, - /*vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_swap_ranges(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, + /*vector=*/std::true_type) noexcept; //------------------------------------------------------------------------ // copy_if @@ -434,8 +410,8 @@ template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> _OutputIterator __brick_copy_if(_ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> -_OutputIterator __brick_copy_if(_ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate, +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __brick_copy_if(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _UnaryPredicate, /*vector=*/std::true_type) noexcept; template <class _DifferenceType, class _ForwardIterator, class _UnaryPredicate> @@ -452,9 +428,9 @@ void __brick_copy_by_mask(_ForwardIterator, _ForwardIterator, _OutputIterator, bool*, /*vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator> +template <class _RandomAccessIterator, class _OutputIterator> void -__brick_copy_by_mask(_ForwardIterator, _ForwardIterator, _OutputIterator, bool* __restrict, +__brick_copy_by_mask(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, bool* __restrict, /*vector=*/std::true_type) noexcept; template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2> @@ -467,24 +443,24 @@ void __brick_partition_by_mask(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator1, _OutputIterator2, bool*, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> _OutputIterator -__pattern_copy_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate, _IsVector, - /*parallel=*/std::false_type) noexcept; +__pattern_copy_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, + _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _UnaryPredicate> _OutputIterator -__pattern_copy_if(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _UnaryPredicate, - _IsVector, /*parallel=*/std::true_type); +__pattern_copy_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator, _UnaryPredicate); //------------------------------------------------------------------------ // count //------------------------------------------------------------------------ -template <class _ForwardIterator, class _Predicate> -typename std::iterator_traits<_ForwardIterator>::difference_type - __brick_count(_ForwardIterator, _ForwardIterator, _Predicate, +template <class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type + __brick_count(_RandomAccessIterator, _RandomAccessIterator, _Predicate, /* is_vector = */ std::true_type) noexcept; template <class _ForwardIterator, class _Predicate> @@ -492,15 +468,14 @@ typename std::iterator_traits<_ForwardIterator>::difference_type __brick_count(_ForwardIterator, _ForwardIterator, _Predicate, /* is_vector = */ std::false_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> typename std::iterator_traits<_ForwardIterator>::difference_type -__pattern_count(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, - /* is_parallel */ std::false_type, _IsVector) noexcept; +__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> -typename std::iterator_traits<_ForwardIterator>::difference_type -__pattern_count(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, - /* is_parallel */ std::true_type, _IsVector); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type +__pattern_count(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Predicate); //------------------------------------------------------------------------ // unique @@ -510,37 +485,35 @@ template <class _ForwardIterator, class _BinaryPredicate> _ForwardIterator __brick_unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate, /*is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _BinaryPredicate> -_ForwardIterator __brick_unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate, - /*is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __brick_unique(_RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate, + /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> _ForwardIterator -__pattern_unique(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> -_ForwardIterator -__pattern_unique(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, _IsVector, - /*is_parallel=*/std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__pattern_unique(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _BinaryPredicate) noexcept; //------------------------------------------------------------------------ // unique_copy //------------------------------------------------------------------------ template <class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> - _OutputIterator __brick_unique_copy(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate, +_OutputIterator __brick_unique_copy(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate, /*vector=*/std::false_type) noexcept; template <class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate> _OutputIterator __brick_unique_copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _BinaryPredicate, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> _OutputIterator -__pattern_unique_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate, - _IsVector, /*parallel=*/std::false_type) noexcept; +__pattern_unique_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, + _BinaryPredicate) noexcept; template <class _ExecutionPolicy, class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> _DifferenceType @@ -552,11 +525,11 @@ _DifferenceType __brick_calc_mask_2(_RandomAccessIterator, _RandomAccessIterator, bool* __restrict, _BinaryPredicate, /*vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _BinaryPredicate> _OutputIterator -__pattern_unique_copy(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator, - _BinaryPredicate, _IsVector, /*parallel=*/std::true_type); +__pattern_unique_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator, _BinaryPredicate); //------------------------------------------------------------------------ // reverse @@ -566,27 +539,25 @@ template <class _BidirectionalIterator> void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, /*__is_vector=*/std::false_type) noexcept; -template <class _BidirectionalIterator> -void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, +template <class _RandomAccessIterator> +void __brick_reverse(_RandomAccessIterator, _RandomAccessIterator, /*__is_vector=*/std::true_type) noexcept; template <class _BidirectionalIterator> void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, /*is_vector=*/std::false_type) noexcept; -template <class _BidirectionalIterator> -void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, +template <class _RandomAccessIterator> +void __brick_reverse(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator> void -__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> void -__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_reverse(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator); //------------------------------------------------------------------------ // reverse_copy @@ -596,19 +567,19 @@ template <class _BidirectionalIterator, class _OutputIterator> _OutputIterator __brick_reverse_copy(_BidirectionalIterator, _BidirectionalIterator, _OutputIterator, /*is_vector=*/std::false_type) noexcept; -template <class _BidirectionalIterator, class _OutputIterator> -_OutputIterator __brick_reverse_copy(_BidirectionalIterator, _BidirectionalIterator, _OutputIterator, +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_reverse_copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator> _OutputIterator -__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_reverse_copy(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, + _OutputIterator) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator> _OutputIterator -__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_reverse_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator); //------------------------------------------------------------------------ // rotate @@ -618,19 +589,18 @@ template <class _ForwardIterator> _ForwardIterator __brick_rotate(_ForwardIterator, _ForwardIterator, _ForwardIterator, /*is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator> -_ForwardIterator __brick_rotate(_ForwardIterator, _ForwardIterator, _ForwardIterator, - /*is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator> +_RandomAccessIterator __brick_rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, + /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator> _ForwardIterator -__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector> -_ForwardIterator -__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _IsVector, - /*is_parallel=*/std::true_type); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +_RandomAccessIterator +__pattern_rotate(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _RandomAccessIterator); //------------------------------------------------------------------------ // rotate_copy @@ -640,21 +610,20 @@ template <class _ForwardIterator, class _OutputIterator> _OutputIterator __brick_rotate_copy(_ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator> -_OutputIterator __brick_rotate_copy(_ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator, +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_rotate_copy(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator> _OutputIterator -__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator, - _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_rotate_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, + _OutputIterator) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator> _OutputIterator -__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator, - _IsVector, - /*is_parallel=*/std::true_type); +__pattern_rotate_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _RandomAccessIterator, _OutputIterator); //------------------------------------------------------------------------ // is_partitioned @@ -664,19 +633,18 @@ template <class _ForwardIterator, class _UnaryPredicate> bool __brick_is_partitioned(_ForwardIterator, _ForwardIterator, _UnaryPredicate, /*is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _UnaryPredicate> -bool __brick_is_partitioned(_ForwardIterator, _ForwardIterator, _UnaryPredicate, +template <class _RandomAccessIterator, class _UnaryPredicate> +bool __brick_is_partitioned(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate, /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> bool -__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> bool -__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_is_partitioned(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _UnaryPredicate); //------------------------------------------------------------------------ // partition @@ -686,19 +654,18 @@ template <class _ForwardIterator, class _UnaryPredicate> _ForwardIterator __brick_partition(_ForwardIterator, _ForwardIterator, _UnaryPredicate, /*is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _UnaryPredicate> -_ForwardIterator __brick_partition(_ForwardIterator, _ForwardIterator, _UnaryPredicate, - /*is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_partition(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> _ForwardIterator -__pattern_partition(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> -_ForwardIterator -__pattern_partition(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel=*/std::true_type); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_partition(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _UnaryPredicate); //------------------------------------------------------------------------ // stable_partition @@ -708,21 +675,19 @@ template <class _BidirectionalIterator, class _UnaryPredicate> _BidirectionalIterator __brick_stable_partition(_BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate, /*__is_vector=*/std::false_type) noexcept; -template <class _BidirectionalIterator, class _UnaryPredicate> -_BidirectionalIterator __brick_stable_partition(_BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate, - /*__is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_stable_partition(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate, + /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> _BidirectionalIterator -__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate, - _IsVector, - /*is_parallelization=*/std::false_type) noexcept; +__pattern_stable_partition(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, + _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector> -_BidirectionalIterator -__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate, - _IsVector, - /*is_parallelization=*/std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_stable_partition(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _UnaryPredicate) noexcept; //------------------------------------------------------------------------ // partition_copy @@ -733,134 +698,123 @@ std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy(_ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2, _UnaryPredicate, /*is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> -std::pair<_OutputIterator1, _OutputIterator2> - __brick_partition_copy(_ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2, _UnaryPredicate, - /*is_vector=*/std::true_type) noexcept; +template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy(_RandomAccessIterator, _RandomAccessIterator, + _OutputIterator1, _OutputIterator2, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, - class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, + class _UnaryPredicate> std::pair<_OutputIterator1, _OutputIterator2> -__pattern_partition_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2, - _UnaryPredicate, _IsVector, - /*is_parallelization=*/std::false_type) noexcept; +__pattern_partition_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator1, + _OutputIterator2, _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2, - class _UnaryPredicate, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, + class _OutputIterator2, class _UnaryPredicate> std::pair<_OutputIterator1, _OutputIterator2> -__pattern_partition_copy(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator1, - _OutputIterator2, _UnaryPredicate, _IsVector, - /*is_parallelization=*/std::true_type); +__pattern_partition_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator1, _OutputIterator2, _UnaryPredicate); //------------------------------------------------------------------------ // sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector, - class _IsMoveConstructible> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible> void -__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector /*is_vector*/, - /*is_parallel=*/std::false_type, _IsMoveConstructible) noexcept; +__pattern_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, + _IsMoveConstructible) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector /*is_vector*/, - /*is_parallel=*/std::true_type, +__pattern_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, /*is_move_constructible=*/std::true_type); //------------------------------------------------------------------------ // stable_sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, - _IsVector /*is_vector*/, - /*is_parallel=*/std::false_type) noexcept; +__pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, - _IsVector /*is_vector*/, - /*is_parallel=*/std::true_type); +__pattern_stable_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Compare); //------------------------------------------------------------------------ // partial_sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, - _Compare, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_partial_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, + _Compare) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, - _Compare, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_partial_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _RandomAccessIterator, _Compare); //------------------------------------------------------------------------ // partial_sort_copy //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector> -_RandomAccessIterator -__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _RandomAccessIterator, - _RandomAccessIterator, _Compare, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 +__pattern_partial_sort_copy(_Tag, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector> -_RandomAccessIterator -__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _RandomAccessIterator, - _RandomAccessIterator, _Compare, _IsVector, - /*is_parallel=*/std::true_type); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 +__pattern_partial_sort_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, + _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _Compare); //------------------------------------------------------------------------ // adjacent_find //------------------------------------------------------------------------ -template <class _ForwardIterator, class _BinaryPredicate> -_ForwardIterator -__brick_adjacent_find(_ForwardIterator, _ForwardIterator, _BinaryPredicate, - /* _IsVector = */ std::true_type, bool) noexcept; +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_adjacent_find(_RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate, + /* IsVector = */ std::true_type, bool) noexcept; template <class _ForwardIterator, class _BinaryPredicate> _ForwardIterator __brick_adjacent_find(_ForwardIterator, _ForwardIterator, _BinaryPredicate, - /* _IsVector = */ std::false_type, bool) noexcept; + /* IsVector = */ std::false_type, bool) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> _ForwardIterator -__pattern_adjacent_find(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, - /* is_parallel */ std::false_type, _IsVector, bool) noexcept; +__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, bool) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> _RandomAccessIterator -__pattern_adjacent_find(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate, - /* is_parallel */ std::true_type, _IsVector, bool); +__pattern_adjacent_find(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _BinaryPredicate, bool); //------------------------------------------------------------------------ // nth_element //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare, - _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_nth_element(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, + _Compare) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare, - _IsVector, - /*is_parallel=*/std::true_type) noexcept; +__pattern_nth_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _RandomAccessIterator, _Compare) noexcept; //------------------------------------------------------------------------ // fill, fill_n //------------------------------------------------------------------------ -template <class _ForwardIterator, class _Tp> +template <class _RandomAccessIterator, class _Tp> void -__brick_fill(_ForwardIterator, _ForwardIterator, const _Tp&, +__brick_fill(_RandomAccessIterator, _RandomAccessIterator, const _Tp&, /* __is_vector = */ std::true_type) noexcept; template <class _ForwardIterator, class _Tp> @@ -868,19 +822,17 @@ void __brick_fill(_ForwardIterator, _ForwardIterator, const _Tp&, /* __is_vector = */ std::false_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp> void -__pattern_fill(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&, - /*is_parallel=*/std::false_type, _IsVector) noexcept; +__pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector> -_ForwardIterator -__pattern_fill(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&, - /*is_parallel=*/std::true_type, _IsVector); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp> +_RandomAccessIterator +__pattern_fill(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, const _Tp&); -template <class _OutputIterator, class _Size, class _Tp> -_OutputIterator -__brick_fill_n(_OutputIterator, _Size, const _Tp&, +template <class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__brick_fill_n(_RandomAccessIterator, _Size, const _Tp&, /* __is_vector = */ std::true_type) noexcept; template <class _OutputIterator, class _Size, class _Tp> @@ -888,15 +840,13 @@ _OutputIterator __brick_fill_n(_OutputIterator, _Size, const _Tp&, /* __is_vector = */ std::false_type) noexcept; -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp> _OutputIterator -__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&, - /*is_parallel=*/std::false_type, _IsVector) noexcept; +__pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&) noexcept; -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector> -_OutputIterator -__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&, - /*is_parallel=*/std::true_type, _IsVector); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__pattern_fill_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, const _Tp&); //------------------------------------------------------------------------ // generate, generate_n @@ -910,33 +860,30 @@ template <class _ForwardIterator, class _Generator> void __brick_generate(_ForwardIterator, _ForwardIterator, _Generator, /* is_vector = */ std::false_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator> void -__pattern_generate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator, - /*is_parallel=*/std::false_type, _IsVector) noexcept; +__pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector> -_ForwardIterator -__pattern_generate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator, - /*is_parallel=*/std::true_type, _IsVector); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator> +_RandomAccessIterator +__pattern_generate(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Generator); -template <class _OutputIterator, class _Size, class _Generator> - _OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator, - /* is_vector = */ std::true_type) noexcept; +template <class _RandomAccessIterator, class _Size, class _Generator> +_RandomAccessIterator __brick_generate_n(_RandomAccessIterator, _Size, _Generator, + /* is_vector = */ std::true_type) noexcept; template <class _OutputIterator, class _Size, class _Generator> - _OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator, +_OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator, /* is_vector = */ std::false_type) noexcept; -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector> - _OutputIterator -__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator, _Size, _Generator, - /*is_parallel=*/std::false_type, _IsVector) noexcept; +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator> +_OutputIterator +__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, _Generator) noexcept; -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector> - _OutputIterator -__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator, _Size, _Generator, - /*is_parallel=*/std::true_type, _IsVector); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Generator> +_RandomAccessIterator +__pattern_generate_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Generator); //------------------------------------------------------------------------ // remove @@ -949,15 +896,14 @@ template <class _RandomAccessIterator, class _UnaryPredicate> _RandomAccessIterator __brick_remove_if(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate, /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> _ForwardIterator -__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel*/ std::false_type) noexcept; +__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> -_ForwardIterator -__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector, - /*is_parallel*/ std::true_type) noexcept; +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_remove_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _UnaryPredicate) noexcept; //------------------------------------------------------------------------ // merge @@ -968,23 +914,22 @@ _OutputIterator __brick_merge(_ForwardIterator1, _ForwardIterator1, _ForwardIter _OutputIterator, _Compare, /* __is_vector = */ std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator __brick_merge(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_merge(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _OutputIterator, _Compare, /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_merge(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, _IsVector, /* is_parallel = */ std::false_type) noexcept; +__pattern_merge(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _OutputIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_merge(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _RandomAccessIterator2, _OutputIterator, _Compare, _IsVector, - /* is_parallel = */ std::true_type); +__pattern_merge(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare); //------------------------------------------------------------------------ // inplace_merge @@ -994,37 +939,34 @@ template <class _BidirectionalIterator, class _Compare> void __brick_inplace_merge(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, _Compare, /* __is_vector = */ std::false_type) noexcept; -template <class _BidirectionalIterator, class _Compare> -void __brick_inplace_merge(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, _Compare, +template <class _RandomAccessIterator, class _Compare> +void __brick_inplace_merge(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare, /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> void -__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, - _Compare, _IsVector, - /* is_parallel = */ std::false_type) noexcept; +__pattern_inplace_merge(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, + _BidirectionalIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, - _Compare, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_inplace_merge(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _RandomAccessIterator, _Compare); //------------------------------------------------------------------------ // includes //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> bool -__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _Compare, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_includes(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> bool -__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _Compare, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_includes(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _Compare); //------------------------------------------------------------------------ // set_union @@ -1035,22 +977,22 @@ _OutputIterator __brick_set_union(_ForwardIterator1, _ForwardIterator1, _Forward _OutputIterator, _Compare, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator __brick_set_union(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_union(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _OutputIterator, _Compare, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::false_type) noexcept; +__pattern_set_union(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _OutputIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type); +__pattern_set_union(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare); //------------------------------------------------------------------------ // set_intersection @@ -1061,23 +1003,23 @@ _OutputIterator __brick_set_intersection(_ForwardIterator1, _ForwardIterator1, _ _OutputIterator, _Compare, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator __brick_set_intersection(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_intersection(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _OutputIterator, _Compare, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _OutputIterator, _Compare, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_set_intersection(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _OutputIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type); +__pattern_set_intersection(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, + _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, + _Compare); //------------------------------------------------------------------------ // set_difference @@ -1088,22 +1030,22 @@ _OutputIterator __brick_set_difference(_ForwardIterator1, _ForwardIterator1, _Fo _OutputIterator, _Compare, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator __brick_set_difference(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_difference(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _OutputIterator, _Compare, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::false_type) noexcept; +__pattern_set_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _OutputIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type); +__pattern_set_difference(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare); //------------------------------------------------------------------------ // set_symmetric_difference @@ -1114,24 +1056,23 @@ _OutputIterator __brick_set_symmetric_difference(_ForwardIterator1, _ForwardIter _ForwardIterator2, _OutputIterator, _Compare, /*__is_vector=*/std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator __brick_set_symmetric_difference(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _OutputIterator, _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_symmetric_difference(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _OutputIterator, _Compare, /*__is_vector=*/std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _OutputIterator, _Compare, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_set_symmetric_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _OutputIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _OutputIterator, _Compare, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_set_symmetric_difference(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, + _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, + _OutputIterator, _Compare); //------------------------------------------------------------------------ // is_heap_until @@ -1145,15 +1086,14 @@ template <class _RandomAccessIterator, class _Compare> _RandomAccessIterator __brick_is_heap_until(_RandomAccessIterator, _RandomAccessIterator, _Compare, /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> _RandomAccessIterator -__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector, - /* is_parallel = */ std::false_type) noexcept; +__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> _RandomAccessIterator -__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector, - /* is_parallel = */ std::true_type) noexcept; +__pattern_is_heap_until(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Compare) noexcept; //------------------------------------------------------------------------ // min_element @@ -1163,19 +1103,18 @@ template <typename _ForwardIterator, typename _Compare> _ForwardIterator __brick_min_element(_ForwardIterator, _ForwardIterator, _Compare, /* __is_vector = */ std::false_type) noexcept; -template <typename _ForwardIterator, typename _Compare> -_ForwardIterator __brick_min_element(_ForwardIterator, _ForwardIterator, _Compare, - /* __is_vector = */ std::true_type) noexcept; +template <typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator __brick_min_element(_RandomAccessIterator, _RandomAccessIterator, _Compare, + /* __is_vector = */ std::true_type) noexcept; -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> _ForwardIterator -__pattern_min_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector, - /* is_parallel = */ std::false_type) noexcept; +__pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; -template <typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _IsVector> +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> _RandomAccessIterator -__pattern_min_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector, - /* is_parallel = */ std::true_type); +__pattern_min_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Compare); //------------------------------------------------------------------------ // minmax_element @@ -1185,19 +1124,19 @@ template <typename _ForwardIterator, typename _Compare> std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element(_ForwardIterator, _ForwardIterator, _Compare, /* __is_vector = */ std::false_type) noexcept; -template <typename _ForwardIterator, typename _Compare> -std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element(_ForwardIterator, _ForwardIterator, _Compare, - /* __is_vector = */ std::true_type) noexcept; +template <typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> + __brick_minmax_element(_RandomAccessIterator, _RandomAccessIterator, _Compare, + /* __is_vector = */ std::true_type) noexcept; -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> std::pair<_ForwardIterator, _ForwardIterator> -__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector, - /* is_parallel = */ std::false_type) noexcept; +__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> -std::pair<_ForwardIterator, _ForwardIterator> -__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector, - /* is_parallel = */ std::true_type); +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> +__pattern_minmax_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Compare); //------------------------------------------------------------------------ // mismatch @@ -1208,22 +1147,22 @@ std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch(_ForwardIterato _ForwardIterator2, _ForwardIterator2, _Predicate, /* __is_vector = */ std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate> -std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch(_ForwardIterator1, _ForwardIterator1, - _ForwardIterator2, _ForwardIterator2, _Predicate, - /* __is_vector = */ std::true_type) noexcept; +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> + __brick_mismatch(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, + _Predicate, + /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> std::pair<_ForwardIterator1, _ForwardIterator2> -__pattern_mismatch(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _Predicate, _IsVector, - /* is_parallel = */ std::false_type) noexcept; +__pattern_mismatch(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, + _Predicate) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Predicate> std::pair<_RandomAccessIterator1, _RandomAccessIterator2> -__pattern_mismatch(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _RandomAccessIterator2, _Predicate, _IsVector, /* is_parallel = */ std::true_type) noexcept; +__pattern_mismatch(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, + _RandomAccessIterator2, _RandomAccessIterator2, _Predicate) noexcept; //------------------------------------------------------------------------ // lexicographical_compare @@ -1234,20 +1173,22 @@ bool __brick_lexicographical_compare(_ForwardIterator1, _ForwardIterator1, _Forw _Compare, /* __is_vector = */ std::false_type) noexcept; -template <class _ForwardIterator1, class _ForwardIterator2, class _Compare> -bool __brick_lexicographical_compare(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, - _Compare, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare> +bool __brick_lexicographical_compare(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, + _RandomAccessIterator2, _Compare, /* __is_vector = */ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> bool -__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _Compare, _IsVector, /* is_parallel = */ std::false_type) noexcept; +__pattern_lexicographical_compare(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, + _ForwardIterator2, _Compare) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> bool -__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator2, _Compare, _IsVector, /* is_parallel = */ std::true_type) noexcept; +__pattern_lexicographical_compare(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, + _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, + _Compare) noexcept; } // namespace __internal } // namespace __pstl diff --git a/libstdc++-v3/include/pstl/algorithm_impl.h b/libstdc++-v3/include/pstl/algorithm_impl.h index 32c1999..aec8c74 100644 --- a/libstdc++-v3/include/pstl/algorithm_impl.h +++ b/libstdc++-v3/include/pstl/algorithm_impl.h @@ -41,33 +41,35 @@ __brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _P return std::any_of(__first, __last, __pred); }; -template <class _ForwardIterator, class _Pred> +template <class _RandomAccessIterator, class _Pred> bool -__brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _Pred __pred, +__brick_any_of(const _RandomAccessIterator __first, const _RandomAccessIterator __last, _Pred __pred, /*__is_vector=*/std::true_type) noexcept { return __unseq_backend::__simd_or(__first, __last - __first, __pred); }; -template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Pred> bool -__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred, - _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_any_of(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) noexcept { - return __internal::__brick_any_of(__first, __last, __pred, __is_vector); + return __internal::__brick_any_of(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Pred> bool -__pattern_any_of(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred, - _IsVector __is_vector, /*parallel=*/std::true_type) +__pattern_any_of(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Pred __pred) { - return __internal::__except_handler([&]() { - return __internal::__parallel_or(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) { - return __internal::__brick_any_of(__i, __j, __pred, __is_vector); - }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __internal::__parallel_or(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__pred](_RandomAccessIterator __i, _RandomAccessIterator __j) + { return __internal::__brick_any_of(__i, __j, __pred, _IsVector{}); }); + }); } // [alg.foreach] @@ -102,46 +104,51 @@ __brick_walk1(_RandomAccessIterator __first, _RandomAccessIterator __last, _Func __unseq_backend::__simd_walk_1(__first, __last - __first, __f); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function> void -__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f, - _IsVector __is_vector, - /*parallel=*/std::false_type) noexcept +__pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f) noexcept { - __internal::__brick_walk1(__first, __last, __f, __is_vector); + __internal::__brick_walk1(__first, __last, __f, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function> void -__pattern_walk1(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f, - _IsVector __is_vector, - /*parallel=*/std::true_type) -{ - __internal::__except_handler([&]() { - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__f, __is_vector](_ForwardIterator __i, _ForwardIterator __j) { - __internal::__brick_walk1(__i, __j, __f, __is_vector); - }); - }); +__pattern_walk1(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Function __f) +{ + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__f](_RandomAccessIterator __i, _RandomAccessIterator __j) + { __internal::__brick_walk1(__i, __j, __f, _IsVector{}); }); + }); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick> void -__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick, - /*parallel=*/std::false_type) noexcept +__pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _Brick __brick) noexcept { __brick(__first, __last); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick> void -__pattern_walk_brick(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick, - /*parallel=*/std::true_type) +__pattern_walk_brick(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Brick __brick) { - __internal::__except_handler([&]() { - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__brick](_ForwardIterator __i, _ForwardIterator __j) { __brick(__i, __j); }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) + { __brick(__i, __j); }); + }); } //------------------------------------------------------------------------ @@ -163,44 +170,45 @@ __brick_walk1_n(_RandomAccessIterator __first, _DifferenceType __n, _Function __ return __unseq_backend::__simd_walk_1(__first, __n, __f); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function> _ForwardIterator -__pattern_walk1_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f) noexcept { - return __internal::__brick_walk1_n(__first, __n, __f, __is_vector); + return __internal::__brick_walk1_n(__first, __n, __f, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function> _RandomAccessIterator -__pattern_walk1_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Function __f, - _IsVector __is_vector, - /*is_parallel=*/std::true_type) +__pattern_walk1_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, + _Function __f) { - __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f, __is_vector, - std::true_type()); + __internal::__pattern_walk1(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f); + return __first + __n; } -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> _ForwardIterator -__pattern_walk_brick_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick, - /*is_parallel=*/std::false_type) noexcept +__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick) noexcept { return __brick(__first, __n); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> _RandomAccessIterator -__pattern_walk_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Brick __brick, - /*is_parallel=*/std::true_type) +__pattern_walk_brick_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _Size __n, _Brick __brick) { - return __internal::__except_handler([&]() { - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, - [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); }); - return __first + __n; - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); }); + return __first + __n; + }); } //------------------------------------------------------------------------ @@ -218,9 +226,10 @@ __brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIte return __first2; } -template <class _ForwardIterator1, class _ForwardIterator2, class _Function> -_ForwardIterator2 -__brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Function __f, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 +__brick_walk2(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _Function __f, /*vector=*/std::true_type) noexcept { return __unseq_backend::__simd_walk_2(__first1, __last1 - __first1, __first2, __f); @@ -236,102 +245,115 @@ __brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first return __first2; } -template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function> -_ForwardIterator2 -__brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f, +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 +__brick_walk2_n(_RandomAccessIterator1 __first1, _Size __n, _RandomAccessIterator2 __first2, _Function __f, /*vector=*/std::true_type) noexcept { return __unseq_backend::__simd_walk_2(__first1, __n, __first2, __f); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function> _ForwardIterator2 -__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _Function __f) noexcept { - return __internal::__brick_walk2(__first1, __last1, __first2, __f, __is_vector); + return __internal::__brick_walk2(__first1, __last1, __first2, __f, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector> -_ForwardIterator2 -__pattern_walk2(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 +__pattern_walk2(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Function __f) { - return __internal::__except_handler([&]() { - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__f, __first1, __first2, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) { - __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, __is_vector); - }); - return __first2 + (__last1 - __first1); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__f, __first1, __first2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, _IsVector{}); }); + return __first2 + (__last1 - __first1); + }); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, + class _Function> _ForwardIterator2 -__pattern_walk2_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f, - _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, + _Function __f) noexcept { - return __internal::__brick_walk2_n(__first1, __n, __first2, __f, __is_vector); + return __internal::__brick_walk2_n(__first1, __n, __first2, __f, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, - class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, + class _RandomAccessIterator2, class _Function> _RandomAccessIterator2 -__pattern_walk2_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n, _RandomAccessIterator2 __first2, - _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type) +__pattern_walk2_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _Size __n, _RandomAccessIterator2 __first2, _Function __f) { - return __internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, __first2, __f, - __is_vector, std::true_type()); + return __internal::__pattern_walk2(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, + __first2, __f); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> _ForwardIterator2 -__pattern_walk2_brick(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _Brick __brick, /*parallel=*/std::false_type) noexcept +__pattern_walk2_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _Brick __brick) noexcept { return __brick(__first1, __last1, __first2); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Brick> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Brick> _RandomAccessIterator2 -__pattern_walk2_brick(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type) +__pattern_walk2_brick(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Brick __brick) { - return __internal::__except_handler([&]() { - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { - __brick(__i, __j, __first2 + (__i - __first1)); - }); - return __first2 + (__last1 - __first1); - }); -} + using __backend_tag = typename decltype(__tag)::__backend_tag; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Brick> -_RandomAccessIterator2 -__pattern_walk2_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n, - _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type) -{ - return __internal::__except_handler([&]() { - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, - [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { - __brick(__i, __j - __i, __first2 + (__i - __first1)); - }); - return __first2 + __n; - }); + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { __brick(__i, __j, __first2 + (__i - __first1)); }); + return __first2 + (__last1 - __first1); + }); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Brick> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, + class _Brick> _ForwardIterator2 -__pattern_walk2_brick_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, - _Brick __brick, /*parallel=*/std::false_type) noexcept +__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, + _Brick __brick) noexcept { return __brick(__first1, __n, __first2); } +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, + class _RandomAccessIterator2, class _Brick> +_RandomAccessIterator2 +__pattern_walk2_brick_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _Size __n, _RandomAccessIterator2 __first2, _Brick __brick) +{ + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { __brick(__i, __j - __i, __first2 + (__i - __first1)); }); + return __first2 + __n; + }); +} + //------------------------------------------------------------------------ // walk3 (pseudo) // @@ -355,31 +377,35 @@ __brick_walk3(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _ return __unseq_backend::__simd_walk_3(__first1, __last1 - __first1, __first2, __first3, __f); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, - class _Function, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, + class _Function> _ForwardIterator3 -__pattern_walk3(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator3 __first3, _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_walk3(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator3 __first3, _Function __f) noexcept { - return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, __is_vector); + return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, - class _RandomAccessIterator3, class _Function, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Function> _RandomAccessIterator3 -__pattern_walk3(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _RandomAccessIterator3 __first3, _Function __f, _IsVector __is_vector, - /*parallel=*/std::true_type) +__pattern_walk3(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator3 __first3, + _Function __f) { - return __internal::__except_handler([&]() { - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__f, __first1, __first2, __first3, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { - __internal::__brick_walk3(__i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f, - __is_vector); - }); - return __first3 + (__last1 - __first1); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__f, __first1, __first2, __first3](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __internal::__brick_walk3(__i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f, + _IsVector{}); + }); + return __first3 + (__last1 - __first1); + }); } //------------------------------------------------------------------------ @@ -405,34 +431,37 @@ __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _ return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */ - std::false_type) noexcept +__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __p) noexcept { - return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, __is_vector); + return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __p, - _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_equal(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _BinaryPredicate __p) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__last1 - __first1 != __last2 - __first2) return false; - return __internal::__except_handler([&]() { - return !__internal::__parallel_or( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { - return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), - __p, __is_vector); - }); - }); + return __internal::__except_handler( + [&]() + { + return !__internal::__parallel_or( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { + return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), + __first2 + (__j - __first1), __p, _IsVector{}); + }); + }); } //------------------------------------------------------------------------ @@ -455,29 +484,30 @@ __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _ return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept +__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __p) noexcept { - return __internal::__brick_equal(__first1, __last1, __first2, __p, __is_vector); + return __internal::__brick_equal(__first1, __last1, __first2, __p, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> bool -__pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _BinaryPredicate __p, _IsVector __is_vector, - /*is_parallel=*/std::true_type) +__pattern_equal(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _BinaryPredicate __p) { - return __internal::__except_handler([&]() { - return !__internal::__parallel_or( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { - return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, __is_vector); - }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return !__internal::__parallel_or( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, _IsVector{}); }); + }); } //------------------------------------------------------------------------ @@ -502,30 +532,31 @@ __brick_find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _Pr [&__pred](_RandomAccessIterator __it, _SizeType __i) { return __pred(__it[__i]); }); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> _ForwardIterator -__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, - _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_find_if(_Tag __tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) noexcept { - return __internal::__brick_find_if(__first, __last, __pred, __is_vector); + return __internal::__brick_find_if(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> -_ForwardIterator -__pattern_find_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, - _IsVector __is_vector, - /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +_RandomAccessIterator +__pattern_find_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Predicate __pred) { - return __internal::__except_handler([&]() { - return __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) { - return __internal::__brick_find_if(__i, __j, __pred, __is_vector); - }, - std::less<typename std::iterator_traits<_ForwardIterator>::difference_type>(), - /*is_first=*/true); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __internal::__parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__pred](_RandomAccessIterator __i, _RandomAccessIterator __j) + { return __internal::__brick_find_if(__i, __j, __pred, _IsVector{}); }, + std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), + /*is_first=*/true); + }); } //------------------------------------------------------------------------ @@ -632,48 +663,51 @@ __brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIt return std::find_end(__first, __last, __s_first, __s_last, __pred); } -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 -__brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 +__brick_find_end(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept { return __find_subrange(__first, __last, __last, __s_first, __s_last, __pred, false, std::true_type()); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_find_end(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, + _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept { - return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, __is_vector); + return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_find_end(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, - _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_find_end(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__last - __first == __s_last - __s_first) { - const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last, - __s_first, __pred, __is_vector, std::true_type()); + const bool __res = __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __s_first, __pred); return __res ? __first : __last; } else { - return __internal::__except_handler([&]() { - return __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) { - return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false, - __is_vector); - }, - std::greater<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/false); - }); + return __internal::__except_handler( + [&]() + { + return __internal::__parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false, + _IsVector{}); + }, + std::greater<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/false); + }); } } @@ -688,95 +722,99 @@ __brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _Forw return std::find_first_of(__first, __last, __s_first, __s_last, __pred); } -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 -__brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 +__brick_find_first_of(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept { return __unseq_backend::__simd_find_first_of(__first, __last, __s_first, __s_last, __pred); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, - _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_find_first_of(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, + _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept { - return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, __is_vector); + return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_find_first_of(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, - _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_find_first_of(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, _BinaryPredicate __pred) noexcept { - return __internal::__except_handler([&]() { - return __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) { - return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, __is_vector); - }, - std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __internal::__parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, _IsVector{}); }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true); + }); } //------------------------------------------------------------------------ // search //------------------------------------------------------------------------ -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 -__brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 +__brick_search(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept { return std::search(__first, __last, __s_first, __s_last, __pred); } -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> -_ForwardIterator1 -__brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 +__brick_search(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept { return __internal::__find_subrange(__first, __last, __last, __s_first, __s_last, __pred, true, std::true_type()); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> _ForwardIterator1 -__pattern_search(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, - _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_search(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, + _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept { - return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, __is_vector); + return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate, - class _IsVector> -_ForwardIterator1 -__pattern_search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, - _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred, - _IsVector __is_vector, - /*is_parallel=*/std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 +__pattern_search(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__last - __first == __s_last - __s_first) { - const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last, - __s_first, __pred, __is_vector, std::true_type()); + const bool __res = __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __s_first, __pred); return __res ? __first : __last; } else { - return __internal::__except_handler([&]() { - return __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) { - return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true, - __is_vector); - }, - std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true); - }); + return __internal::__except_handler( + [&]() + { + return __internal::__parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true, + _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/true); + }); } } @@ -791,49 +829,49 @@ __brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __coun return std::search_n(__first, __last, __count, __value, __pred); } -template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> -_ForwardIterator -__brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, +template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate> +_RandomAccessIterator +__brick_search_n(_RandomAccessIterator __first, _RandomAccessIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept { return __internal::__find_subrange(__first, __last, __last, __count, __value, __pred, std::true_type()); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> _ForwardIterator -__pattern_search_n(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Size __count, - const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_search_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Size __count, + const _Tp& __value, _BinaryPredicate __pred) noexcept { - return __internal::__brick_search_n(__first, __last, __count, __value, __pred, __is_vector); + return __internal::__brick_search_n(__first, __last, __count, __value, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, + class _BinaryPredicate> _RandomAccessIterator -__pattern_search_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _Size __count, const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector, - /*is_parallel=*/std::true_type) noexcept +__pattern_search_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (static_cast<_Size>(__last - __first) == __count) { - const bool __result = !__internal::__pattern_any_of( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__value, &__pred](const _Tp& __val) { return !__pred(__val, __value); }, __is_vector, - /*is_parallel*/ std::true_type()); + const bool __result = + !__internal::__pattern_any_of(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__value, &__pred](const _Tp& __val) { return !__pred(__val, __value); }); return __result ? __first : __last; } else { - return __internal::__except_handler([&__exec, __first, __last, __count, &__value, __pred, __is_vector]() { - return __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__last, __count, &__value, __pred, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) { - return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, __is_vector); - }, - std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true); - }); + return __internal::__except_handler( + [&__exec, __first, __last, __count, &__value, __pred]() + { + return __internal::__parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__last, __count, &__value, __pred](_RandomAccessIterator __i, _RandomAccessIterator __j) + { return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, _IsVector{}); }, + std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), + /*is_first=*/true); + }); } } @@ -848,12 +886,14 @@ __brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /* return std::copy_n(__first, __n, __result); } -template <class _ForwardIterator, class _Size, class _OutputIterator> -_OutputIterator -__brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_copy_n(_RandomAccessIterator1 __first, _Size __n, _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { return __unseq_backend::__simd_assign( - __first, __n, __result, [](_ForwardIterator __first, _OutputIterator __result) { *__result = *__first; }); + __first, __n, __result, + [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = *__first; }); } //------------------------------------------------------------------------ @@ -867,14 +907,14 @@ __brick_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator return std::copy(__first, __last, __result); } -template <class _RandomAccessIterator, class _OutputIterator> -_OutputIterator -__brick_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, /*vector=*/std::true_type) noexcept { return __unseq_backend::__simd_assign( __first, __last - __first, __result, - [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = *__first; }); + [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = *__first; }); } //------------------------------------------------------------------------ @@ -888,36 +928,38 @@ __brick_move(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator return std::move(__first, __last, __result); } -template <class _RandomAccessIterator, class _OutputIterator> -_OutputIterator -__brick_move(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_move(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, /*vector=*/std::true_type) noexcept { return __unseq_backend::__simd_assign( __first, __last - __first, __result, - [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = std::move(*__first); }); + [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = std::move(*__first); }); } struct __brick_move_destroy { - template <typename _Iterator, typename _OutputIterator> - _OutputIterator - operator()(_Iterator __first, _Iterator __last, _OutputIterator __result, /*vec*/ std::true_type) const + template <typename _RandomAccessIterator1, typename _RandomAccessIterator2> + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, + /*vec*/ std::true_type) const { - using _IteratorValueType = typename std::iterator_traits<_Iterator>::value_type; + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; return __unseq_backend::__simd_assign(__first, __last - __first, __result, - [](_Iterator __first, _OutputIterator __result) { + [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = std::move(*__first); (*__first).~_IteratorValueType(); }); } - template <typename _Iterator, typename _OutputIterator> - _OutputIterator - operator()(_Iterator __first, _Iterator __last, _OutputIterator __result, /*vec*/ std::false_type) const + template <typename _RandomAccessIterator1, typename _RandomAccessIterator2> + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, + /*vec*/ std::false_type) const { - using _IteratorValueType = typename std::iterator_traits<_Iterator>::value_type; + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; for (; __first != __last; ++__first, ++__result) { @@ -939,14 +981,14 @@ __brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIt return std::swap_ranges(__first, __last, __result); } -template <class _ForwardIterator, class _OutputIterator> -_OutputIterator -__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_swap_ranges(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, /*vector=*/std::true_type) noexcept { using std::iter_swap; return __unseq_backend::__simd_assign(__first, __last - __first, __result, - iter_swap<_ForwardIterator, _OutputIterator>); + iter_swap<_RandomAccessIterator1, _RandomAccessIterator2>); } //------------------------------------------------------------------------ @@ -960,12 +1002,13 @@ __brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterat return std::copy_if(__first, __last, __result, __pred); } -template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> -_OutputIterator -__brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _UnaryPredicate __pred, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _UnaryPredicate> +_RandomAccessIterator2 +__brick_copy_if(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, + _UnaryPredicate __pred, /*vector=*/std::true_type) noexcept { -#if (_PSTL_MONOTONIC_PRESENT) +#if defined(_PSTL_MONOTONIC_PRESENT) return __unseq_backend::__simd_copy_if(__first, __last - __first, __result, __pred); #else return std::copy_if(__first, __last, __result, __pred); @@ -981,7 +1024,7 @@ __brick_calc_mask_1(_ForwardIterator __first, _ForwardIterator __last, bool* __r auto __count_true = _DifferenceType(0); auto __size = __last - __first; - static_assert(__is_random_access_iterator<_ForwardIterator>::value, + static_assert(__are_random_access_iterators<_ForwardIterator>::value, "Pattern-brick error. Should be a random access iterator."); for (; __first != __last; ++__first, ++__mask) @@ -1019,12 +1062,12 @@ __brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputI } } -template <class _ForwardIterator, class _OutputIterator, class _Assigner> +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Assigner> void -__brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_copy_by_mask(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, bool* __restrict __mask, _Assigner __assigner, /*vector=*/std::true_type) noexcept { -#if (_PSTL_MONOTONIC_PRESENT) +#if defined(_PSTL_MONOTONIC_PRESENT) __unseq_backend::__simd_copy_by_mask(__first, __last - __first, __result, __mask, __assigner); #else __internal::__brick_copy_by_mask(__first, __last, __result, __mask, __assigner, std::false_type()); @@ -1051,67 +1094,72 @@ __brick_partition_by_mask(_ForwardIterator __first, _ForwardIterator __last, _Ou } } -template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2> +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3> void -__brick_partition_by_mask(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator1 __out_true, - _OutputIterator2 __out_false, bool* __mask, /*vector=*/std::true_type) noexcept +__brick_partition_by_mask(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, _RandomAccessIterator3 __out_false, bool* __mask, + /*vector=*/std::true_type) noexcept { -#if (_PSTL_MONOTONIC_PRESENT) +#if defined(_PSTL_MONOTONIC_PRESENT) __unseq_backend::__simd_partition_by_mask(__first, __last - __first, __out_true, __out_false, __mask); #else __internal::__brick_partition_by_mask(__first, __last, __out_true, __out_false, __mask, std::false_type()); #endif } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> _OutputIterator -__pattern_copy_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, - _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_copy_if(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, + _UnaryPredicate __pred) noexcept { - return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector); + return __internal::__brick_copy_if(__first, __last, __result, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate, - class _IsVector> -_OutputIterator -__pattern_copy_if(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _OutputIterator __result, _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _UnaryPredicate> +_RandomAccessIterator2 +__pattern_copy_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, _UnaryPredicate __pred) { - typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; const _DifferenceType __n = __last - __first; if (_DifferenceType(1) < __n) { __par_backend::__buffer<bool> __mask_buf(__n); - return __internal::__except_handler([&__exec, __n, __first, __result, __is_vector, __pred, &__mask_buf]() { - bool* __mask = __mask_buf.get(); - _DifferenceType __m{}; - __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), - [=](_DifferenceType __i, _DifferenceType __len) { // Reduce - return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len), - __mask + __i, __pred, __is_vector) - .first; - }, - std::plus<_DifferenceType>(), // Combine - [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan - __internal::__brick_copy_by_mask( - __first + __i, __first + (__i + __len), __result + __initial, __mask + __i, - [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector); - }, - [&__m](_DifferenceType __total) { __m = __total; }); - return __result + __m; - }); + return __internal::__except_handler( + [&__exec, __n, __first, __result, __pred, &__mask_buf]() + { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len), + __mask + __i, __pred, _IsVector{}) + .first; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + __internal::__brick_copy_by_mask( + __first + __i, __first + (__i + __len), __result + __initial, __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); } // trivial sequence - use serial algorithm - return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector); + return __internal::__brick_copy_if(__first, __last, __result, __pred, _IsVector{}); } //------------------------------------------------------------------------ // count //------------------------------------------------------------------------ -template <class _ForwardIterator, class _Predicate> -typename std::iterator_traits<_ForwardIterator>::difference_type -__brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, +template <class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type +__brick_count(_RandomAccessIterator __first, _RandomAccessIterator __last, _Predicate __pred, /* is_vector = */ std::true_type) noexcept { return __unseq_backend::__simd_count(__first, __last - __first, __pred); @@ -1125,66 +1173,70 @@ __brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pr return std::count_if(__first, __last, __pred); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> typename std::iterator_traits<_ForwardIterator>::difference_type -__pattern_count(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, - /* is_parallel */ std::false_type, _IsVector __is_vector) noexcept +__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) noexcept { - return __internal::__brick_count(__first, __last, __pred, __is_vector); + return __internal::__brick_count(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector> -typename std::iterator_traits<_ForwardIterator>::difference_type -__pattern_count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, - /* is_parallel */ std::true_type, _IsVector __is_vector) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type +__pattern_count(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Predicate __pred) { - typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType; - return __internal::__except_handler([&]() { - return __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, _SizeType(0), - [__pred, __is_vector](_ForwardIterator __begin, _ForwardIterator __end, _SizeType __value) -> _SizeType { - return __value + __internal::__brick_count(__begin, __end, __pred, __is_vector); - }, - std::plus<_SizeType>()); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + return __internal::__except_handler( + [&]() + { + return __par_backend::__parallel_reduce( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, _SizeType(0), + [__pred](_RandomAccessIterator __begin, _RandomAccessIterator __end, _SizeType __value) -> _SizeType + { return __value + __internal::__brick_count(__begin, __end, __pred, _IsVector{}); }, + std::plus<_SizeType>()); + }); } //------------------------------------------------------------------------ // unique //------------------------------------------------------------------------ -template <class _ForwardIterator, class _BinaryPredicate> -_ForwardIterator -__brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred, /*is_vector=*/std::false_type) noexcept { return std::unique(__first, __last, __pred); } -template <class _ForwardIterator, class _BinaryPredicate> -_ForwardIterator -__brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred, /*is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::unique(__first, __last, __pred); } -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> _ForwardIterator -__pattern_unique(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __pred) noexcept { - return __internal::__brick_unique(__first, __last, __pred, __is_vector); + return __internal::__brick_unique(__first, __last, __pred, typename _Tag::__is_vector{}); } // That function is shared between two algorithms - remove_if (__pattern_remove_if) and unique (pattern unique). But a mask calculation is different. // So, a caller passes _CalcMask brick into remove_elements. -template <class _ExecutionPolicy, class _ForwardIterator, class _CalcMask, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _ForwardIterator, class _CalcMask> _ForwardIterator -__remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _CalcMask __calc_mask, - _IsVector __is_vector) +__remove_elements(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _ForwardIterator __first, + _ForwardIterator __last, _CalcMask __calc_mask) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType; typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp; _DifferenceType __n = __last - __first; @@ -1193,9 +1245,10 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI return __internal::__except_handler([&]() { bool* __mask = __mask_buf.get(); _DifferenceType __min = __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), _DifferenceType(0), __n, __n, - [__first, __mask, &__calc_mask, __is_vector](_DifferenceType __i, _DifferenceType __j, - _DifferenceType __local_min) -> _DifferenceType { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), _DifferenceType(0), __n, __n, + [__first, __mask, &__calc_mask](_DifferenceType __i, _DifferenceType __j, + _DifferenceType __local_min) -> _DifferenceType + { // Create mask __calc_mask(__mask + __i, __mask + __j, __first + __i); @@ -1205,17 +1258,16 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI return __local_min; } // find first iterator that should be removed - bool* __result = __internal::__brick_find_if(__mask + __i, __mask + __j, - [](bool __val) { return !__val; }, __is_vector); + bool* __result = __internal::__brick_find_if( + __mask + __i, __mask + __j, [](bool __val) { return !__val; }, _IsVector{}); if (__result - __mask == __j) { return __local_min; } return std::min(__local_min, _DifferenceType(__result - __mask)); }, - [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType { - return std::min(__local_min1, __local_min2); - }); + [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType + { return std::min(__local_min1, __local_min2); }); // No elements to remove - exit if (__min == __n) @@ -1231,44 +1283,46 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI _DifferenceType __m{}; // 2. Elements that doesn't satisfy pred are moved to result __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), - [__mask, __is_vector](_DifferenceType __i, _DifferenceType __len) { - return __internal::__brick_count(__mask + __i, __mask + __i + __len, [](bool __val) { return __val; }, - __is_vector); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), + [__mask](_DifferenceType __i, _DifferenceType __len) + { + return __internal::__brick_count( + __mask + __i, __mask + __i + __len, [](bool __val) { return __val; }, _IsVector{}); }, std::plus<_DifferenceType>(), - [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) + { __internal::__brick_copy_by_mask( __first + __i, __first + __i + __len, __result + __initial, __mask + __i, - [](_ForwardIterator __x, _Tp* __z) { - __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); }, - [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + [](_ForwardIterator __x, _Tp* __z) + { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); }, - __is_vector); + _IsVector{}); }, [&__m](_DifferenceType __total) { __m = __total; }); // 3. Elements from result are moved to [first, last) __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __result, __result + __m, - [__result, __first, __is_vector](_Tp* __i, _Tp* __j) { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + __m, + [__result, __first](_Tp* __i, _Tp* __j) + { __invoke_if_else( - std::is_trivial<_Tp>(), - [&]() { __brick_move(__i, __j, __first + (__i - __result), __is_vector); }, - [&]() { - __brick_move_destroy()(__i, __j, __first + (__i - __result), __is_vector); - }); + std::is_trivial<_Tp>(), [&]() { __brick_move(__i, __j, __first + (__i - __result), _IsVector{}); }, + [&]() { __brick_move_destroy()(__i, __j, __first + (__i - __result), _IsVector{}); }); }); return __first + __m; }); } -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> -_ForwardIterator -__pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__pattern_unique(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _BinaryPredicate __pred) noexcept { - typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; if (__first == __last) { @@ -1277,16 +1331,16 @@ __pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt if (__first + 1 == __last || __first + 2 == __last) { // Trivial sequence - use serial algorithm - return __internal::__brick_unique(__first, __last, __pred, __is_vector); + return __internal::__brick_unique(__first, __last, __pred, _IsVector{}); } return __internal::__remove_elements( - std::forward<_ExecutionPolicy>(__exec), ++__first, __last, - [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) { + __tag, std::forward<_ExecutionPolicy>(__exec), ++__first, __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) + { __internal::__brick_walk3( __b, __e, __it - 1, __it, - [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, __is_vector); - }, - __is_vector); + [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, _IsVector{}); + }); } //------------------------------------------------------------------------ @@ -1294,32 +1348,31 @@ __pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt //------------------------------------------------------------------------ template <class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> - _OutputIterator +_OutputIterator __brick_unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept { return std::unique_copy(__first, __last, __result, __pred); } -template <class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate> - _OutputIterator -__brick_unique_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator2 +__brick_unique_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept { -#if (_PSTL_MONOTONIC_PRESENT) +#if defined(_PSTL_MONOTONIC_PRESENT) return __unseq_backend::__simd_unique_copy(__first, __last - __first, __result, __pred); #else return std::unique_copy(__first, __last, __result, __pred); #endif } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> _OutputIterator -__pattern_unique_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, - _BinaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept +__pattern_unique_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __result, _BinaryPredicate __pred) noexcept { - return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector); + return __internal::__brick_unique_copy(__first, __last, __result, __pred, typename _Tag::__is_vector{}); } template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> @@ -1344,54 +1397,58 @@ __brick_calc_mask_2(_RandomAccessIterator __first, _RandomAccessIterator __last, return __unseq_backend::__simd_calc_mask_2(__first, __last - __first, __mask, __pred); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate, - class _IsVector> -_OutputIterator -__pattern_unique_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _OutputIterator __result, _BinaryPredicate __pred, _IsVector __is_vector, - /*parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator2 +__pattern_unique_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, _BinaryPredicate __pred) { - typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; const _DifferenceType __n = __last - __first; if (_DifferenceType(2) < __n) { __par_backend::__buffer<bool> __mask_buf(__n); if (_DifferenceType(2) < __n) { - return __internal::__except_handler([&__exec, __n, __first, __result, __pred, __is_vector, &__mask_buf]() { - bool* __mask = __mask_buf.get(); - _DifferenceType __m{}; - __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), - [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce - _DifferenceType __extra = 0; - if (__i == 0) - { - // Special boundary case - __mask[__i] = true; - if (--__len == 0) - return 1; - ++__i; - ++__extra; - } - return __internal::__brick_calc_mask_2<_DifferenceType>(__first + __i, __first + (__i + __len), - __mask + __i, __pred, __is_vector) + - __extra; - }, - std::plus<_DifferenceType>(), // Combine - [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan - // Phase 2 is same as for __pattern_copy_if - __internal::__brick_copy_by_mask( - __first + __i, __first + (__i + __len), __result + __initial, __mask + __i, - [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector); - }, - [&__m](_DifferenceType __total) { __m = __total; }); - return __result + __m; - }); + return __internal::__except_handler( + [&__exec, __n, __first, __result, __pred, &__mask_buf]() + { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce + _DifferenceType __extra = 0; + if (__i == 0) + { + // Special boundary case + __mask[__i] = true; + if (--__len == 0) + return 1; + ++__i; + ++__extra; + } + return __internal::__brick_calc_mask_2<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) + + __extra; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + // Phase 2 is same as for __pattern_copy_if + __internal::__brick_copy_by_mask( + __first + __i, __first + (__i + __len), __result + __initial, __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); } } // trivial sequence - use serial algorithm - return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector); + return __internal::__brick_unique_copy(__first, __last, __result, __pred, _IsVector{}); } //------------------------------------------------------------------------ @@ -1404,14 +1461,14 @@ __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, / std::reverse(__first, __last); } -template <class _BidirectionalIterator> +template <class _RandomAccessIterator> void -__brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::true_type) noexcept +__brick_reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, /*__is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; const auto __n = (__last - __first) / 2; - __unseq_backend::__simd_walk_2(__first, __n, std::reverse_iterator<_BidirectionalIterator>(__last), + __unseq_backend::__simd_walk_2(__first, __n, std::reverse_iterator<_RandomAccessIterator>(__last), [](_ReferenceType __x, _ReferenceType __y) { using std::swap; swap(__x, __y); @@ -1432,39 +1489,38 @@ __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _ } // this brick is called in parallel version, so we can use iterator arithmetic -template <class _BidirectionalIterator> +template <class _RandomAccessIterator> void -__brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __d_last, +__brick_reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomAccessIterator __d_last, /*is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; - __unseq_backend::__simd_walk_2(__first, __last - __first, std::reverse_iterator<_BidirectionalIterator>(__d_last), + __unseq_backend::__simd_walk_2(__first, __last - __first, std::reverse_iterator<_RandomAccessIterator>(__d_last), [](_ReferenceType __x, _ReferenceType __y) { using std::swap; swap(__x, __y); }); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator> void -__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last, - _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last) noexcept { - __internal::__brick_reverse(__first, __last, __is_vector); + __internal::__brick_reverse(__first, __last, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> void -__pattern_reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, - _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_reverse(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first, __first + (__last - __first) / 2, - [__is_vector, __first, __last](_BidirectionalIterator __inner_first, _BidirectionalIterator __inner_last) { - __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), __is_vector); - }); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __first + (__last - __first) / 2, + [__first, __last](_RandomAccessIterator __inner_first, _RandomAccessIterator __inner_last) + { __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), _IsVector{}); }); } //------------------------------------------------------------------------ @@ -1479,39 +1535,41 @@ __brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __la return std::reverse_copy(__first, __last, __d_first); } -template <class _BidirectionalIterator, class _OutputIterator> -_OutputIterator -__brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __d_first, +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_reverse_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first, /*is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType1; - typedef typename std::iterator_traits<_OutputIterator>::reference _ReferenceType2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; - return __unseq_backend::__simd_walk_2(std::reverse_iterator<_BidirectionalIterator>(__last), __last - __first, + return __unseq_backend::__simd_walk_2(std::reverse_iterator<_RandomAccessIterator1>(__last), __last - __first, __d_first, [](_ReferenceType1 __x, _ReferenceType2 __y) { __y = __x; }); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator> _OutputIterator -__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last, - _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_reverse_copy(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last, + _OutputIterator __d_first) noexcept { - return __internal::__brick_reverse_copy(__first, __last, __d_first, __is_vector); + return __internal::__brick_reverse_copy(__first, __last, __d_first, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector> -_OutputIterator -__pattern_reverse_copy(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, - _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__pattern_reverse_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + auto __len = __last - __first; - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__is_vector, __first, __len, __d_first](_BidirectionalIterator __inner_first, - _BidirectionalIterator __inner_last) { - __internal::__brick_reverse_copy(__inner_first, __inner_last, - __d_first + (__len - (__inner_last - __first)), - __is_vector); - }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__first, __len, __d_first](_RandomAccessIterator1 __inner_first, _RandomAccessIterator1 __inner_last) + { + __internal::__brick_reverse_copy(__inner_first, __inner_last, + __d_first + (__len - (__inner_last - __first)), _IsVector{}); + }); return __d_first + __len; } @@ -1523,7 +1581,7 @@ _ForwardIterator __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, /*is_vector=*/std::false_type) noexcept { -#if _PSTL_CPP11_STD_ROTATE_BROKEN +#if defined(_PSTL_CPP11_STD_ROTATE_BROKEN) std::rotate(__first, __middle, __last); return std::next(__first, std::distance(__middle, __last)); #else @@ -1531,14 +1589,14 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter #endif } -template <class _ForwardIterator> -_ForwardIterator -__brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, +template <class _RandomAccessIterator> +_RandomAccessIterator +__brick_rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, /*is_vector=*/std::true_type) noexcept { auto __n = __last - __first; auto __m = __middle - __first; - const _ForwardIterator __ret = __first + (__last - __middle); + const _RandomAccessIterator __ret = __first + (__last - __middle); bool __is_left = (__m <= __n / 2); if (!__is_left) @@ -1553,7 +1611,7 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter for (; __last - __first >= __m_2; __first += __m) { __unseq_backend::__simd_assign(__first, __m, __first + __m, - iter_swap<_ForwardIterator, _ForwardIterator>); + iter_swap<_RandomAccessIterator, _RandomAccessIterator>); } } else @@ -1561,7 +1619,7 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter for (; __last - __first >= __m_2; __last -= __m) { __unseq_backend::__simd_assign(__last - __m, __m, __last - __m_2, - iter_swap<_ForwardIterator, _ForwardIterator>); + iter_swap<_RandomAccessIterator, _RandomAccessIterator>); } } __is_left = !__is_left; @@ -1572,73 +1630,73 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter return __ret; } -template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator> _ForwardIterator -__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, - _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last) noexcept { - return __internal::__brick_rotate(__first, __middle, __last, __is_vector); + return __internal::__brick_rotate(__first, __middle, __last, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector> -_ForwardIterator -__pattern_rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, - _ForwardIterator __last, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +_RandomAccessIterator +__pattern_rotate(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __middle, _RandomAccessIterator __last) { - typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp; + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; auto __n = __last - __first; auto __m = __middle - __first; if (__m <= __n / 2) { __par_backend::__buffer<_Tp> __buf(__n - __m); - return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() { - _Tp* __result = __buf.get(); - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __middle, __last, - [__middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) { - __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), __is_vector); - }); + return __internal::__except_handler( + [&__exec, __n, __m, __first, __middle, __last, &__buf]() + { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __middle, __last, + [__middle, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) + { __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), _IsVector{}); }); - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle, - [__last, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) { - __internal::__brick_move(__b, __e, __b + (__last - __middle), - __is_vector); - }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle, + [__last, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) + { __internal::__brick_move(__b, __e, __b + (__last - __middle), _IsVector{}); }); - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + (__n - __m), - [__first, __result, __is_vector](_Tp* __b, _Tp* __e) { - __brick_move_destroy()( - __b, __e, __first + (__b - __result), __is_vector); - }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + (__n - __m), + [__first, __result](_Tp* __b, _Tp* __e) + { __brick_move_destroy()(__b, __e, __first + (__b - __result), _IsVector{}); }); - return __first + (__last - __middle); - }); + return __first + (__last - __middle); + }); } else { __par_backend::__buffer<_Tp> __buf(__m); - return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() { - _Tp* __result = __buf.get(); - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle, - [__first, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) { - __internal::__brick_uninitialized_move( - __b, __e, __result + (__b - __first), __is_vector); - }); - - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __middle, __last, - [__first, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) { - __internal::__brick_move(__b, __e, __first + (__b - __middle), - __is_vector); - }); - - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + __m, - [__n, __m, __first, __result, __is_vector](_Tp* __b, _Tp* __e) { - __brick_move_destroy()( - __b, __e, __first + ((__n - __m) + (__b - __result)), __is_vector); - }); - - return __first + (__last - __middle); - }); + return __internal::__except_handler( + [&__exec, __n, __m, __first, __middle, __last, &__buf]() + { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle, + [__first, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) + { __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __first), _IsVector{}); }); + + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __middle, __last, + [__first, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) + { __internal::__brick_move(__b, __e, __first + (__b - __middle), _IsVector{}); }); + + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + __m, + [__n, __m, __first, __result](_Tp* __b, _Tp* __e) + { __brick_move_destroy()(__b, __e, __first + ((__n - __m) + (__b - __result)), _IsVector{}); }); + + return __first + (__last - __middle); + }); } } @@ -1654,47 +1712,49 @@ __brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _Forwar return std::rotate_copy(__first, __middle, __last, __result); } -template <class _ForwardIterator, class _OutputIterator> -_OutputIterator -__brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, - _OutputIterator __result, /*__is_vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_rotate_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __middle, _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, /*__is_vector=*/std::true_type) noexcept { - _OutputIterator __res = __internal::__brick_copy(__middle, __last, __result, std::true_type()); + _RandomAccessIterator2 __res = __internal::__brick_copy(__middle, __last, __result, std::true_type()); return __internal::__brick_copy(__first, __middle, __res, std::true_type()); } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator> _OutputIterator -__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, - _OutputIterator __result, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_rotate_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last, _OutputIterator __result) noexcept { - return __internal::__brick_rotate_copy(__first, __middle, __last, __result, __is_vector); + return __internal::__brick_rotate_copy(__first, __middle, __last, __result, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector> -_OutputIterator -__pattern_rotate_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, - _ForwardIterator __last, _OutputIterator __result, _IsVector __is_vector, - /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__pattern_rotate_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __middle, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__first, __last, __middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__first, __last, __middle, __result](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) + { if (__b > __middle) { - __internal::__brick_copy(__b, __e, __result + (__b - __middle), __is_vector); + __internal::__brick_copy(__b, __e, __result + (__b - __middle), _IsVector{}); } else { - _OutputIterator __new_result = __result + ((__last - __middle) + (__b - __first)); + _RandomAccessIterator2 __new_result = __result + ((__last - __middle) + (__b - __first)); if (__e < __middle) { - __internal::__brick_copy(__b, __e, __new_result, __is_vector); + __internal::__brick_copy(__b, __e, __new_result, _IsVector{}); } else { - __internal::__brick_copy(__b, __middle, __new_result, __is_vector); - __internal::__brick_copy(__middle, __e, __result, __is_vector); + __internal::__brick_copy(__b, __middle, __new_result, _IsVector{}); + __internal::__brick_copy(__middle, __e, __result, _IsVector{}); } } }); @@ -1713,21 +1773,21 @@ __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _Unary return std::is_partitioned(__first, __last, __pred); } -template <class _ForwardIterator, class _UnaryPredicate> +template <class _RandomAccessIterator, class _UnaryPredicate> bool -__brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, +__brick_is_partitioned(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred, /*is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; if (__first == __last) { return true; } else { - _ForwardIterator __result = __unseq_backend::__simd_first( + _RandomAccessIterator __result = __unseq_backend::__simd_first( __first, _SizeType(0), __last - __first, - [&__pred](_ForwardIterator __it, _SizeType __i) { return !__pred(__it[__i]); }); + [&__pred](_RandomAccessIterator __it, _SizeType __i) { return !__pred(__it[__i]); }); if (__result == __last) { return true; @@ -1740,18 +1800,18 @@ __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _Unary } } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> bool -__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _UnaryPredicate __pred) noexcept { - return __internal::__brick_is_partitioned(__first, __last, __pred, __is_vector); + return __internal::__brick_is_partitioned(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> bool -__pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, - _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_is_partitioned(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryPredicate __pred) { if (__first == __last) { @@ -1759,6 +1819,8 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F } else { + using __backend_tag = typename decltype(__tag)::__backend_tag; + return __internal::__except_handler([&]() { // State of current range: // broken - current range is not partitioned by pred @@ -1782,9 +1844,10 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F __broken, __broken, __true_false, __broken}; __init = __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, - [&__pred, &__table, __is_vector](_ForwardIterator __i, _ForwardIterator __j, - _ReduceType __value) -> _ReduceType { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, + [&__pred, &__table](_RandomAccessIterator __i, _RandomAccessIterator __j, + _ReduceType __value) -> _ReduceType + { if (__value == __broken) { return __broken; @@ -1794,12 +1857,12 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F if (__pred(*__i)) { // find first element that don't satisfy pred - _ForwardIterator __x = - __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), __is_vector); + _RandomAccessIterator __x = + __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), _IsVector{}); if (__x != __j) { // find first element after "x" that satisfy pred - _ForwardIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, __is_vector); + _RandomAccessIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, _IsVector{}); // if it was found then range isn't partitioned by pred if (__y != __j) { @@ -1819,7 +1882,7 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F { // if first element doesn't satisfy pred // then we should find the first element that satisfy pred. // If we found it then range isn't partitioned by pred - if (__internal::__brick_find_if(__i + 1, __j, __pred, __is_vector) != __j) + if (__internal::__brick_find_if(__i + 1, __j, __pred, _IsVector{}) != __j) { return __broken; } @@ -1832,7 +1895,8 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F return (__value == -1) ? __res : __table[__value * 4 + __res]; }, - [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType { + [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType + { if (__val1 == __broken || __val2 == __broken) { return __broken; @@ -1857,43 +1921,45 @@ __brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredi return std::partition(__first, __last, __pred); } -template <class _ForwardIterator, class _UnaryPredicate> -_ForwardIterator -__brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__brick_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred, /*is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::partition(__first, __last, __pred); } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> _ForwardIterator -__pattern_partition(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, - _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept +__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _UnaryPredicate __pred) noexcept { - return __internal::__brick_partition(__first, __last, __pred, __is_vector); + return __internal::__brick_partition(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> -_ForwardIterator -__pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, - _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_partition(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; // 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; + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; }; return __internal::__except_handler([&]() { _PartitionRange __init{__last, __last, __last}; // lambda for merging two partitioned ranges to one partitioned range - auto __reductor = [&__exec, __is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __reductor = [&__exec](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange + { auto __size1 = __val1.__end - __val1.__pivot; auto __size2 = __val2.__pivot - __val2.__begin; auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); @@ -1908,10 +1974,10 @@ __pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forwar else if (__size2 > __size1) { __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size1, - [__val1, __val2, __size1, __is_vector](_ForwardIterator __i, _ForwardIterator __j) { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size1, + [__val1, __val2, __size1](_RandomAccessIterator __i, _RandomAccessIterator __j) { __internal::__brick_swap_ranges(__i, __j, (__val2.__pivot - __size1) + (__i - __val1.__pivot), - __is_vector); + _IsVector{}); }); return {__new_begin, __val2.__pivot - __size1, __val2.__end}; } @@ -1919,20 +1985,21 @@ __pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forwar else { __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size2, - [__val1, __val2, __is_vector](_ForwardIterator __i, _ForwardIterator __j) { - __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), __is_vector); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size2, + [__val1, __val2](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), _IsVector{}); }); return {__new_begin, __val1.__pivot + __size2, __val2.__end}; } }; _PartitionRange __result = __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, - [__pred, __is_vector, __reductor](_ForwardIterator __i, _ForwardIterator __j, - _PartitionRange __value) -> _PartitionRange { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, + [__pred, __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, + _PartitionRange __value) -> _PartitionRange + { //1. serial partition - _ForwardIterator __pivot = __internal::__brick_partition(__i, __j, __pred, __is_vector); + _RandomAccessIterator __pivot = __internal::__brick_partition(__i, __j, __pred, _IsVector{}); // 2. merging of two ranges (left and right respectively) return __reductor(__value, {__i, __pivot, __j}); @@ -1954,44 +2021,45 @@ __brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator return std::stable_partition(__first, __last, __pred); } -template <class _BidirectionalIterator, class _UnaryPredicate> -_BidirectionalIterator -__brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred, +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__brick_stable_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::stable_partition(__first, __last, __pred); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> _BidirectionalIterator -__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last, - _UnaryPredicate __pred, _IsVector __is_vector, - /*is_parallelization=*/std::false_type) noexcept +__pattern_stable_partition(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last, + _UnaryPredicate __pred) noexcept { - return __internal::__brick_stable_partition(__first, __last, __pred, __is_vector); + return __internal::__brick_stable_partition(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector> -_BidirectionalIterator -__pattern_stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, - _UnaryPredicate __pred, _IsVector __is_vector, - /*is_parallelization=*/std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_stable_partition(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + // 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; + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; }; return __internal::__except_handler([&]() { _PartitionRange __init{__last, __last, __last}; // lambda for merging two partitioned ranges to one partitioned range - auto __reductor = [__is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __reductor = [](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange + { auto __size1 = __val1.__end - __val1.__pivot; auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); @@ -2004,17 +2072,18 @@ __pattern_stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __f // then we should swap the false part of left range and last part of true part of right range else { - __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, __is_vector); + __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, _IsVector{}); return {__new_begin, __val2.__pivot - __size1, __val2.__end}; } }; _PartitionRange __result = __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, - [&__pred, __is_vector, __reductor](_BidirectionalIterator __i, _BidirectionalIterator __j, - _PartitionRange __value) -> _PartitionRange { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, + [&__pred, __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, + _PartitionRange __value) -> _PartitionRange + { //1. serial stable_partition - _BidirectionalIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, __is_vector); + _RandomAccessIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, _IsVector{}); // 2. merging of two ranges (left and right respectively) return __reductor(__value, {__i, __pivot, __j}); @@ -2036,170 +2105,190 @@ __brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _Outpu return std::partition_copy(__first, __last, __out_true, __out_false, __pred); } -template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> -std::pair<_OutputIterator1, _OutputIterator2> -__brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true, - _OutputIterator2 __out_false, _UnaryPredicate __pred, /*is_vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, + class _UnaryPredicate> +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> +__brick_partition_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { -#if (_PSTL_MONOTONIC_PRESENT) +#if defined(_PSTL_MONOTONIC_PRESENT) return __unseq_backend::__simd_partition_copy(__first, __last - __first, __out_true, __out_false, __pred); #else return std::partition_copy(__first, __last, __out_true, __out_false, __pred); #endif } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, - class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, + class _UnaryPredicate> std::pair<_OutputIterator1, _OutputIterator2> -__pattern_partition_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, - _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred, - _IsVector __is_vector, /*is_parallelization=*/std::false_type) noexcept +__pattern_partition_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred) noexcept { - return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector); + return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2, - class _UnaryPredicate, class _IsVector> -std::pair<_OutputIterator1, _OutputIterator2> -__pattern_partition_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred, - _IsVector __is_vector, /*is_parallelization=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _UnaryPredicate> +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> +__pattern_partition_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, _UnaryPredicate __pred) { - typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; typedef std::pair<_DifferenceType, _DifferenceType> _ReturnType; const _DifferenceType __n = __last - __first; if (_DifferenceType(1) < __n) { __par_backend::__buffer<bool> __mask_buf(__n); - return __internal::__except_handler([&__exec, __n, __first, __out_true, __out_false, __is_vector, __pred, - &__mask_buf]() { - bool* __mask = __mask_buf.get(); - _ReturnType __m{}; - __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n, std::make_pair(_DifferenceType(0), _DifferenceType(0)), - [=](_DifferenceType __i, _DifferenceType __len) { // Reduce - return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len), - __mask + __i, __pred, __is_vector); - }, - [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType { - return std::make_pair(__x.first + __y.first, __x.second + __y.second); - }, // Combine - [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan - __internal::__brick_partition_by_mask(__first + __i, __first + (__i + __len), - __out_true + __initial.first, __out_false + __initial.second, - __mask + __i, __is_vector); - }, - [&__m](_ReturnType __total) { __m = __total; }); - return std::make_pair(__out_true + __m.first, __out_false + __m.second); - }); + return __internal::__except_handler( + [&__exec, __n, __first, __out_true, __out_false, __pred, &__mask_buf]() + { + bool* __mask = __mask_buf.get(); + _ReturnType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, + std::make_pair(_DifferenceType(0), _DifferenceType(0)), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len), + __mask + __i, __pred, _IsVector{}); + }, + [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType + { return std::make_pair(__x.first + __y.first, __x.second + __y.second); }, // Combine + [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan + __internal::__brick_partition_by_mask( + __first + __i, __first + (__i + __len), __out_true + __initial.first, + __out_false + __initial.second, __mask + __i, _IsVector{}); + }, + [&__m](_ReturnType __total) { __m = __total; }); + return std::make_pair(__out_true + __m.first, __out_false + __m.second); + }); } // trivial sequence - use serial algorithm - return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector); + return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, _IsVector{}); } //------------------------------------------------------------------------ // sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector, - class _IsMoveConstructible> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible> void -__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, - _IsVector /*is_vector*/, /*is_parallel=*/std::false_type, _IsMoveConstructible) noexcept +__pattern_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, + _IsMoveConstructible) noexcept { std::sort(__first, __last, __comp); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, - _IsVector /*is_vector*/, /*is_parallel=*/std::true_type, /*is_move_constructible=*/std::true_type) +__pattern_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp, /*is_move_constructible=*/std::true_type) { - __internal::__except_handler([&]() { - __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - [](_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) { std::sort(__first, __last, __comp); }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler( + [&]() + { + __par_backend::__parallel_stable_sort( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) + { std::sort(__first, __last, __comp); }); + }); } //------------------------------------------------------------------------ // stable_sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, - _IsVector /*is_vector*/, /*is_parallel=*/std::false_type) noexcept +__pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) noexcept { std::stable_sort(__first, __last, __comp); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp, _IsVector /*is_vector*/, /*is_parallel=*/std::true_type) +__pattern_stable_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) { - __internal::__except_handler([&]() { - __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - [](_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) { std::stable_sort(__first, __last, __comp); }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler( + [&]() + { + __par_backend::__parallel_stable_sort( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) + { std::stable_sort(__first, __last, __comp); }); + }); } //------------------------------------------------------------------------ // partial_sort //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __middle, - _RandomAccessIterator __last, _Compare __comp, _IsVector, - /*is_parallel=*/std::false_type) noexcept +__pattern_partial_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __middle, + _RandomAccessIterator __last, _Compare __comp) noexcept { std::partial_sort(__first, __middle, __last, __comp); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_partial_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __middle, - _RandomAccessIterator __last, _Compare __comp, _IsVector, /*is_parallel=*/std::true_type) +__pattern_partial_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + const auto __n = __middle - __first; if (__n == 0) return; - __internal::__except_handler([&]() { - __par_backend::__parallel_stable_sort( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) { - if (__n < __end - __begin) - std::partial_sort(__begin, __begin + __n, __end, __comp); - else - std::sort(__begin, __end, __comp); - }, - __n); - }); + __internal::__except_handler( + [&]() + { + __par_backend::__parallel_stable_sort( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, + [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) + { + if (__n < __end - __begin) + std::partial_sort(__begin, __begin + __n, __end, __comp); + else + std::sort(__begin, __end, __comp); + }, + __n); + }); } //------------------------------------------------------------------------ // partial_sort_copy //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare> _RandomAccessIterator -__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, - _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp, _IsVector, - /*is_parallel=*/std::false_type) noexcept +__pattern_partial_sort_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp) noexcept { return std::partial_sort_copy(__first, __last, __d_first, __d_last, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector> -_RandomAccessIterator -__pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, - _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp, - _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 +__pattern_partial_sort_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first, + _RandomAccessIterator2 __d_last, _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__last == __first || __d_last == __d_first) { return __d_first; @@ -2210,18 +2299,18 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, if (__n2 >= __n1) { __par_backend::__parallel_stable_sort( - std::forward<_ExecutionPolicy>(__exec), __d_first, __d_first + __n1, __comp, - [__first, __d_first, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j, - _Compare __comp) { - _ForwardIterator __i1 = __first + (__i - __d_first); - _ForwardIterator __j1 = __first + (__j - __d_first); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __d_first, __d_first + __n1, __comp, + [__first, __d_first](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j, _Compare __comp) + { + _RandomAccessIterator1 __i1 = __first + (__i - __d_first); + _RandomAccessIterator1 __j1 = __first + (__j - __d_first); // 1. Copy elements from input to output -# if !_PSTL_ICC_18_OMP_SIMD_BROKEN - __internal::__brick_copy(__i1, __j1, __i, __is_vector); -# else +#if !defined(_PSTL_ICC_18_OMP_SIMD_BROKEN) + __internal::__brick_copy(__i1, __j1, __i, _IsVector{}); +#else std::copy(__i1, __j1, __i); -# endif +#endif // 2. Sort elements in output sequence std::sort(__i, __j, __comp); }, @@ -2230,38 +2319,38 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, } else { - typedef typename std::iterator_traits<_ForwardIterator>::value_type _T1; - typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _T2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _T1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _T2; __par_backend::__buffer<_T1> __buf(__n1); _T1* __r = __buf.get(); - __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n1, __comp, - [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) { - _ForwardIterator __it = __first + (__i - __r); + __par_backend::__parallel_stable_sort( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n1, __comp, + [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) + { + _RandomAccessIterator1 __it = __first + (__i - __r); - // 1. Copy elements from input to raw memory - for (_T1* __k = __i; __k != __j; ++__k, ++__it) - { - ::new (__k) _T2(*__it); - } + // 1. Copy elements from input to raw memory + for (_T1* __k = __i; __k != __j; ++__k, ++__it) + { + ::new (__k) _T2(*__it); + } - // 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); + // 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(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n2, - [__r, __d_first, __is_vector](_T1* __i, _T1* __j) { - __brick_move_destroy()( - __i, __j, __d_first + (__i - __r), __is_vector); - }); - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __r + __n2, __r + __n1, - [__is_vector](_T1* __i, _T1* __j) { __brick_destroy(__i, __j, __is_vector); }); + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n2, + [__r, __d_first](_T1* __i, _T1* __j) + { __brick_move_destroy()(__i, __j, __d_first + (__i - __r), _IsVector{}); }); + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r + __n2, + __r + __n1, + [](_T1* __i, _T1* __j) { __brick_destroy(__i, __j, _IsVector{}); }); return __d_first + __n2; } @@ -2271,9 +2360,9 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, //------------------------------------------------------------------------ // adjacent_find //------------------------------------------------------------------------ -template <class _ForwardIterator, class _BinaryPredicate> -_ForwardIterator -__brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_adjacent_find(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred, /* IsVector = */ std::true_type, bool __or_semantic) noexcept { return __unseq_backend::__simd_adjacent_find(__first, __last, __pred, __or_semantic); @@ -2287,78 +2376,79 @@ __brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _Binary return std::adjacent_find(__first, __last, __pred); } -template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> _ForwardIterator -__pattern_adjacent_find(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred, - /* is_parallel */ std::false_type, _IsVector __is_vector, bool __or_semantic) noexcept +__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __pred, bool __or_semantic) noexcept { - return __internal::__brick_adjacent_find(__first, __last, __pred, __is_vector, __or_semantic); + return __internal::__brick_adjacent_find(__first, __last, __pred, typename _Tag::__is_vector{}, __or_semantic); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> _RandomAccessIterator -__pattern_adjacent_find(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _BinaryPredicate __pred, /* is_parallel */ std::true_type, _IsVector __is_vector, - bool __or_semantic) +__pattern_adjacent_find(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _BinaryPredicate __pred, bool __or_semantic) { if (__last - __first < 2) return __last; - return __internal::__except_handler([&]() { - return __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __last, - [__last, __pred, __is_vector, __or_semantic](_RandomAccessIterator __begin, _RandomAccessIterator __end, - _RandomAccessIterator __value) -> _RandomAccessIterator { - // TODO: investigate performance benefits from the use of shared variable for the result, - // checking (compare_and_swap idiom) its __value at __first. - if (__or_semantic && __value < __last) - { //found - __par_backend::__cancel_execution(); - return __value; - } + using __backend_tag = typename decltype(__tag)::__backend_tag; - if (__value > __begin) + return __internal::__except_handler( + [&]() + { + return __par_backend::__parallel_reduce( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __last, + [__last, __pred, __or_semantic](_RandomAccessIterator __begin, _RandomAccessIterator __end, + _RandomAccessIterator __value) -> _RandomAccessIterator { - // modify __end to check the predicate on the boundary __values; - // TODO: to use a custom range with boundaries overlapping - // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1) - // then check the pair [__last-1, __last) - if (__end != __last) - ++__end; - - //correct the global result iterator if the "brick" returns a local "__last" - const _RandomAccessIterator __res = - __internal::__brick_adjacent_find(__begin, __end, __pred, __is_vector, __or_semantic); - if (__res < __end) - __value = __res; - } - return __value; - }, - [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator { - return __x < __y ? __x : __y; - } //reduce a __value - ); - }); + // TODO: investigate performance benefits from the use of shared variable for the result, + // checking (compare_and_swap idiom) its __value at __first. + if (__or_semantic && __value < __last) + { //found + __par_backend::__cancel_execution(); + return __value; + } + + if (__value > __begin) + { + // modify __end to check the predicate on the boundary __values; + // TODO: to use a custom range with boundaries overlapping + // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1) + // then check the pair [__last-1, __last) + if (__end != __last) + ++__end; + + //correct the global result iterator if the "brick" returns a local "__last" + const _RandomAccessIterator __res = + __internal::__brick_adjacent_find(__begin, __end, __pred, _IsVector{}, __or_semantic); + if (__res < __end) + __value = __res; + } + return __value; + }, + [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator + { return __x < __y ? __x : __y; } //reduce a __value + ); + }); } //------------------------------------------------------------------------ // nth_element //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __nth, - _RandomAccessIterator __last, _Compare __comp, _IsVector, - /*is_parallel=*/std::false_type) noexcept +__pattern_nth_element(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Compare __comp) noexcept { std::nth_element(__first, __nth, __last, __comp); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __nth, - _RandomAccessIterator __last, _Compare __comp, _IsVector __is_vector, - /*is_parallel=*/std::true_type) noexcept +__pattern_nth_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) noexcept { if (__first == __last || __nth == __last) { @@ -2370,10 +2460,8 @@ __pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __x; do { - __x = __internal::__pattern_partition(std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, - [&__comp, __first](const _Tp& __x) { return __comp(__x, *__first); }, - __is_vector, - /*is_parallel=*/std::true_type()); + __x = __internal::__pattern_partition(__tag, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, + [&__comp, __first](const _Tp& __x) { return __comp(__x, *__first); }); --__x; if (__x != __first) { @@ -2404,9 +2492,9 @@ __pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, //------------------------------------------------------------------------ // fill, fill_n //------------------------------------------------------------------------ -template <class _ForwardIterator, class _Tp> +template <class _RandomAccessIterator, class _Tp> void -__brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, +__brick_fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, /* __is_vector = */ std::true_type) noexcept { __unseq_backend::__simd_fill_n(__first, __last - __first, __value); @@ -2420,31 +2508,34 @@ __brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val std::fill(__first, __last, __value); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp> void -__pattern_fill(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, - /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept +__pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept { - __internal::__brick_fill(__first, __last, __value, __is_vector); + __internal::__brick_fill(__first, __last, __value, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector> -_ForwardIterator -__pattern_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, - /*is_parallel=*/std::true_type, _IsVector __is_vector) -{ - return __internal::__except_handler([&__exec, __first, __last, &__value, __is_vector]() { - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__value, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) { - __internal::__brick_fill(__begin, __end, __value, __is_vector); - }); - return __last; - }); +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp> +_RandomAccessIterator +__pattern_fill(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, const _Tp& __value) +{ + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&__exec, __first, __last, &__value]() + { + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__value](_RandomAccessIterator __begin, _RandomAccessIterator __end) + { __internal::__brick_fill(__begin, __end, __value, _IsVector{}); }); + return __last; + }); } -template <class _OutputIterator, class _Size, class _Tp> -_OutputIterator -__brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __is_vector = */ std::true_type) noexcept +template <class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__brick_fill_n(_RandomAccessIterator __first, _Size __count, const _Tp& __value, + /* __is_vector = */ std::true_type) noexcept { return __unseq_backend::__simd_fill_n(__first, __count, __value); } @@ -2456,21 +2547,20 @@ __brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __ return std::fill_n(__first, __count, __value); } -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp> _OutputIterator -__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, const _Tp& __value, - /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept +__pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, const _Tp& __value) noexcept { - return __internal::__brick_fill_n(__first, __count, __value, __is_vector); + return __internal::__brick_fill_n(__first, __count, __value, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector> -_OutputIterator -__pattern_fill_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, const _Tp& __value, - /*is_parallel=*/std::true_type, _IsVector __is_vector) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__pattern_fill_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _Size __count, const _Tp& __value) { - return __internal::__pattern_fill(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __value, - std::true_type(), __is_vector); + return __internal::__pattern_fill(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, + __value); } //------------------------------------------------------------------------ @@ -2492,59 +2582,61 @@ __brick_generate(_ForwardIterator __first, _ForwardIterator __last, _Generator _ std::generate(__first, __last, __g); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator> void -__pattern_generate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g, - /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept +__pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) noexcept { - __internal::__brick_generate(__first, __last, __g, __is_vector); + __internal::__brick_generate(__first, __last, __g, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector> -_ForwardIterator -__pattern_generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g, - /*is_parallel=*/std::true_type, _IsVector __is_vector) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator> +_RandomAccessIterator +__pattern_generate(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Generator __g) { - return __internal::__except_handler([&]() { - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__g, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) { - __internal::__brick_generate(__begin, __end, __g, __is_vector); - }); - return __last; - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__g](_RandomAccessIterator __begin, _RandomAccessIterator __end) + { __internal::__brick_generate(__begin, __end, __g, _IsVector{}); }); + return __last; + }); } -template <class _OutputIterator, class _Size, class _Generator> - _OutputIterator -__brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g, /* is_vector = */ std::true_type) noexcept +template <class _RandomAccessIterator, class _Size, class _Generator> +_RandomAccessIterator +__brick_generate_n(_RandomAccessIterator __first, _Size __count, _Generator __g, + /* is_vector = */ std::true_type) noexcept { return __unseq_backend::__simd_generate_n(__first, __count, __g); } template <class _OutputIterator, class _Size, class _Generator> - _OutputIterator +_OutputIterator __brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept { return std::generate_n(__first, __count, __g); } -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator> _OutputIterator -__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g, - /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept +__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g) noexcept { - return __internal::__brick_generate_n(__first, __count, __g, __is_vector); + return __internal::__brick_generate_n(__first, __count, __g, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector> -_OutputIterator -__pattern_generate_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, _Generator __g, - /*is_parallel=*/std::true_type, _IsVector __is_vector) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Generator> +_RandomAccessIterator +__pattern_generate_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _Size __count, _Generator __g) { - static_assert(__is_random_access_iterator<_OutputIterator>::value, + static_assert(__are_random_access_iterators<_RandomAccessIterator>::value, "Pattern-brick error. Should be a random access iterator."); - return __internal::__pattern_generate(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __g, - std::true_type(), __is_vector); + return __internal::__pattern_generate(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, + __g); } //------------------------------------------------------------------------ @@ -2564,41 +2656,41 @@ _RandomAccessIterator __brick_remove_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred, /* __is_vector = */ std::true_type) noexcept { -#if _PSTL_MONOTONIC_PRESENT +#if defined(_PSTL_MONOTONIC_PRESENT) return __unseq_backend::__simd_remove_if(__first, __last - __first, __pred); #else return std::remove_if(__first, __last, __pred); #endif } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> _ForwardIterator -__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, - _IsVector __is_vector, /*is_parallel*/ std::false_type) noexcept +__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _UnaryPredicate __pred) noexcept { - return __internal::__brick_remove_if(__first, __last, __pred, __is_vector); + return __internal::__brick_remove_if(__first, __last, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector> -_ForwardIterator -__pattern_remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, - _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel*/ std::true_type) noexcept +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator +__pattern_remove_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryPredicate __pred) noexcept { - typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; if (__first == __last || __first + 1 == __last) { // Trivial sequence - use serial algorithm - return __internal::__brick_remove_if(__first, __last, __pred, __is_vector); + return __internal::__brick_remove_if(__first, __last, __pred, _IsVector{}); } return __internal::__remove_elements( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) { - __internal::__brick_walk2(__b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); }, - __is_vector); - }, - __is_vector); + __tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) + { + __internal::__brick_walk2( + __b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); }, _IsVector{}); + }); } //------------------------------------------------------------------------ @@ -2614,39 +2706,42 @@ __brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIte return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp); } -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator -__brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__brick_merge(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _RandomAccessIterator3 __d_first, _Compare __comp, /* __is_vector = */ std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_merge(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp, _IsVector __is_vector, - /* is_parallel = */ std::false_type) noexcept +__pattern_merge(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __d_first, + _Compare __comp) noexcept { - return __internal::__brick_merge(__first1, __last1, __first2, __last2, __d_first, __comp, __is_vector); + return __internal::__brick_merge(__first1, __last1, __first2, __last2, __d_first, __comp, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, - class _Compare, class _IsVector> -_OutputIterator -__pattern_merge(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _OutputIterator __d_first, - _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__pattern_merge(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __d_first, _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + __par_backend::__parallel_merge( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, __comp, - [__is_vector](_RandomAccessIterator1 __f1, _RandomAccessIterator1 __l1, _RandomAccessIterator2 __f2, - _RandomAccessIterator2 __l2, _OutputIterator __f3, _Compare __comp) { - return __internal::__brick_merge(__f1, __l1, __f2, __l2, __f3, __comp, __is_vector); - }); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, + __comp, + [](_RandomAccessIterator1 __f1, _RandomAccessIterator1 __l1, _RandomAccessIterator2 __f2, + _RandomAccessIterator2 __l2, _RandomAccessIterator3 __f3, _Compare __comp) + { return __internal::__brick_merge(__f1, __l1, __f2, __l2, __f3, __comp, _IsVector{}); }); return __d_first + (__last1 - __first1) + (__last2 - __first2); } @@ -2661,83 +2756,89 @@ __brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __m std::inplace_merge(__first, __middle, __last, __comp); } -template <class _BidirectionalIterator, class _Compare> +template <class _RandomAccessIterator, class _Compare> void -__brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, +__brick_inplace_merge(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __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); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> void -__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __middle, - _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector, - /* is_parallel = */ std::false_type) noexcept +__pattern_inplace_merge(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __middle, + _BidirectionalIterator __last, _Compare __comp) noexcept { - __internal::__brick_inplace_merge(__first, __middle, __last, __comp, __is_vector); + __internal::__brick_inplace_merge(__first, __middle, __last, __comp, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> void -__pattern_inplace_merge(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __middle, - _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector, - /*is_parallel=*/std::true_type) +__pattern_inplace_merge(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__first == __last || __first == __middle || __middle == __last) { return; } - typedef typename std::iterator_traits<_BidirectionalIterator>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; auto __n = __last - __first; __par_backend::__buffer<_Tp> __buf(__n); _Tp* __r = __buf.get(); - __internal::__except_handler([&]() { - auto __move_values = [](_BidirectionalIterator __x, _Tp* __z) { - __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); }, - [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); - }; + __internal::__except_handler( + [&]() + { + auto __move_values = [](_RandomAccessIterator __x, _Tp* __z) + { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + }; - auto __move_sequences = [](_BidirectionalIterator __first1, _BidirectionalIterator __last1, _Tp* __first2) { - return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector()); - }; + auto __move_sequences = [](_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Tp* __first2) + { return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector()); }; - __par_backend::__parallel_merge( - std::forward<_ExecutionPolicy>(__exec), __first, __middle, __middle, __last, __r, __comp, - [__n, __move_values, __move_sequences](_BidirectionalIterator __f1, _BidirectionalIterator __l1, - _BidirectionalIterator __f2, _BidirectionalIterator __l2, _Tp* __f3, - _Compare __comp) { - (__utils::__serial_move_merge(__n))(__f1, __l1, __f2, __l2, __f3, __comp, __move_values, __move_values, - __move_sequences, __move_sequences); - return __f3 + (__l1 - __f1) + (__l2 - __f2); - }); - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __r, __r + __n, [__r, __first, __is_vector](_Tp* __i, _Tp* __j) { - __brick_move_destroy()(__i, __j, __first + (__i - __r), __is_vector); - }); - }); + __par_backend::__parallel_merge( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __middle, __last, __r, + __comp, + [__n, __move_values, __move_sequences](_RandomAccessIterator __f1, _RandomAccessIterator __l1, + _RandomAccessIterator __f2, _RandomAccessIterator __l2, + _Tp* __f3, _Compare __comp) + { + (__utils::__serial_move_merge(__n))(__f1, __l1, __f2, __l2, __f3, __comp, __move_values, + __move_values, __move_sequences, __move_sequences); + return __f3 + (__l1 - __f1) + (__l2 - __f2); + }); + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n, + [__r, __first](_Tp* __i, _Tp* __j) + { __brick_move_destroy()(__i, __j, __first + (__i - __r), _IsVector{}); }); + }); } //------------------------------------------------------------------------ // includes //------------------------------------------------------------------------ -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> bool -__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector, - /*is_parallel=*/std::false_type) noexcept +__pattern_includes(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) noexcept { return std::includes(__first1, __last1, __first2, __last2, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> bool -__pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector, - /*is_parallel=*/std::true_type) +__pattern_includes(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__first2 >= __last2) return true; @@ -2751,51 +2852,55 @@ __pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forwa if (__last2 - __first2 == 1) return !__comp(*__first1, *__first2) && !__comp(*__first2, *__first1); - return __internal::__except_handler([&]() { - return !__internal::__parallel_or( - std::forward<_ExecutionPolicy>(__exec), __first2, __last2, - [__first1, __last1, __first2, __last2, &__comp](_ForwardIterator2 __i, _ForwardIterator2 __j) { - _PSTL_ASSERT(__j > __i); - //assert(__j - __i > 1); - - //1. moving boundaries to "consume" subsequence of equal elements - auto __is_equal = [&__comp](_ForwardIterator2 __a, _ForwardIterator2 __b) -> bool { - return !__comp(*__a, *__b) && !__comp(*__b, *__a); - }; - - //1.1 left bound, case "aaa[aaaxyz...]" - searching "x" - if (__i > __first2 && __is_equal(__i, __i - 1)) + return __internal::__except_handler( + [&]() + { + return !__internal::__parallel_or( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, + [__first1, __last1, __first2, __last2, &__comp](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j) { - //whole subrange continues to content equal elements - return "no op" - if (__is_equal(__i, __j - 1)) - return false; + _PSTL_ASSERT(__j > __i); + //_PSTL_ASSERT(__j - __i > 1); - __i = std::upper_bound(__i, __last2, *__i, __comp); - } + //1. moving boundaries to "consume" subsequence of equal elements + auto __is_equal = [&__comp](_RandomAccessIterator2 __a, _RandomAccessIterator2 __b) -> bool + { return !__comp(*__a, *__b) && !__comp(*__b, *__a); }; - //1.2 right bound, case "[...aaa]aaaxyz" - searching "x" - if (__j < __last2 && __is_equal(__j - 1, __j)) - __j = std::upper_bound(__j, __last2, *__j, __comp); + //1.1 left bound, case "aaa[aaaxyz...]" - searching "x" + if (__i > __first2 && __is_equal(__i, __i - 1)) + { + //whole subrange continues to content equal elements - return "no op" + if (__is_equal(__i, __j - 1)) + return false; - //2. testing is __a subsequence of the second range included into the first range - auto __b = std::lower_bound(__first1, __last1, *__i, __comp); + __i = std::upper_bound(__i, __last2, *__i, __comp); + } - _PSTL_ASSERT(!__comp(*(__last1 - 1), *__b)); - _PSTL_ASSERT(!__comp(*(__j - 1), *__i)); - return !std::includes(__b, __last1, __i, __j, __comp); - }); - }); + //1.2 right bound, case "[...aaa]aaaxyz" - searching "x" + if (__j < __last2 && __is_equal(__j - 1, __j)) + __j = std::upper_bound(__j, __last2, *__j, __comp); + + //2. testing is __a subsequence of the second range included into the first range + auto __b = std::lower_bound(__first1, __last1, *__i, __comp); + + _PSTL_ASSERT(!__comp(*(__last1 - 1), *__b)); + _PSTL_ASSERT(!__comp(*(__j - 1), *__i)); + return !std::includes(__b, __last1, __i, __j, __comp); + }); + }); } constexpr auto __set_algo_cut_off = 1000; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector, class _SizeFunction, class _SetOP> +template <class _IsVector, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, + class _OutputIterator, class _Compare, class _SizeFunction, class _SetOP> _OutputIterator -__parallel_set_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, - _SizeFunction __size_func, _SetOP __set_op, _IsVector __is_vector) +__parallel_set_op(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, + _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _OutputIterator __result, _Compare __comp, _SizeFunction __size_func, _SetOP __set_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; @@ -2814,100 +2919,100 @@ __parallel_set_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forwar __par_backend::__buffer<_Tp> __buf(__size_func(__n1, __n2)); - return __internal::__except_handler([&__exec, __n1, __first1, __last1, __first2, __last2, __result, __is_vector, - __comp, __size_func, __set_op, &__buf]() { - auto __buffer = __buf.get(); - _DifferenceType __m{}; - auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan - if (!__s.empty()) - __brick_move_destroy()(__buffer + __s.__buf_pos, - __buffer + (__s.__buf_pos + __s.__len), __result + __s.__pos, - __is_vector); - }; - __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n1, _SetRange{0, 0, 0}, //-1, 0}, - [=](_DifferenceType __i, _DifferenceType __len) { // Reduce - //[__b; __e) - a subrange of the first sequence, to reduce - _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len); + return __internal::__except_handler( + [&__exec, __n1, __first1, __last1, __first2, __last2, __result, __comp, __size_func, __set_op, &__buf]() + { + auto __buffer = __buf.get(); + _DifferenceType __m{}; + auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan + if (!__s.empty()) + __brick_move_destroy()(__buffer + __s.__buf_pos, __buffer + (__s.__buf_pos + __s.__len), + __result + __s.__pos, _IsVector{}); + }; + __par_backend::__parallel_strict_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n1, _SetRange{0, 0, 0}, //-1, 0}, + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + //[__b; __e) - a subrange of the first sequence, to reduce + _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len); - //try searching for the first element which not equal to *__b - if (__b != __first1) - __b = std::upper_bound(__b, __last1, *__b, __comp); + //try searching for the first element which not equal to *__b + if (__b != __first1) + __b = std::upper_bound(__b, __last1, *__b, __comp); - //try searching for the first element which not equal to *__e - if (__e != __last1) - __e = std::upper_bound(__e, __last1, *__e, __comp); + //try searching for the first element which not equal to *__e + if (__e != __last1) + __e = std::upper_bound(__e, __last1, *__e, __comp); - //check is [__b; __e) empty - if (__e - __b < 1) - { - _ForwardIterator2 __bb = __last2; - if (__b != __last1) - __bb = std::lower_bound(__first2, __last2, *__b, __comp); + //check is [__b; __e) empty + if (__e - __b < 1) + { + _ForwardIterator2 __bb = __last2; + if (__b != __last1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); - const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); - return _SetRange{0, 0, __buf_pos}; - } + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + return _SetRange{0, 0, __buf_pos}; + } - //try searching for "corresponding" subrange [__bb; __ee) in the second sequence - _ForwardIterator2 __bb = __first2; - if (__b != __first1) - __bb = std::lower_bound(__first2, __last2, *__b, __comp); + //try searching for "corresponding" subrange [__bb; __ee) in the second sequence + _ForwardIterator2 __bb = __first2; + if (__b != __first1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); - _ForwardIterator2 __ee = __last2; - if (__e != __last1) - __ee = std::lower_bound(__bb, __last2, *__e, __comp); + _ForwardIterator2 __ee = __last2; + if (__e != __last1) + __ee = std::lower_bound(__bb, __last2, *__e, __comp); - const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); - auto __buffer_b = __buffer + __buf_pos; - auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp); + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + auto __buffer_b = __buffer + __buf_pos; + auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp); - return _SetRange{0, __res - __buffer_b, __buf_pos}; - }, - [](const _SetRange& __a, const _SetRange& __b) { // Combine - if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty())) - return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos}; - return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos}; - }, - __scan, // Scan - [&__m, &__scan](const _SetRange& __total) { // Apex - //final scan - __scan(0, 0, __total); - __m = __total.__pos + __total.__len; - }); - return __result + __m; - }); + return _SetRange{0, __res - __buffer_b, __buf_pos}; + }, + [](const _SetRange& __a, const _SetRange& __b) { // Combine + if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty())) + return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos}; + return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos}; + }, + __scan, // Scan + [&__m, &__scan](const _SetRange& __total) { // Apex + //final scan + __scan(0, 0, __total); + __m = __total.__pos + __total.__len; + }); + return __result + __m; + }); } //a shared parallel pattern for '__pattern_set_union' and '__pattern_set_symmetric_difference' -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _SetUnionOp, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare, class _SetUnionOp> _OutputIterator -__parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +__parallel_set_union_op(_Tag __tag, _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _SetUnionOp __set_union_op, _IsVector __is_vector) + _Compare __comp, _SetUnionOp __set_union_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; const auto __n1 = __last1 - __first1; const auto __n2 = __last2 - __first2; - auto __copy_range1 = [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { - return __internal::__brick_copy(__begin, __end, __res, __is_vector); - }; - auto __copy_range2 = [__is_vector](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) { - return __internal::__brick_copy(__begin, __end, __res, __is_vector); - }; + auto copy_range1 = [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) + { return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); }; + auto copy_range2 = [](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) + { return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); }; // {1} {}: parallel copying just first sequence if (__n2 == 0) - return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, - __copy_range1, std::true_type()); + return __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + __result, copy_range1); // {} {2}: parallel copying justmake second sequence if (__n1 == 0) - return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, - __copy_range2, std::true_type()); + return __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, + __result, copy_range2); // testing whether the sequences are intersected _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); @@ -2916,14 +3021,16 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ { //{1} < {2}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 __par_backend::__parallel_invoke( - std::forward<_ExecutionPolicy>(__exec), - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, - __copy_range1, std::true_type()); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + __result, copy_range1); }, - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, - __result + __n1, __copy_range2, std::true_type()); + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, + __result + __n1, copy_range2); }); return __result + __n1 + __n2; } @@ -2935,14 +3042,16 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ { //{2} < {1}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 __par_backend::__parallel_invoke( - std::forward<_ExecutionPolicy>(__exec), - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, - __copy_range2, std::true_type()); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, + __result, copy_range2); }, - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - __result + __n2, __copy_range1, std::true_type()); + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + __result + __n2, copy_range1); }); return __result + __n1 + __n2; } @@ -2953,17 +3062,19 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ auto __res_or = __result; __result += __m1; //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) __par_backend::__parallel_invoke( - std::forward<_ExecutionPolicy>(__exec), + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), //do parallel copying of [first1; left_bound_seq_1) - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __left_bound_seq_1, - __res_or, __copy_range1, std::true_type()); + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __left_bound_seq_1, __res_or, copy_range1); }, - [=, &__result] { + [=, &__result] + { __result = __internal::__parallel_set_op( - std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result, - __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op, - __is_vector); + __tag, std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, + __result, __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); }); return __result; } @@ -2975,24 +3086,26 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ auto __res_or = __result; __result += __m2; //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) __par_backend::__parallel_invoke( - std::forward<_ExecutionPolicy>(__exec), + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), //do parallel copying of [first2; left_bound_seq_2) - [=] { - __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __left_bound_seq_2, - __res_or, __copy_range2, std::true_type()); + [=] + { + __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, + __left_bound_seq_2, __res_or, copy_range2); }, - [=, &__result] { + [=, &__result] + { __result = __internal::__parallel_set_op( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result, - __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op, - __is_vector); + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, + __result, __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); }); return __result; } return __internal::__parallel_set_op( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op, __is_vector); + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op); } //------------------------------------------------------------------------ @@ -3019,33 +3132,33 @@ struct __BrickCopyConstruct } }; -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> _OutputIterator -__brick_set_union(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, +__brick_set_union(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _OutputIterator __result, _Compare __comp, /*__is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, - _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_set_union(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, + _Compare __comp) noexcept { - return __internal::__brick_set_union(__first1, __last1, __first2, __last2, __result, __comp, __is_vector); + return __internal::__brick_set_union(__first1, __last1, __first2, __last2, __result, __comp, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _OutputIterator, class _Compare> _OutputIterator -__pattern_set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, - _IsVector __is_vector, /*__is_parallel=*/std::true_type) +__pattern_set_union(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _OutputIterator __result, _Compare __comp) { const auto __n1 = __last1 - __first1; @@ -3057,13 +3170,13 @@ __pattern_set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forw typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; return __parallel_set_union_op( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _Tp* __result, _Compare __comp) { + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, + [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) + { return __pstl::__utils::__set_union_construct(__first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); - }, - __is_vector); + }); } //------------------------------------------------------------------------ @@ -3079,35 +3192,37 @@ __brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1, return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator -__brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__brick_set_intersection(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, _Compare __comp, /*__is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +__pattern_set_intersection(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept + _Compare __comp) noexcept { - return __internal::__brick_set_intersection(__first1, __last1, __first2, __last2, __result, __comp, __is_vector); + return __internal::__brick_set_intersection(__first1, __last1, __first2, __last2, __result, __comp, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> -_OutputIterator -__pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__pattern_set_intersection(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp) { - typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; - typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; const auto __n1 = __last1 - __first1; const auto __n2 = __last2 - __first2; @@ -3117,13 +3232,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1 return __result; // testing whether the sequences are intersected - _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); //{1} < {2}: seq 2 is wholly greater than seq 1, so, the intersection is empty if (__left_bound_seq_1 == __last1) return __result; // testing whether the sequences are intersected - _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); //{2} < {1}: seq 1 is wholly greater than seq 2, so, the intersection is empty if (__left_bound_seq_2 == __last2) return __result; @@ -3133,14 +3248,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1 { //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) return __internal::__parallel_set_op( - std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result, __comp, - [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, - [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) { + __tag, std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result, + __comp, [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) { return __pstl::__utils::__set_intersection_construct(__first1, __last1, __first2, __last2, __result, __comp); - }, - __is_vector); + }); } const auto __m2 = __last2 - __left_bound_seq_2 + __n1; @@ -3148,14 +3262,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1 { //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) __result = __internal::__parallel_set_op( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result, __comp, - [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, - [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) { + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result, + __comp, [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) { return __pstl::__utils::__set_intersection_construct(__first2, __last2, __first1, __last1, __result, __comp); - }, - __is_vector); + }); return __result; } @@ -3176,35 +3289,36 @@ __brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _F return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator -__brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__brick_set_difference(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp, /*__is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +__pattern_set_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept + _Compare __comp) noexcept { - return __internal::__brick_set_difference(__first1, __last1, __first2, __last2, __result, __comp, __is_vector); + return __internal::__brick_set_difference(__first1, __last1, __first2, __last2, __result, __comp, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> -_OutputIterator -__pattern_set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__pattern_set_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp) { - typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; - typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; const auto __n1 = __last1 - __first1; const auto __n2 = __last2 - __first2; @@ -3216,44 +3330,38 @@ __pattern_set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, // {1} \ {}: parallel copying just first sequence if (__n2 == 0) return __internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, - [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { - return __internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - std::true_type()); + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) + { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); }); // testing whether the sequences are intersected - _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); //{1} < {2}: seq 2 is wholly greater than seq 1, so, parallel copying just first sequence if (__left_bound_seq_1 == __last1) return __internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, - [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { - return __internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - std::true_type()); + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) + { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); }); // testing whether the sequences are intersected - _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); //{2} < {1}: seq 1 is wholly greater than seq 2, so, parallel copying just first sequence if (__left_bound_seq_2 == __last2) return __internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, - [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { - return __internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - std::true_type()); + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) + { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); }); if (__n1 + __n2 > __set_algo_cut_off) - return __parallel_set_op(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, - __comp, [](_DifferenceType __n, _DifferenceType) { return __n; }, - [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) { - return __pstl::__utils::__set_difference_construct( - __first1, __last1, __first2, __last2, __result, __comp, - __BrickCopyConstruct<_IsVector>()); - }, - __is_vector); + return __parallel_set_op( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, + [](_DifferenceType __n, _DifferenceType) { return __n; }, + [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) + { + return __pstl::__utils::__set_difference_construct(__first1, __last1, __first2, __last2, __result, + __comp, __BrickCopyConstruct<_IsVector>()); + }); // use serial algorithm return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); @@ -3272,33 +3380,35 @@ __brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 _ return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> -_OutputIterator -__brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__brick_set_symmetric_difference(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, _Compare __comp, /*__is_vector=*/std::true_type) noexcept { _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial"); return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, + class _Compare> _OutputIterator -__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +__pattern_set_symmetric_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept + _Compare __comp) noexcept { return __internal::__brick_set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp, - __is_vector); + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, - class _Compare, class _IsVector> -_OutputIterator -__pattern_set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, - _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 +__pattern_set_symmetric_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, _Compare __comp) { const auto __n1 = __last1 - __first1; @@ -3308,15 +3418,15 @@ __pattern_set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 if (__n1 + __n2 <= __set_algo_cut_off) return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); - typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; return __internal::__parallel_set_union_op( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _Tp* __result, _Compare __comp) { + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, + [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) + { return __pstl::__utils::__set_symmetric_difference_construct(__first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); - }, - __is_vector); + }); } //------------------------------------------------------------------------ @@ -3344,12 +3454,12 @@ __brick_is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __las [&__comp](_RandomAccessIterator __it, _SizeType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); }); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> _RandomAccessIterator -__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept +__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) noexcept { - return __internal::__brick_is_heap_until(__first, __last, __comp, __is_vector); + return __internal::__brick_is_heap_until(__first, __last, __comp, typename _Tag::__is_vector{}); } template <class _RandomAccessIterator, class _DifferenceType, class _Compare> @@ -3378,22 +3488,27 @@ __is_heap_until_local(_RandomAccessIterator __first, _DifferenceType __begin, _D [&__comp](_RandomAccessIterator __it, _DifferenceType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); }); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> _RandomAccessIterator -__pattern_is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept +__pattern_is_heap_until(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__last - __first < 2) return __last; - return __internal::__except_handler([&]() { - return __parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__first, __comp, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) { - return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, __is_vector); - }, - std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true); - }); + return __internal::__except_handler( + [&]() + { + return __parallel_find( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__first, __comp](_RandomAccessIterator __i, _RandomAccessIterator __j) { + return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, + _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true); + }); } //------------------------------------------------------------------------ @@ -3408,47 +3523,51 @@ __brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare return std::min_element(__first, __last, __comp); } -template <typename _ForwardIterator, typename _Compare> -_ForwardIterator -__brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp, +template <typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator +__brick_min_element(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, /* __is_vector = */ std::true_type) noexcept { -#if _PSTL_UDR_PRESENT +#if defined(_PSTL_UDR_PRESENT) return __unseq_backend::__simd_min_element(__first, __last - __first, __comp); #else return std::min_element(__first, __last, __comp); #endif } -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> _ForwardIterator -__pattern_min_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp, - _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept +__pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) noexcept { - return __internal::__brick_min_element(__first, __last, __comp, __is_vector); + return __internal::__brick_min_element(__first, __last, __comp, typename _Tag::__is_vector{}); } -template <typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _IsVector> +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> _RandomAccessIterator -__pattern_min_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type) +__pattern_min_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) { if (__first == __last) return __last; - return __internal::__except_handler([&]() { - return __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, __first, - [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, - _RandomAccessIterator __init) -> _RandomAccessIterator { - const _RandomAccessIterator subresult = - __internal::__brick_min_element(__begin, __end, __comp, __is_vector); - return __internal::__cmp_iterators_by_values(__init, subresult, __comp); - }, - [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator { - return __internal::__cmp_iterators_by_values(__it1, __it2, __comp); - }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __par_backend::__parallel_reduce( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, __first, + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, + _RandomAccessIterator __init) -> _RandomAccessIterator + { + const _RandomAccessIterator subresult = + __internal::__brick_min_element(__begin, __end, __comp, _IsVector{}); + return __internal::__cmp_iterators_by_values(__init, subresult, __comp); + }, + [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator + { return __internal::__cmp_iterators_by_values(__it1, __it2, __comp); }); + }); } //------------------------------------------------------------------------ @@ -3463,46 +3582,51 @@ __brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compa return std::minmax_element(__first, __last, __comp); } -template <typename _ForwardIterator, typename _Compare> -std::pair<_ForwardIterator, _ForwardIterator> -__brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp, +template <typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> +__brick_minmax_element(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, /* __is_vector = */ std::true_type) noexcept { -#if _PSTL_UDR_PRESENT +#if defined(_PSTL_UDR_PRESENT) return __unseq_backend::__simd_minmax_element(__first, __last - __first, __comp); #else return std::minmax_element(__first, __last, __comp); #endif } -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> std::pair<_ForwardIterator, _ForwardIterator> -__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp, - _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept +__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) noexcept { - return __internal::__brick_minmax_element(__first, __last, __comp, __is_vector); + return __internal::__brick_minmax_element(__first, __last, __comp, typename _Tag::__is_vector{}); } -template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector> -std::pair<_ForwardIterator, _ForwardIterator> -__pattern_minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp, - _IsVector __is_vector, /* is_parallel = */ std::true_type) +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> +__pattern_minmax_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) { if (__first == __last) return std::make_pair(__first, __first); + using __backend_tag = typename decltype(__tag)::__backend_tag; + return __internal::__except_handler([&]() { - typedef std::pair<_ForwardIterator, _ForwardIterator> _Result; + typedef std::pair<_RandomAccessIterator, _RandomAccessIterator> _Result; return __par_backend::__parallel_reduce( - std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, std::make_pair(__first, __first), - [=](_ForwardIterator __begin, _ForwardIterator __end, _Result __init) -> _Result { - const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, __is_vector); + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, + std::make_pair(__first, __first), + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Result __init) -> _Result + { + const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, _IsVector{}); return std::make_pair( __internal::__cmp_iterators_by_values(__subresult.first, __init.first, __comp), __internal::__cmp_iterators_by_values(__init.second, __subresult.second, std::not_fn(__comp))); }, - [=](_Result __p1, _Result __p2) -> _Result { + [=](_Result __p1, _Result __p2) -> _Result + { return std::make_pair( __internal::__cmp_iterators_by_values(__p1.first, __p2.first, __comp), __internal::__cmp_iterators_by_values(__p2.second, __p1.second, std::not_fn(__comp))); @@ -3518,7 +3642,7 @@ std::pair<_ForwardIterator1, _ForwardIterator2> __mismatch_serial(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) { -#if _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT +#if defined(_PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT) return std::mismatch(__first1, __last1, __first2, __last2, __pred); #else for (; __first1 != __last1 && __first2 != __last2 && __pred(*__first1, *__first2); ++__first1, ++__first2) @@ -3536,38 +3660,40 @@ __brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _Forward return __mismatch_serial(__first1, __last1, __first2, __last2, __pred); } -template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate> -std::pair<_ForwardIterator1, _ForwardIterator2> -__brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> +__brick_mismatch(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::true_type) noexcept { auto __n = std::min(__last1 - __first1, __last2 - __first2); return __unseq_backend::__simd_first(__first1, __n, __first2, std::not_fn(__pred)); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> std::pair<_ForwardIterator1, _ForwardIterator2> -__pattern_mismatch(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Predicate __pred, _IsVector __is_vector, - /* is_parallel = */ std::false_type) noexcept +__pattern_mismatch(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Predicate __pred) noexcept { - return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, __is_vector); + return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Predicate> std::pair<_RandomAccessIterator1, _RandomAccessIterator2> -__pattern_mismatch(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _Predicate __pred, - _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept +__pattern_mismatch(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _Predicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + return __internal::__except_handler([&]() { auto __n = std::min(__last1 - __first1, __last2 - __first2); auto __result = __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, - [__first1, __first2, __pred, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, + [__first1, __first2, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), - __pred, __is_vector) + __pred, _IsVector{}) .first; }, std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true); @@ -3588,10 +3714,11 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __ return std::lexicographical_compare(__first1, __last1, __first2, __last2, __comp); } -template <class _ForwardIterator1, class _ForwardIterator2, class _Compare> +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare> bool -__brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _Compare __comp, /* __is_vector = */ std::true_type) noexcept +__brick_lexicographical_compare(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { if (__first2 == __last2) { // if second sequence is empty @@ -3603,12 +3730,12 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __ } else { - typedef typename std::iterator_traits<_ForwardIterator1>::reference ref_type1; - typedef typename std::iterator_traits<_ForwardIterator2>::reference ref_type2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference ref_type1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference ref_type2; --__last1; --__last2; auto __n = std::min(__last1 - __first1, __last2 - __first2); - std::pair<_ForwardIterator1, _ForwardIterator2> __result = __unseq_backend::__simd_first( + std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __result = __unseq_backend::__simd_first( __first1, __n, __first2, [__comp](const ref_type1 __x, const ref_type2 __y) mutable { return __comp(__x, __y) || __comp(__y, __x); }); @@ -3624,21 +3751,25 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __ } } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> bool -__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, - _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept +__pattern_lexicographical_compare(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) noexcept { - return __internal::__brick_lexicographical_compare(__first1, __last1, __first2, __last2, __comp, __is_vector); + return __internal::__brick_lexicographical_compare(__first1, __last1, __first2, __last2, __comp, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Compare> bool -__pattern_lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, - _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept +__pattern_lexicographical_compare(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + if (__first2 == __last2) { // if second sequence is empty return false; @@ -3649,22 +3780,23 @@ __pattern_lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 _ } else { - typedef typename std::iterator_traits<_ForwardIterator1>::reference _RefType1; - typedef typename std::iterator_traits<_ForwardIterator2>::reference _RefType2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _RefType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _RefType2; --__last1; --__last2; auto __n = std::min(__last1 - __first1, __last2 - __first2); auto __result = __internal::__parallel_find( - std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, - [__first1, __first2, &__comp, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) { - return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), - [&__comp](const _RefType1 __x, const _RefType2 __y) { - return !__comp(__x, __y) && !__comp(__y, __x); - }, - __is_vector) + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, + [__first1, __first2, &__comp](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) + { + return __internal::__brick_mismatch( + __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), + [&__comp](const _RefType1 __x, const _RefType2 __y) + { return !__comp(__x, __y) && !__comp(__y, __x); }, + _IsVector{}) .first; }, - std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true); + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true); if (__result == __last1 && __first2 + (__result - __first1) != __last2) { // if first sequence shorter than second diff --git a/libstdc++-v3/include/pstl/execution_defs.h b/libstdc++-v3/include/pstl/execution_defs.h index 3eca558..522518c 100644 --- a/libstdc++-v3/include/pstl/execution_defs.h +++ b/libstdc++-v3/include/pstl/execution_defs.h @@ -22,88 +22,20 @@ 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{}; - } }; // 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{}; - } }; 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 @@ -135,7 +67,7 @@ struct is_execution_policy<__pstl::execution::unsequenced_policy> : std::true_ty { }; -#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT +#if defined (_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT) template <class _Tp> constexpr bool is_execution_policy_v = __pstl::execution::is_execution_policy<_Tp>::value; #endif @@ -155,6 +87,12 @@ using __enable_if_execution_policy = typename std::enable_if<__pstl::execution::is_execution_policy<typename std::decay<_ExecPolicy>::type>::value, _Tp>::type; #endif + +template <class _IsVector> +struct __serial_tag; +template <class _IsVector> +struct __parallel_tag; + } // namespace __internal } // namespace __pstl diff --git a/libstdc++-v3/include/pstl/execution_impl.h b/libstdc++-v3/include/pstl/execution_impl.h index e0969a1..64f6cc4 100644 --- a/libstdc++-v3/include/pstl/execution_impl.h +++ b/libstdc++-v3/include/pstl/execution_impl.h @@ -20,140 +20,79 @@ namespace __pstl namespace __internal { -using namespace __pstl::execution; +template <typename _IteratorTag, typename... _IteratorTypes> +using __are_iterators_of = std::conjunction< + std::is_base_of<_IteratorTag, typename std::iterator_traits<std::decay_t<_IteratorTypes>>::iterator_category>...>; -/* predicate */ +template <typename... _IteratorTypes> +using __are_random_access_iterators = __are_iterators_of<std::random_access_iterator_tag, _IteratorTypes...>; -template <typename _Tp> -std::false_type __lazy_and(_Tp, std::false_type) -{ - return std::false_type{}; -} - -template <typename _Tp> -inline _Tp -__lazy_and(_Tp __a, std::true_type) -{ - return __a; -} - -template <typename _Tp> -std::true_type __lazy_or(_Tp, std::true_type) -{ - return std::true_type{}; -} - -template <typename _Tp> -inline _Tp -__lazy_or(_Tp __a, std::false_type) -{ - return __a; -} - -/* iterator */ -template <typename _IteratorType, typename... _OtherIteratorTypes> -struct __is_random_access_iterator -{ - static constexpr bool value = __internal::__is_random_access_iterator<_IteratorType>::value && - __internal::__is_random_access_iterator<_OtherIteratorTypes...>::value; - typedef std::integral_constant<bool, value> type; -}; - -template <typename _IteratorType> -struct __is_random_access_iterator<_IteratorType> - : std::is_same<typename std::iterator_traits<_IteratorType>::iterator_category, std::random_access_iterator_tag> +struct __serial_backend_tag { }; - -/* policy */ -template <typename _Policy> -struct __policy_traits +struct __tbb_backend_tag { }; - -template <> -struct __policy_traits<sequenced_policy> +struct __openmp_backend_tag { - typedef std::false_type allow_parallel; - typedef std::false_type allow_unsequenced; - typedef std::false_type allow_vector; }; -template <> -struct __policy_traits<unsequenced_policy> -{ - typedef std::false_type allow_parallel; - typedef std::true_type allow_unsequenced; - typedef std::true_type allow_vector; -}; +#if defined(_PSTL_PAR_BACKEND_TBB) +using __par_backend_tag = __tbb_backend_tag; +#elif defined(_PSTL_PAR_BACKEND_OPENMP) +using __par_backend_tag = __openmp_backend_tag; +#elif defined(_PSTL_PAR_BACKEND_SERIAL) +using __par_backend_tag = __serial_backend_tag; +#else +# error "A parallel backend must be specified"; +#endif -template <> -struct __policy_traits<parallel_policy> +template <class _IsVector> +struct __serial_tag { - typedef std::true_type allow_parallel; - typedef std::false_type allow_unsequenced; - typedef std::false_type allow_vector; + using __is_vector = _IsVector; }; -template <> -struct __policy_traits<parallel_unsequenced_policy> +template <class _IsVector> +struct __parallel_tag { - typedef std::true_type allow_parallel; - typedef std::true_type allow_unsequenced; - typedef std::true_type allow_vector; + using __is_vector = _IsVector; + // backend tag can be change depending on + // TBB availability in the environment + using __backend_tag = __par_backend_tag; }; -template <typename _ExecutionPolicy> -using __collector_t = - typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__collector_type; - -template <typename _ExecutionPolicy> -using __allow_vector = - typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_vector; +template <class _IsVector, class... _IteratorTypes> +using __tag_type = typename std::conditional<__internal::__are_random_access_iterators<_IteratorTypes...>::value, + __parallel_tag<_IsVector>, __serial_tag<_IsVector>>::type; -template <typename _ExecutionPolicy> -using __allow_unsequenced = - typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_unsequenced; - -template <typename _ExecutionPolicy> -using __allow_parallel = - typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_parallel; - -template <typename _ExecutionPolicy, typename... _IteratorTypes> -auto -__is_vectorization_preferred(_ExecutionPolicy&& __exec) - -> decltype(__internal::__lazy_and(__exec.__allow_vector(), - typename __internal::__is_random_access_iterator<_IteratorTypes...>::type())) +template <class... _IteratorTypes> +__serial_tag</*_IsVector = */ std::false_type> +__select_backend(__pstl::execution::sequenced_policy, _IteratorTypes&&...) { - return __internal::__lazy_and(__exec.__allow_vector(), - typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()); + return {}; } -template <typename _ExecutionPolicy, typename... _IteratorTypes> -auto -__is_parallelization_preferred(_ExecutionPolicy&& __exec) - -> decltype(__internal::__lazy_and(__exec.__allow_parallel(), - typename __internal::__is_random_access_iterator<_IteratorTypes...>::type())) +template <class... _IteratorTypes> +__serial_tag<__internal::__are_random_access_iterators<_IteratorTypes...>> +__select_backend(__pstl::execution::unsequenced_policy, _IteratorTypes&&...) { - return __internal::__lazy_and(__exec.__allow_parallel(), - typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()); + return {}; } -template <typename __policy, typename... _IteratorTypes> -struct __prefer_unsequenced_tag +template <class... _IteratorTypes> +__tag_type</*_IsVector = */ std::false_type, _IteratorTypes...> +__select_backend(__pstl::execution::parallel_policy, _IteratorTypes&&...) { - static constexpr bool value = __internal::__allow_unsequenced<__policy>::value && - __internal::__is_random_access_iterator<_IteratorTypes...>::value; - typedef std::integral_constant<bool, value> type; -}; + return {}; +} -template <typename __policy, typename... _IteratorTypes> -struct __prefer_parallel_tag +template <class... _IteratorTypes> +__tag_type<__internal::__are_random_access_iterators<_IteratorTypes...>, _IteratorTypes...> +__select_backend(__pstl::execution::parallel_unsequenced_policy, _IteratorTypes&&...) { - static constexpr bool value = __internal::__allow_parallel<__policy>::value && - __internal::__is_random_access_iterator<_IteratorTypes...>::value; - typedef std::integral_constant<bool, value> type; -}; + return {}; +} } // namespace __internal } // namespace __pstl diff --git a/libstdc++-v3/include/pstl/glue_algorithm_impl.h b/libstdc++-v3/include/pstl/glue_algorithm_impl.h index b16306f..5be45ce 100644 --- a/libstdc++-v3/include/pstl/glue_algorithm_impl.h +++ b/libstdc++-v3/include/pstl/glue_algorithm_impl.h @@ -26,10 +26,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> any_of(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return __pstl::__internal::__pattern_any_of( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_any_of(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __pred); } // [alg.all_of] @@ -56,20 +56,19 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Function> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> for_each(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f) { - __pstl::__internal::__pattern_walk1( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __f, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __f); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> for_each_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, _Function __f) { - return __pstl::__internal::__pattern_walk1_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, __f, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_walk1_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + __f); } // [alg.find] @@ -78,10 +77,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> find_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return __pstl::__internal::__pattern_find_if( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_find_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> @@ -105,12 +104,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera find_end(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_find_end( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_end(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __s_first, __s_last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -128,12 +125,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera find_first_of(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_find_first_of( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_first_of(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __s_first, __s_last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -150,23 +145,20 @@ template <class _ExecutionPolicy, class _ForwardIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; - return __pstl::__internal::__pattern_adjacent_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, std::equal_to<_ValueType>(), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - /*first_semantic*/ false); + return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, std::equal_to<_ValueType>(), /*first_semantic*/ false); } template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_adjacent_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - /*first_semantic*/ false); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pred, /*first_semantic*/ false); } // [alg.count] @@ -179,12 +171,11 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, typename iterator_traits<_ForwardIterator>::difference_type> count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; - return __pstl::__internal::__pattern_count( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__value](const _ValueType& __x) { return __value == __x; }, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + return __pstl::__internal::__pattern_count(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__value](const _ValueType& __x) { return __value == __x; }); } template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> @@ -192,10 +183,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, typename iterator_traits<_ForwardIterator>::difference_type> count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - return __pstl::__internal::__pattern_count( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_count(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __pred); } // [alg.search] @@ -205,12 +195,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_search( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_search(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __s_first, __s_last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -226,10 +214,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera search_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_search_n( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __count, __value, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_search_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __count, __value, __pred); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> @@ -247,34 +235,28 @@ template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterato __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result) { - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) { - return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, + [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) + { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); }); } template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> copy_n(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _Size __n, _ForwardIterator2 __result) { - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__pattern_walk2_brick_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, - [__is_vector](_ForwardIterator1 __begin, _Size __sz, _ForwardIterator2 __res) { - return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector); - }, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, + [](_ForwardIterator1 __begin, _Size __sz, _ForwardIterator2 __res) + { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); }); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> @@ -282,12 +264,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _Predicate __pred) { - return __pstl::__internal::__pattern_copy_if( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_copy_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __result, __pred); } // [alg.swap] @@ -299,16 +279,16 @@ swap_ranges(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardItera { typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2; - return __pstl::__internal::__pattern_walk2( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, - [](_ReferenceType1 __x, _ReferenceType2 __y) { - using std::swap; - swap(__x, __y); - }, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, + [](_ReferenceType1 __x, _ReferenceType2 __y) + { + using std::swap; + swap(__x, __y); + }); } // [alg.transform] @@ -320,13 +300,12 @@ transform(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator { typedef typename iterator_traits<_ForwardIterator1>::reference _InputType; typedef typename iterator_traits<_ForwardIterator2>::reference _OutputType; - return __pstl::__internal::__pattern_walk2( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [__op](_InputType __x, _OutputType __y) mutable { __y = __op(__x); }, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __result, + [__op](_InputType __x, _OutputType __y) mutable { __y = __op(__x); }); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator, @@ -338,13 +317,12 @@ transform(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterato typedef typename iterator_traits<_ForwardIterator1>::reference _Input1Type; typedef typename iterator_traits<_ForwardIterator2>::reference _Input2Type; typedef typename iterator_traits<_ForwardIterator>::reference _OutputType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + return __pstl::__internal::__pattern_walk3( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __result, - [__op](_Input1Type __x, _Input2Type __y, _OutputType __z) mutable { __z = __op(__x, __y); }, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __result, + [__op](_Input1Type __x, _Input2Type __y, _OutputType __z) mutable { __z = __op(__x, __y); }); } // [alg.replace] @@ -355,16 +333,17 @@ replace_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator const _Tp& __new_value) { typedef typename iterator_traits<_ForwardIterator>::reference _ElementType; - __pstl::__internal::__pattern_walk1( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__pred, &__new_value](_ElementType __elem) { - if (__pred(__elem)) - { - __elem = __new_value; - } - }, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__pred, &__new_value](_ElementType __elem) + { + if (__pred(__elem)) + { + __elem = __new_value; + } + }); } template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> @@ -383,13 +362,12 @@ replace_copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIt { typedef typename iterator_traits<_ForwardIterator1>::reference _InputType; typedef typename iterator_traits<_ForwardIterator2>::reference _OutputType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + return __pstl::__internal::__pattern_walk2( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [__pred, &__new_value](_InputType __x, _OutputType __y) mutable { __y = __pred(__x) ? __new_value : __x; }, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, + [__pred, &__new_value](_InputType __x, _OutputType __y) mutable { __y = __pred(__x) ? __new_value : __x; }); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> @@ -407,10 +385,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - __pstl::__internal::__pattern_fill( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __value, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_fill(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __value); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> @@ -420,10 +398,10 @@ fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, const if (__count <= 0) return __first; - return __pstl::__internal::__pattern_fill_n( - std::forward<_ExecutionPolicy>(__exec), __first, __count, __value, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_fill_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __count, __value); } // [alg.generate] @@ -431,10 +409,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Generator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) { - __pstl::__internal::__pattern_generate( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __g, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_generate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __g); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Generator> @@ -444,10 +422,10 @@ generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, _ if (__count <= 0) return __first; - return __pstl::__internal::__pattern_generate_n( - std::forward<_ExecutionPolicy>(__exec), __first, __count, __g, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_generate_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __count, __g); } // [alg.remove] @@ -473,10 +451,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { - return __pstl::__internal::__pattern_remove_if( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_remove_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> @@ -493,10 +471,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_unique( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_unique(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __pred); } template <class _ExecutionPolicy, class _ForwardIterator> @@ -511,12 +489,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera unique_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_unique_copy( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_unique_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __result, __pred); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -532,10 +508,9 @@ template <class _ExecutionPolicy, class _BidirectionalIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last) { - __pstl::__internal::__pattern_reverse( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_reverse(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last); } template <class _ExecutionPolicy, class _BidirectionalIterator, class _ForwardIterator> @@ -543,12 +518,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera reverse_copy(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _ForwardIterator __d_first) { - return __pstl::__internal::__pattern_reverse_copy( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator, _ForwardIterator>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator, _ForwardIterator>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_reverse_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __d_first); } // [alg.rotate] @@ -557,10 +530,10 @@ template <class _ExecutionPolicy, class _ForwardIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { - return __pstl::__internal::__pattern_rotate( - std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_rotate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __middle, __last); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -568,12 +541,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera rotate_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __middle, _ForwardIterator1 __last, _ForwardIterator2 __result) { - return __pstl::__internal::__pattern_rotate_copy( - std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __result, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_rotate_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __middle, __last, __result); } // [alg.partitions] @@ -582,20 +553,19 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { - return __pstl::__internal::__pattern_is_partitioned( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_is_partitioned(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { - return __pstl::__internal::__pattern_partition( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_partition(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pred); } template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> @@ -603,10 +573,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Bidirectiona stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred) { - return __pstl::__internal::__pattern_stable_partition( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_stable_partition(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __last, __pred); } template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardIterator1, class _ForwardIterator2, @@ -615,12 +584,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_Fo partition_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _ForwardIterator1 __out_true, _ForwardIterator2 __out_false, _UnaryPredicate __pred) { - return __pstl::__internal::__pattern_partition_copy( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __out_true, __out_false, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator, _ForwardIterator1, - _ForwardIterator2>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator, _ForwardIterator1, - _ForwardIterator2>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __out_true, __out_false); + + return __pstl::__internal::__pattern_partition_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __out_true, __out_false, __pred); } // [alg.sort] @@ -629,12 +596,11 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; - return __pstl::__internal::__pattern_sort( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - typename std::is_move_constructible<_InputType>::type()); + return __pstl::__internal::__pattern_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __comp, typename std::is_move_constructible<_InputType>::type()); } template <class _ExecutionPolicy, class _RandomAccessIterator> @@ -651,10 +617,10 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - return __pstl::__internal::__pattern_stable_sort( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_stable_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __comp); } template <class _ExecutionPolicy, class _RandomAccessIterator> @@ -672,12 +638,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_Fo mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) { - return __pstl::__internal::__pattern_mismatch( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __pred, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_mismatch(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __last2, __pred); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> @@ -714,10 +678,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __p) { - return __pstl::__internal::__pattern_equal( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __p, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __p); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -732,10 +696,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __p) { - return __pstl::__internal::__pattern_equal( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __p, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __last2, __p); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -751,17 +715,14 @@ template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterato __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first) { - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, - [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) { - return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector); - }, - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, + [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) + { return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector{}); }); } // [partial.sort] @@ -771,10 +732,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> partial_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp) { - __pstl::__internal::__pattern_partial_sort( - std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_partial_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __middle, __last, __comp); } template <class _ExecutionPolicy, class _RandomAccessIterator> @@ -793,12 +754,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccess partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp) { - return __pstl::__internal::__pattern_partial_sort_copy( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator, _RandomAccessIterator>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator, _RandomAccessIterator>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_partial_sort_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __last, __d_first, __d_last, __comp); } template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator> @@ -815,11 +774,11 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - const _ForwardIterator __res = __pstl::__internal::__pattern_adjacent_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__reorder_pred<_Compare>(__comp), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - /*first_semantic*/ false); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + const _ForwardIterator __res = + __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*first_semantic*/ false); return __res == __last ? __last : std::next(__res); } @@ -835,12 +794,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - return __pstl::__internal::__pattern_adjacent_find( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - __pstl::__internal::__reorder_pred<_Compare>(__comp), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - /*or_semantic*/ true) == __last; + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*or_semantic*/ true) == __last; } template <class _ExecutionPolicy, class _ForwardIterator> @@ -858,12 +815,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera merge(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __d_first, _Compare __comp) { - return __pstl::__internal::__pattern_merge( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __d_first); + + return __pstl::__internal::__pattern_merge(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __last2, __d_first, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> @@ -880,10 +835,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> inplace_merge(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { - __pstl::__internal::__pattern_inplace_merge( - std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_inplace_merge(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __middle, __last, __comp); } template <class _ExecutionPolicy, class _BidirectionalIterator> @@ -902,12 +857,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) { - return __pstl::__internal::__pattern_includes( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_includes(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __last2, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> @@ -926,12 +879,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp) { - return __pstl::__internal::__pattern_set_union( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_union(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, + __last1, __first2, __last2, __result, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> @@ -951,12 +902,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp) { - return __pstl::__internal::__pattern_set_intersection( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_intersection(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first1, __last1, __first2, __last2, __result, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> @@ -976,12 +925,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp) { - return __pstl::__internal::__pattern_set_difference( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_difference(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first1, __last1, __first2, __last2, __result, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> @@ -1002,12 +949,10 @@ set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + return __pstl::__internal::__pattern_set_symmetric_difference( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2, - _ForwardIterator>(__exec)); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> @@ -1024,10 +969,10 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - return __pstl::__internal::__pattern_is_heap_until( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_is_heap_until(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __comp); } template <class _ExecutionPolicy, class _RandomAccessIterator> @@ -1059,10 +1004,9 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - return __pstl::__internal::__pattern_min_element( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_min_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __comp); } template <class _ExecutionPolicy, class _ForwardIterator> @@ -1094,10 +1038,9 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - return __pstl::__internal::__pattern_minmax_element( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_minmax_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __comp); } template <class _ExecutionPolicy, class _ForwardIterator> @@ -1115,10 +1058,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) { - __pstl::__internal::__pattern_nth_element( - std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_nth_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __nth, + __last, __comp); } template <class _ExecutionPolicy, class _RandomAccessIterator> @@ -1137,12 +1080,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) { - return __pstl::__internal::__pattern_lexicographical_compare( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_lexicographical_compare(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first1, __last1, __first2, __last2, __comp); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> diff --git a/libstdc++-v3/include/pstl/glue_execution_defs.h b/libstdc++-v3/include/pstl/glue_execution_defs.h index 24ede33..e7b36c7 100644 --- a/libstdc++-v3/include/pstl/glue_execution_defs.h +++ b/libstdc++-v3/include/pstl/glue_execution_defs.h @@ -18,10 +18,10 @@ namespace std { // Type trait using __pstl::execution::is_execution_policy; -#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT -# if __INTEL_COMPILER -template <class T> -constexpr bool is_execution_policy_v = is_execution_policy<T>::value; +#if defined(_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT) +# if defined(__INTEL_COMPILER) +template <class _Tp> +constexpr bool is_execution_policy_v = is_execution_policy<_Tp>::value; # else using __pstl::execution::is_execution_policy_v; # endif diff --git a/libstdc++-v3/include/pstl/glue_memory_impl.h b/libstdc++-v3/include/pstl/glue_memory_impl.h index ea462e9..7850605 100644 --- a/libstdc++-v3/include/pstl/glue_memory_impl.h +++ b/libstdc++-v3/include/pstl/glue_memory_impl.h @@ -13,6 +13,8 @@ #include "utils.h" #include "algorithm_fwd.h" +#include "execution_impl.h" + namespace std { @@ -27,28 +29,25 @@ uninitialized_copy(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIter typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { - return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) + { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); }); }, - [&]() { - return __pstl::__internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first, __last, - __result, - [](_ReferenceType1 __val1, _ReferenceType2 __val2) { - ::new (std::addressof(__val2)) _ValueType2(__val1); - }, - __is_vector, __is_parallel); + [&]() + { + return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) + { ::new (std::addressof(__val2)) _ValueType2(__val1); }); }); } @@ -61,27 +60,25 @@ uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __ typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk2_brick_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, - [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { - return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) + { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); }); }, - [&]() { - return __pstl::__internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, - [](_ReferenceType1 __val1, _ReferenceType2 __val2) { - ::new (std::addressof(__val2)) _ValueType2(__val1); - }, - __is_vector, __is_parallel); + [&]() + { + return __pstl::__internal::__pattern_walk2_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __n, __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) + { ::new (std::addressof(__val2)) _ValueType2(__val1); }); }); } @@ -96,28 +93,25 @@ uninitialized_move(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIter typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk2_brick( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { - return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) + { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); }); }, - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk2( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, - [](_ReferenceType1 __val1, _ReferenceType2 __val2) { - ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); - }, - __is_vector, __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) + { ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); }); }); } @@ -130,28 +124,25 @@ uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __ typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk2_brick_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, - [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { - return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) + { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); }); }, - [&]() { - return __pstl::__internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, - [](_ReferenceType1 __val1, _ReferenceType2 __val2) { - ::new (std::addressof(__val2)) - _ValueType2(std::move(__val1)); - }, - __is_vector, __is_parallel); + [&]() + { + return __pstl::__internal::__pattern_walk2_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) + { ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); }); }); } @@ -164,26 +155,24 @@ uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forward typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; __pstl::__internal::__invoke_if_else( std::is_arithmetic<_ValueType>(), - [&]() { + [&]() + { __pstl::__internal::__pattern_walk_brick( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__value, &__is_vector](_ForwardIterator __begin, _ForwardIterator __end) { - __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__value](_ForwardIterator __begin, _ForwardIterator __end) + { __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector{}); }); }, - [&]() { - __pstl::__internal::__pattern_walk1( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }, __is_vector, - __is_parallel); + [&]() + { + __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [&__value](_ReferenceType __val) + { ::new (std::addressof(__val)) _ValueType(__value); }); }); } @@ -194,26 +183,24 @@ uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::is_arithmetic<_ValueType>(), - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk_brick_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, - [&__value, &__is_vector](_ForwardIterator __begin, _Size __count) { - return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector); - }, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + [&__value](_ForwardIterator __begin, _Size __count) + { return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector{}); }); }, - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk1_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, - [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }, __is_vector, - __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }); }); } @@ -226,16 +213,15 @@ destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __ typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); - __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), [&]() { - __pstl::__internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector, - __is_parallel); - }); + __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), + [&]() + { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [](_ReferenceType __val) { __val.~_ValueType(); }); + }); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size> @@ -245,17 +231,15 @@ destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); return __pstl::__internal::__invoke_if_else( std::is_trivially_destructible<_ValueType>(), [&]() { return std::next(__first, __n); }, - [&]() { - return __pstl::__internal::__pattern_walk1_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, - [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector, - __is_parallel); + [&]() + { + return __pstl::__internal::__pattern_walk1_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __n, + [](_ReferenceType __val) { __val.~_ValueType(); }); }); } @@ -268,16 +252,15 @@ uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __fi typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); - __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(), [&]() { - __pstl::__internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }, - __is_vector, __is_parallel); - }); + __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(), + [&]() + { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }); + }); } template <class _ExecutionPolicy, class _ForwardIterator, class _Size> @@ -287,17 +270,15 @@ uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __ typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); return __pstl::__internal::__invoke_if_else( std::is_trivial<_ValueType>(), [&]() { return std::next(__first, __n); }, - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk1_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, - [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }, __is_vector, __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }); }); } @@ -310,25 +291,24 @@ uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __firs typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; __pstl::__internal::__invoke_if_else( std::is_trivial<_ValueType>(), - [&]() { - __pstl::__internal::__pattern_walk_brick(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__is_vector](_ForwardIterator __begin, _ForwardIterator __end) { - __pstl::__internal::__brick_fill(__begin, __end, _ValueType(), - __is_vector); - }, - __is_parallel); + [&]() + { + __pstl::__internal::__pattern_walk_brick( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [](_ForwardIterator __begin, _ForwardIterator __end) + { __pstl::__internal::__brick_fill(__begin, __end, _ValueType(), __is_vector{}); }); }, - [&]() { - __pstl::__internal::__pattern_walk1( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }, __is_vector, __is_parallel); + [&]() + { + __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [](_ReferenceType __val) + { ::new (std::addressof(__val)) _ValueType(); }); }); } @@ -339,25 +319,24 @@ uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __fi typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; - const auto __is_parallel = - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); - const auto __is_vector = - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; return __pstl::__internal::__invoke_if_else( std::is_trivial<_ValueType>(), - [&]() { - return __pstl::__internal::__pattern_walk_brick_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, - [__is_vector](_ForwardIterator __begin, _Size __count) { - return __pstl::__internal::__brick_fill_n( - __begin, __count, _ValueType(), __is_vector); - }, - __is_parallel); + [&]() + { + return __pstl::__internal::__pattern_walk_brick_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + [](_ForwardIterator __begin, _Size __count) + { return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(), __is_vector{}); }); }, - [&]() { + [&]() + { return __pstl::__internal::__pattern_walk1_n( - std::forward<_ExecutionPolicy>(__exec), __first, __n, - [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }, __is_vector, __is_parallel); + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, + [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }); }); } diff --git a/libstdc++-v3/include/pstl/glue_numeric_impl.h b/libstdc++-v3/include/pstl/glue_numeric_impl.h index 9db64b5..490175c 100644 --- a/libstdc++-v3/include/pstl/glue_numeric_impl.h +++ b/libstdc++-v3/include/pstl/glue_numeric_impl.h @@ -54,14 +54,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp> transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType; - return __pstl::__internal::__pattern_transform_reduce( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, std::plus<_InputType>(), - std::multiplies<_InputType>(), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first1, __last1, __first2, __init, std::plus<_InputType>(), + std::multiplies<_InputType>()); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, @@ -70,12 +68,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp> transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2) { - return __pstl::__internal::__pattern_transform_reduce( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, __binary_op1, __binary_op2, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first1, __last1, __first2, __init, __binary_op1, + __binary_op2); } template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation> @@ -83,10 +79,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp> transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __unary_op) { - return __pstl::__internal::__pattern_transform_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op, __unary_op, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __last, __init, __binary_op, __unary_op); } // [exclusive.scan] @@ -96,12 +91,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + using namespace __pstl; - return __internal::__pattern_transform_scan( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init, - std::plus<_Tp>(), /*inclusive=*/std::false_type(), - __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec), - __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec)); + return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __result, __pstl::__internal::__no_op(), __init, std::plus<_Tp>(), + /*inclusive=*/std::false_type()); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation> @@ -109,12 +104,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + using namespace __pstl; - return __internal::__pattern_transform_scan( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init, - __binary_op, /*inclusive=*/std::false_type(), - __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec), - __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec)); + return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + __result, __pstl::__internal::__no_op(), __init, __binary_op, + /*inclusive=*/std::false_type()); } // [inclusive.scan] @@ -156,13 +151,11 @@ transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __unary_op) { - return __pstl::__internal::__pattern_transform_scan( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op, - /*inclusive=*/std::false_type(), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __result, __unary_op, __init, __binary_op, + /*inclusive=*/std::false_type()); } // [transform.inclusive.scan] @@ -174,13 +167,11 @@ transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op, _Tp __init) { - return __pstl::__internal::__pattern_transform_scan( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op, - /*inclusive=*/std::true_type(), - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, + __last, __result, __unary_op, __init, __binary_op, + /*inclusive=*/std::true_type()); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryOperation, @@ -213,12 +204,10 @@ adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _Forwa if (__first == __last) return __d_first; - return __pstl::__internal::__pattern_adjacent_difference( - std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __op, - __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec), - __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>( - __exec)); + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_adjacent_difference(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), + __first, __last, __d_first, __op); } template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> diff --git a/libstdc++-v3/include/pstl/memory_impl.h b/libstdc++-v3/include/pstl/memory_impl.h index be5a103..8cb32d0 100644 --- a/libstdc++-v3/include/pstl/memory_impl.h +++ b/libstdc++-v3/include/pstl/memory_impl.h @@ -36,13 +36,13 @@ __brick_uninitialized_move(_ForwardIterator __first, _ForwardIterator __last, _O return __result; } -template <typename _ForwardIterator, typename _OutputIterator> +template <typename _RandomAccessIterator, typename _OutputIterator> _OutputIterator -__brick_uninitialized_move(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_uninitialized_move(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, /*vector=*/std::true_type) noexcept { using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; - using _ReferenceType1 = typename std::iterator_traits<_ForwardIterator>::reference; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; return __unseq_backend::__simd_walk_2( @@ -60,12 +60,12 @@ __brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::false_type) __first->~_ValueType(); } -template <typename _Iterator> +template <typename _RandomAccessIterator> void -__brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::true_type) noexcept +__brick_destroy(_RandomAccessIterator __first, _RandomAccessIterator __last, /*vector*/ std::true_type) noexcept { - using _ValueType = typename std::iterator_traits<_Iterator>::value_type; - using _ReferenceType = typename std::iterator_traits<_Iterator>::reference; + using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type; + using _ReferenceType = typename std::iterator_traits<_RandomAccessIterator>::reference; __unseq_backend::__simd_walk_1(__first, __last - __first, [](_ReferenceType __x) { __x.~_ValueType(); }); } @@ -87,13 +87,13 @@ __brick_uninitialized_copy(_ForwardIterator __first, _ForwardIterator __last, _O return __result; } -template <typename _ForwardIterator, typename _OutputIterator> +template <typename _RandomAccessIterator, typename _OutputIterator> _OutputIterator -__brick_uninitialized_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_uninitialized_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, /*vector=*/std::true_type) noexcept { using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; - using _ReferenceType1 = typename std::iterator_traits<_ForwardIterator>::reference; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; return __unseq_backend::__simd_walk_2( diff --git a/libstdc++-v3/include/pstl/numeric_fwd.h b/libstdc++-v3/include/pstl/numeric_fwd.h index d92cacb..e98e3b1 100644 --- a/libstdc++-v3/include/pstl/numeric_fwd.h +++ b/libstdc++-v3/include/pstl/numeric_fwd.h @@ -22,9 +22,10 @@ namespace __internal // transform_reduce (version with two binary functions, according to draft N4659) //------------------------------------------------------------------------ -template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2> -_Tp __brick_transform_reduce(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp, _BinaryOperation1, - _BinaryOperation2, +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1, + class _BinaryOperation2> +_Tp __brick_transform_reduce(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _Tp, + _BinaryOperation1, _BinaryOperation2, /*__is_vector=*/std::true_type) noexcept; template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2> @@ -32,45 +33,41 @@ _Tp __brick_transform_reduce(_ForwardIterator1, _ForwardIterator1, _ForwardItera _BinaryOperation2, /*__is_vector=*/std::false_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, - class _BinaryOperation2, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, + class _BinaryOperation1, class _BinaryOperation2> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp, - _BinaryOperation1, _BinaryOperation2, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp, + _BinaryOperation1, _BinaryOperation2) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, - class _BinaryOperation1, class _BinaryOperation2, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Tp, class _BinaryOperation1, class _BinaryOperation2> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, - _Tp, _BinaryOperation1, _BinaryOperation2, _IsVector __is_vector, - /*is_parallel=*/std::true_type); +__pattern_transform_reduce(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, + _RandomAccessIterator1, _RandomAccessIterator2, _Tp, _BinaryOperation1, _BinaryOperation2); //------------------------------------------------------------------------ // transform_reduce (version with unary and binary functions) //------------------------------------------------------------------------ -template <class _ForwardIterator, class _Tp, class _UnaryOperation, class _BinaryOperation> -_Tp __brick_transform_reduce(_ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, _UnaryOperation, +template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation> +_Tp __brick_transform_reduce(_RandomAccessIterator, _RandomAccessIterator, _Tp, _BinaryOperation, _UnaryOperation, /*is_vector=*/std::true_type) noexcept; template <class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation> _Tp __brick_transform_reduce(_ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, _UnaryOperation, /*is_vector=*/std::false_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, + class _UnaryOperation> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, - _UnaryOperation, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, + _UnaryOperation) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp, class _BinaryOperation, + class _UnaryOperation> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, - _UnaryOperation, _IsVector, - /*is_parallel=*/std::true_type); +__pattern_transform_reduce(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _Tp, _BinaryOperation, _UnaryOperation); //------------------------------------------------------------------------ // transform_exclusive_scan @@ -83,29 +80,28 @@ std::pair<_OutputIterator, _Tp> __brick_transform_scan(_ForwardIterator, _Forwar _UnaryOperation, _Tp, _BinaryOperation, /*Inclusive*/ std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> -std::pair<_OutputIterator, _Tp> __brick_transform_scan(_ForwardIterator, _ForwardIterator, _OutputIterator, +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +std::pair<_OutputIterator, _Tp> __brick_transform_scan(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _UnaryOperation, _Tp, _BinaryOperation, /*Inclusive*/ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, + class _Tp, class _BinaryOperation, class _Inclusive> _OutputIterator -__pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryOperation, _Tp, - _BinaryOperation, _Inclusive, _IsVector, - /*is_parallel=*/std::false_type) noexcept; +__pattern_transform_scan(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryOperation, + _Tp, _BinaryOperation, _Inclusive) noexcept; -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type -__pattern_transform_scan(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator, - _UnaryOperation, _Tp, _BinaryOperation, _Inclusive, _IsVector, /*is_parallel=*/std::true_type); +__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&&, _RandomAccessIterator, + _RandomAccessIterator, _OutputIterator, _UnaryOperation, _Tp, _BinaryOperation, _Inclusive); -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type -__pattern_transform_scan(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator, - _UnaryOperation, _Tp, _BinaryOperation, _Inclusive, _IsVector, /*is_parallel=*/std::true_type); +__pattern_transform_scan(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, + _OutputIterator, _UnaryOperation, _Tp, _BinaryOperation, _Inclusive); //------------------------------------------------------------------------ // adjacent_difference @@ -115,20 +111,20 @@ template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation> _OutputIterator __brick_adjacent_difference(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation, /*is_vector*/ std::false_type) noexcept; -template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation> -_OutputIterator __brick_adjacent_difference(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation, +template <class _RandomAccessIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __brick_adjacent_difference(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, + _BinaryOperation, /*is_vector*/ std::true_type) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation> _OutputIterator -__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation, - _IsVector, /*is_parallel*/ std::false_type) noexcept; +__pattern_adjacent_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, + _BinaryOperation) noexcept; -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _BinaryOperation> _OutputIterator -__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation, +__pattern_adjacent_difference(_ExecutionPolicy&&, _OutputIterator, _OutputIterator, _OutputIterator, _BinaryOperation, _IsVector, /*is_parallel*/ std::true_type); } // namespace __internal diff --git a/libstdc++-v3/include/pstl/numeric_impl.h b/libstdc++-v3/include/pstl/numeric_impl.h index 0b02bcf..7ba83ee 100644 --- a/libstdc++-v3/include/pstl/numeric_impl.h +++ b/libstdc++-v3/include/pstl/numeric_impl.h @@ -38,50 +38,56 @@ __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, return std::inner_product(__first1, __last1, __first2, __init, __binary_op1, __binary_op2); } -template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2> +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1, + class _BinaryOperation2> _Tp -__brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init, - _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2, +__brick_transform_reduce(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2, /*is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; return __unseq_backend::__simd_transform_reduce( __last1 - __first1, __init, __binary_op1, [=, &__binary_op2](_DifferenceType __i) { return __binary_op2(__first1[__i], __first2[__i]); }); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, - class _BinaryOperation2, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, + class _BinaryOperation1, class _BinaryOperation2> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, - _BinaryOperation2 __binary_op2, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept + _BinaryOperation2 __binary_op2) noexcept { - return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2, __is_vector); + return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, - class _BinaryOperation1, class _BinaryOperation2, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _Tp, class _BinaryOperation1, class _BinaryOperation2> _Tp -__pattern_transform_reduce(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, - _BinaryOperation2 __binary_op2, _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2) { - return __internal::__except_handler([&]() { - return __par_backend::__parallel_transform_reduce( - std::forward<_ExecutionPolicy>(__exec), __first1, __last1, - [__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable { - return __binary_op2(*__i, *(__first2 + (__i - __first1))); - }, - __init, - __binary_op1, // Combine - [__first1, __first2, __binary_op1, __binary_op2, - __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j, _Tp __init) -> _Tp { - return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, __binary_op1, - __binary_op2, __is_vector); - }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __par_backend::__parallel_transform_reduce( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, + [__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable + { return __binary_op2(*__i, *(__first2 + (__i - __first1))); }, + __init, + __binary_op1, // Combine + [__first1, __first2, __binary_op1, __binary_op2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j, + _Tp __init) -> _Tp + { + return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, + __binary_op1, __binary_op2, _IsVector{}); + }); + }); } //------------------------------------------------------------------------ @@ -96,42 +102,47 @@ __brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp return std::transform_reduce(__first, __last, __init, __binary_op, __unary_op); } -template <class _ForwardIterator, class _Tp, class _UnaryOperation, class _BinaryOperation> +template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation> _Tp -__brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op, - _UnaryOperation __unary_op, /*is_vector=*/std::true_type) noexcept +__brick_transform_reduce(_RandomAccessIterator __first, _RandomAccessIterator __last, _Tp __init, + _BinaryOperation __binary_op, _UnaryOperation __unary_op, + /*is_vector=*/std::true_type) noexcept { - typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; return __unseq_backend::__simd_transform_reduce( __last - __first, __init, __binary_op, [=, &__unary_op](_DifferenceType __i) { return __unary_op(__first[__i]); }); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, + class _UnaryOperation> _Tp -__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, - _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector, - /*is_parallel=*/std::false_type) noexcept +__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, + _BinaryOperation __binary_op, _UnaryOperation __unary_op) noexcept { - return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, __is_vector); + return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, + typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation, - class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp, class _BinaryOperation, + class _UnaryOperation> _Tp -__pattern_transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, - _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector, - /*is_parallel=*/std::true_type) +__pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Tp __init, _BinaryOperation __binary_op, + _UnaryOperation __unary_op) { - return __internal::__except_handler([&]() { - return __par_backend::__parallel_transform_reduce( - std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__unary_op](_ForwardIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op, - [__unary_op, __binary_op, __is_vector](_ForwardIterator __i, _ForwardIterator __j, _Tp __init) { - return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, __is_vector); - }); - }); + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler( + [&]() + { + return __par_backend::__parallel_transform_reduce( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op, + [__unary_op, __binary_op](_RandomAccessIterator __i, _RandomAccessIterator __j, _Tp __init) { + return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, _IsVector{}); + }); + }); } //------------------------------------------------------------------------ @@ -157,9 +168,9 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu } // Inclusive form -template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> std::pair<_OutputIterator, _Tp> -__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, /*Inclusive*/ std::true_type, /*is_vector=*/std::false_type) noexcept { @@ -179,14 +190,14 @@ using is_arithmetic_udop = std::integral_constant<bool, std::is_arithmetic<_Tp>: // [restriction] - T shall be DefaultConstructible. // [violation] - default ctor of T shall set the identity value for binary_op. -template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation, +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<!is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type -__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive, /*is_vector=*/std::true_type) noexcept { -#if (_PSTL_UDS_PRESENT) +#if defined(_PSTL_UDS_PRESENT) return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, __init, __binary_op, _Inclusive()); #else @@ -196,10 +207,10 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu #endif } -template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation, +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type -__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, +__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive, /*is_vector=*/std::true_type) noexcept { @@ -207,55 +218,62 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu /*is_vector=*/std::false_type()); } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, + class _Tp, class _BinaryOperation, class _Inclusive> _OutputIterator -__pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, +__pattern_transform_scan(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, - _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept + _Inclusive) noexcept { return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(), - __is_vector) + typename _Tag::__is_vector{}) .first; } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type -__pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, - _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; - return __internal::__except_handler([&]() { - __par_backend::__parallel_transform_scan( - std::forward<_ExecutionPolicy>(__exec), __last - __first, - [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init, - __binary_op, - [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) { - // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan. - return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op, - __unary_op, - /*__is_vector*/ std::false_type()); - }, - [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __j, - _Tp __init) { - return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op, - __init, __binary_op, _Inclusive(), __is_vector) - .second; - }); - return __result + (__last - __first); - }); + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_transform_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __last - __first, + [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init, + __binary_op, + [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) + { + // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan. + return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op, + __unary_op, + /*__is_vector*/ std::false_type()); + }, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init) + { + return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op, + __init, __binary_op, _Inclusive(), _IsVector{}) + .second; + }); + return __result + (__last - __first); + }); } -template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, - class _BinaryOperation, class _Inclusive, class _IsVector> +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, + class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive> typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type -__pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, - _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, - _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type) +__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, + _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; _DifferenceType __n = __last - __first; @@ -263,26 +281,31 @@ __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __firs { return __result; } - return __internal::__except_handler([&]() { - __par_backend::__parallel_strict_scan( - std::forward<_ExecutionPolicy>(__exec), __n, __init, - [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __len) { - return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i, - __unary_op, _Tp{}, __binary_op, _Inclusive(), __is_vector) - .second; - }, - __binary_op, - [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) { - return *(std::transform(__result + __i, __result + __i + __len, __result + __i, - [&__initial, &__binary_op](const _Tp& __x) { - _PSTL_PRAGMA_FORCEINLINE - return __binary_op(__initial, __x); - }) - - 1); - }, - [](_Tp) {}); - return __result + (__last - __first); - }); + return __internal::__except_handler( + [&]() + { + __par_backend::__parallel_strict_scan( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, __init, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len) + { + return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i, + __unary_op, _Tp{}, __binary_op, _Inclusive(), _IsVector{}) + .second; + }, + __binary_op, + [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) + { + return *(std::transform(__result + __i, __result + __i + __len, __result + __i, + [&__initial, &__binary_op](const _Tp& __x) + { + _PSTL_PRAGMA_FORCEINLINE + return __binary_op(__initial, __x); + }) - + 1); + }, + [](_Tp) {}); + return __result + (__last - __first); + }); } //------------------------------------------------------------------------ @@ -297,15 +320,16 @@ __brick_adjacent_difference(_ForwardIterator __first, _ForwardIterator __last, _ return std::adjacent_difference(__first, __last, __d_first, __op); } -template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation> -_ForwardIterator2 -__brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first, - _BinaryOperation __op, /*is_vector=*/std::true_type) noexcept +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryOperation> +_RandomAccessIterator2 +__brick_adjacent_difference(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, _BinaryOperation __op, + /*is_vector=*/std::true_type) noexcept { _PSTL_ASSERT(__first != __last); - typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1; - typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; auto __n = __last - __first; *__d_first = *__first; @@ -314,37 +338,38 @@ __brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1 __last, [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__x, __y); }); } -template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation, - class _IsVector> +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation> _OutputIterator -__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, - _OutputIterator __d_first, _BinaryOperation __op, _IsVector __is_vector, - /*is_parallel*/ std::false_type) noexcept +__pattern_adjacent_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __d_first, _BinaryOperation __op) noexcept { - return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, __is_vector); + return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, typename _Tag::__is_vector{}); } -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation, - class _IsVector> -_ForwardIterator2 -__pattern_adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, - _ForwardIterator2 __d_first, _BinaryOperation __op, _IsVector __is_vector, - /*is_parallel=*/std::true_type) +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, + class _BinaryOperation> +_RandomAccessIterator2 +__pattern_adjacent_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, _BinaryOperation __op) { _PSTL_ASSERT(__first != __last); - typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1; - typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2; + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + using __backend_tag = typename decltype(__tag)::__backend_tag; *__d_first = *__first; - __par_backend::__parallel_for( - std::forward<_ExecutionPolicy>(__exec), __first, __last - 1, - [&__op, __is_vector, __d_first, __first](_ForwardIterator1 __b, _ForwardIterator1 __e) { - _ForwardIterator2 __d_b = __d_first + (__b - __first); - __internal::__brick_walk3( - __b, __e, __b + 1, __d_b + 1, - [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); }, - __is_vector); - }); + __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last - 1, + [&__op, __d_first, __first](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) + { + _RandomAccessIterator2 __d_b = __d_first + (__b - __first); + __internal::__brick_walk3( + __b, __e, __b + 1, __d_b + 1, + [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) + { __z = __op(__y, __x); }, + _IsVector{}); + }); return __d_first + (__last - __first); } diff --git a/libstdc++-v3/include/pstl/parallel_backend.h b/libstdc++-v3/include/pstl/parallel_backend.h index 4caa4a8..e9a90e1 100644 --- a/libstdc++-v3/include/pstl/parallel_backend.h +++ b/libstdc++-v3/include/pstl/parallel_backend.h @@ -22,6 +22,12 @@ namespace __pstl { namespace __par_backend = __tbb_backend; } +#elif defined(_PSTL_PAR_BACKEND_OPENMP) +# include "parallel_backend_omp.h" +namespace __pstl +{ +namespace __par_backend = __omp_backend; +} #else _PSTL_PRAGMA_MESSAGE("Parallel backend was not specified"); #endif diff --git a/libstdc++-v3/include/pstl/parallel_backend_serial.h b/libstdc++-v3/include/pstl/parallel_backend_serial.h index 16e773d..db2da43 100644 --- a/libstdc++-v3/include/pstl/parallel_backend_serial.h +++ b/libstdc++-v3/include/pstl/parallel_backend_serial.h @@ -50,15 +50,15 @@ __cancel_execution() template <class _ExecutionPolicy, class _Index, class _Fp> void -__parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +__parallel_for(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) { __f(__first, __last); } template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction> _Value -__parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity, - const _RealBody& __real_body, const _Reduction&) +__parallel_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction&) { if (__first == __last) { @@ -72,16 +72,16 @@ __parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Valu template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce> _Tp -__parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, - _Reduce __reduce) +__parallel_transform_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { return __reduce(__first, __last, __init); } template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap> void -__parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan, - _Ap __apex) +__parallel_strict_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) { _Tp __sum = __initial; if (__n) @@ -93,15 +93,16 @@ __parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __redu template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce, class _Scan> _Tp -__parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _UnaryOp, _Tp __init, _BinaryOp, _Reduce, _Scan __scan) +__parallel_transform_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _UnaryOp, + _Tp __init, _BinaryOp, _Reduce, _Scan __scan) { return __scan(_Index(0), __n, __init); } template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort> void -__parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, - _LeafSort __leaf_sort, std::size_t = 0) +__parallel_stable_sort(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort, std::size_t = 0) { __leaf_sort(__first, __last, __comp); } @@ -109,16 +110,16 @@ __parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _Rando template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge> void -__parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _RandomAccessIterator3 __outit, - _Compare __comp, _LeafMerge __leaf_merge) +__parallel_merge(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, _Compare __comp, _LeafMerge __leaf_merge) { __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); } template <class _ExecutionPolicy, typename _F1, typename _F2> void -__parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +__parallel_invoke(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) { std::forward<_F1>(__f1)(); std::forward<_F2>(__f2)(); diff --git a/libstdc++-v3/include/pstl/parallel_backend_tbb.h b/libstdc++-v3/include/pstl/parallel_backend_tbb.h index 3fd1a06..3ff5523 100644 --- a/libstdc++-v3/include/pstl/parallel_backend_tbb.h +++ b/libstdc++-v3/include/pstl/parallel_backend_tbb.h @@ -99,7 +99,7 @@ class __parallel_for_body // wrapper over tbb::parallel_for template <class _ExecutionPolicy, class _Index, class _Fp> void -__parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +__parallel_for(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) { tbb::this_task_arena::isolate([=]() { tbb::parallel_for(tbb::blocked_range<_Index>(__first, __last), __parallel_for_body<_Index, _Fp>(__f)); @@ -110,8 +110,8 @@ __parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) // wrapper over tbb::parallel_reduce template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction> _Value -__parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity, - const _RealBody& __real_body, const _Reduction& __reduction) +__parallel_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction& __reduction) { return tbb::this_task_arena::isolate([__first, __last, &__identity, &__real_body, &__reduction]() -> _Value { return tbb::parallel_reduce( @@ -191,8 +191,8 @@ struct __par_trans_red_body template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp> _Tp -__parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _Up __u, _Tp __init, _Cp __combine, - _Rp __brick_reduce) +__parallel_transform_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce) { __tbb_backend::__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce); // The grain size of 3 is used in order to provide mininum 2 elements for each body @@ -354,8 +354,8 @@ __downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsi // T must have a trivial constructor and destructor. template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap> void -__parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan, - _Ap __apex) +__parallel_strict_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) { tbb::this_task_arena::isolate([=, &__combine]() { if (__n > 1) @@ -394,8 +394,8 @@ __parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __redu template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp, class _Sp> _Tp -__parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce, - _Sp __scan) +__parallel_transform_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init, + _Cp __combine, _Rp __brick_reduce, _Sp __scan) { __trans_scan_body<_Index, _Up, _Tp, _Cp, _Rp, _Sp> __body(__u, __init, __combine, __brick_reduce, __scan); auto __range = tbb::blocked_range<_Index>(0, __n); @@ -1154,8 +1154,8 @@ __stable_sort_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _Le template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort> void -__parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp, - _LeafSort __leaf_sort, std::size_t __nsort = 0) +__parallel_stable_sort(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __xs, + _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, std::size_t __nsort = 0) { tbb::this_task_arena::isolate([=, &__nsort]() { //sorting based on task tree and parallel merge @@ -1248,9 +1248,9 @@ operator()(__task* __self) template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge> void -__parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, - _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, - _LeafMerge __leaf_merge) +__parallel_merge(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) { typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; @@ -1279,7 +1279,7 @@ __parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __xs, _RandomAccessI //------------------------------------------------------------------------ template <class _ExecutionPolicy, typename _F1, typename _F2> void -__parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +__parallel_invoke(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) { //TODO: a version of tbb::this_task_arena::isolate with variadic arguments pack should be added in the future tbb::this_task_arena::isolate([&]() { tbb::parallel_invoke(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); }); diff --git a/libstdc++-v3/include/pstl/parallel_impl.h b/libstdc++-v3/include/pstl/parallel_impl.h index 46560c6..4cf2abd 100644 --- a/libstdc++-v3/include/pstl/parallel_impl.h +++ b/libstdc++-v3/include/pstl/parallel_impl.h @@ -24,17 +24,19 @@ namespace __internal //----------------------------------------------------------------------- /** Return extremum value returned by brick f[i,j) for subranges [i,j) of [first,last) Each f[i,j) must return a value in [i,j). */ -template <class _ExecutionPolicy, class _Index, class _Brick, class _Compare> +template <class _BackendTag, class _ExecutionPolicy, class _Index, class _Brick, class _Compare> _Index -__parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) +__parallel_find(_BackendTag __tag, _ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, + _Compare __comp, bool __b_first) { typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; const _DifferenceType __n = __last - __first; _DifferenceType __initial_dist = __b_first ? __n : -1; std::atomic<_DifferenceType> __extremum(__initial_dist); // TODO: find out what is better here: parallel_for or parallel_reduce - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { + __par_backend::__parallel_for(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__comp, __f, __first, &__extremum](_Index __i, _Index __j) + { // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of // why using a shared variable scales fairly well in this situation. if (__comp(__i - __first, __extremum)) @@ -59,13 +61,14 @@ __parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick // parallel_or //------------------------------------------------------------------------ //! Return true if brick f[i,j) returns true for some subrange [i,j) of [first,last) -template <class _ExecutionPolicy, class _Index, class _Brick> +template <class _BackendTag, class _ExecutionPolicy, class _Index, class _Brick> bool -__parallel_or(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f) +__parallel_or(_BackendTag __tag, _ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f) { std::atomic<bool> __found(false); - __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last, - [__f, &__found](_Index __i, _Index __j) { + __par_backend::__parallel_for(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, + [__f, &__found](_Index __i, _Index __j) + { if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) { __found.store(true, std::memory_order_relaxed); diff --git a/libstdc++-v3/include/pstl/pstl_config.h b/libstdc++-v3/include/pstl/pstl_config.h index d1bf08e..74d2139 100644 --- a/libstdc++-v3/include/pstl/pstl_config.h +++ b/libstdc++-v3/include/pstl/pstl_config.h @@ -11,12 +11,12 @@ #define _PSTL_CONFIG_H // The version is XYYZ, where X is major, YY is minor, and Z is patch (i.e. X.YY.Z) -#define _PSTL_VERSION 12000 +#define _PSTL_VERSION 17000 #define _PSTL_VERSION_MAJOR (_PSTL_VERSION / 1000) #define _PSTL_VERSION_MINOR ((_PSTL_VERSION % 1000) / 10) #define _PSTL_VERSION_PATCH (_PSTL_VERSION % 10) -#if !defined(_PSTL_PAR_BACKEND_SERIAL) && !defined(_PSTL_PAR_BACKEND_TBB) +#if !defined(_PSTL_PAR_BACKEND_SERIAL) && !defined(_PSTL_PAR_BACKEND_TBB) && !defined(_PSTL_PAR_BACKEND_OPENMP) # error "A parallel backend must be specified" #endif @@ -53,13 +53,15 @@ // the actual GCC version on the system. #define _PSTL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if __clang__ +#if defined(__clang__) // according to clang documentation, version can be vendor specific # define _PSTL_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #endif // Enable SIMD for compilers that support OpenMP 4.0 -#if (_OPENMP >= 201307) || (__INTEL_COMPILER >= 1600) || (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \ +#if (defined(_OPENMP) && _OPENMP >= 201307) || \ + (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600) || \ + (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \ defined(__clang__) # define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd) # define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd) @@ -74,13 +76,13 @@ # define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) #endif //Enable SIMD -#if (__INTEL_COMPILER) +#if defined(__INTEL_COMPILER) # define _PSTL_PRAGMA_FORCEINLINE _PSTL_PRAGMA(forceinline) #else # define _PSTL_PRAGMA_FORCEINLINE #endif -#if (__INTEL_COMPILER >= 1900) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900 # define _PSTL_PRAGMA_SIMD_SCAN(PRM) _PSTL_PRAGMA(omp simd reduction(inscan, PRM)) # define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan inclusive(PRM)) # define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan exclusive(PRM)) @@ -91,34 +93,50 @@ #endif // Should be defined to 1 for environments with a vendor implementation of C++17 execution policies -#define _PSTL_CPP17_EXECUTION_POLICIES_PRESENT (_MSC_VER >= 1912) +#define _PSTL_CPP17_EXECUTION_POLICIES_PRESENT (_MSC_VER >= 1912 && _MSVC_LANG >= 201703L) || \ + (_GLIBCXX_RELEASE >= 9 && __GLIBCXX__ >= 20190503 && __cplusplus >= 201703L) -#define _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT \ - (_MSC_VER >= 1900 || __cplusplus >= 201300L || __cpp_lib_robust_nonmodifying_seq_ops == 201304) -#define _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT \ - (_MSC_VER >= 1900 || __cplusplus >= 201402L || __cpp_lib_make_reverse_iterator == 201402) -#define _PSTL_CPP14_INTEGER_SEQUENCE_PRESENT (_MSC_VER >= 1900 || __cplusplus >= 201402L) -#define _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT \ - (!__INTEL_COMPILER || __INTEL_COMPILER >= 1700) && (_MSC_FULL_VER >= 190023918 || __cplusplus >= 201402L) +#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + __cplusplus >= 201300L || \ + __cpp_lib_robust_nonmodifying_seq_ops == 201304 +# define _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT +#endif +#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + __cplusplus >= 201402L || \ + __cpp_lib_make_reverse_iterator == 201402 +# define _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT +#endif +#if (defined(_MSC_VER) && _MSC_VER >= 1900) || __cplusplus >= 201402L +# define _PSTL_CPP14_INTEGER_SEQUENCE_PRESENT +#endif +#if (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700) || \ + (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918) || \ + __cplusplus >= 201402L +# define _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT +#endif -#define _PSTL_EARLYEXIT_PRESENT (__INTEL_COMPILER >= 1800) -#define _PSTL_MONOTONIC_PRESENT (__INTEL_COMPILER >= 1800) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800 +# define _PSTL_EARLYEXIT_PRESENT +# define _PSTL_MONOTONIC_PRESENT +#endif -#if (__INTEL_COMPILER >= 1900 || !defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900 || _OPENMP >= 201307) -# define _PSTL_UDR_PRESENT 1 -#else -# define _PSTL_UDR_PRESENT 0 +#if (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900) || \ + (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \ + (defined(_OPENMP) && _OPENMP >= 201307) +# define _PSTL_UDR_PRESENT #endif -#define _PSTL_UDS_PRESENT (__INTEL_COMPILER >= 1900 && __INTEL_COMPILER_BUILD_DATE >= 20180626) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900 && __INTEL_COMPILER_BUILD_DATE >= 20180626 +# define _PSTL_UDS_PRESENT +#endif -#if _PSTL_EARLYEXIT_PRESENT +#if defined(_PSTL_EARLYEXIT_PRESENT) # define _PSTL_PRAGMA_SIMD_EARLYEXIT _PSTL_PRAGMA(omp simd early_exit) #else # define _PSTL_PRAGMA_SIMD_EARLYEXIT #endif -#if _PSTL_MONOTONIC_PRESENT +#if defined(_PSTL_MONOTONIC_PRESENT) # define _PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC(PRM) _PSTL_PRAGMA(omp ordered simd monotonic(PRM)) # define _PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC_2ARGS(PRM1, PRM2) _PSTL_PRAGMA(omp ordered simd monotonic(PRM1, PRM2)) #else @@ -136,7 +154,7 @@ #define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) \ _PSTL_PRAGMA(omp declare reduction(NAME:OP : omp_out(omp_in)) initializer(omp_priv = omp_orig)) -#if (__INTEL_COMPILER >= 1600) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600 # define _PSTL_PRAGMA_VECTOR_UNALIGNED _PSTL_PRAGMA(vector unaligned) #else # define _PSTL_PRAGMA_VECTOR_UNALIGNED @@ -149,7 +167,7 @@ # define _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED #endif -#if _MSC_VER || __INTEL_COMPILER //the preprocessors don't type a message location +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) // the preprocessors don't type a message location # define _PSTL_PRAGMA_LOCATION __FILE__ ":" _PSTL_STRING(__LINE__) ": [Parallel STL message]: " #else # define _PSTL_PRAGMA_LOCATION " [Parallel STL message]: " @@ -157,7 +175,7 @@ #define _PSTL_PRAGMA_MESSAGE_IMPL(x) _PSTL_PRAGMA(message(_PSTL_STRING_CONCAT(_PSTL_PRAGMA_LOCATION, x))) -#if _PSTL_USAGE_WARNINGS +#if defined(_PSTL_USAGE_WARNINGS) # define _PSTL_PRAGMA_MESSAGE(x) _PSTL_PRAGMA_MESSAGE_IMPL(x) # define _PSTL_PRAGMA_MESSAGE_POLICIES(x) _PSTL_PRAGMA_MESSAGE_IMPL(x) #else @@ -166,8 +184,13 @@ #endif // broken macros -#define _PSTL_CPP11_STD_ROTATE_BROKEN ((__GLIBCXX__ && __GLIBCXX__ < 20150716) || (_MSC_VER && _MSC_VER < 1800)) +#if (defined(__GLIBCXX__) && __GLIBCXX__ < 20150716) || \ + (defined(_MSC_VER) && _MSC_VER < 1800) +# define _PSTL_CPP11_STD_ROTATE_BROKEN +#endif -#define _PSTL_ICC_18_OMP_SIMD_BROKEN (__INTEL_COMPILER == 1800) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER == 1800 +# define _PSTL_ICC_18_OMP_SIMD_BROKEN +#endif #endif /* _PSTL_CONFIG_H */ diff --git a/libstdc++-v3/include/pstl/unseq_backend_simd.h b/libstdc++-v3/include/pstl/unseq_backend_simd.h index 7cda7ff..69784bc 100644 --- a/libstdc++-v3/include/pstl/unseq_backend_simd.h +++ b/libstdc++-v3/include/pstl/unseq_backend_simd.h @@ -61,7 +61,7 @@ template <class _Index, class _DifferenceType, class _Pred> bool __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept { -#if _PSTL_EARLYEXIT_PRESENT +#if defined(_PSTL_EARLYEXIT_PRESENT) _DifferenceType __i; _PSTL_PRAGMA_VECTOR_UNALIGNED _PSTL_PRAGMA_SIMD_EARLYEXIT @@ -74,7 +74,7 @@ __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept const _Index __last = __first + __n; while (__last != __first) { - __INT32_TYPE__ __flag = 1; + int32_t __flag = 1; _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag) for (_DifferenceType __i = 0; __i < __block_size; ++__i) if (__pred(*(__first + __i))) @@ -101,7 +101,7 @@ template <class _Index, class _DifferenceType, class _Compare> _Index __simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp) noexcept { -#if _PSTL_EARLYEXIT_PRESENT +#if defined(_PSTL_EARLYEXIT_PRESENT) _DifferenceType __i = __begin; _PSTL_PRAGMA_VECTOR_UNALIGNED // Do not generate peel loop part _PSTL_PRAGMA_SIMD_EARLYEXIT for (; __i < __end; ++__i) @@ -161,7 +161,7 @@ template <class _Index1, class _DifferenceType, class _Index2, class _Pred> std::pair<_Index1, _Index2> __simd_first(_Index1 __first1, _DifferenceType __n, _Index2 __first2, _Pred __pred) noexcept { -#if _PSTL_EARLYEXIT_PRESENT +#if defined(_PSTL_EARLYEXIT_PRESENT) _DifferenceType __i = 0; _PSTL_PRAGMA_VECTOR_UNALIGNED _PSTL_PRAGMA_SIMD_EARLYEXIT @@ -383,7 +383,7 @@ __simd_adjacent_find(_Index __first, _Index __last, _BinaryPredicate __pred, boo typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; _DifferenceType __i = 0; -#if _PSTL_EARLYEXIT_PRESENT +#if defined(_PSTL_EARLYEXIT_PRESENT) //Some compiler versions fail to compile the following loop when iterators are used. Indices are used instead const _DifferenceType __n = __last - __first - 1; _PSTL_PRAGMA_VECTOR_UNALIGNED @@ -532,7 +532,7 @@ struct _Combiner _BinaryOp* __bin_op; // Here is a pointer to function because of default ctor _Combiner() : __value{}, __bin_op(nullptr) {} - _Combiner(const _Tp& value, const _BinaryOp* __bin_op) : __value(value), __bin_op(const_cast<_BinaryOp*>(__bin_op)) {} + _Combiner(const _Tp& __v, const _BinaryOp* __b) : __value(__v), __bin_op(const_cast<_BinaryOp*>(__b)) {} _Combiner(const _Combiner& __obj) : __value{}, __bin_op(__obj.__bin_op) {} void @@ -624,8 +624,8 @@ __simd_min_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcep _Compare* __min_comp; _ComplexType() : __min_val{}, __min_ind{}, __min_comp(nullptr) {} - _ComplexType(const _ValueType& __val, const _Compare* comp) - : __min_val(__val), __min_ind(0), __min_comp(const_cast<_Compare*>(comp)) + _ComplexType(const _ValueType& val, const _Compare* comp) + : __min_val(val), __min_ind(0), __min_comp(const_cast<_Compare*>(comp)) { } _ComplexType(const _ComplexType& __obj) @@ -685,9 +685,9 @@ __simd_minmax_element(_ForwardIterator __first, _Size __n, _Compare __comp) noex _Compare* __minmax_comp; _ComplexType() : __min_val{}, __max_val{}, __min_ind{}, __max_ind{}, __minmax_comp(nullptr) {} - _ComplexType(const _ValueType& __min_val, const _ValueType& __max_val, const _Compare* comp) - : __min_val(__min_val), __max_val(__max_val), __min_ind(0), __max_ind(0), - __minmax_comp(const_cast<_Compare*>(comp)) + _ComplexType(const _ValueType& __min, const _ValueType& __max, const _Compare* __comp) + : __min_val(__min), __max_val(__max), __min_ind(0), __max_ind(0), + __minmax_comp(const_cast<_Compare*>(__comp)) { } _ComplexType(const _ComplexType& __obj) diff --git a/libstdc++-v3/include/pstl/utils.h b/libstdc++-v3/include/pstl/utils.h index 0e908f1..e261105 100644 --- a/libstdc++-v3/include/pstl/utils.h +++ b/libstdc++-v3/include/pstl/utils.h @@ -19,8 +19,8 @@ namespace __internal { template <typename _Fp> -typename std::result_of<_Fp()>::type -__except_handler(_Fp __f) +auto +__except_handler(_Fp __f) -> decltype(__f()) { try { @@ -44,8 +44,7 @@ __invoke_if(std::true_type, _Fp __f) } template <typename _Fp> -void -__invoke_if(std::false_type, _Fp __f) +void __invoke_if(std::false_type, _Fp) { } @@ -57,21 +56,20 @@ __invoke_if_not(std::false_type, _Fp __f) } template <typename _Fp> -void -__invoke_if_not(std::true_type, _Fp __f) +void __invoke_if_not(std::true_type, _Fp) { } template <typename _F1, typename _F2> -typename std::result_of<_F1()>::type -__invoke_if_else(std::true_type, _F1 __f1, _F2 __f2) +auto +__invoke_if_else(std::true_type, _F1 __f1, _F2) -> decltype(__f1()) { return __f1(); } template <typename _F1, typename _F2> -typename std::result_of<_F2()>::type -__invoke_if_else(std::false_type, _F1 __f1, _F2 __f2) +auto +__invoke_if_else(std::false_type, _F1, _F2 __f2) -> decltype(__f2()) { return __f2(); } @@ -87,23 +85,6 @@ struct __no_op } }; -//! Logical negation of a predicate -template <typename _Pred> -class __not_pred -{ - _Pred _M_pred; - - public: - explicit __not_pred(_Pred __pred) : _M_pred(__pred) {} - - template <typename... _Args> - bool - operator()(_Args&&... __args) - { - return !_M_pred(std::forward<_Args>(__args)...); - } -}; - template <typename _Pred> class __reorder_pred { @@ -120,36 +101,6 @@ class __reorder_pred } }; -//! "==" comparison. -/** Not called "equal" to avoid (possibly unfounded) concerns about accidental invocation via - argument-dependent name lookup by code expecting to find the usual std::equal. */ -class __pstl_equal -{ - public: - explicit __pstl_equal() {} - - template <typename _Xp, typename _Yp> - bool - operator()(_Xp&& __x, _Yp&& __y) const - { - return std::forward<_Xp>(__x) == std::forward<_Yp>(__y); - } -}; - -//! "<" comparison. -class __pstl_less -{ - public: - explicit __pstl_less() {} - - template <typename _Xp, typename _Yp> - bool - operator()(_Xp&& __x, _Yp&& __y) const - { - return std::forward<_Xp>(__x) < std::forward<_Yp>(__y); - } -}; - //! Like a polymorphic lambda for pred(...,value) template <typename _Tp, typename _Predicate> class __equal_value_by_pred diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc index dc09941..407e488 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc @@ -112,12 +112,12 @@ test_uninit_construct_by_type() } } -int32_t +int main() { // for user-defined types -#if !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) test_uninit_construct_by_type<Wrapper<int32_t>>(); test_uninit_construct_by_type<Wrapper<std::vector<std::string>>>(); #endif diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc index 73b0982..2558147 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc @@ -81,16 +81,16 @@ struct test_uninitialized_copy_move std::destroy_n(exec, out_first, n); } -#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) template <typename InputIterator, typename OutputIterator> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, /*is_trivial<T>=*/std::true_type) { } template <typename InputIterator, typename OutputIterator> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, /*is_trivial<T>=*/std::true_type) { } @@ -101,8 +101,6 @@ struct test_uninitialized_copy_move operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, /*is_trivial<T>=*/std::true_type) { - typedef typename std::iterator_traits<InputIterator>::value_type T; - std::uninitialized_copy(exec, first, last, out_first); EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy"); std::destroy_n(exec, out_first, n); @@ -134,7 +132,7 @@ test_uninitialized_copy_move_by_type() } } -int32_t +int main() { @@ -143,8 +141,8 @@ main() test_uninitialized_copy_move_by_type<float64_t>(); // for user-defined types -#if !_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && !_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && \ - !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) && !defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) && \ + !defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) test_uninitialized_copy_move_by_type<Wrapper<int8_t>>(); #endif diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc index 1683e64..fed9bdb 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc @@ -87,7 +87,7 @@ test_uninitialized_fill_destroy_by_type() } } -int32_t +int main() { // for trivial types diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc index 1499344..576f224 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc @@ -30,18 +30,18 @@ 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare> void - operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, + operator()(__pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { } template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare> void - operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, + operator()(__pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { } @@ -54,8 +54,6 @@ struct test_one_policy 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<BiDirIt1>::value_type; const BiDirIt1 mid1 = std::next(first1, m); fill_data(first1, mid1, generator1); fill_data(mid1, last1, generator2); @@ -72,8 +70,7 @@ struct test_one_policy template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare> typename std::enable_if<is_same_iterator_category<BiDirIt1, std::forward_iterator_tag>::value, void>::type - operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) + operator()(Policy&&, BiDirIt1, BiDirIt1, BiDirIt1, BiDirIt1, Size, Size, Generator1, Generator2, Compare) { } }; @@ -146,7 +143,7 @@ struct test_non_const } }; -int32_t +int main() { test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, @@ -160,6 +157,13 @@ main() test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const<int32_t>>()); + test_by_type<MemoryChecker>( + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2)}; }, + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2 + 1)}; }, + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from inplace_merge: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from inplace_merge: number of ctors calls > num of dtors calls"); + std::cout << done() << std::endl; return 0; } diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc index e6eeb1d..eab1260 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc @@ -23,6 +23,7 @@ #else #include <execution> #include <algorithm> +#include <functional> #endif // PSTL_STANDALONE_TESTS #include "pstl/test_utils.h" @@ -58,8 +59,7 @@ struct test_merge void operator()(Policy&& exec, std::reverse_iterator<InputIterator1> first1, std::reverse_iterator<InputIterator1> last1, std::reverse_iterator<InputIterator2> first2, std::reverse_iterator<InputIterator2> last2, - std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last, - Compare comp) + std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last, Compare) { using namespace std; typedef typename std::iterator_traits<std::reverse_iterator<InputIterator1>>::value_type T; @@ -106,13 +106,13 @@ struct test_non_const } }; -int32_t +int main() { test_merge_by_type<int32_t>([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; }); test_merge_by_type<float64_t>([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); }); -#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT +#if !defined(_PSTL_ICC_16_17_TEST_64_TIMEOUT) test_merge_by_type<Wrapper<int16_t>>([](size_t v) { return Wrapper<int16_t>(v % 100); }, [](size_t v) { return Wrapper<int16_t>(v % 10); }); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc index 5b90e83..9c1f172 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc @@ -29,7 +29,7 @@ using namespace TestUtils; struct run_copy_if { -#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration +#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) // dummy specializations to skip testing in case of broken configuration template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename Predicate, typename T> void @@ -131,7 +131,7 @@ struct test_non_const } }; -int32_t +int main() { test<float64_t>(-666.0, [](const float64_t& x) { return x * x <= 1024; }, @@ -140,12 +140,12 @@ main() test<int32_t>(-666, [](const int32_t& x) { return x != 42; }, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? int32_t(j + 1) : 42; }); -#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN +#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) test<Number>(Number(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); #endif -#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test<int32_t>(-666, [](const int32_t& x) { return true; }, [](size_t j) { return j; }, false); +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN) + test<int32_t>(-666, [](const int32_t&) { return true; }, [](size_t j) { return j; }, false); #endif test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc index 73c368b..5f4f984 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc @@ -31,11 +31,11 @@ using namespace TestUtils; struct run_copy { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, T trash) { @@ -43,7 +43,7 @@ struct run_copy template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, T trash) { @@ -54,8 +54,7 @@ struct run_copy typename T> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, - Size n, T trash) + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size n, T trash) { // Cleaning std::fill_n(expected_first, size, trash); @@ -84,11 +83,11 @@ template <typename T> struct run_move { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, T trash) { @@ -96,7 +95,7 @@ struct run_move template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, T trash) { @@ -106,8 +105,7 @@ struct run_move template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, - Size n, T trash) + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size, T trash) { // Cleaning std::fill_n(expected_first, size, trash); @@ -127,11 +125,11 @@ template <typename T> struct run_move<Wrapper<T>> { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, Wrapper<T> trash) { @@ -139,7 +137,7 @@ struct run_move<Wrapper<T>> template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, Size n, Wrapper<T> trash) { @@ -149,8 +147,7 @@ struct run_move<Wrapper<T>> template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size, - Size n, Wrapper<T> trash) + OutputIterator out_last, OutputIterator2, OutputIterator2, Size size, Size, Wrapper<T> trash) { // Cleaning std::fill_n(out_first, size, trash); @@ -194,13 +191,13 @@ test(T trash, Convert convert) } } -int32_t +int main() { test<int32_t>(-666, [](size_t j) { return int32_t(j); }); test<Wrapper<float64_t>>(Wrapper<float64_t>(-666.0), [](int32_t j) { return Wrapper<float64_t>(j); }); -#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT +#if !defined(_PSTL_ICC_16_17_TEST_64_TIMEOUT) test<float64_t>(-666.0, [](size_t j) { return float64_t(j); }); test<Number>(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc index 733657b..d5b4065 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc @@ -84,14 +84,14 @@ template <typename T> void test_fill_by_type(std::size_t n) { - Sequence<T> in(n, [](std::size_t v) -> T { return T(0); }); //fill with zeros + Sequence<T> in(n, [](std::size_t) -> T { return T(0); }); //fill with zeros T value = -1; invoke_on_all_policies(test_fill(), in.begin(), in.end(), value); invoke_on_all_policies(test_fill_n(), in.begin(), n, value); } -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc index 1bd2621..c04e512 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc @@ -57,17 +57,18 @@ struct test_generate { Generator_count<T> g; generate(exec, first, last, g); - EXPECT_TRUE(std::count(first, last, g.default_value()) == n, "generate wrong result for generate"); + Size count = std::count(first, last, g.default_value()); + EXPECT_TRUE(count == n, "generate wrong result for generate"); std::fill(first, last, T(0)); } { Generator_count<T> g; const auto m = n / 2; - auto last = generate_n(exec, first, m, g); - EXPECT_TRUE(std::count(first, last, g.default_value()) == m && last == std::next(first, m), - "generate_n wrong result for generate_n"); - std::fill(first, last, T(0)); + auto actual_last = generate_n(exec, first, m, g); + Size count = std::count(first, actual_last, g.default_value()); + EXPECT_TRUE(count == m && actual_last == std::next(first, m), "generate_n wrong result for generate_n"); + std::fill(first, actual_last, T(0)); } } }; @@ -78,7 +79,7 @@ test_generate_by_type() { for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n)) { - Sequence<T> in(n, [](size_t v) -> T { return T(0); }); //fill by zero + Sequence<T> in(n, [](size_t) -> T { return T(0); }); //fill by zero invoke_on_all_policies(test_generate(), in.begin(), in.end(), in.size()); } @@ -98,7 +99,7 @@ struct test_non_const } }; -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc index 3c70b14..20ee7d2 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc @@ -29,16 +29,16 @@ using namespace TestUtils; struct test_one_policy { //dummy specialization by policy type, in case of broken configuration -#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) template <typename Iterator1, typename Predicate> void - operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + operator()(__pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) { } template <typename Iterator1, typename Predicate> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) { } #endif @@ -92,14 +92,14 @@ struct test_non_const } }; -int32_t +int main() { test<float64_t>([](const float64_t x) { return x < 0; }); test<int32_t>([](const int32_t x) { return x > 1000; }); test<uint16_t>([](const uint16_t x) { return x % 5 < 3; }); -#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN && !_PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN - test<LocalWrapper<float64_t>>([](const LocalWrapper<float64_t>& x) { return true; }); +#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN) && !defined(_PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN) + test<LocalWrapper<float64_t>>([](const LocalWrapper<float64_t>&) { return true; }); #endif test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc index d084995..e13fe93 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc @@ -66,15 +66,15 @@ is_equal(Iterator first, Iterator last, Iterator d_first) template <typename Iterator> typename std::enable_if<!std::is_trivial<typename std::iterator_traits<Iterator>::value_type>::value, bool>::type -is_equal(Iterator first, Iterator last, Iterator d_first) + is_equal(Iterator, Iterator, Iterator) { 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 specializations to skip testing in case of broken configuration +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specializations to skip testing in case of broken configuration template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator> void operator()(__pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, @@ -88,7 +88,7 @@ struct test_one_policy BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) { } -#elif _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specializations to skip testing in case of broken configuration +#elif defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) //dummy specializations to skip testing in case of broken configuration template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator> void operator()(__pstl::execution::parallel_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, @@ -106,8 +106,8 @@ struct test_one_policy template <typename Policy, typename BiDirIt, typename Size, typename UnaryOp, typename Generator> typename std::enable_if<!is_same_iterator_category<BiDirIt, std::forward_iterator_tag>::value, void>::type - operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, - UnaryOp unary_op, Generator generator) + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size, UnaryOp unary_op, + Generator generator) { // partition { @@ -130,8 +130,7 @@ struct test_one_policy } template <typename Policy, typename BiDirIt, typename Size, typename UnaryOp, typename Generator> typename std::enable_if<is_same_iterator_category<BiDirIt, std::forward_iterator_tag>::value, void>::type - operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, - UnaryOp unary_op, Generator generator) + operator()(Policy&&, BiDirIt, BiDirIt, BiDirIt, BiDirIt, Size, UnaryOp, Generator) { } }; @@ -170,10 +169,10 @@ struct test_non_const } }; -int32_t +int main() { -#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN) test_by_type<int32_t>([](int32_t i) { return i; }, [](int32_t) { return true; }); #endif test_by_type<float64_t>([](int32_t i) { return -i; }, [](const float64_t x) { return x < 0; }); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc index 63e1f21..804fcba 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc @@ -35,24 +35,23 @@ struct test_partition_copy template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp> void - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator true_first, - OutputIterator true_last, OutputIterator2 false_first, OutputIterator2 false_last, UnaryOp unary_op) + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator true_first, OutputIterator, + OutputIterator2 false_first, OutputIterator2, UnaryOp unary_op) { auto actual_ret = std::partition_copy(exec, first, last, true_first, false_first, unary_op); EXPECT_TRUE(std::distance(true_first, actual_ret.first) == std::count_if(first, last, unary_op), "partition_copy has wrong effect from true sequence"); - EXPECT_TRUE(std::distance(false_first, actual_ret.second) == - std::count_if(first, last, __pstl::__internal::__not_pred<UnaryOp>(unary_op)), + EXPECT_TRUE(std::distance(false_first, actual_ret.second) == std::count_if(first, last, std::not_fn(unary_op)), "partition_copy has wrong effect from false sequence"); } //dummy specialization by iterator type and policy type, in case of broken configuration -#if _PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN +#if defined(_PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN) template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp> void - operator()(pstl::execution::unsequenced_policy, std::reverse_iterator<InputIterator> first, + operator()(__pstl::execution::unsequenced_policy, std::reverse_iterator<InputIterator> first, std::reverse_iterator<InputIterator> last, std::reverse_iterator<OutputIterator> true_first, std::reverse_iterator<OutputIterator> true_last, std::reverse_iterator<OutputIterator2> false_first, OutputIterator2 false_last, UnaryOp unary_op) @@ -60,7 +59,7 @@ struct test_partition_copy } template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp> void - operator()(pstl::execution::parallel_unsequenced_policy, std::reverse_iterator<InputIterator> first, + operator()(__pstl::execution::parallel_unsequenced_policy, std::reverse_iterator<InputIterator> first, std::reverse_iterator<InputIterator> last, std::reverse_iterator<OutputIterator> true_first, std::reverse_iterator<OutputIterator> true_last, std::reverse_iterator<OutputIterator2> false_first, OutputIterator2 false_last, UnaryOp unary_op) @@ -106,13 +105,13 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>([](const int32_t value) { return value % 2; }); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test<int32_t>([](const int32_t value) { return true; }); +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN) + test<int32_t>([](const int32_t) { return true; }); #endif test<float64_t>([](const float64_t value) { return value > 2 << 6; }); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc index f2e7520..9d8e5b9 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc @@ -29,18 +29,18 @@ using namespace TestUtils; struct run_remove { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename OutputIterator, typename Size, typename T> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, const T& value) { } template <typename InputIterator, typename OutputIterator, typename Size, typename T> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, const T& value) { @@ -67,18 +67,18 @@ struct run_remove struct run_remove_if { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, Predicate pred) { } template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, Predicate pred) { @@ -138,11 +138,11 @@ struct test_non_const } }; -int32_t +int main() { -#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN - test<int32_t>(666, 42, [](int32_t val) { return true; }, [](size_t j) { return j; }); +#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN) + test<int32_t>(666, 42, [](int32_t) { return true; }, [](size_t j) { return j; }); #endif test<int32_t>(666, 2001, [](const int32_t& val) { return val != 2001; }, @@ -150,13 +150,20 @@ main() test<float64_t>(-666.0, 8.5, [](const float64_t& val) { return val != 8.5; }, [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); -#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN +#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) test<Number>(Number(-666, OddTag()), Number(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); #endif test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>()); + test<MemoryChecker>(MemoryChecker{0}, MemoryChecker{1}, + [](const MemoryChecker& val){ return val.value() == 1; }, + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx % 3 == 0)}; } + ); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from remove,remove_if: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from remove,remove_if: number of ctors calls > num of dtors calls"); + std::cout << done() << std::endl; return 0; } diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc index 9cc8c82..37d7b66 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc @@ -33,16 +33,17 @@ struct run_remove_copy typename T> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n, - const T& value, T trash) + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, const T& value, + T trash) { // Cleaning std::fill_n(expected_first, n, trash); std::fill_n(out_first, n, trash); // Run copy_if - auto i = remove_copy(first, last, expected_first, value); - auto k = remove_copy(exec, first, last, out_first, value); + auto i = std::remove_copy(first, last, expected_first, value); + (void)i; + auto k = std::remove_copy(exec, first, last, out_first, value); EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy effect"); for (size_t j = 0; j < GuardSize; ++j) { @@ -84,7 +85,7 @@ test(T trash, const T& value, Convert convert, bool check_weakness = true) } } -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc index db82b87..c6a515e 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc @@ -31,9 +31,10 @@ struct copy_int { int32_t value; int32_t copied_times = 0; - explicit copy_int(int32_t val = 0) { value = val; } + constexpr explicit copy_int(int32_t val = 0) : value(val) {} + constexpr copy_int(copy_int const& other) : value(other.value), copied_times(other.copied_times) { } - copy_int& + constexpr copy_int& operator=(const copy_int& other) { if (&other == this) @@ -46,7 +47,7 @@ struct copy_int return *this; } - bool + constexpr bool operator==(const copy_int& other) const { return (value == other.value); @@ -112,13 +113,13 @@ test(Pred pred) const std::size_t max_len = 100000; - const T1 value = T1(0); - const T1 new_value = T1(666); + static constexpr T1 value = T1(0); + static constexpr T1 new_value = T1(666); Sequence<T2> expected(max_len); Sequence<T2> actual(max_len); - Sequence<T2> data(max_len, [&value](std::size_t i) { + Sequence<T2> data(max_len, [](std::size_t i) { if (i % 3 == 2) { return T1(i); @@ -153,7 +154,7 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t, float32_t>(__pstl::__internal::__equal_value<int32_t>(666)); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc index 6931162..18f6b54 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc @@ -34,8 +34,8 @@ struct test_replace_copy typename Predicate, typename T> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n, - Predicate pred, const T& old_value, const T& new_value, T trash) + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred, + const T& old_value, const T& new_value, T trash) { // Cleaning std::fill_n(expected_first, n, trash); @@ -91,7 +91,7 @@ struct test_non_const } }; -int32_t +int main() { @@ -101,7 +101,7 @@ main() test<int32_t>(-666, 42, 99, [](const int32_t& x) { return x != 42; }, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); }); -#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN +#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) test<Number>(Number(42, OddTag()), Number(2001, OddTag()), Number(2017, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return ((j + 1) % 3 & 2) != 0 ? Number(2001, OddTag()) : Number(j, OddTag()); }); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc index c7e00fb..9ec9b3b 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc @@ -83,8 +83,8 @@ struct compare<wrapper<T>> 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 specializations to skip testing in case of broken configuration +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specializations to skip testing in case of broken configuration template <typename Iterator, typename Size> void operator()(__pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, @@ -123,10 +123,10 @@ struct test_one_policy template <typename ExecutionPolicy, typename Iterator, typename Size> typename std::enable_if< is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value && - !std::is_same<ExecutionPolicy, __pstl::execution::sequenced_policy>::value && + !std::is_same<ExecutionPolicy, std::execution::sequenced_policy>::value && std::is_same<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value, bool>::type - check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) + check_move(ExecutionPolicy&&, Iterator b, Iterator e, Size shift) { bool result = all_of(b, e, [](wrapper<float32_t>& a) { bool temp = a.move_count > 0; @@ -139,10 +139,10 @@ struct test_one_policy template <typename ExecutionPolicy, typename Iterator, typename Size> typename std::enable_if< !(is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value && - !std::is_same<ExecutionPolicy, __pstl::execution::sequenced_policy>::value && + !std::is_same<ExecutionPolicy, std::execution::sequenced_policy>::value && std::is_same<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value), bool>::type - check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) + check_move(ExecutionPolicy&&, Iterator, Iterator, Size) { return true; } @@ -171,7 +171,7 @@ test() } } -int32_t +int main() { test<int32_t>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc index f80ec5a..ea647c6 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc @@ -78,17 +78,17 @@ struct comparator 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename Iterator1, typename Iterator2> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, std::size_t shift) { } template <typename Iterator1, typename Iterator2> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, std::size_t shift) { } @@ -142,7 +142,7 @@ test() } } -int32_t +int main() { test<int32_t, int8_t>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc index d17c11d..e371c3b 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc @@ -61,7 +61,7 @@ template <typename T> struct check_swap { bool - operator()(T& a) + operator()(T&) { return true; } @@ -129,7 +129,7 @@ test() } } -int32_t +int main() { test<wrapper<uint16_t>>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc index 226a81a..1f5f239 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc @@ -70,10 +70,11 @@ struct test_one_policy template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryOp> void - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - OutputIterator out_first, OutputIterator out_last, BinaryOp op) + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2, + OutputIterator out_first, OutputIterator, BinaryOp op) { - auto orrr = std::transform(exec, first1, last1, first2, out_first, op); + auto result = std::transform(exec, first1, last1, first2, out_first, op); + (void)result; check_and_reset(first1, last1, first2, out_first); } }; @@ -87,7 +88,7 @@ test(Predicate pred) Sequence<In1> in1(n, [](size_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); Sequence<In2> in2(n, [](size_t k) { return k % 7 != 2 ? 5 * k - 5 : 0; }); - Sequence<Out> out(n, [](size_t k) { return -1; }); + Sequence<Out> out(n, [](size_t) { return -1; }); invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.begin(), in2.end(), out.begin(), out.end(), pred); @@ -110,7 +111,7 @@ struct test_non_const } }; -int32_t +int main() { //const operator() diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc index cece475..ddd8249 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc @@ -83,7 +83,7 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t, int32_t>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc index 54c9953..0f21e04 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc @@ -29,32 +29,32 @@ using namespace TestUtils; struct run_unique { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename ForwardIt, typename Generator> void - operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + operator()(__pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, Generator generator) { } template <typename ForwardIt, typename Generator> void - operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + operator()(__pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, Generator generator) { } template <typename ForwardIt, typename BinaryPred, typename Generator> void - operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + operator()(__pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, BinaryPred pred, Generator generator) { } template <typename ForwardIt, typename BinaryPred, typename Generator> void - operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + operator()(__pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, BinaryPred pred, Generator generator) { } @@ -144,10 +144,10 @@ struct test_non_const } }; -int32_t +int main() { -#if !_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN +#if !defined(_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN) test<int32_t>([](size_t j) { return j / 3; }, [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; }); test<float64_t>([](size_t) { return float64_t(1); }, @@ -160,6 +160,12 @@ main() test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>()); + test<MemoryChecker>( + [](std::size_t idx){ return MemoryChecker{std::int32_t(idx / 3)}; }, + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from unique: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from unique: number of ctors calls > num of dtors calls"); + std::cout << done() << std::endl; return 0; } diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc index 0351db7..c5bc25c 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc @@ -29,7 +29,7 @@ using namespace TestUtils; struct run_unique_copy { -#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration +#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) // dummy specializations to skip testing in case of broken configuration template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename Predicate, typename T> void @@ -53,8 +53,8 @@ struct run_unique_copy typename Predicate, typename T> void operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n, - Predicate pred, T trash) + OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred, + T trash) { // Cleaning std::fill_n(expected_first, n, trash); @@ -123,17 +123,17 @@ struct test_non_const } }; -int32_t -main(int32_t argc, char* argv[]) +int +main() { test<Number>(Number(42, OddTag()), std::equal_to<Number>(), [](int32_t j) { return Number(3 * j / 13 ^ (j & 8), OddTag()); }); test<float32_t>(float32_t(42), std::equal_to<float32_t>(), [](int32_t j) { return float32_t(5 * j / 23 ^ (j / 7)); }); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test<float32_t>(float32_t(42), [](float32_t x, float32_t y) { return false; }, - [](int32_t j) { return float32_t(j); }, false); +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN) + test<float32_t>(float32_t(42), [](float32_t, float32_t) { return false; }, [](int32_t j) { return float32_t(j); }, + false); #endif test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc index 81bca82..a79f11b 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc @@ -50,13 +50,13 @@ test_adjacent_find_by_type() { size_t counts[] = {2, 3, 500}; - for (int32_t c = 0; c < const_size(counts); ++c) + for (size_t c = 0; c < const_size(counts); ++c) { - for (int32_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e) + for (size_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e) { - Sequence<T> in(counts[c], [](int32_t v) -> T { return T(v); }); //fill 0...n - in[e] = in[e + 1] = -1; //make an adjacent pair + Sequence<T> in(counts[c], [](size_t v) -> T { return T(v); }); //fill 0...n + in[e] = in[e + 1] = -1; //make an adjacent pair auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to<T>()); EXPECT_TRUE(i == in.cbegin() + e, "std::adjacent_find returned wrong result"); @@ -67,9 +67,9 @@ test_adjacent_find_by_type() } //special cases: size=0, size=1; - for (int32_t expect = 0; expect < 1; ++expect) + for (size_t expect = 0; expect < 1; ++expect) { - Sequence<T> in(expect, [](int32_t v) -> T { return T(v); }); //fill 0...n + Sequence<T> in(expect, [](size_t v) -> T { return T(v); }); //fill 0...n auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to<T>()); EXPECT_TRUE(i == in.cbegin() + expect, "std::adjacent_find returned wrong result"); @@ -109,7 +109,7 @@ struct test_non_const } }; -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc index d1c3b98..0f03d00 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc @@ -69,7 +69,7 @@ test(size_t bits) { // Sequence of odd values - Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); // Even value, or false when T is bool. T spike(2 * HashBits(n, bits - 1)); @@ -108,13 +108,13 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(8 * sizeof(int32_t)); test<uint16_t>(8 * sizeof(uint16_t)); test<float64_t>(53); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN) test<bool>(1); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc index 7b2f3c7..a4bbb7d 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc @@ -55,7 +55,7 @@ test(size_t bits) { // Sequence of odd values - Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); // Even value, or false when T is bool. T spike(2 * HashBits(n, bits - 1)); @@ -94,13 +94,13 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(8 * sizeof(int32_t)); test<uint16_t>(8 * sizeof(uint16_t)); test<float64_t>(53); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN) test<bool>(1); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc index 25a1350..b99754c 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc @@ -98,12 +98,12 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(42, IsEqual<int32_t>(50, OddTag()), [](int32_t j) { return j; }); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test<int32_t>(42, [](const int32_t& x) { return true; }, [](int32_t j) { return j; }); +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN) + test<int32_t>(42, [](const int32_t&) { return true; }, [](int32_t j) { return j; }); #endif test<float64_t>(42, IsEqual<float64_t>(50, OddTag()), [](int32_t j) { return float64_t(j); }); test<Number>(Number(42, OddTag()), IsEqual<Number>(Number(50, OddTag()), OddTag()), diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc index cec6b20..0e5ad030 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc @@ -30,10 +30,10 @@ using namespace TestUtils; struct UserType { + size_t key; float32_t f; float64_t d; int32_t i; - size_t key; bool operator()(UserType a, UserType b) @@ -157,14 +157,14 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(8 * sizeof(int32_t)); test<uint16_t>(8 * sizeof(uint16_t)); test<float64_t>(53); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN) test<bool>(1); #endif test<UserType>(256); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc index 1eb9db3..c303ba6 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc @@ -29,16 +29,16 @@ using namespace TestUtils; struct test_find { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator, typename Value> void - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) + operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) { } template <typename Iterator, typename Value> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) { } #endif @@ -88,12 +88,12 @@ class Weird Weird(int32_t val, OddTag) : value(val, OddTag()) {} }; -int32_t +int main() { // Note that the "hit" and "miss" functions here avoid overflow issues. - test<Number>(Weird(42, OddTag()), [](int32_t j) { return Number(42, OddTag()); }, // hit - [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss + test<Number>(Weird(42, OddTag()), [](int32_t) { return Number(42, OddTag()); }, // hit + [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss // Test with value that is equal to two different bit patterns (-0.0 and 0.0) test<float32_t>(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc index e106b5c..e6a65a9 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc @@ -26,105 +26,77 @@ using namespace TestUtils; -struct test_one_policy +struct test_find { -#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 Iterator1, typename Iterator2, typename Predicate> +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration + template <typename Iterator, typename Value> void - operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) + operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) { } - template <typename Iterator1, typename Iterator2, typename Predicate> + template <typename Iterator, typename Value> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) { } #endif - template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate> + template <typename Policy, typename Iterator, typename Value> void - operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) + operator()(Policy&& exec, Iterator first, Iterator last, Value value) { - using namespace std; - // For find_end - { - auto expected = find_end(b, e, bsub, esub, pred); - auto actual = find_end(exec, b, e, bsub, esub); - EXPECT_TRUE(actual == expected, "wrong return result from find_end"); - - actual = find_end(exec, b, e, bsub, esub, pred); - EXPECT_TRUE(actual == expected, "wrong return result from find_end with a predicate"); - } - - // For search - { - auto expected = search(b, e, bsub, esub, pred); - auto actual = search(exec, b, e, bsub, esub); - EXPECT_TRUE(actual == expected, "wrong return result from search"); - - actual = search(exec, b, e, bsub, esub, pred); - EXPECT_TRUE(actual == expected, "wrong return result from search with a predicate"); - } + auto i = std::find(first, last, value); + auto j = find(exec, first, last, value); + EXPECT_TRUE(i == j, "wrong return value from find"); } }; -template <typename T> +template <typename T, typename Value, typename Hit, typename Miss> void -test(const std::size_t bits) +test(Value value, Hit hit, Miss miss) { - - const std::size_t max_n1 = 1000; - const std::size_t max_n2 = (max_n1 * 10) / 8; - Sequence<T> in(max_n1, [max_n1, bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); }); - Sequence<T> sub(max_n2, [max_n1, bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1)); }); - for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) { - std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; - std::size_t res[] = {0, 1, n1 / 2, n1}; - for (auto n2 : sub_n) + Sequence<T> in(n, [&](size_t k) -> T { return miss(n ^ k); }); + // Try different find positions, including not found. + // By going backwards, we can add extra matches that are *not* supposed to be found. + // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. + for (size_t m = n; m > 0; m *= 0.6) { - for (auto r : res) - { - std::size_t i = r, isub = 0; - for (; i < n1 && isub < n2; ++i, ++isub) - in[i] = sub[isub]; - invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2, - std::equal_to<T>()); - invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(), - sub.cbegin() + n2, std::equal_to<T>()); - } + if (m < n) + in[m] = hit(n ^ m); + invoke_on_all_policies(test_find(), in.begin(), in.end(), value); + invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value); } } } -template <typename T> -struct test_non_const +// Type defined for sake of checking that std::find works with asymmetric ==. +class Weird { - template <typename Policy, typename FirstIterator, typename SecondInterator> - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + Number value; + + public: + friend bool + operator==(Number x, Weird y) { - invoke_if(exec, [&]() { - find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>())); - search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>())); - }); + return x == y.value; } + Weird(int32_t val, OddTag) : value(val, OddTag()) {} }; -int32_t +int main() { - test<int32_t>(8 * sizeof(int32_t)); - test<uint16_t>(8 * sizeof(uint16_t)); - test<float64_t>(53); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test<bool>(1); -#endif + // Note that the "hit" and "miss" functions here avoid overflow issues. + test<Number>(Weird(42, OddTag()), [](int32_t) { return Number(42, OddTag()); }, // hit + [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss - test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>()); + // Test with value that is equal to two different bit patterns (-0.0 and 0.0) + test<float32_t>(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit + [](int32_t j) { return j == 0 ? ~j : j; }); // miss std::cout << done() << std::endl; return 0; diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc index 365771d..5a4a81a 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc @@ -28,17 +28,17 @@ 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator1, typename Iterator2, typename Predicate> void - operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + operator()(__pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { } template <typename Iterator1, typename Iterator2, typename Predicate> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) { } @@ -66,8 +66,8 @@ test(Predicate pred) const std::size_t max_n1 = 1000; const std::size_t max_n2 = (max_n1 * 10) / 8; - Sequence<T> in1(max_n1, [](std::size_t k) { return T(1); }); - Sequence<T> in2(max_n2, [](std::size_t k) { return T(0); }); + Sequence<T> in1(max_n1, [](std::size_t) { return T(1); }); + Sequence<T> in2(max_n2, [](std::size_t) { return T(0); }); for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) { std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8}; @@ -106,7 +106,7 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(std::equal_to<int32_t>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc index 0449ced..04ef148 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc @@ -29,17 +29,17 @@ using namespace TestUtils; struct test_find_if { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator, typename Predicate, typename NotPredicate> void - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, + operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) { } template <typename Iterator, typename Predicate, typename NotPredicate> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) { } @@ -97,10 +97,10 @@ struct test_non_const } }; -int32_t +int main() { -#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN +#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) // Note that the "hit" and "miss" functions here avoid overflow issues. test<Number>(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit [](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); }); // miss diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc index 412367c..51c5122 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc @@ -62,7 +62,7 @@ struct test_one_policy EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each"); // Try for_each_n - std::for_each_n(__pstl::execution::seq, expected_first, n, Flip<T>(1)); + std::for_each_n(std::execution::seq, expected_first, n, Flip<T>(1)); for_each_n(exec, first, n, Flip<T>(1)); EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n"); } @@ -96,7 +96,7 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc index 36096b1..1173186 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc @@ -53,7 +53,7 @@ struct test_mismatch using namespace std; typedef typename iterator_traits<Iterator1>::value_type T; { - const auto expected = mismatch(__pstl::execution::seq, first1, last1, first2, last2, std::equal_to<T>()); + const auto expected = mismatch(std::execution::seq, first1, last1, first2, last2, std::equal_to<T>()); const auto res1 = mismatch(exec, first1, last1, first2, last2, std::equal_to<T>()); EXPECT_TRUE(expected == res1, "wrong return result from mismatch"); const auto res2 = mismatch(exec, first1, last1, first2, last2); @@ -129,7 +129,7 @@ struct test_non_const } }; -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc index b563e48..a49b6b2 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc @@ -55,7 +55,7 @@ test(size_t bits) { // Sequence of odd values - Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); }); // Even value, or false when T is bool. T spike(2 * HashBits(n, bits - 1)); @@ -92,13 +92,13 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(8 * sizeof(int32_t)); test<uint16_t>(8 * sizeof(uint16_t)); test<float64_t>(53); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN) test<bool>(1); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc index 9aca6d2..61bbca7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc @@ -78,17 +78,17 @@ is_equal(const T& x, const T& y) 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + operator()(__pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { } template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) { } @@ -123,8 +123,7 @@ struct test_one_policy template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare> typename std::enable_if<!is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) + operator()(Policy&&, Iterator1, Iterator1, Iterator1, Iterator1, Size, Size, Generator1, Generator2, Compare) { } }; @@ -166,7 +165,7 @@ struct test_non_const } }; -int32_t +int main() { test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc index 7db9049..f3cc5d3 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc @@ -30,17 +30,17 @@ 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 +#if defined(_PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN) || defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename Iterator1, typename Iterator2> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) { } template <typename Iterator1, typename Iterator2> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) { } @@ -63,7 +63,7 @@ struct test_one_policy template <typename ExecutionPolicy, typename Iterator1, typename Iterator2> typename std::enable_if<is_same_iterator_category<Iterator1, std::forward_iterator_tag>::value>::type - operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) + operator()(ExecutionPolicy&&, Iterator1, Iterator1, Iterator2, Iterator2) { } }; @@ -98,13 +98,13 @@ struct wrapper } }; -int32_t +int main() { test<int32_t>(); test<uint16_t>(); test<float64_t>(); -#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN +#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN) test<wrapper<float64_t>>(); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc index 3ec0408..a6c39a2 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc @@ -70,16 +70,16 @@ struct test_one_policy 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename Iterator1> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + operator()(__pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) { } template <typename Iterator1> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) { } #endif @@ -90,7 +90,6 @@ struct test_one_policy { using namespace std; using T = typename iterator_traits<Iterator1>::value_type; - using DifferenceType = typename iterator_traits<Iterator1>::difference_type; fill(actual_b, actual_e, T(-123)); Iterator1 actual_return = reverse_copy(exec, data_b, data_e, actual_b); @@ -127,11 +126,9 @@ test() } } -int32_t +int main() { - // clang-3.8 fails to correctly auto vectorize the loop in some cases of different types of container's elements, - // for example: int32_t and int8_t. This issue isn't detected for clang-3.9 and newer versions. test<int16_t, int8_t>(); test<uint16_t, float32_t>(); test<float64_t, int64_t>(); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc index c0b73868..fab146f 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc @@ -28,16 +28,16 @@ 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator, typename Size, typename T, typename Predicate> void - operator()(pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) + operator()(__pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) { } template <typename Iterator, typename Size, typename T, typename Predicate> void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) { } @@ -77,7 +77,7 @@ test() } for (auto r : res) { - Sequence<T> in(n1, [n1](std::size_t k) { return T(0); }); + Sequence<T> in(n1, [](std::size_t) { return T(0); }); std::size_t i = r, isub = 0; for (; i < n1 && isub < n2; ++i, ++isub) in[i] = value; @@ -100,13 +100,13 @@ struct test_non_const } }; -int32_t +int main() { test<int32_t>(); test<uint16_t>(); test<float64_t>(); -#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN +#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN) test<bool>(); #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc index 3cf06aa..ed07810 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc @@ -67,8 +67,7 @@ struct test_one_policy template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) { } }; @@ -104,11 +103,11 @@ test_includes(Compare compare) } } -int32_t +int main() { - test_includes<float64_t, float64_t>(__pstl::__internal::__pstl_less()); + test_includes<float64_t, float64_t>(std::less<>()); test_includes<Num<int64_t>, Num<int32_t>>([](const Num<int64_t>& x, const Num<int32_t>& y) { return x < y; }); std::cout << done() << std::endl; diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc index a458993..bb3c3a5 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc @@ -43,16 +43,16 @@ struct WithCmpOp struct test_is_heap { -#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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator, typename Predicate> typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) + operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) { } template <typename Iterator, typename Predicate> typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) { } #endif @@ -87,13 +87,14 @@ struct test_is_heap const Iterator actual = is_heap_until(exec, first, last, pred); const auto x = std::distance(first, actual); EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate"); + EXPECT_EQ(x, y, "both iterators should be the same distance away from 'first'"); } } // is_heap, is_heap_until works only with random access iterators template <typename Policy, typename Iterator, typename Predicate> typename std::enable_if<!is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type - operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + operator()(Policy&&, Iterator, Iterator, Predicate) { } }; @@ -121,7 +122,7 @@ test_is_heap_by_type(Comp comp) invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); } - Sequence<T> in(max_size / 10, [](size_t v) -> T { return T(1); }); + Sequence<T> in(max_size / 10, [](size_t) -> T { return T(1); }); invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); } @@ -139,7 +140,7 @@ struct test_non_const } }; -int32_t +int main() { test_is_heap_by_type<float32_t>(std::greater<float32_t>()); diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc index 3c0230d..d88144e 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc @@ -76,7 +76,7 @@ test_is_sorted_by_type() invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end())); //non-descending order - Sequence<T> in1(9, [](size_t v) -> T { return T(0); }); + Sequence<T> in1(9, [](size_t) -> T { return T(0); }); invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end())); invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end())); } @@ -93,7 +93,7 @@ struct test_non_const } }; -int32_t +int main() { diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc index 1cc480c..924aa78 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc @@ -165,12 +165,12 @@ struct test_non_const } }; -int32_t +int main() { test<uint16_t, float64_t>(std::less<float64_t>()); test<float32_t, int32_t>(std::greater<float32_t>()); -#if !_PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN +#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN) test<float64_t, int32_t>([](const float64_t x, const int32_t y) { return x * x < y * y; }); #endif test<LocalWrapper<int32_t>, LocalWrapper<int32_t>>( diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc index 60522a4..0a9f41c 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc @@ -184,7 +184,7 @@ struct test_non_const } }; -int32_t +int main() { using TestUtils::float64_t; diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc index cf12bfc..6d441cc 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc @@ -90,19 +90,18 @@ struct test_brick_partial_sort //checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads; if (m1 - first > 1) { - auto complex = std::ceil(n * std::log(float32_t(m1 - first))); -#if _PSTL_USE_PAR_POLICIES +#ifdef _DEBUG +# if defined(_PSTL_PAR_BACKEND_TBB) auto p = tbb::this_task_arena::max_concurrency(); -#else +# else auto p = 1; -#endif - -#ifdef _DEBUG +# endif + auto complex = std::ceil(n * std::log(float32_t(m1 - first))); if (count_comp > complex * p) { std::cout << "complexity exceeded" << std::endl; } -#endif +#endif // _DEBUG } } } @@ -110,8 +109,7 @@ struct test_brick_partial_sort template <typename Policy, typename InputIterator, typename Compare> typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value, void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, - Compare compare) + operator()(Policy&&, InputIterator, InputIterator, InputIterator, InputIterator, Compare) { } }; @@ -142,7 +140,7 @@ struct test_non_const } }; -int32_t +int main() { count_val = 0; diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc index 7c5608a..72336d6 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc @@ -64,32 +64,32 @@ struct test_one_policy : 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename InputIterator, typename Size, typename T, typename Compare> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { } template <typename InputIterator, typename Size, typename T, typename Compare> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, Compare compare) { } template <typename InputIterator, typename Size, typename T> void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { } template <typename InputIterator, typename Size, typename T> void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) { } @@ -187,7 +187,7 @@ struct test_non_const } }; -int32_t +int main() { test_partial_sort_copy<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; }); @@ -195,6 +195,11 @@ main() test_algo_basic_double<int32_t>(run_for_rnd<test_non_const<int32_t>>()); + test_partial_sort_copy<MemoryChecker>( + [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() < val2.value(); }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from partial_sort_copy: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from partial_sort_copy: number of ctors calls > num of dtors calls"); + std::cout << done() << std::endl; return 0; } diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc index 5d411a8..0343739 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc @@ -60,7 +60,8 @@ struct Num } }; -struct test_one_policy +template <typename Type> +struct test_set_union { template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type @@ -75,30 +76,98 @@ struct test_one_policy Sequence<T1> expect(n); Sequence<T1> out(n); - //1. set_union auto expect_res = std::set_union(first1, last1, first2, last2, expect.begin(), comp); auto res = std::set_union(exec, first1, last1, first2, last2, out.begin(), comp); EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_union"); EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_union effect"); + } + + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template <typename Type> +struct test_set_intersection +{ + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits<InputIterator1>::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence<T1> expect(n); + Sequence<T1> out(n); - //2. set_intersection - expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp); + auto expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp); EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_intersection"); EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_intersection effect"); + } + + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template <typename Type> +struct test_set_difference +{ + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits<InputIterator1>::value_type; - //3. set_difference - expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp); + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence<T1> expect(n); + Sequence<T1> out(n); + + auto expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp); EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_difference"); EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_difference effect"); + } + + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) + { + } +}; + +template <typename Type> +struct test_set_symmetric_difference +{ + template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> + typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits<InputIterator1>::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence<T1> expect(n); + Sequence<T1> out(n); - //4. set_symmetric_difference - expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp); + auto expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp); EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_symmetric_difference"); EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), @@ -107,8 +176,7 @@ struct test_one_policy template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare> typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) + operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare) { } }; @@ -128,43 +196,92 @@ test_set(Compare compare) for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) { //prepare the input ranges - Sequence<T1> in1(n, [n](std::size_t k) { return rand() % (2 * k + 1); }); + Sequence<T1> in1(n, [](std::size_t k) { return rand() % (2 * k + 1); }); Sequence<T2> in2(m, [m](std::size_t k) { return (m % 2) * rand() + rand() % (k + 1); }); std::sort(in1.begin(), in1.end(), compare); std::sort(in2.begin(), in2.end(), compare); - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); + invoke_on_all_policies(test_set_union<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_intersection<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_difference<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + compare); + + invoke_on_all_policies(test_set_symmetric_difference<T1>(), in1.begin(), in1.end(), in2.cbegin(), + in2.cend(), compare); } } } template <typename T> -struct test_non_const +struct test_non_const_set_difference { template <typename Policy, typename InputIterator, typename OutputInterator> void operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) { set_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>())); + } +}; +template <typename T> +struct test_non_const_set_intersection +{ + template <typename Policy, typename InputIterator, typename OutputInterator> + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>())); + } +}; +template <typename T> +struct test_non_const_set_symmetric_difference +{ + template <typename Policy, typename InputIterator, typename OutputInterator> + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>())); + } +}; +template <typename T> +struct test_non_const_set_union +{ + template <typename Policy, typename InputIterator, typename OutputInterator> + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>())); } }; -int32_t +int main() { - test_set<float64_t, float64_t>(__pstl::__internal::__pstl_less()); + test_set<float64_t, float64_t>(std::less<>()); test_set<Num<int64_t>, Num<int32_t>>([](const Num<int64_t>& x, const Num<int32_t>& y) { return x < y; }); - test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>()); + test_set<MemoryChecker, MemoryChecker>([](const MemoryChecker& val1, const MemoryChecker& val2) -> bool { + return val1.value() < val2.value(); + }); + EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from set algorithms: number of ctors calls < num of dtors calls"); + EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from set algorithms: number of ctors calls > num of dtors calls"); + + test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_difference<int32_t>>()); + + test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_intersection<int32_t>>()); + + test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_symmetric_difference<int32_t>>()); + + test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_union<int32_t>>()); std::cout << done() << std::endl; diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc index b460c59..94257bd 100644 --- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc +++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc @@ -94,7 +94,7 @@ class ParanoidKey index = k.index; return *this; } - ParanoidKey(int32_t index, int32_t value, OddTag) : index(index), value(value) {} + ParanoidKey(int32_t index, int32_t value, OddTag) : value(value), index(index) {} ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index) { EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead"); @@ -171,7 +171,7 @@ struct test_sort_with_compare typename std::enable_if<is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value, void>::type operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, - OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) + OutputIterator2 expected_last, InputIterator first, InputIterator, Size n, Compare compare) { using namespace std; copy_n(first, n, expected_first); @@ -198,8 +198,8 @@ struct test_sort_with_compare typename Compare> typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value, void>::type - operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, - OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) + operator()(Policy&&, OutputIterator, OutputIterator, OutputIterator2, OutputIterator2, InputIterator, InputIterator, + Size, Compare) { } }; @@ -233,7 +233,7 @@ struct test_non_const } }; -int32_t +int main() { std::srand(42); diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc index b784108..cf42b71 100644 --- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc +++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc @@ -33,19 +33,19 @@ template <typename T> struct wrapper { T t; - explicit wrapper(T t_) : t(t_) {} + constexpr explicit wrapper(T t_) : t(t_) {} template <typename T2> - wrapper(const wrapper<T2>& a) + constexpr wrapper(const wrapper<T2>& a) { t = a.t; } template <typename T2> - void + constexpr void operator=(const wrapper<T2>& a) { t = a.t; } - wrapper<T> + constexpr wrapper<T> operator-(const wrapper<T>& a) const { return wrapper<T>(t - a.t); @@ -75,9 +75,11 @@ compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Functio if (first == last) return true; - T2 temp(*first); - if (!compare(temp, *d_first)) - return false; + { + T2 temp(*first); + if (!compare(temp, *d_first)) + return false; + } Iterator1 second = std::next(first); ++d_first; @@ -94,25 +96,25 @@ compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Functio // 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 Iterator1, typename Iterator2, typename T, typename Function> -typename std::enable_if<std::is_floating_point<T>::value, bool>::type -compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function) +typename std::enable_if<std::is_floating_point<T>::value, bool>::type compute_and_check(Iterator1, Iterator1, Iterator2, + 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 +#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \ + defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration template <typename Iterator1, typename Iterator2, typename T, typename Function> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, T trash, Function f) { } template <typename Iterator1, typename Iterator2, typename T, typename Function> typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, T trash, Function f) { } @@ -146,16 +148,14 @@ template <typename T1, typename T2, typename Pred> void test(Pred pred) { - typedef typename Sequence<T2>::iterator iterator_type; - const std::size_t max_len = 100000; - const T2 value = T2(77); - const T1 trash = T1(31); + static constexpr T2 value = T2(77); + static constexpr T1 trash = T1(31); Sequence<T1> actual(max_len, [](std::size_t i) { return T1(i); }); - Sequence<T2> data(max_len, [&value](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; }); + Sequence<T2> data(max_len, [](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)) { @@ -166,7 +166,7 @@ test(Pred pred) } } -int32_t +int main() { test<uint8_t, uint32_t>([](uint32_t a, uint32_t b) { return a - b; }); diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc index e9f506b..5a8f921 100644 --- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc +++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc @@ -62,7 +62,7 @@ test_long_form(T init, BinaryOp binary_op, F f) struct test_two_short_forms { -#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specialization by policy type, in case of broken configuration +#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) //dummy specialization by policy type, in case of broken configuration template <typename Iterator> void operator()(__pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected) @@ -105,7 +105,7 @@ test_short_forms() } } -int32_t +int main() { // Test for popular types diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc index 2173d7b..bcd5ad1 100644 --- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc +++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc @@ -108,12 +108,13 @@ struct test_scan_with_plus template <typename Policy, typename Iterator1, typename Iterator2, typename Iterator3, typename Size, typename T> void operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, T trash) + Iterator3 expected_first, Iterator3, Size n, T init, T trash) { using namespace std; auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first) : exclusive_scan_serial(in_first, in_last, expected_first, init); + (void)orr1; auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first) : exclusive_scan(exec, in_first, in_last, out_first, init); EXPECT_TRUE(out_last == orr, @@ -146,12 +147,13 @@ struct test_scan_with_binary_op typename BinaryOp> typename std::enable_if<!TestUtils::isReverse<Iterator1>::value, void>::type operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) + Iterator3 expected_first, Iterator3, Size n, T init, BinaryOp binary_op, T trash) { using namespace std; auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first, binary_op, init) : exclusive_scan_serial(in_first, in_last, expected_first, init, binary_op); + (void)orr1; auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first, binary_op, init) : exclusive_scan(exec, in_first, in_last, out_first, init, binary_op); @@ -162,8 +164,7 @@ struct test_scan_with_binary_op template <typename Policy, typename Iterator1, typename Iterator2, typename Iterator3, typename Size, typename T, typename BinaryOp> typename std::enable_if<TestUtils::isReverse<Iterator1>::value, void>::type - operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) + operator()(Policy&&, Iterator1, Iterator1, Iterator2, Iterator2, Iterator3, Iterator3, Size, T, BinaryOp, T) { } }; @@ -186,13 +187,13 @@ test_matrix(Out init, BinaryOp binary_op, Out trash) } } -int32_t +int main() { for (int32_t mode = 0; mode < 2; ++mode) { inclusive = mode != 0; -#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN +#if !defined(_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN) // Test with highly restricted type and associative but not commutative operation test_matrix<Matrix2x2<int32_t>, Matrix2x2<int32_t>>(Matrix2x2<int32_t>(), multiply_matrix<int32_t>, Matrix2x2<int32_t>(-666, 666)); diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc index bec1c14..7497d60 100644 --- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc +++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc @@ -54,7 +54,7 @@ class MyClass int32_t my_field; MyClass() { my_field = 0; } MyClass(int32_t in) { my_field = in; } - MyClass(const MyClass& in) { my_field = in.my_field; } + MyClass(const MyClass& in) = default; friend MyClass operator+(const MyClass& x, const MyClass& y) @@ -66,11 +66,13 @@ class MyClass { return MyClass(-x.my_field); } - friend MyClass operator*(const MyClass& x, const MyClass& y) { return MyClass(x.my_field * y.my_field); } - bool - operator==(const MyClass& in) const + friend MyClass operator*(const MyClass& x, const MyClass& y) { - return my_field == in.my_field; + return MyClass(x.my_field * y.my_field); + } + friend bool operator==(const MyClass& x, const MyClass& y) + { + return x.my_field == y.my_field; } }; @@ -78,13 +80,13 @@ template <typename T> void CheckResults(const T& expected, const T& in) { - EXPECT_TRUE(Equal(expected, in), "wrong result of transform_reduce"); + EXPECT_TRUE(expected == in, "wrong result of transform_reduce"); } // We need to check correctness only for "int" (for example) except cases // if we have "floating-point type"-specialization void -CheckResults(const float32_t& expected, const float32_t& in) +CheckResults(const float32_t&, const float32_t&) { } @@ -94,7 +96,7 @@ struct test_transform_reduce template <typename Policy, typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1, typename BinaryOperation2, typename UnaryOp> void - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2, T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU) { @@ -125,20 +127,19 @@ test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU, } } -int32_t +int main() { test_by_type<int32_t>(42, std::plus<int32_t>(), std::multiplies<int32_t>(), std::negate<int32_t>(), - [](std::size_t a) -> int32_t { return int32_t(rand() % 1000); }); + [](std::size_t) -> int32_t { return int32_t(rand() % 1000); }); test_by_type<int64_t>(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(), [](const int64_t& x) -> int64_t { return x * 2; }, - [](std::size_t a) -> int64_t { return int64_t(rand() % 1000); }); - test_by_type<float32_t>(1.0f, std::multiplies<float32_t>(), - [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, - [](const float32_t& x) -> float32_t { return x + 2; }, - [](std::size_t a) -> float32_t { return rand() % 1000; }); + [](std::size_t) -> int64_t { return int64_t(rand() % 1000); }); + test_by_type<float32_t>( + 1.0f, std::multiplies<float32_t>(), [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, + [](const float32_t& x) -> float32_t { return x + 2; }, [](std::size_t) -> float32_t { return rand() % 1000; }); test_by_type<MyClass>(MyClass(), std::plus<MyClass>(), std::multiplies<MyClass>(), std::negate<MyClass>(), - [](std::size_t a) -> MyClass { return MyClass(rand() % 1000); }); + [](std::size_t) -> MyClass { return MyClass(rand() % 1000); }); std::cout << done() << std::endl; return 0; diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc index c9694af..e785a95 100644 --- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc +++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc @@ -47,15 +47,15 @@ struct test_transform_scan typename T, typename BinaryOp> typename std::enable_if<!TestUtils::isReverse<InputIterator>::value, void>::type operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, - UnaryOp unary_op, T init, BinaryOp binary_op, T trash) + OutputIterator out_last, OutputIterator expected_first, OutputIterator, Size n, UnaryOp unary_op, T init, + BinaryOp binary_op, T trash) { using namespace std; - auto orr1 = inclusive ? transform_inclusive_scan(__pstl::execution::seq, first, last, expected_first, binary_op, - unary_op, init) - : transform_exclusive_scan(__pstl::execution::seq, first, last, expected_first, init, - binary_op, unary_op); + auto orr1 = + inclusive + ? transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op, init) + : transform_exclusive_scan(std::execution::seq, first, last, expected_first, init, binary_op, unary_op); auto orr2 = inclusive ? transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op, init) : transform_exclusive_scan(exec, first, last, out_first, init, binary_op, unary_op); EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); @@ -64,7 +64,7 @@ struct test_transform_scan // Checks inclusive scan if init is not provided if (inclusive && n > 0) { - orr1 = transform_inclusive_scan(__pstl::execution::seq, first, last, expected_first, binary_op, unary_op); + orr1 = transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op); orr2 = transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op); EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); check_and_reset(expected_first, out_first, n, trash); @@ -74,9 +74,8 @@ struct test_transform_scan template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename UnaryOp, typename T, typename BinaryOp> typename std::enable_if<TestUtils::isReverse<InputIterator>::value, void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, - UnaryOp unary_op, T init, BinaryOp binary_op, T trash) + operator()(Policy&&, InputIterator, InputIterator, OutputIterator, OutputIterator, OutputIterator, OutputIterator, + Size, UnaryOp, T, BinaryOp, T) { } }; @@ -140,6 +139,7 @@ test(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) inclusive ? transform_inclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op) : transform_exclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op); + (void)result; check_and_reset(expected.begin(), out.begin(), out.size(), trash); invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), @@ -167,13 +167,13 @@ test_matrix(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) } } -int32_t +int main() { for (int32_t mode = 0; mode < 2; ++mode) { inclusive = mode != 0; -#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN +#if !defined(_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN) test_matrix<Matrix2x2<int32_t>, Matrix2x2<int32_t>>([](const Matrix2x2<int32_t> x) { return x; }, Matrix2x2<int32_t>(), multiply_matrix<int32_t>, Matrix2x2<int32_t>(-666, 666)); diff --git a/libstdc++-v3/testsuite/util/pstl/test_utils.h b/libstdc++-v3/testsuite/util/pstl/test_utils.h index 80a8f9c..ed6d48b 100644 --- a/libstdc++-v3/testsuite/util/pstl/test_utils.h +++ b/libstdc++-v3/testsuite/util/pstl/test_utils.h @@ -30,7 +30,7 @@ typedef float float32_t; template <class T, std::size_t N> constexpr size_t -const_size(const T (&array)[N]) noexcept +const_size(const T (&)[N]) noexcept { return N; } @@ -119,7 +119,7 @@ expect_equal(Iterator1 expected_first, Iterator2 actual_first, Size n, const cha const char* message) { size_t error_count = 0; - for (size_t k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first) + for (Size k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first) { if (!(*expected_first == *actual_first)) { @@ -231,6 +231,82 @@ fill_data(Iterator first, Iterator last, F f) } } +struct MemoryChecker { + // static counters and state tags + static std::atomic<std::int64_t> alive_object_counter; // initialized outside + static constexpr std::int64_t alive_state = 0xAAAAAAAAAAAAAAAA; + static constexpr std::int32_t dead_state = 0; // only used as a set value to cancel alive_state + + std::int32_t _value; // object value used for algorithms + std::int64_t _state; // state tag used for checks + + // ctors, dtors, assign ops + explicit MemoryChecker(std::int32_t value = 0) : _value(value) { + // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since we cannot guarantee that + // raw memory for object being constructed does not have a bit sequence being equal to alive_state + + // set constructed state and increment counter for living object + inc_alive_objects(); + _state = alive_state; + } + MemoryChecker(MemoryChecker&& other) : _value(other.value()) { + // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since + // compiler can optimize out the move ctor call that results in false positive failure + EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker(MemoryChecker&&): attemp to construct an object from non-existing object"); + // set constructed state and increment counter for living object + inc_alive_objects(); + _state = alive_state; + } + MemoryChecker(const MemoryChecker& other) : _value(other.value()) { + // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since + // compiler can optimize out the copy ctor call that results in false positive failure + EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker(const MemoryChecker&): attemp to construct an object from non-existing object"); + // set constructed state and increment counter for living object + inc_alive_objects(); + _state = alive_state; + } + MemoryChecker& operator=(MemoryChecker&& other) { + // check if we do not assign over uninitialized memory + EXPECT_TRUE(state() == alive_state, "wrong effect from MemoryChecker::operator=(MemoryChecker&& other): attemp to assign to non-existing object"); + EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker::operator=(MemoryChecker&& other): attemp to assign from non-existing object"); + // just assign new value, counter is the same, state is the same + _value = other.value(); + + return *this; + } + MemoryChecker& operator=(const MemoryChecker& other) { + // check if we do not assign over uninitialized memory + EXPECT_TRUE(state() == alive_state, "wrong effect from MemoryChecker::operator=(const MemoryChecker& other): attemp to assign to non-existing object"); + EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker::operator=(const MemoryChecker& other): attemp to assign from non-existing object"); + // just assign new value, counter is the same, state is the same + _value = other.value(); + + return *this; + } + ~MemoryChecker() { + // check if we do not double destruct the object + EXPECT_TRUE(state() == alive_state, "wrong effect from ~MemoryChecker(): attemp to destroy non-existing object"); + // set destructed state and decrement counter for living object + static_cast<volatile std::int64_t&>(_state) = dead_state; + dec_alive_objects(); + } + + // getters + std::int32_t value() const { return _value; } + std::int64_t state() const { return _state; } + static std::int32_t alive_objects() { return alive_object_counter.load(); } +private: + // setters + void inc_alive_objects() { alive_object_counter.fetch_add(1); } + void dec_alive_objects() { alive_object_counter.fetch_sub(1); } +}; + +std::atomic<std::int64_t> MemoryChecker::alive_object_counter{0}; + +std::ostream& operator<<(std::ostream& os, const MemoryChecker& val) { return (os << val.value()); } +bool operator==(const MemoryChecker& v1, const MemoryChecker& v2) { return v1.value() == v2.value(); } +bool operator<(const MemoryChecker& v1, const MemoryChecker& v2) { return v1.value() < v2.value(); } + // Sequence<T> is a container of a sequence of T with lots of kinds of iterators. // Prefixes on begin/end mean: // c = "const" @@ -572,7 +648,7 @@ struct Matrix2x2 T a[2][2]; Matrix2x2() : a{{1, 0}, {0, 1}} {} Matrix2x2(T x, T y) : a{{0, x}, {x, y}} {} -#if !_PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN +#if !defined(_PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN) Matrix2x2(const Matrix2x2& m) : a{{m.a[0][0], m.a[0][1]}, {m.a[1][0], m.a[1][1]}} {} Matrix2x2& operator=(const Matrix2x2& m) @@ -651,7 +727,7 @@ struct ReverseAdapter iterator_type operator()(Iterator it) { -#if _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT +#if defined(_PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT) return std::make_reverse_iterator(it); #else return iterator_type(it); @@ -1191,7 +1267,7 @@ transform_reduce_serial(InputIterator first, InputIterator last, T init, BinaryO static const char* done() { -#if _PSTL_TEST_SUCCESSFUL_KEYWORD +#if defined(_PSTL_TEST_SUCCESSFUL_KEYWORD) return "done"; #else return "passed"; @@ -1228,8 +1304,12 @@ template <typename Policy, typename F> static void invoke_if(Policy&&, F f) { -#if _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN - __pstl::__internal::invoke_if_not(__pstl::__internal::allow_unsequenced<Policy>(), f); +#if defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) + using decay_policy = typename std::decay<Policy>::type; + using allow_unsequenced = + std::integral_constant<bool, (std::is_same<decay_policy, std::execution::unsequenced_policy>::value || + std::is_same<decay_policy, std::execution::parallel_unsequenced_policy>::value)>; + __pstl::__internal::__invoke_if_not(allow_unsequenced{}, f); #else f(); #endif |