summaryrefslogtreecommitdiffstats
path: root/pstl/test/std/algorithms
diff options
context:
space:
mode:
authorLouis Dionne <ldionne@apple.com>2019-03-27 21:28:24 +0000
committerLouis Dionne <ldionne@apple.com>2019-03-27 21:28:24 +0000
commit3b62047b8b2209bed57d239f581bdbfc91a10b94 (patch)
treee321a0dea2d7355c3eca7c9cf9ae1f2b89823c1d /pstl/test/std/algorithms
parent4bc38cfe297746858a7159bd4a537261d628b47e (diff)
downloadbcm5719-llvm-3b62047b8b2209bed57d239f581bdbfc91a10b94.tar.gz
bcm5719-llvm-3b62047b8b2209bed57d239f581bdbfc91a10b94.zip
Restructure test suite to follow libc++ standard layout
Summary: Subsumes changes requested in https://reviews.llvm.org/D59110 Reviewers: EricWF, ldionne Subscribers: mgorny, krytarowski, jfb, jdoerfert, libcxx-commits Differential Revision: https://reviews.llvm.org/D59856 llvm-svn: 357124
Diffstat (limited to 'pstl/test/std/algorithms')
-rw-r--r--pstl/test/std/algorithms/alg.merge/inplace_merge.pass.cpp160
-rw-r--r--pstl/test/std/algorithms/alg.merge/merge.pass.cpp119
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp150
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp104
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp183
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp120
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp108
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp137
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp204
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/fill.pass.cpp104
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/generate.pass.cpp107
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/remove.pass.cpp157
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp94
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/replace.pass.cpp163
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp108
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp177
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp150
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp137
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp124
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp94
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/unique.pass.cpp160
-rw-r--r--pstl/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp138
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp118
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp120
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp106
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/count.pass.cpp111
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/equal.pass.cpp171
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/find.pass.cpp99
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp126
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp115
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp112
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp105
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp139
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp104
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp181
-rw-r--r--pstl/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp112
-rw-r--r--pstl/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp148
-rw-r--r--pstl/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp179
-rw-r--r--pstl/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp198
-rw-r--r--pstl/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp111
-rw-r--r--pstl/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp167
-rw-r--r--pstl/test/std/algorithms/alg.sorting/is_sorted.pass.cpp104
-rw-r--r--pstl/test/std/algorithms/alg.sorting/partial_sort.pass.cpp156
-rw-r--r--pstl/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp195
-rw-r--r--pstl/test/std/algorithms/alg.sorting/sort.pass.cpp251
45 files changed, 6226 insertions, 0 deletions
diff --git a/pstl/test/std/algorithms/alg.merge/inplace_merge.pass.cpp b/pstl/test/std/algorithms/alg.merge/inplace_merge.pass.cpp
new file mode 100644
index 00000000000..6e89ab82eff
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.merge/inplace_merge.pass.cpp
@@ -0,0 +1,160 @@
+// -*- C++ -*-
+//===-- inplace_merge.pass.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <algorithm>
+#include "pstl/execution"
+#include "pstl/algorithm"
+
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+ template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
+ void
+ operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2,
+ Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
+ {
+ }
+
+ template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2,
+ BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
+ {
+ }
+#endif
+
+ // inplace_merge works with bidirectional iterators at least
+ template <typename 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)
+ {
+
+ 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);
+
+ const BiDirIt1 mid2 = std::next(first2, m);
+ fill_data(first2, mid2, generator1);
+ fill_data(mid2, last2, generator2);
+
+ std::inplace_merge(first1, mid1, last1, comp);
+ std::inplace_merge(exec, first2, mid2, last2, comp);
+ EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate");
+ }
+
+ template <typename 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)
+ {
+ }
+};
+
+template <typename T, typename Generator1, typename Generator2, typename Compare>
+void
+test_by_type(Generator1 generator1, Generator2 generator2, Compare comp)
+{
+ using namespace std;
+ size_t max_size = 100000;
+ Sequence<T> in1(max_size, [](size_t v) { return T(v); });
+ Sequence<T> exp(max_size, [](size_t v) { return T(v); });
+ size_t m;
+
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ m = 0;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
+ generator1, generator2, comp);
+
+ m = n / 3;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
+ generator1, generator2, comp);
+
+ m = 2 * n / 3;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m,
+ generator1, generator2, comp);
+ }
+}
+
+template <typename T>
+struct LocalWrapper
+{
+ explicit LocalWrapper(int32_t k) : my_val(k) {}
+ LocalWrapper(LocalWrapper&& input) { my_val = std::move(input.my_val); }
+ LocalWrapper&
+ operator=(LocalWrapper&& input)
+ {
+ my_val = std::move(input.my_val);
+ return *this;
+ }
+ bool
+ operator<(const LocalWrapper<T>& w) const
+ {
+ return my_val < w.my_val;
+ }
+ friend bool
+ operator==(const LocalWrapper<T>& x, const LocalWrapper<T>& y)
+ {
+ return x.my_val == y.my_val;
+ }
+ friend std::ostream&
+ operator<<(std::ostream& stream, const LocalWrapper<T>& input)
+ {
+ return stream << input.my_val;
+ }
+
+ private:
+ T my_val;
+};
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() { inplace_merge(exec, iter, iter, iter, non_const(std::less<T>())); });
+ }
+};
+
+int32_t
+main()
+{
+ test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); },
+ [](const float64_t x, const float64_t y) { return x > y; });
+
+ test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>());
+
+ test_by_type<LocalWrapper<float32_t>>([](int32_t i) { return LocalWrapper<float32_t>(2 * i + 1); },
+ [](int32_t i) { return LocalWrapper<float32_t>(2 * i); },
+ std::less<LocalWrapper<float32_t>>());
+
+ test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.merge/merge.pass.cpp b/pstl/test/std/algorithms/alg.merge/merge.pass.cpp
new file mode 100644
index 00000000000..a80bbae07f8
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.merge/merge.pass.cpp
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+//===-- merge.pass.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <algorithm>
+#include <functional>
+#include "pstl/execution"
+#include "pstl/algorithm"
+
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_merge
+{
+ template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator,
+ typename Compare>
+ void
+ operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
+ OutputIterator out_first, OutputIterator out_last, Compare comp)
+ {
+ using namespace std;
+ {
+ const auto res = merge(exec, first1, last1, first2, last2, out_first, comp);
+ EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate");
+ EXPECT_TRUE(is_sorted(out_first, res, comp), "wrong result from merge with predicate");
+ EXPECT_TRUE(includes(out_first, res, first1, last1, comp), "first sequence is not a part of result");
+ EXPECT_TRUE(includes(out_first, res, first2, last2, comp), "second sequence is not a part of result");
+ }
+ {
+ const auto res = merge(exec, first1, last1, first2, last2, out_first);
+ EXPECT_TRUE(res == out_last, "wrong return result from merge");
+ EXPECT_TRUE(is_sorted(out_first, res), "wrong result from merge");
+ }
+ }
+
+ // for reverse iterators
+ template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator,
+ typename Compare>
+ 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)
+ {
+ using namespace std;
+ typedef typename std::iterator_traits<std::reverse_iterator<InputIterator1>>::value_type T;
+ const auto res = merge(exec, first1, last1, first2, last2, out_first, std::greater<T>());
+
+ EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate");
+ EXPECT_TRUE(is_sorted(out_first, res, std::greater<T>()), "wrong result from merge with predicate");
+ EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater<T>()),
+ "first sequence is not a part of result");
+ EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater<T>()),
+ "second sequence is not a part of result");
+ }
+};
+
+template <typename T, typename Generator1, typename Generator2>
+void
+test_merge_by_type(Generator1 generator1, Generator2 generator2)
+{
+ using namespace std;
+ size_t max_size = 100000;
+ Sequence<T> in1(max_size, generator1);
+ Sequence<T> in2(max_size / 2, generator2);
+ Sequence<T> out(in1.size() + in2.size());
+ std::sort(in1.begin(), in1.end());
+ std::sort(in2.begin(), in2.end());
+
+ for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size))
+ {
+ invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2,
+ out.begin(), out.begin() + 1.5 * size, std::less<T>());
+ invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2,
+ out.begin(), out.begin() + 3 * size / 2, std::less<T>());
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputIterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter)
+ {
+ merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+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
+ 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
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp
new file mode 100644
index 00000000000..5e6ea34ed80
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp
@@ -0,0 +1,150 @@
+// -*- C++ -*-
+//===-- copy_if.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for copy_if and remove_copy_if
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ typename Predicate, typename T>
+ void
+ operator()(pstl::execution::parallel_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+ OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n,
+ Predicate pred, T trash)
+ {
+ }
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ typename Predicate, typename T>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+ OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
+ OutputIterator2 expected_last, Size n, Predicate pred, T trash)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+
+ // Run copy_if
+ auto i = copy_if(first, last, expected_first, pred);
+ auto k = copy_if(exec, first, last, out_first, pred);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong copy_if effect");
+ for (size_t j = 0; j < GuardSize; ++j)
+ {
+ ++k;
+ }
+ EXPECT_TRUE(out_last == k, "wrong return value from copy_if");
+
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+ // Run remove_copy_if
+ i = remove_copy_if(first, last, expected_first, [=](const T& x) { return !pred(x); });
+ k = remove_copy_if(exec, first, last, out_first, [=](const T& x) { return !pred(x); });
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy_if effect");
+ for (size_t j = 0; j < GuardSize; ++j)
+ {
+ ++k;
+ }
+ EXPECT_TRUE(out_last == k, "wrong return value from remove_copy_if");
+ }
+};
+
+template <typename T, typename Predicate, typename Convert>
+void
+test(T trash, Predicate pred, Convert convert, bool check_weakness = true)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ // count is number of output elements, plus a handful
+ // more for sake of detecting buffer overruns.
+ size_t count = GuardSize;
+ Sequence<T> in(n, [&](size_t k) -> T {
+ T val = convert(n ^ k);
+ count += pred(val) ? 1 : 0;
+ return val;
+ });
+
+ Sequence<T> out(count, [=](size_t) { return trash; });
+ Sequence<T> expected(count, [=](size_t) { return trash; });
+ if (check_weakness)
+ {
+ auto expected_result = copy_if(in.cfbegin(), in.cfend(), expected.begin(), pred);
+ size_t m = expected_result - expected.begin();
+ EXPECT_TRUE(n / 4 <= m && m <= 3 * (n + 1) / 4, "weak test for copy_if");
+ }
+ invoke_on_all_policies(run_copy_if(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), count, pred, trash);
+ invoke_on_all_policies(run_copy_if(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(),
+ expected.end(), count, pred, trash);
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even));
+
+ invoke_if(exec, [&]() { remove_copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even)); });
+ }
+};
+
+int32_t
+main()
+{
+ test<float64_t>(-666.0, [](const float64_t& x) { return x * x <= 1024; },
+ [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? float64_t(j % 32) : float64_t(j % 33 + 34); });
+
+ 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
+ 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);
+#endif
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp
new file mode 100644
index 00000000000..5d665d25516
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//===-- is_partitioned.pass.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+
+ template <typename Iterator1, typename Predicate>
+ void
+ 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)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Predicate pred)
+ {
+ const bool expected = std::is_partitioned(begin1, end1, pred);
+ const bool actual = std::is_partitioned(exec, begin1, end1, pred);
+ EXPECT_TRUE(actual == expected, "wrong return result from is_partitioned");
+ }
+};
+
+template <typename T, typename Predicate>
+void
+test(Predicate pred)
+{
+
+ const std::size_t max_n = 1000000;
+ Sequence<T> in(max_n, [](std::size_t k) { return T(k); });
+
+ for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
+ {
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, pred);
+ std::partition(in.begin(), in.begin() + n1, pred);
+ invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, pred);
+ }
+}
+
+template <typename T>
+struct LocalWrapper
+{
+ explicit LocalWrapper(std::size_t k) : my_val(k) {}
+
+ private:
+ T my_val;
+};
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ invoke_if(exec, [&]() { is_partitioned(exec, iter, iter, non_const(is_even)); });
+ }
+};
+
+int32_t
+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; });
+#endif
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp
new file mode 100644
index 00000000000..b79a27a44a0
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp
@@ -0,0 +1,183 @@
+// -*- C++ -*-
+//===-- partition.pass.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for stable_partition and partition
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+#include <iterator>
+#include <type_traits>
+
+using namespace TestUtils;
+
+template <typename T>
+struct DataType
+{
+ explicit DataType(int32_t k) : my_val(k) {}
+ DataType(DataType&& input) { my_val = std::move(input.my_val); }
+ DataType&
+ operator=(DataType&& input)
+ {
+ my_val = std::move(input.my_val);
+ return *this;
+ }
+ T
+ get_val() const
+ {
+ return my_val;
+ }
+
+ friend std::ostream&
+ operator<<(std::ostream& stream, const DataType<T>& input)
+ {
+ return stream << input.my_val;
+ }
+
+ private:
+ T my_val;
+};
+
+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)
+{
+ return std::equal(first, last, 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)
+{
+ 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
+ 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,
+ Size n, UnaryOp unary_op, Generator generator)
+ {
+ }
+
+ template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first,
+ 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
+ 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,
+ Size n, UnaryOp unary_op, Generator generator)
+ {
+ }
+
+ template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first,
+ BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator)
+ {
+ }
+#endif
+
+ template <typename 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)
+ {
+ // partition
+ {
+ fill_data(first, last, generator);
+ BiDirIt actual_ret = std::partition(exec, first, last, unary_op);
+ EXPECT_TRUE(std::all_of(first, actual_ret, unary_op) && !std::any_of(actual_ret, last, unary_op),
+ "wrong effect from partition");
+ }
+ // stable_partition
+ {
+ fill_data(exp_first, exp_last, generator);
+ BiDirIt exp_ret = std::stable_partition(exp_first, exp_last, unary_op);
+ fill_data(first, last, generator);
+ BiDirIt actual_ret = std::stable_partition(exec, first, last, unary_op);
+
+ EXPECT_TRUE(std::distance(first, actual_ret) == std::distance(exp_first, exp_ret),
+ "wrong result from stable_partition");
+ EXPECT_TRUE((is_equal<BiDirIt>(exp_first, exp_last, first)), "wrong effect from stable_partition");
+ }
+ }
+ 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)
+ {
+ }
+};
+
+template <typename T, typename Generator, typename UnaryPred>
+void
+test_by_type(Generator generator, UnaryPred pred)
+{
+
+ using namespace std;
+ size_t max_size = 100000;
+ Sequence<T> in(max_size, [](size_t v) { return T(v); });
+ Sequence<T> exp(max_size, [](size_t v) { return T(v); });
+
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, n, pred,
+ generator);
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ invoke_if(exec, [&]() {
+ partition(exec, iter, iter, non_const(is_even));
+ stable_partition(exec, iter, iter, non_const(is_even));
+ });
+ }
+};
+
+int32_t
+main()
+{
+#if !__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; });
+ test_by_type<int64_t>([](int32_t i) { return i + 1; }, [](int64_t x) { return x % 3 == 0; });
+ test_by_type<DataType<float32_t>>([](int32_t i) { return DataType<float32_t>(2 * i + 1); },
+ [](const DataType<float32_t>& x) { return x.get_val() < 0; });
+
+ test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp
new file mode 100644
index 00000000000..c27e51ca798
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+//===-- partition_copy.pass.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for stable_partition and partition_copy
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+#include <cstdlib>
+#include <iterator>
+
+using namespace TestUtils;
+
+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)
+ {
+
+ 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)),
+ "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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp>
+ void
+ 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)
+ {
+ }
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp>
+ void
+ 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)
+ {
+ }
+#endif
+};
+
+template <typename T, typename UnaryPred>
+void
+test(UnaryPred pred)
+{
+
+ const std::size_t max_size = 100000;
+ Sequence<T> in(max_size, [](std::size_t v) -> T { return T(v); });
+ Sequence<T> actual_true(max_size);
+ Sequence<T> actual_false(max_size);
+ for (std::size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : std::size_t(3.1415 * n))
+ {
+
+ // for non-const input iterators
+ invoke_on_all_policies(test_partition_copy(), in.begin(), in.begin() + n, actual_true.begin(),
+ actual_true.begin() + n, actual_false.begin(), actual_false.begin() + n, pred);
+
+ // for const input iterators
+ invoke_on_all_policies(test_partition_copy(), in.cbegin(), in.cbegin() + n, actual_true.begin(),
+ actual_true.begin() + n, actual_false.begin(), actual_false.begin() + n, pred);
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+
+ partition_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(is_even));
+ }
+};
+
+int32_t
+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; });
+#endif
+
+ test<float64_t>([](const float64_t value) { return value > 2 << 6; });
+ test<Wrapper<float64_t>>([](const Wrapper<float64_t>& value) -> bool { return value.get_my_field() != nullptr; });
+
+ test_algo_basic_double<int32_t>(run_for_rnd_bi<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp
new file mode 100644
index 00000000000..ad722df3a83
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+//===-- reverse.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iterator>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+#if __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN || __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+ template <typename 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,
+ 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,
+ Iterator2 actual_e)
+ {
+ }
+#endif
+
+ 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)
+ {
+ using namespace std;
+
+ copy(data_b, data_e, actual_b);
+
+ reverse(exec, actual_b, actual_e);
+
+ bool check = equal(data_b, data_e, reverse_iterator<Iterator2>(actual_e));
+
+ EXPECT_TRUE(check, "wrong result of reverse");
+ }
+
+ 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)
+ {
+ }
+};
+
+template <typename T>
+void
+test()
+{
+ const std::size_t max_len = 100000;
+
+ Sequence<T> actual(max_len);
+
+ Sequence<T> data(max_len, [](std::size_t i) { return T(i); });
+
+ for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
+ {
+ invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(),
+ actual.begin() + len);
+ }
+}
+
+template <typename T>
+struct wrapper
+{
+ T t;
+ wrapper() {}
+ explicit wrapper(T t_) : t(t_) {}
+ bool
+ operator==(const wrapper<T>& a) const
+ {
+ return t == a.t;
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t>();
+ test<uint16_t>();
+ test<float64_t>();
+#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+ test<wrapper<float64_t>>();
+#endif
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp
new file mode 100644
index 00000000000..d26f41f175d
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//===-- reverse_copy.pass.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iterator>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct wrapper
+{
+ T t;
+ wrapper() {}
+ explicit wrapper(T t_) : t(t_) {}
+ wrapper&
+ operator=(const T& t_)
+ {
+ t = t_;
+ return *this;
+ }
+ bool
+ operator==(const wrapper& t_) const
+ {
+ return t == t_.t;
+ }
+};
+
+template <typename T1, typename T2>
+bool
+eq(const wrapper<T1>& a, const wrapper<T2>& b)
+{
+ return a.t == b.t;
+}
+
+template <typename T1, typename T2>
+bool
+eq(const T1& a, const T2& b)
+{
+ return a == b;
+}
+
+// we need to save state here, because we need to test with different types of iterators
+// due to the caller invoke_on_all_policies does forcing modification passed iterator type to cover additional usage cases.
+template <typename Iterator>
+struct test_one_policy
+{
+ Iterator data_b;
+ Iterator data_e;
+ test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {}
+
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+ template <typename 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)
+ {
+ }
+ 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)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator1>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e)
+ {
+ 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);
+
+ EXPECT_TRUE(actual_return == actual_e, "wrong result of reverse_copy");
+
+ const auto n = std::distance(data_b, data_e);
+ Sequence<T> res(n);
+ std::copy(std::reverse_iterator<Iterator>(data_e), std::reverse_iterator<Iterator>(data_b), res.begin());
+
+ EXPECT_EQ_N(res.begin(), actual_b, n, "wrong effect of reverse_copy");
+ }
+};
+
+template <typename T1, typename T2>
+void
+test()
+{
+ typedef typename Sequence<T1>::iterator iterator_type;
+ typedef typename Sequence<T1>::const_bidirectional_iterator cbi_iterator_type;
+
+ const std::size_t max_len = 100000;
+
+ Sequence<T2> actual(max_len);
+
+ Sequence<T1> data(max_len, [](std::size_t i) { return T1(i); });
+
+ for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
+ {
+ invoke_on_all_policies(test_one_policy<iterator_type>(data.begin(), data.begin() + len), actual.begin(),
+ actual.begin() + len);
+ invoke_on_all_policies(test_one_policy<cbi_iterator_type>(data.cbibegin(), std::next(data.cbibegin(), len)),
+ actual.begin(), actual.begin() + len);
+ }
+}
+
+int32_t
+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>();
+ test<wrapper<float64_t>, wrapper<float64_t>>();
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp
new file mode 100644
index 00000000000..89de3f92c9e
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp
@@ -0,0 +1,204 @@
+// -*- C++ -*-
+//===-- copy_move.pass.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for copy, move and copy_n
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T>
+ void
+ 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)
+ {
+ }
+
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T>
+ void
+ 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)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ // Cleaning
+ std::fill_n(expected_first, size, trash);
+ std::fill_n(out_first, size, trash);
+
+ // Run copy
+ copy(first, last, expected_first);
+ auto k = copy(exec, first, last, out_first);
+ for (size_t j = 0; j < GuardSize; ++j)
+ ++k;
+ EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy");
+ EXPECT_TRUE(out_last == k, "wrong return value from copy");
+
+ // Cleaning
+ std::fill_n(out_first, size, trash);
+ // Run copy_n
+ k = copy_n(exec, first, n, out_first);
+ for (size_t j = 0; j < GuardSize; ++j)
+ ++k;
+ EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from copy_n");
+ EXPECT_TRUE(out_last == k, "wrong return value from copy_n");
+ }
+};
+
+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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
+ void
+ 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)
+ {
+ }
+
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
+ void
+ 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)
+ {
+ }
+#endif
+
+ 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)
+ {
+ // Cleaning
+ std::fill_n(expected_first, size, trash);
+ std::fill_n(out_first, size, trash);
+
+ // Run move
+ move(first, last, expected_first);
+ auto k = move(exec, first, last, out_first);
+ for (size_t j = 0; j < GuardSize; ++j)
+ ++k;
+ EXPECT_EQ_N(expected_first, out_first, size, "wrong effect from move");
+ EXPECT_TRUE(out_last == k, "wrong return value from move");
+ }
+};
+
+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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
+ void
+ 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)
+ {
+ }
+
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
+ void
+ 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)
+ {
+ }
+#endif
+
+ 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)
+ {
+ // Cleaning
+ std::fill_n(out_first, size, trash);
+ Wrapper<T>::SetMoveCount(0);
+
+ // Run move
+ auto k = move(exec, first, last, out_first);
+ for (size_t j = 0; j < GuardSize; ++j)
+ ++k;
+ EXPECT_TRUE(Wrapper<T>::MoveCount() == size, "wrong effect from move");
+ EXPECT_TRUE(out_last == k, "wrong return value from move");
+ }
+};
+
+template <typename T, typename Convert>
+void
+test(T trash, Convert convert)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ // count is number of output elements, plus a handful
+ // more for sake of detecting buffer overruns.
+ Sequence<T> in(n, [&](size_t k) -> T {
+ T val = convert(n ^ k);
+ return val;
+ });
+
+ const size_t outN = n + GuardSize;
+ Sequence<T> out(outN, [=](size_t) { return trash; });
+ Sequence<T> expected(outN, [=](size_t) { return trash; });
+ invoke_on_all_policies(run_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), outN, n, trash);
+ invoke_on_all_policies(run_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(),
+ expected.end(), outN, n, trash);
+ invoke_on_all_policies(run_move<T>(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), n, n, trash);
+
+ // For this test const iterator isn't suitable
+ // because const rvalue-reference call copy assignment operator
+ }
+}
+
+int32_t
+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
+ 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
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/fill.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/fill.pass.cpp
new file mode 100644
index 00000000000..19bc150b31b
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/fill.pass.cpp
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//===-- fill.pass.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_fill
+{
+ template <typename It, typename T>
+ bool
+ check(It first, It last, const T& value)
+ {
+ for (; first != last; ++first)
+ if (*first != value)
+ return false;
+ return true;
+ }
+
+ template <typename Policy, typename Iterator, typename T>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, const T& value)
+ {
+ fill(first, last, T(value + 1)); // initialize memory with different value
+
+ fill(exec, first, last, value);
+ EXPECT_TRUE(check(first, last, value), "fill wrong result");
+ }
+};
+
+struct test_fill_n
+{
+ template <typename It, typename Size, typename T>
+ bool
+ check(It first, Size n, const T& value)
+ {
+ for (Size i = 0; i < n; ++i, ++first)
+ if (*first != value)
+ return false;
+ return true;
+ }
+
+ template <typename Policy, typename Iterator, typename Size, typename T>
+ void
+ operator()(Policy&& exec, Iterator first, Size n, const T& value)
+ {
+ fill_n(first, n, T(value + 1)); // initialize memory with different value
+
+ const Iterator one_past_last = fill_n(exec, first, n, value);
+ const Iterator expected_return = std::next(first, n);
+
+ EXPECT_TRUE(expected_return == one_past_last, "fill_n should return Iterator to one past the element assigned");
+ EXPECT_TRUE(check(first, n, value), "fill_n wrong result");
+
+ //n == -1
+ const Iterator res = fill_n(exec, first, -1, value);
+ EXPECT_TRUE(res == first, "fill_n wrong result for n == -1");
+ }
+};
+
+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
+ 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
+main()
+{
+
+ const std::size_t N = 100000;
+
+ for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ test_fill_by_type<int32_t>(n);
+ test_fill_by_type<float64_t>(n);
+ }
+
+ std::cout << done() << std::endl;
+
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/generate.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/generate.pass.cpp
new file mode 100644
index 00000000000..9862f14ba62
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/generate.pass.cpp
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//===-- generate.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <atomic>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct Generator_count
+{
+ const T def_val = T(-1);
+ T
+ operator()()
+ {
+ return def_val;
+ }
+ T
+ default_value() const
+ {
+ return def_val;
+ }
+};
+
+struct test_generate
+{
+ template <typename Policy, typename Iterator, typename Size>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Size n)
+ {
+ using namespace std;
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ // Try random-access iterator
+ {
+ Generator_count<T> g;
+ generate(exec, first, last, g);
+ EXPECT_TRUE(std::count(first, last, g.default_value()) == 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));
+ }
+ }
+};
+
+template <typename T>
+void
+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
+
+ invoke_on_all_policies(test_generate(), in.begin(), in.end(), in.size());
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto gen = []() { return T(0); };
+
+ generate(exec, iter, iter, non_const(gen));
+ generate_n(exec, iter, 0, non_const(gen));
+ }
+};
+
+int32_t
+main()
+{
+
+ test_generate_by_type<int32_t>();
+ test_generate_by_type<float64_t>();
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/remove.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/remove.pass.cpp
new file mode 100644
index 00000000000..82b986bcfbf
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/remove.pass.cpp
@@ -0,0 +1,157 @@
+// -*- C++ -*-
+//===-- remove.pass.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Test for remove, remove_if
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename InputIterator, typename OutputIterator, typename Size, typename T>
+ void
+ 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,
+ OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first,
+ OutputIterator expected_last, Size n, const T& value)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename T>
+ void
+ operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
+ OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size,
+ const T& value)
+ {
+ // Cleaning
+ std::copy(first, last, expected_first);
+ std::copy(first, last, out_first);
+
+ // Run remove
+ OutputIterator i = remove(expected_first, expected_last, value);
+ OutputIterator k = remove(exec, out_first, out_last, value);
+ EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k), "wrong return value from remove");
+ EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove effect");
+ }
+};
+
+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
+ template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate>
+ void
+ 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,
+ OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first,
+ OutputIterator expected_last, Size n, Predicate pred)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename Predicate>
+ void
+ operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
+ OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size,
+ Predicate pred)
+ {
+ // Cleaning
+ std::copy(first, last, expected_first);
+ std::copy(first, last, out_first);
+
+ // Run remove_if
+ OutputIterator i = remove_if(expected_first, expected_last, pred);
+ OutputIterator k = remove_if(exec, out_first, out_last, pred);
+ EXPECT_TRUE(std::distance(expected_first, i) == std::distance(out_first, k),
+ "wrong return value from remove_if");
+ EXPECT_EQ_N(expected_first, out_first, std::distance(expected_first, i), "wrong remove_if effect");
+ }
+};
+
+template <typename T, typename Predicate, typename Convert>
+void
+test(T trash, const T& value, Predicate pred, Convert convert)
+{
+ const std::size_t max_size = 100000;
+ Sequence<T> out(max_size, [trash](size_t) { return trash; });
+ Sequence<T> expected(max_size, [trash](size_t) { return trash; });
+
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<T> data(n, [&](size_t k) -> T { return convert(k); });
+
+ invoke_on_all_policies(run_remove(), data.begin(), data.end(), out.begin(), out.begin() + n, expected.begin(),
+ expected.begin() + n, n, value);
+ invoke_on_all_policies(run_remove_if(), data.begin(), data.end(), out.begin(), out.begin() + n,
+ expected.begin(), expected.begin() + n, n, pred);
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+
+ invoke_if(exec, [&]() { remove_if(exec, iter, iter, non_const(is_even)); });
+ }
+};
+
+int32_t
+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; });
+#endif
+
+ test<int32_t>(666, 2001, [](const int32_t& val) { return val != 2001; },
+ [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 2001 : -1 - int32_t(j); });
+ 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
+ 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>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp
new file mode 100644
index 00000000000..0437292af4f
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp
@@ -0,0 +1,94 @@
+// -*- C++ -*-
+//===-- remove_copy.pass.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct run_remove_copy
+{
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ // 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);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy effect");
+ for (size_t j = 0; j < GuardSize; ++j)
+ {
+ ++k;
+ }
+ EXPECT_TRUE(out_last == k, "wrong return value from remove_copy");
+ }
+};
+
+template <typename T, typename Convert>
+void
+test(T trash, const T& value, Convert convert, bool check_weakness = true)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ // count is number of output elements, plus a handful
+ // more for sake of detecting buffer overruns.
+ size_t count = GuardSize;
+ Sequence<T> in(n, [&](size_t k) -> T {
+ T x = convert(n ^ k);
+ count += !(x == value) ? 1 : 0;
+ return x;
+ });
+ using namespace std;
+
+ Sequence<T> out(count, [=](size_t) { return trash; });
+ Sequence<T> expected(count, [=](size_t) { return trash; });
+ if (check_weakness)
+ {
+ auto expected_result = remove_copy(in.cfbegin(), in.cfend(), expected.begin(), value);
+ size_t m = expected_result - expected.begin();
+ EXPECT_TRUE(n / 4 <= m && m <= 3 * (n + 1) / 4, "weak test for remove_copy");
+ }
+ invoke_on_all_policies(run_remove_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), count, value, trash);
+ invoke_on_all_policies(run_remove_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(),
+ expected.end(), count, value, trash);
+ }
+}
+
+int32_t
+main()
+{
+
+ test<float64_t>(-666.0, 8.5, [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); });
+
+ test<int32_t>(-666, 42, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); });
+
+ test<Number>(Number(42, OddTag()), Number(2001, OddTag()),
+ [](int32_t j) { return ((j + 1) % 3 & 2) != 0 ? Number(2001, OddTag()) : Number(j, OddTag()); });
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/replace.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/replace.pass.cpp
new file mode 100644
index 00000000000..5aeaac88812
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/replace.pass.cpp
@@ -0,0 +1,163 @@
+// -*- C++ -*-
+//===-- replace.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+// This class is needed to check the self-copying
+struct copy_int
+{
+ int32_t value;
+ int32_t copied_times = 0;
+ explicit copy_int(int32_t val = 0) { value = val; }
+
+ copy_int&
+ operator=(const copy_int& other)
+ {
+ if (&other == this)
+ copied_times++;
+ else
+ {
+ value = other.value;
+ copied_times = other.copied_times;
+ }
+ return *this;
+ }
+
+ bool
+ operator==(const copy_int& other) const
+ {
+ return (value == other.value);
+ }
+};
+
+template <typename Iterator>
+struct test_one_policy
+{
+ std::size_t len;
+ Iterator data_b;
+ Iterator data_e;
+ test_one_policy(Iterator data_, std::size_t len_)
+ {
+ len = len_;
+ data_b = data_;
+ data_e = std::next(data_b, len);
+ }
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename T, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 expected_b, Iterator1 expected_e, Iterator2 actual_b,
+ Iterator2 actual_e, Predicate pred, const T& value, const T& old_value)
+ {
+ using namespace std;
+
+ copy(data_b, data_e, expected_b);
+ copy(data_b, data_e, actual_b);
+
+ replace(expected_b, expected_e, old_value, value);
+ replace(exec, actual_b, actual_e, old_value, value);
+
+ EXPECT_TRUE((check<T, Iterator2>(actual_b, actual_e)), "wrong result of self assignment check");
+ EXPECT_TRUE(equal(expected_b, expected_e, actual_b), "wrong result of replace");
+
+ copy(data_b, data_e, expected_b);
+ copy(data_b, data_e, actual_b);
+
+ replace_if(expected_b, expected_e, pred, value);
+ replace_if(exec, actual_b, actual_e, pred, value);
+ EXPECT_TRUE(equal(expected_b, expected_e, actual_b), "wrong result of replace_if");
+ }
+
+ template <typename T, typename Iterator1>
+ bool
+ check(Iterator1 b, Iterator1 e)
+ {
+ return true;
+ }
+
+ template <typename T, typename Iterator1>
+ typename std::enable_if<std::is_same<T, copy_int>::value, bool>::type_t
+ check(Iterator1 b, Iterator1 e)
+ {
+ return std::all_of(b, e, [](const copy_int& elem) { return elem.copied_times == 0; });
+ }
+};
+
+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 T1 value = T1(0);
+ const 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) {
+ if (i % 3 == 2)
+ {
+ return T1(i);
+ }
+ else
+ {
+ return value;
+ }
+ });
+
+ for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
+ {
+ test_one_policy<iterator_type> temp(data.begin(), len);
+
+ invoke_on_all_policies(temp, expected.begin(), expected.begin() + len, actual.begin(), actual.begin() + len,
+ pred, new_value, value);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ invoke_if(exec, [&]() { replace_if(exec, iter, iter, non_const(is_even), T(0)); });
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t, float32_t>(__pstl::internal::equal_value<int32_t>(666));
+ test<uint16_t, uint8_t>([](const uint16_t& elem) { return elem % 3 < 2; });
+ test<float64_t, int64_t>([](const float64_t& elem) { return elem * elem - 3.5 * elem > 10; });
+ test<copy_int, copy_int>([](const copy_int& val) { return val.value / 5 > 2; });
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp
new file mode 100644
index 00000000000..7ebbf4c0c7f
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+//===-- replace_copy.pass.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for replace_copy and replace_copy_if
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_replace_copy
+{
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+ // Run replace_copy
+ auto i = std::replace_copy(first, last, expected_first, old_value, new_value);
+ auto k = std::replace_copy(exec, first, last, out_first, old_value, new_value);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong replace_copy effect");
+ EXPECT_TRUE(out_last == k, "wrong return value from replace_copy");
+
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+ // Run replace_copy_if
+ i = replace_copy_if(first, last, expected_first, pred, new_value);
+ k = replace_copy_if(exec, first, last, out_first, pred, new_value);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong replace_copy_if effect");
+ EXPECT_TRUE(out_last == k, "wrong return value from replace_copy_if");
+ }
+};
+
+template <typename T, typename Convert, typename Predicate>
+void
+test(T trash, const T& old_value, const T& new_value, Predicate pred, Convert convert)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<T> in(n, [&](size_t k) -> T { return convert(n ^ k); });
+ Sequence<T> out(n, [=](size_t) { return trash; });
+ Sequence<T> expected(n, [=](size_t) { return trash; });
+
+ invoke_on_all_policies(test_replace_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), out.size(), pred, old_value, new_value, trash);
+ invoke_on_all_policies(test_replace_copy(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(),
+ expected.end(), out.size(), pred, old_value, new_value, trash);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+
+ invoke_if(exec, [&]() { replace_copy_if(exec, input_iter, input_iter, out_iter, non_const(is_even), T(0)); });
+ }
+};
+
+int32_t
+main()
+{
+
+ test<float64_t>(-666.0, 8.5, 0.33, [](const float64_t& x) { return x * x <= 1024; },
+ [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); });
+
+ 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
+ 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
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp
new file mode 100644
index 00000000000..2bebc4e57da
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp
@@ -0,0 +1,177 @@
+// -*- C++ -*-
+//===-- rotate.pass.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iterator>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct wrapper
+{
+ T t;
+ int move_count;
+ explicit wrapper(T t_) : t(t_), move_count(0) {}
+ wrapper&
+ operator=(const T& t_)
+ {
+ t = t_;
+ return *this;
+ }
+
+ wrapper(const wrapper<T>& a) : move_count(0) { t = a.t; }
+
+ wrapper<T>&
+ operator=(wrapper<T>& a)
+ {
+ t = a.t;
+ return *this;
+ }
+
+ wrapper<T>&
+ operator=(wrapper<T>&& a)
+ {
+ t = a.t;
+ move_count += 1;
+ return *this;
+ }
+};
+
+template <typename T>
+struct compare
+{
+ bool
+ operator()(const T& a, const T& b)
+ {
+ return a == b;
+ }
+};
+
+template <typename T>
+struct compare<wrapper<T>>
+{
+ bool
+ operator()(const wrapper<T>& a, const wrapper<T>& b)
+ {
+ return a.t == b.t;
+ }
+};
+#include <typeinfo>
+
+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
+ template <typename Iterator, typename Size>
+ void
+ operator()(pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b,
+ Iterator actual_e, Size shift)
+ {
+ }
+ template <typename Iterator, typename Size>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b,
+ Iterator actual_e, Size shift)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator, typename Size>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator data_b, Iterator data_e, Iterator actual_b, Iterator actual_e,
+ Size shift)
+ {
+ using namespace std;
+ using T = typename iterator_traits<Iterator>::value_type;
+ Iterator actual_m = std::next(actual_b, shift);
+
+ copy(data_b, data_e, actual_b);
+ Iterator actual_return = rotate(exec, actual_b, actual_m, actual_e);
+
+ EXPECT_TRUE(actual_return == std::next(actual_b, std::distance(actual_m, actual_e)), "wrong result of rotate");
+ auto comparator = compare<T>();
+ bool check = std::equal(actual_return, actual_e, data_b, comparator);
+ check = check && std::equal(actual_b, actual_return, std::next(data_b, shift), comparator);
+
+ EXPECT_TRUE(check, "wrong effect of rotate");
+ EXPECT_TRUE(check_move(exec, actual_b, actual_e, shift), "wrong move test of rotate");
+ }
+
+ 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<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value,
+ bool>::type
+ check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift)
+ {
+ bool result = all_of(b, e, [](wrapper<float32_t>& a) {
+ bool temp = a.move_count > 0;
+ a.move_count = 0;
+ return temp;
+ });
+ return shift == 0 || result;
+ }
+
+ 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<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value),
+ bool>::type
+ check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift)
+ {
+ return true;
+ }
+};
+
+template <typename T>
+void
+test()
+{
+ const int32_t max_len = 100000;
+
+ Sequence<T> actual(max_len, [](std::size_t i) { return T(i); });
+ Sequence<T> data(max_len, [](std::size_t i) { return T(i); });
+
+ for (int32_t len = 0; len < max_len; len = len <= 16 ? len + 1 : int32_t(3.1415 * len))
+ {
+ int32_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1};
+ for (auto shift : shifts)
+ {
+ if (shift >= 0 && shift < len)
+ {
+ invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(),
+ actual.begin() + len, shift);
+ }
+ }
+ }
+}
+
+int32_t
+main()
+{
+ test<int32_t>();
+ test<wrapper<float64_t>>();
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp
new file mode 100644
index 00000000000..7d0ec7ec450
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp
@@ -0,0 +1,150 @@
+// -*- C++ -*-
+//===-- rotate_copy.pass.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iterator>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct wrapper;
+
+template <typename T>
+bool
+compare(const wrapper<T>& a, const wrapper<T>& b)
+{
+ return a.t == b.t;
+}
+
+template <typename T>
+bool
+compare(const T& a, const T& b)
+{
+ return a == b;
+}
+
+template <typename T>
+struct wrapper
+{
+ explicit wrapper(T t_) : t(t_) {}
+ wrapper&
+ operator=(const T& t_)
+ {
+ t = t_;
+ return *this;
+ }
+ friend bool
+ compare<T>(const wrapper<T>& a, const wrapper<T>& b);
+
+ private:
+ T t;
+};
+
+template <typename T, typename It1, typename It2>
+struct comparator
+{
+ using T1 = typename std::iterator_traits<It1>::value_type;
+ using T2 = typename std::iterator_traits<It2>::value_type;
+ bool
+ operator()(T1 a, T2 b)
+ {
+ T temp = a;
+ return compare(temp, b);
+ }
+};
+
+struct test_one_policy
+{
+
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+ template <typename 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,
+ 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,
+ Iterator2 actual_e, std::size_t shift)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e,
+ std::size_t shift)
+ {
+ using namespace std;
+ using T = typename iterator_traits<Iterator2>::value_type;
+ Iterator1 data_m = std::next(data_b, shift);
+
+ fill(actual_b, actual_e, T(-123));
+ Iterator2 actual_return = rotate_copy(exec, data_b, data_m, data_e, actual_b);
+
+ EXPECT_TRUE(actual_return == actual_e, "wrong result of rotate_copy");
+ auto comparer = comparator<T, Iterator1, Iterator2>();
+ bool check = std::equal(data_m, data_e, actual_b, comparer);
+ check = check && std::equal(data_b, data_m, std::next(actual_b, std::distance(data_m, data_e)), comparer);
+
+ EXPECT_TRUE(check, "wrong effect of rotate_copy");
+ }
+};
+
+template <typename T1, typename T2>
+void
+test()
+{
+
+ const std::size_t max_len = 100000;
+
+ Sequence<T2> actual(max_len, [](std::size_t i) { return T1(i); });
+
+ Sequence<T1> data(max_len, [](std::size_t i) { return T1(i); });
+
+ for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
+ {
+ std::size_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1};
+ for (std::size_t shift : shifts)
+ {
+ if (shift > 0 && shift < len)
+ {
+ invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(),
+ actual.begin() + len, shift);
+ invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(),
+ actual.begin() + len, shift);
+ }
+ }
+ }
+}
+
+int32_t
+main()
+{
+ test<int32_t, int8_t>();
+ test<uint16_t, float32_t>();
+ test<float64_t, int64_t>();
+ test<wrapper<float64_t>, wrapper<float64_t>>();
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp
new file mode 100644
index 00000000000..b53003c4626
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//===-- swap_ranges.pass.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iterator>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct wrapper
+{
+ T t;
+ std::size_t number_of_swaps = 0;
+ wrapper() {}
+ explicit wrapper(T t_) : t(t_) {}
+ template <typename U>
+ void
+ operator=(const U& b)
+ {
+ t = b;
+ }
+ bool
+ operator==(const wrapper<T>& a) const
+ {
+ return t == a.t;
+ }
+};
+
+template <typename T>
+void
+swap(wrapper<T>& a, wrapper<T>& b)
+{
+ std::swap(a.t, b.t);
+ a.number_of_swaps++;
+ b.number_of_swaps++;
+}
+
+template <typename T>
+struct check_swap
+{
+ bool
+ operator()(T& a)
+ {
+ return true;
+ }
+};
+
+template <typename T>
+struct check_swap<wrapper<T>>
+{
+ bool
+ operator()(wrapper<T>& a)
+ {
+ bool temp = (a.number_of_swaps == 1);
+ a.number_of_swaps = 0;
+ return temp;
+ }
+};
+
+struct test_one_policy
+{
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e)
+ {
+ using namespace std;
+ using T_ref = typename iterator_traits<Iterator1>::reference;
+ using T = typename iterator_traits<Iterator1>::value_type;
+
+ iota(data_b, data_e, 0);
+ iota(actual_b, actual_e, std::distance(data_b, data_e));
+
+ Iterator2 actual_return = swap_ranges(exec, data_b, data_e, actual_b);
+ bool check_return = (actual_return == actual_e);
+ EXPECT_TRUE(check_return, "wrong result of swap_ranges");
+ if (check_return)
+ {
+ std::size_t i = 0;
+ bool check = all_of(actual_b, actual_e, [&i](T_ref a) { return a == T(i++); }) &&
+ all_of(data_b, data_e, [&i](T_ref a) { return a == T(i++); });
+
+ EXPECT_TRUE(check, "wrong effect of swap_ranges");
+
+ if (check)
+ {
+ bool swap_check =
+ all_of(data_b, data_e, check_swap<T>()) && all_of(actual_b, actual_e, check_swap<T>());
+ EXPECT_TRUE(swap_check, "wrong effect of swap_ranges swap check");
+ }
+ }
+ }
+};
+
+template <typename T>
+void
+test()
+{
+ const std::size_t max_len = 100000;
+
+ Sequence<T> data(max_len);
+ Sequence<T> actual(max_len);
+
+ for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
+ {
+ invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(),
+ actual.begin() + len);
+ }
+}
+
+int32_t
+main()
+{
+ test<wrapper<uint16_t>>();
+ test<wrapper<float64_t>>();
+ test<int32_t>();
+ test<float32_t>();
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp
new file mode 100644
index 00000000000..2d680c369f2
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp
@@ -0,0 +1,124 @@
+// -*- C++ -*-
+//===-- transform_binary.pass.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/algorithm"
+#include "pstl/execution"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename In1, typename In2, typename Out>
+class TheOperation
+{
+ Out val;
+
+ public:
+ TheOperation(Out v) : val(v) {}
+ Out
+ operator()(const In1& x, const In2& y) const
+ {
+ return Out(val + x - y);
+ }
+};
+
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+void
+check_and_reset(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator out_first)
+{
+ typedef typename std::iterator_traits<OutputIterator>::value_type Out;
+ typename std::iterator_traits<OutputIterator>::difference_type k = 0;
+ for (; first1 != last1; ++first1, ++first2, ++out_first, ++k)
+ {
+ // check
+ Out expected = Out(1.5) + *first1 - *first2;
+ Out actual = *out_first;
+ if (std::is_floating_point<Out>::value)
+ {
+ EXPECT_TRUE((expected > actual ? expected - actual : actual - expected) < 1e7,
+ "wrong value in output sequence");
+ }
+ else
+ {
+ EXPECT_EQ(expected, actual, "wrong value in output sequence");
+ }
+ // reset
+ *out_first = k % 7 != 4 ? 7 * k - 5 : 0;
+ }
+}
+
+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)
+ {
+ auto orrr = std::transform(exec, first1, last1, first2, out_first, op);
+ check_and_reset(first1, last1, first2, out_first);
+ }
+};
+
+template <typename In1, typename In2, typename Out, typename Predicate>
+void
+test(Predicate pred)
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ 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; });
+
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.begin(), in2.end(), out.begin(),
+ out.end(), pred);
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cend(), in2.cbegin(), in2.cend(), out.begin(),
+ out.end(), pred);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ invoke_if(exec, [&]() {
+ InputIterator input_iter2 = input_iter;
+ transform(exec, input_iter, input_iter, input_iter2, out_iter, non_const(std::plus<T>()));
+ });
+ }
+};
+
+int32_t
+main()
+{
+ //const operator()
+ test<int32_t, int32_t, int32_t>(TheOperation<int32_t, int32_t, int32_t>(1));
+ test<float32_t, float32_t, float32_t>(TheOperation<float32_t, float32_t, float32_t>(1.5));
+ //non-const operator()
+ test<int32_t, float32_t, float32_t>(non_const(TheOperation<int32_t, float32_t, float32_t>(1.5)));
+ test<int64_t, float64_t, float32_t>(non_const(TheOperation<int64_t, float64_t, float32_t>(1.5)));
+ //lambda
+ test<int8_t, float64_t, int8_t>([](const int8_t& x, const float64_t& y) { return int8_t(int8_t(1.5) + x - y); });
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp
new file mode 100644
index 00000000000..e198c6e2a8b
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp
@@ -0,0 +1,94 @@
+// -*- C++ -*-
+//===-- transform_unary.pass.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/algorithm"
+#include "pstl/execution"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename InputIterator, typename OutputIterator>
+void
+check_and_reset(InputIterator first, InputIterator last, OutputIterator out_first)
+{
+ typedef typename std::iterator_traits<OutputIterator>::value_type Out;
+ typename std::iterator_traits<OutputIterator>::difference_type k = 0;
+ for (; first != last; ++first, ++out_first, ++k)
+ {
+ // check
+ Out expected = 1 - *first;
+ Out actual = *out_first;
+ EXPECT_EQ(expected, actual, "wrong value in output sequence");
+ // reset
+ *out_first = k % 7 != 4 ? 7 * k - 5 : 0;
+ }
+}
+
+struct test_one_policy
+{
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename UnaryOp>
+ void
+ operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
+ OutputIterator out_last, UnaryOp op)
+ {
+ auto orr = std::transform(exec, first, last, out_first, op);
+ EXPECT_TRUE(out_last == orr, "transform returned wrong iterator");
+ check_and_reset(first, last, out_first);
+ }
+};
+
+template <typename Tin, typename Tout>
+void
+test()
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<Tin> in(n, [](int32_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; });
+
+ Sequence<Tout> out(n);
+
+ const auto flip = Complement<Tin, Tout>(1);
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), out.begin(), out.end(), flip);
+ invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), out.begin(), out.end(), flip);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ invoke_if(exec, [&]() { transform(exec, input_iter, input_iter, out_iter, non_const(std::negate<T>())); });
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t, int32_t>();
+ test<int32_t, float32_t>();
+ test<uint16_t, float32_t>();
+ test<float32_t, float64_t>();
+ test<float64_t, float64_t>();
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/unique.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/unique.pass.cpp
new file mode 100644
index 00000000000..06639ccf685
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/unique.pass.cpp
@@ -0,0 +1,160 @@
+// -*- C++ -*-
+//===-- unique.pass.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Test for unique
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename ForwardIt, typename Generator>
+ void
+ 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,
+ ForwardIt last2, Generator generator)
+ {
+ }
+
+ template <typename ForwardIt, typename BinaryPred, typename Generator>
+ void
+ 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,
+ ForwardIt last2, BinaryPred pred, Generator generator)
+ {
+ }
+#endif
+
+ template <typename Policy, typename ForwardIt, typename Generator>
+ void
+ operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, Generator generator)
+ {
+ using namespace std;
+
+ // Preparation
+ fill_data(first1, last1, generator);
+ fill_data(first2, last2, generator);
+
+ ForwardIt i = unique(first1, last1);
+ ForwardIt k = unique(exec, first2, last2);
+
+ auto n = std::distance(first1, i);
+ EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique without predicate");
+ EXPECT_EQ_N(first1, first2, n, "wrong effect from unique without predicate");
+ }
+
+ template <typename Policy, typename ForwardIt, typename BinaryPred, typename Generator>
+ void
+ operator()(Policy&& exec, ForwardIt first1, ForwardIt last1, ForwardIt first2, ForwardIt last2, BinaryPred pred,
+ Generator generator)
+ {
+ using namespace std;
+
+ // Preparation
+ fill_data(first1, last1, generator);
+ fill_data(first2, last2, generator);
+
+ ForwardIt i = unique(first1, last1, pred);
+ ForwardIt k = unique(exec, first2, last2, pred);
+
+ auto n = std::distance(first1, i);
+ EXPECT_TRUE(std::distance(first2, k) == n, "wrong return value from unique with predicate");
+ EXPECT_EQ_N(first1, first2, n, "wrong effect from unique with predicate");
+ }
+};
+
+template <typename T, typename Generator, typename Predicate>
+void
+test(Generator generator, Predicate pred)
+{
+ const std::size_t max_size = 1000000;
+ Sequence<T> in(max_size, [](size_t v) { return T(v); });
+ Sequence<T> exp(max_size, [](size_t v) { return T(v); });
+
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, generator);
+ invoke_on_all_policies(run_unique(), exp.begin(), exp.begin() + n, in.begin(), in.begin() + n, pred, generator);
+ }
+}
+
+template <typename T>
+struct LocalWrapper
+{
+ T my_val;
+
+ explicit LocalWrapper(T k) : my_val(k) {}
+ LocalWrapper(LocalWrapper&& input) : my_val(std::move(input.my_val)) {}
+ LocalWrapper&
+ operator=(LocalWrapper&& input)
+ {
+ my_val = std::move(input.my_val);
+ return *this;
+ }
+ friend bool
+ operator==(const LocalWrapper<T>& x, const LocalWrapper<T>& y)
+ {
+ return x.my_val == y.my_val;
+ }
+};
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() { unique(exec, iter, iter, non_const(std::equal_to<T>())); });
+ }
+};
+
+int32_t
+main()
+{
+#if !__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); },
+ [](const float64_t& val1, const float64_t& val2) { return val1 != val2; });
+#endif
+ test<LocalWrapper<uint32_t>>([](size_t j) { return LocalWrapper<uint32_t>(j); },
+ [](const LocalWrapper<uint32_t>& val1, const LocalWrapper<uint32_t>& val2) {
+ return val1.my_val != val2.my_val;
+ });
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp b/pstl/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp
new file mode 100644
index 00000000000..c948e80d45a
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp
@@ -0,0 +1,138 @@
+// -*- C++ -*-
+//===-- unique_copy_equal.pass.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for unique_copy
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ typename Predicate, typename T>
+ void
+ operator()(pstl::execution::parallel_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+ OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n,
+ Predicate pred, T trash)
+ {
+ }
+
+ template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ typename Predicate, typename T>
+ void
+ operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+ OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
+ OutputIterator2 expected_last, Size n, Predicate pred, T trash)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+
+ // Run unique_copy
+ auto i = unique_copy(first, last, expected_first);
+ auto k = unique_copy(exec, first, last, out_first);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong unique_copy effect");
+ for (size_t j = 0; j < GuardSize; ++j)
+ {
+ ++k;
+ }
+ EXPECT_TRUE(out_last == k, "wrong return value from unique_copy");
+
+ // Cleaning
+ std::fill_n(expected_first, n, trash);
+ std::fill_n(out_first, n, trash);
+ // Run unique_copy with predicate
+ i = unique_copy(first, last, expected_first, pred);
+ k = unique_copy(exec, first, last, out_first, pred);
+ EXPECT_EQ_N(expected_first, out_first, n, "wrong unique_copy with predicate effect");
+ for (size_t j = 0; j < GuardSize; ++j)
+ {
+ ++k;
+ }
+ EXPECT_TRUE(out_last == k, "wrong return value from unique_copy with predicate");
+ }
+};
+
+template <typename T, typename BinaryPredicate, typename Convert>
+void
+test(T trash, BinaryPredicate pred, Convert convert, bool check_weakness = true)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ // count is number of output elements, plus a handful
+ // more for sake of detecting buffer overruns.
+ Sequence<T> in(n, [&](size_t k) -> T { return convert(k ^ n); });
+ using namespace std;
+ size_t count = GuardSize;
+ for (size_t k = 0; k < in.size(); ++k)
+ count += k == 0 || !pred(in[k], in[k - 1]) ? 1 : 0;
+ Sequence<T> out(count, [=](size_t) { return trash; });
+ Sequence<T> expected(count, [=](size_t) { return trash; });
+ if (check_weakness)
+ {
+ auto expected_result = unique_copy(in.begin(), in.end(), expected.begin(), pred);
+ size_t m = expected_result - expected.begin();
+ EXPECT_TRUE(n / (n < 10000 ? 4 : 6) <= m && m <= (3 * n + 1) / 4, "weak test for unique_copy");
+ }
+ invoke_on_all_policies(run_unique_copy(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
+ expected.end(), count, pred, trash);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ unique_copy(exec, input_iter, input_iter, out_iter, non_const(std::equal_to<T>()));
+ }
+};
+
+int32_t
+main(int32_t argc, char* argv[])
+{
+ 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);
+#endif
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp
new file mode 100644
index 00000000000..50b01e38bc1
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//===-- adjacent_find.pass.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_adjacent_find
+{
+ template <typename Policy, typename Iterator, typename Pred>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Pred pred)
+ {
+ using namespace std;
+
+ auto k = std::adjacent_find(first, last, pred);
+ auto i = adjacent_find(exec, first, last, pred);
+ EXPECT_TRUE(i == k, "wrong return value from adjacent_find with predicate");
+
+ i = adjacent_find(exec, first, last);
+ EXPECT_TRUE(i == k, "wrong return value from adjacent_find without predicate");
+ }
+};
+
+template <typename T>
+void
+test_adjacent_find_by_type()
+{
+
+ size_t counts[] = {2, 3, 500};
+ for (int32_t c = 0; c < const_size(counts); ++c)
+ {
+
+ for (int32_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
+
+ 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");
+
+ invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to<T>());
+ }
+ }
+
+ //special cases: size=0, size=1;
+ for (int32_t expect = 0; expect < 1; ++expect)
+ {
+ Sequence<T> in(expect, [](int32_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");
+
+ invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to<T>());
+ }
+
+ //special cases:
+ Sequence<T> a1 = {5, 5, 5, 6, 7, 8, 9};
+ invoke_on_all_policies(test_adjacent_find(), a1.begin(), a1.end(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), a1.begin() + 1, a1.end(), std::equal_to<T>());
+
+ invoke_on_all_policies(test_adjacent_find(), a1.cbegin(), a1.cend(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), a1.cbegin() + 1, a1.cend(), std::equal_to<T>());
+
+ Sequence<T> a2 = {5, 6, 7, 8, 9, 9};
+ invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end() - 1, std::equal_to<T>());
+
+ invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend(), std::equal_to<T>());
+ invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend() - 1, std::equal_to<T>());
+
+ Sequence<T> a3 = {5, 6, 6, 6, 7, 9, 9, 9, 9};
+ invoke_on_all_policies(test_adjacent_find(), a3.begin(), a3.end(), std::equal_to<T>());
+
+ invoke_on_all_policies(test_adjacent_find(), a3.cbegin(), a3.cend(), std::equal_to<T>());
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ adjacent_find(exec, iter, iter, non_const(std::equal_to<T>()));
+ }
+};
+
+int32_t
+main()
+{
+
+ test_adjacent_find_by_type<int32_t>();
+ test_adjacent_find_by_type<float64_t>();
+
+ test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp
new file mode 100644
index 00000000000..f6372c44bd5
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+//===-- all_of.pass.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+/*
+ TODO: consider implementing the following tests for a better code coverage
+ - correctness
+ - bad input argument (if applicable)
+ - data corruption around/of input and output
+ - correctly work with nested parallelism
+ - check that algorithm does not require anything more than is described in its requirements section
+*/
+
+using namespace TestUtils;
+
+struct test_all_of
+{
+ template <typename ExecutionPolicy, typename Iterator, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected)
+ {
+
+ auto actualr = std::all_of(exec, begin, end, pred);
+ EXPECT_EQ(expected, actualr, "result for all_of");
+ }
+};
+
+template <typename T>
+struct Parity
+{
+ bool parity;
+
+ public:
+ Parity(bool parity_) : parity(parity_) {}
+ bool
+ operator()(T value) const
+ {
+ return (size_t(value) ^ parity) % 2 == 0;
+ }
+};
+
+template <typename T>
+void
+test(size_t bits)
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+
+ // Sequence of odd values
+ Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+
+ // Even value, or false when T is bool.
+ T spike(2 * HashBits(n, bits - 1));
+ Sequence<T> inCopy(in);
+
+ invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity<T>(1), true);
+ invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity<T>(1), true);
+ EXPECT_EQ(in, inCopy, "all_of modified input sequence");
+ if (n > 0)
+ {
+ // Sprinkle in a miss
+ in[2 * n / 3] = spike;
+ invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity<T>(1), false);
+ invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity<T>(1), false);
+
+ // Sprinkle in a few more misses
+ in[n / 2] = spike;
+ in[n / 3] = spike;
+ invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity<T>(1), false);
+ invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity<T>(1), false);
+ }
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ all_of(exec, iter, iter, non_const(is_even));
+ }
+};
+
+int32_t
+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
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp
new file mode 100644
index 00000000000..70bd4b2fb3b
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp
@@ -0,0 +1,106 @@
+// -*- C++ -*-
+//===-- any_of.pass.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+/*
+ TODO: consider implementing the following tests for a better code coverage
+ - correctness
+ - bad input argument (if applicable)
+ - data corruption around/of input and output
+ - correctly work with nested parallelism
+ - check that algorithm does not require anything more than is described in its requirements section
+*/
+
+using namespace TestUtils;
+
+struct test_any_of
+{
+ template <typename ExecutionPolicy, typename Iterator, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected)
+ {
+
+ auto actualr = std::any_of(exec, begin, end, pred);
+ EXPECT_EQ(expected, actualr, "result for any_of");
+ }
+};
+
+template <typename T>
+void
+test(size_t bits)
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+
+ // Sequence of odd values
+ Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+
+ // Even value, or false when T is bool.
+ T spike(2 * HashBits(n, bits - 1));
+ Sequence<T> inCopy(in);
+
+ invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to<T>(spike), false);
+ invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), false);
+ EXPECT_EQ(in, inCopy, "any_of modified input sequence");
+ if (n > 0)
+ {
+ // Sprinkle in a hit
+ in[2 * n / 3] = spike;
+ invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to<T>(spike), true);
+ invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), true);
+
+ // Sprinkle in a few more hits
+ in[n / 2] = spike;
+ in[n / 3] = spike;
+ invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to<T>(spike), true);
+ invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), true);
+ }
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ any_of(exec, iter, iter, non_const(is_even));
+ }
+};
+
+int32_t
+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
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/count.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/count.pass.cpp
new file mode 100644
index 00000000000..38c553762f3
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/count.pass.cpp
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//===-- count.pass.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for count and count_if
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_count
+{
+ template <typename Policy, typename Iterator, typename T>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, T needle)
+ {
+ auto expected = std::count(first, last, needle);
+ auto result = std::count(exec, first, last, needle);
+ EXPECT_EQ(expected, result, "wrong count result");
+ }
+};
+
+struct test_count_if
+{
+ template <typename Policy, typename Iterator, typename Predicate>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred)
+ {
+ auto expected = std::count_if(first, last, pred);
+ auto result = std::count_if(exec, first, last, pred);
+ EXPECT_EQ(expected, result, "wrong count_if result");
+ }
+};
+
+template <typename T>
+class IsEqual
+{
+ T value;
+
+ public:
+ IsEqual(T value_, OddTag) : value(value_) {}
+ bool
+ operator()(const T& x) const
+ {
+ return x == value;
+ }
+};
+
+template <typename In, typename T, typename Predicate, typename Convert>
+void
+test(T needle, Predicate pred, Convert convert)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<In> in(n, [=](size_t k) -> In {
+ // Sprinkle "42" and "50" early, so that short sequences have non-zero count.
+ return convert((n - k - 1) % 3 == 0 ? 42 : (n - k - 2) % 5 == 0 ? 50 : 3 * (int(k) % 1000 - 500));
+ });
+ invoke_on_all_policies(test_count(), in.begin(), in.end(), needle);
+ invoke_on_all_policies(test_count_if(), in.begin(), in.end(), pred);
+
+ invoke_on_all_policies(test_count(), in.cbegin(), in.cend(), needle);
+ invoke_on_all_policies(test_count_if(), in.cbegin(), in.cend(), pred);
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ count_if(exec, iter, iter, non_const(is_even));
+ }
+};
+
+int32_t
+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; });
+#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()),
+ [](int32_t j) { return Number(j, OddTag()); });
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/equal.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/equal.pass.cpp
new file mode 100644
index 00000000000..0e4f38c2eb7
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/equal.pass.cpp
@@ -0,0 +1,171 @@
+// -*- C++ -*-
+//===-- equal.pass.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+#define CPP14_ENABLED 0
+
+struct UserType
+{
+ float32_t f;
+ float64_t d;
+ int32_t i;
+ size_t key;
+
+ bool
+ operator()(UserType a, UserType b)
+ {
+ return a.key < b.key;
+ }
+ bool
+ operator<(UserType a)
+ {
+ return a.key < key;
+ }
+ bool
+ operator>=(UserType a)
+ {
+ return a.key <= key;
+ }
+ bool
+ operator<=(UserType a)
+ {
+ return a.key >= key;
+ }
+ bool
+ operator==(UserType a)
+ {
+ return a.key == key;
+ }
+ bool
+ operator==(UserType a) const
+ {
+ return a.key == key;
+ }
+ bool
+ operator!=(UserType a)
+ {
+ return a.key != key;
+ }
+ UserType operator!()
+ {
+ UserType tmp;
+ tmp.key = !key;
+ return tmp;
+ }
+ friend std::ostream&
+ operator<<(std::ostream& stream, const UserType a)
+ {
+ stream << a.key;
+ return stream;
+ }
+
+ UserType() : key(-1), f(0.0f), d(0.0), i(0) {}
+ UserType(size_t Number) : key(Number), f(0.0f), d(0.0), i(0) {}
+ UserType&
+ operator=(const UserType& other)
+ {
+ key = other.key;
+ return *this;
+ }
+ UserType(const UserType& other) : key(other.key), f(other.f), d(other.d), i(other.i) {}
+ UserType(UserType&& other) : key(other.key), f(other.f), d(other.d), i(other.i)
+ {
+ other.key = -1;
+ other.f = 0.0f;
+ other.d = 0.0;
+ other.i = 0;
+ }
+};
+
+struct test_one_policy
+{
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, bool is_true_equal)
+ {
+ using namespace std;
+
+ auto expected = equal(first1, last1, first2);
+ auto actual = equal(exec, first1, last1, first2);
+ EXPECT_EQ(expected, actual, "result for equal for random-access iterator, checking against std::equal()");
+
+ // testing bool
+ EXPECT_TRUE(is_true_equal == actual, "result for equal for random-access iterator, bool");
+
+//add C++14 equal symantics tests
+//add more cases for inCopy size less than in
+#if CPP14_ENABLED
+ auto actualr14 = std::equal(in.cbegin(), in.cend(), inCopy.cbegin(), inCopy.cend());
+ EXPECT_EQ(expected, actualr14, "result for equal for random-access iterator");
+#endif
+ }
+};
+
+template <typename T>
+void
+test(size_t bits)
+{
+ for (size_t n = 1; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+
+ // Sequence of odd values
+ Sequence<T> in(n, [bits](size_t k) { return T(2 * HashBits(k, bits - 1) ^ 1); });
+ Sequence<T> inCopy(in);
+
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), true);
+ invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), true);
+
+ // testing bool !equal()
+ inCopy[0] = !inCopy[0];
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), false);
+ invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), false);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename FirstIterator, typename SecondInterator>
+ void
+ operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+ {
+ equal(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
+ }
+};
+
+int32_t
+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
+ test<UserType>(256);
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/find.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/find.pass.cpp
new file mode 100644
index 00000000000..60e56ae4628
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/find.pass.cpp
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+//===-- find.pass.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for find
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename Iterator, typename Value>
+ void
+ 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)
+ {
+ }
+#endif
+
+ template <typename Policy, typename Iterator, typename Value>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Value value)
+ {
+ 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, typename Value, typename Hit, typename Miss>
+void
+test(Value value, Hit hit, Miss miss)
+{
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * 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)
+ {
+ 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);
+ }
+ }
+}
+
+// Type defined for sake of checking that std::find works with asymmetric ==.
+class Weird
+{
+ Number value;
+
+ public:
+ friend bool
+ operator==(Number x, Weird y)
+ {
+ return x == y.value;
+ }
+ Weird(int32_t val, OddTag) : value(val, OddTag()) {}
+};
+
+int32_t
+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 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/pstl/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp
new file mode 100644
index 00000000000..4059630b3d1
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp
@@ -0,0 +1,126 @@
+// -*- C++ -*-
+//===-- find_end.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+ template <typename Iterator1, typename Iterator2, typename Predicate>
+ void
+ 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,
+ Predicate pred)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred)
+ {
+ 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");
+ }
+ }
+};
+
+template <typename T>
+void
+test(const std::size_t bits)
+{
+
+ 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 k) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); });
+ Sequence<T> sub(max_n2, [max_n1, bits](std::size_t k) { 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))
+ {
+ 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)
+ {
+ 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>());
+ }
+ }
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename FirstIterator, typename SecondInterator>
+ void
+ operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+ {
+ 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>()));
+ });
+ }
+};
+
+int32_t
+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
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp
new file mode 100644
index 00000000000..ee62e84fd16
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+//===-- find_first_of.pass.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+ template <typename Iterator1, typename Iterator2, typename Predicate>
+ void
+ 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,
+ Predicate pred)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred)
+ {
+ using namespace std;
+ Iterator1 expected = find_first_of(b, e, bsub, esub, pred);
+ Iterator1 actual = find_first_of(exec, b, e, bsub, esub, pred);
+ EXPECT_TRUE(actual == expected, "wrong return result from find_first_of with a predicate");
+
+ expected = find_first_of(b, e, bsub, esub);
+ actual = find_first_of(exec, b, e, bsub, esub);
+ EXPECT_TRUE(actual == expected, "wrong return result from find_first_of");
+ }
+};
+
+template <typename T, typename Predicate>
+void
+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); });
+ 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};
+ for (const auto n2 : sub_n)
+ {
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.data(), in2.data() + n2, pred);
+
+ in2[n2 / 2] = T(1);
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2,
+ pred);
+
+ if (n2 >= 3)
+ {
+ in2[2 * n2 / 3] = T(1);
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(),
+ in2.begin() + n2, pred);
+ in2[2 * n2 / 3] = T(0);
+ }
+ in2[n2 / 2] = T(0);
+ }
+ }
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(),
+ in1.data() + max_n1 / 10, pred);
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename FirstIterator, typename SecondInterator>
+ void
+ operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+ {
+ invoke_if(exec, [&]() {
+ find_first_of(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
+ });
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t>(std::equal_to<int32_t>());
+ test<uint16_t>(std::not_equal_to<uint16_t>());
+ test<float64_t>([](const float64_t x, const float64_t y) { return x * x == y * y; });
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp
new file mode 100644
index 00000000000..2ea8765077f
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//===-- find_if.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for find_if and find_if_not
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+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
+ template <typename Iterator, typename Predicate, typename NotPredicate>
+ void
+ 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,
+ NotPredicate not_pred)
+ {
+ }
+#endif
+
+ template <typename Policy, typename Iterator, typename Predicate, typename NotPredicate>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred)
+ {
+ auto i = std::find_if(first, last, pred);
+ auto j = find_if(exec, first, last, pred);
+ EXPECT_TRUE(i == j, "wrong return value from find_if");
+ auto i_not = find_if_not(exec, first, last, not_pred);
+ EXPECT_TRUE(i_not == i, "wrong return value from find_if_not");
+ }
+};
+
+template <typename T, typename Predicate, typename Hit, typename Miss>
+void
+test(Predicate pred, Hit hit, Miss miss)
+{
+ auto not_pred = [pred](T x) { return !pred(x); };
+ // Try sequences of various lengths.
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * 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)
+ {
+ if (m < n)
+ in[m] = hit(n ^ m);
+ invoke_on_all_policies(test_find_if(), in.begin(), in.end(), pred, not_pred);
+ invoke_on_all_policies(test_find_if(), in.cbegin(), in.cend(), pred, not_pred);
+ }
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+
+ invoke_if(exec, [&]() {
+ find_if(exec, iter, iter, non_const(is_even));
+ find_if_not(exec, iter, iter, non_const(is_even));
+ });
+ }
+};
+
+int32_t
+main()
+{
+#if !__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
+#endif
+
+ // Try type for which algorithm can really be vectorized.
+ test<float32_t>([](float32_t x) { return x >= 0; }, [](float32_t j) { return j * j; },
+ [](float32_t j) { return -1 - j * j; });
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp
new file mode 100644
index 00000000000..cb0fa06dcda
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp
@@ -0,0 +1,105 @@
+// -*- C++ -*-
+//===-- for_each.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename Type>
+struct Gen
+{
+ Type
+ operator()(std::size_t k)
+ {
+ return Type(k % 5 != 1 ? 3 * k - 7 : 0);
+ };
+};
+
+template <typename T>
+struct Flip
+{
+ int32_t val;
+ Flip(int32_t y) : val(y) {}
+ T
+ operator()(T& x) const
+ {
+ return x = val - x;
+ }
+};
+
+struct test_one_policy
+{
+ template <typename Policy, typename Iterator, typename Size>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ // Try for_each
+ std::for_each(expected_first, expected_last, Flip<T>(1));
+ for_each(exec, first, last, Flip<T>(1));
+ 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));
+ for_each_n(exec, first, n, Flip<T>(1));
+ EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n");
+ }
+};
+
+template <typename T>
+void
+test()
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<T> inout(n, Gen<T>());
+ Sequence<T> expected(n, Gen<T>());
+ invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(),
+ inout.size());
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() {
+ auto f = [](typename std::iterator_traits<Iterator>::reference x) { x = x + 1; };
+
+ for_each(exec, iter, iter, non_const(f));
+ for_each_n(exec, iter, 0, non_const(f));
+ });
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t>();
+ test<uint16_t>();
+ test<float64_t>();
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp
new file mode 100644
index 00000000000..ec34af08fb0
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+//===-- mismatch.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#include "pstl/numeric"
+#include "pstl/memory"
+
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_mismatch
+{
+ template <typename Policy, typename Iterator1, typename Iterator2>
+ void
+ operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2)
+ {
+ using namespace std;
+ typedef typename iterator_traits<Iterator1>::value_type T;
+ {
+ const auto expected = std::mismatch(first1, last1, first2, std::equal_to<T>());
+ const auto res3 = mismatch(exec, first1, last1, first2, std::equal_to<T>());
+ EXPECT_TRUE(expected == res3, "wrong return result from mismatch");
+ const auto res4 = mismatch(exec, first1, last1, first2);
+ EXPECT_TRUE(expected == res4, "wrong return result from mismatch");
+ }
+ }
+ template <typename Policy, typename Iterator1, typename Iterator2>
+ void
+ operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ 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 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);
+ EXPECT_TRUE(expected == res2, "wrong return result from mismatch");
+ }
+ }
+};
+
+template <typename T>
+void
+test_mismatch_by_type()
+{
+ using namespace std;
+ for (size_t size = 0; size <= 100000; size = size <= 16 ? size + 1 : size_t(3.1415 * size))
+ {
+ const T val = T(-1);
+ Sequence<T> in(size, [](size_t v) -> T { return T(v % 100); });
+ {
+ Sequence<T> in2(in);
+ invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end());
+ invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin());
+
+ const size_t min_size = 3;
+ if (size > min_size)
+ {
+ const size_t idx_for_1 = size / min_size;
+ in[idx_for_1] = val, in[idx_for_1 + 1] = val, in[idx_for_1 + 2] = val;
+ invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end());
+ invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin());
+ }
+
+ const size_t idx_for_2 = 500;
+ if (size >= idx_for_2 - 1)
+ {
+ in2[size / idx_for_2] = val;
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend());
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin());
+ }
+ }
+ {
+ Sequence<T> in2(100, [](size_t v) -> T { return T(v); });
+ invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end());
+ // We can't call std::mismatch with semantic below when size of second sequence less than size of first sequence
+ if (in2.size() <= in.size())
+ invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin());
+
+ const size_t idx = 97;
+ in2[idx] = val;
+ in2[idx + 1] = val;
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend());
+ if (in.size() <= in2.size())
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin());
+ }
+ {
+ Sequence<T> in2({});
+ invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end());
+
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend());
+ if (in.size() == 0)
+ invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin());
+ }
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename FirstIterator, typename SecondInterator>
+ void
+ operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+ {
+ mismatch(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+main()
+{
+
+ test_mismatch_by_type<int32_t>();
+ test_mismatch_by_type<float64_t>();
+ test_mismatch_by_type<Wrapper<int32_t>>();
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp
new file mode 100644
index 00000000000..47a01a15027
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//===-- none_of.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+/*
+ TODO: consider implementing the following tests for a better code coverage
+ - correctness
+ - bad input argument (if applicable)
+ - data corruption around/of input and output
+ - correctly work with nested parallelism
+ - check that algorithm does not require anything more than is described in its requirements section
+*/
+
+using namespace TestUtils;
+
+struct test_none_of
+{
+ template <typename ExecutionPolicy, typename Iterator, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected)
+ {
+
+ auto actualr = std::none_of(exec, begin, end, pred);
+ EXPECT_EQ(expected, actualr, "result for none_of");
+ }
+};
+
+template <typename T>
+void
+test(size_t bits)
+{
+ for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+
+ // Sequence of odd values
+ Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+
+ // Even value, or false when T is bool.
+ T spike(2 * HashBits(n, bits - 1));
+
+ invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), true);
+ invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), true);
+ if (n > 0)
+ {
+ // Sprinkle in a hit
+ in[2 * n / 3] = spike;
+ invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), false);
+ invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), false);
+
+ // Sprinkle in a few more hits
+ in[n / 3] = spike;
+ in[n / 2] = spike;
+ invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to<T>(spike), false);
+ invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to<T>(spike), false);
+ }
+ }
+}
+
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ auto is_even = [&](float64_t v) {
+ uint32_t i = (uint32_t)v;
+ return i % 2 == 0;
+ };
+ none_of(exec, iter, iter, non_const(is_even));
+ }
+};
+
+int32_t
+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
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp
new file mode 100644
index 00000000000..f8154d2426d
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp
@@ -0,0 +1,181 @@
+// -*- C++ -*-
+//===-- nth_element.pass.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <algorithm>
+#include <iostream>
+#include "pstl/execution"
+#include "pstl/algorithm"
+
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+// User defined type with minimal requirements
+template <typename T>
+struct DataType
+{
+ explicit DataType(int32_t k) : my_val(k) {}
+ DataType(DataType&& input)
+ {
+ my_val = std::move(input.my_val);
+ input.my_val = T(0);
+ }
+ DataType&
+ operator=(DataType&& input)
+ {
+ my_val = std::move(input.my_val);
+ input.my_val = T(0);
+ return *this;
+ }
+ T
+ get_val() const
+ {
+ return my_val;
+ }
+
+ friend std::ostream&
+ operator<<(std::ostream& stream, const DataType<T>& input)
+ {
+ return stream << input.my_val;
+ }
+
+ private:
+ T my_val;
+};
+
+template <typename T>
+bool
+is_equal(const DataType<T>& x, const DataType<T>& y)
+{
+ return x.get_val() == y.get_val();
+}
+
+template <typename T>
+bool
+is_equal(const T& x, const T& y)
+{
+ return x == 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
+ 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,
+ 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,
+ Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
+ {
+ }
+#endif
+
+ // nth_element works only with random access iterators
+ 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)
+ {
+
+ using T = typename std::iterator_traits<Iterator1>::value_type;
+ const Iterator1 mid1 = std::next(first1, m);
+ const Iterator1 mid2 = std::next(first2, m);
+
+ fill_data(first1, mid1, generator1);
+ fill_data(mid1, last1, generator2);
+ fill_data(first2, mid2, generator1);
+ fill_data(mid2, last2, generator2);
+ std::nth_element(first1, mid1, last1, comp);
+ std::nth_element(exec, first2, mid2, last2, comp);
+ if (m > 0 && m < n)
+ {
+ EXPECT_TRUE(is_equal(*mid1, *mid2), "wrong result from nth_element with predicate");
+ }
+ EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2, [comp](T& x, T& y) { return comp(y, x); }) == mid2,
+ "wrong effect from nth_element with predicate");
+ }
+
+ 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)
+ {
+ }
+};
+
+template <typename T, typename Generator1, typename Generator2, typename Compare>
+void
+test_by_type(Generator1 generator1, Generator2 generator2, Compare comp)
+{
+ using namespace std;
+ size_t max_size = 10000;
+ Sequence<T> in1(max_size, [](size_t v) { return T(v); });
+ Sequence<T> exp(max_size, [](size_t v) { return T(v); });
+ size_t m;
+
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ m = 0;
+ invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
+ generator1, generator2, comp);
+ m = n / 7;
+ invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
+ generator1, generator2, comp);
+ m = 3 * n / 5;
+ invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m,
+ generator1, generator2, comp);
+ }
+ invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + max_size, in1.begin(), in1.begin() + max_size,
+ max_size, max_size, generator1, generator2, comp);
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() { nth_element(exec, iter, iter, iter, non_const(std::less<T>())); });
+ }
+};
+
+int32_t
+main()
+{
+ test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>());
+ test_by_type<int32_t>([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less<int32_t>());
+
+ test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); },
+ [](const float64_t x, const float64_t y) { return x > y; });
+
+ test_by_type<DataType<float32_t>>(
+ [](int32_t i) { return DataType<float32_t>(2 * i + 1); }, [](int32_t i) { return DataType<float32_t>(2 * i); },
+ [](const DataType<float32_t>& x, const DataType<float32_t>& y) { return x.get_val() < y.get_val(); });
+
+ test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp b/pstl/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp
new file mode 100644
index 00000000000..c0c6040e176
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//===-- search_n.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+ template <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)
+ {
+ }
+ 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,
+ Predicate pred)
+ {
+ }
+#endif
+
+ template <typename ExecutionPolicy, typename Iterator, typename Size, typename T, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator b, Iterator e, Size count, const T& value, Predicate pred)
+ {
+ using namespace std;
+ auto expected = search_n(b, e, count, value, pred);
+ auto actual = search_n(exec, b, e, count, value);
+ EXPECT_TRUE(actual == expected, "wrong return result from search_n");
+
+ actual = search_n(exec, b, e, count, value, pred);
+ EXPECT_TRUE(actual == expected, "wrong return result from search_n with a predicate");
+ }
+};
+
+template <typename T>
+void
+test()
+{
+
+ const std::size_t max_n1 = 100000;
+ const T value = T(1);
+ 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, 3, n1, (n1 * 10) / 8};
+ std::size_t res[] = {0, 1, n1 / 2, n1};
+ for (auto n2 : sub_n)
+ {
+ // Some of standard libraries return "first" in this case. We return "last" according to the standard
+ if (n2 == 0)
+ {
+ continue;
+ }
+ for (auto r : res)
+ {
+ Sequence<T> in(n1, [n1](std::size_t k) { return T(0); });
+ std::size_t i = r, isub = 0;
+ for (; i < n1 & isub < n2; ++i, ++isub)
+ in[i] = value;
+
+ invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, n2, value, std::equal_to<T>());
+ invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, n2, value, std::equal_to<T>());
+ }
+ }
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() { search_n(exec, iter, iter, 0, T(0), non_const(std::equal_to<T>())); });
+ }
+};
+
+int32_t
+main()
+{
+ test<int32_t>();
+ test<uint16_t>();
+ test<float64_t>();
+#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+ test<bool>();
+#endif
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp b/pstl/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp
new file mode 100644
index 00000000000..0c70342426e
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp
@@ -0,0 +1,148 @@
+// -*- C++ -*-
+//===-- is_heap.pass.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for is_heap, is_heap_until
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+#include <iostream>
+
+using namespace TestUtils;
+
+struct WithCmpOp
+{
+ int32_t _first;
+ int32_t _second;
+ WithCmpOp() : _first(0), _second(0){};
+ explicit WithCmpOp(int32_t x) : _first(x), _second(x){};
+ bool
+ operator<(const WithCmpOp& rhs) const
+ {
+ return this->_first < rhs._first;
+ }
+};
+
+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
+ 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)
+ {
+ }
+ 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)
+ {
+ }
+#endif
+
+ 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)
+ {
+ using namespace std;
+ // is_heap
+ {
+ bool expected = is_heap(first, last);
+ bool actual = is_heap(exec, first, last);
+ EXPECT_TRUE(expected == actual, "wrong return value from is_heap");
+ }
+ // is_heap with predicate
+ {
+ bool expected = is_heap(first, last, pred);
+ bool actual = is_heap(exec, first, last, pred);
+ EXPECT_TRUE(expected == actual, "wrong return value from is_heap with predicate");
+ }
+ // is_heap_until
+ {
+ Iterator expected = is_heap_until(first, last);
+ Iterator actual = is_heap_until(exec, first, last);
+ EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until");
+ }
+ // is_heap_until with predicate
+ {
+ const Iterator expected = is_heap_until(first, last, pred);
+ const auto y = std::distance(first, expected);
+ 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");
+ }
+ }
+
+ // 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)
+ {
+ }
+};
+
+template <typename T, typename Comp>
+void
+test_is_heap_by_type(Comp comp)
+{
+ using namespace std;
+
+ const size_t max_size = 100000;
+ for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ Sequence<T> in(n, [](size_t v) -> T { return T(v); });
+
+ invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);
+
+ std::make_heap(in.begin(), in.begin() + n / 4, comp);
+ invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp);
+
+ std::make_heap(in.begin(), in.begin() + n / 3, comp);
+ invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);
+
+ std::make_heap(in.begin(), in.end(), 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); });
+ invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ invoke_if(exec, [&]() {
+ is_heap(exec, iter, iter, non_const(std::less<T>()));
+ is_heap_until(exec, iter, iter, non_const(std::less<T>()));
+ });
+ }
+};
+
+int32_t
+main()
+{
+ test_is_heap_by_type<float32_t>(std::greater<float32_t>());
+ test_is_heap_by_type<WithCmpOp>(std::less<WithCmpOp>());
+ test_is_heap_by_type<uint64_t>([](uint64_t x, uint64_t y) { return x % 100 < y % 100; });
+
+ test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp b/pstl/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp
new file mode 100644
index 00000000000..236e34290ae
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+//===-- lexicographical_compare.pass.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include <iostream>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_one_policy
+{
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2,
+ Predicate pred)
+ {
+ const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2, pred);
+ const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2, pred);
+ EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare with predicate");
+ }
+
+ template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
+ void
+ operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2)
+ {
+ const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2);
+ const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2);
+ EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare without predicate");
+ }
+};
+
+template <typename T1, typename T2, typename Predicate>
+void
+test(Predicate pred)
+{
+
+ const std::size_t max_n = 1000000;
+ Sequence<T1> in1(max_n, [](std::size_t k) { return T1(k); });
+ Sequence<T2> in2(2 * max_n, [](std::size_t k) { return T2(k); });
+
+ std::size_t n2;
+
+ // Test case: Call algorithm's version without predicate.
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10,
+ in2.cbegin() + 5 * max_n / 10);
+
+ // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other.
+ std::size_t max_n2 = max_n / 10;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2,
+ pred);
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2,
+ in2.begin() + 3 * max_n2, pred);
+
+ // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other.
+ max_n2 = 2 * max_n;
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2,
+ pred);
+
+ for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
+ {
+ // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal.
+ n2 = n1;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);
+
+ n2 = n1;
+ // Test case: two ranges have different elements and are of the same length (second sequence less than first)
+ std::size_t ind = n1 / 2;
+ in2[ind] = T2(-1);
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);
+ in2[ind] = T2(ind);
+
+ // Test case: two ranges have different elements and are of the same length (first sequence less than second)
+ ind = n1 / 5;
+ in1[ind] = T1(-1);
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred);
+ in1[ind] = T1(ind);
+ }
+}
+
+template <typename Predicate>
+void
+test_string(Predicate pred)
+{
+
+ const std::size_t max_n = 1000000;
+ std::string in1 = "";
+ std::string in2 = "";
+ for (std::size_t n1 = 0; n1 <= max_n; ++n1)
+ {
+ in1 += n1;
+ }
+
+ for (std::size_t n1 = 0; n1 <= 2 * max_n; ++n1)
+ {
+ in2 += n1;
+ }
+
+ std::size_t n2;
+
+ for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1))
+ {
+ // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal.
+ n2 = n1;
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);
+
+ n2 = n1;
+ // Test case: two ranges have different elements and are of the same length (second sequence less than first)
+ in2[n1 / 2] = 'a';
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred);
+
+ // Test case: two ranges have different elements and are of the same length (first sequence less than second)
+ in1[n1 / 5] = 'a';
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred);
+ }
+ invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10,
+ in2.cbegin() + 5 * max_n / 10);
+}
+
+template <typename T>
+struct LocalWrapper
+{
+ explicit LocalWrapper(std::size_t k) : my_val(k) {}
+ bool
+ operator<(const LocalWrapper<T>& w) const
+ {
+ return my_val < w.my_val;
+ }
+
+ private:
+ T my_val;
+};
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename FirstIterator, typename SecondInterator>
+ void
+ operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+ {
+ invoke_if(exec, [&]() {
+ lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less<T>()));
+ });
+ }
+};
+
+int32_t
+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
+ 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>>(
+ [](const LocalWrapper<int32_t>& x, const LocalWrapper<int32_t>& y) { return x < y; });
+ test_string([](const char x, const char y) { return x < y; });
+
+ test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp b/pstl/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp
new file mode 100644
index 00000000000..e3fec868375
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp
@@ -0,0 +1,198 @@
+// -*- C++ -*-
+//===-- minmax_element.pass.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+#include <set>
+#include <cassert>
+#include <cmath>
+
+using namespace TestUtils;
+
+struct check_minelement
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator begin, Iterator end)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+ const Iterator expect = std::min_element(begin, end);
+ const Iterator result = std::min_element(exec, begin, end);
+ const Iterator result_pred = std::min_element(exec, begin, end, std::less<T>());
+ EXPECT_TRUE(expect == result, "wrong return result from min_element");
+ EXPECT_TRUE(expect == result_pred, "wrong return result from min_element");
+ }
+};
+
+struct check_maxelement
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator begin, Iterator end)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+ const Iterator expect = std::max_element(begin, end);
+ const Iterator result = std::max_element(exec, begin, end);
+ const Iterator result_pred = std::max_element(exec, begin, end, std::less<T>());
+ EXPECT_TRUE(expect == result, "wrong return result from max_element");
+ EXPECT_TRUE(expect == result_pred, "wrong return result from max_element");
+ }
+};
+
+struct check_minmaxelement
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator begin, Iterator end)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+ const std::pair<Iterator, Iterator> expect = std::minmax_element(begin, end);
+ const std::pair<Iterator, Iterator> got = std::minmax_element(exec, begin, end);
+ const std::pair<Iterator, Iterator> got_pred = std::minmax_element(exec, begin, end, std::less<T>());
+ EXPECT_TRUE(expect.first == got.first, "wrong return result from minmax_element (min part)");
+ EXPECT_TRUE(expect.second == got.second, "wrong return result from minmax_element (max part)");
+ EXPECT_TRUE(expect == got_pred, "wrong return result from minmax_element");
+ }
+};
+
+template <typename T>
+struct sequence_wrapper
+{
+ TestUtils::Sequence<T> seq;
+ const T min_value;
+ const T max_value;
+ static const std::size_t bits = 30; // We assume that T can handle signed 2^bits+1 value
+
+ // TestUtils::HashBits returns value between 0 and (1<<bits)-1,
+ // therefore we could threat 1<<bits as maximum and -(1<<bits) as a minimum
+ sequence_wrapper(std::size_t n) : seq(n), min_value(-(1 << bits)), max_value(1 << bits) {}
+
+ void
+ pattern_fill()
+ {
+ seq.fill([](std::size_t i) -> T { return T(TestUtils::HashBits(i, bits)); });
+ }
+
+ // sets first one at position `at` and bunch of them farther
+ void
+ set_desired_value(std::size_t at, T value)
+ {
+ if (seq.size() == 0)
+ return;
+ seq[at] = value;
+
+ //Producing serveral red herrings
+ for (std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5))
+ seq[i] = value;
+ }
+};
+
+template <typename T>
+void
+test_by_type(std::size_t n)
+{
+ sequence_wrapper<T> wseq(n);
+
+ // to avoid overtesing we use std::set to leave only unique indexes
+ std::set<std::size_t> targets{0};
+ if (n > 1)
+ {
+ targets.insert(1);
+ targets.insert(2.718282 * n / 3);
+ targets.insert(n / 2);
+ targets.insert(n / 7.389056);
+ targets.insert(n - 1); // last
+ }
+
+ for (std::set<std::size_t>::iterator it = targets.begin(); it != targets.end(); ++it)
+ {
+ wseq.pattern_fill();
+ wseq.set_desired_value(*it, wseq.min_value);
+ TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.cbegin(), wseq.seq.cend());
+ TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.begin(), wseq.seq.end());
+
+ wseq.set_desired_value(*it, wseq.max_value);
+ TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.cbegin(), wseq.seq.cend());
+ TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.begin(), wseq.seq.end());
+
+ if (targets.size() > 1)
+ {
+ for (std::set<std::size_t>::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit)
+ {
+ if (*rit == *it) // we requires at least 2 unique indexes in targets
+ break;
+ wseq.pattern_fill();
+ wseq.set_desired_value(*it, wseq.min_value); // setting minimum element
+ wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element
+ TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend());
+ TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end());
+ }
+ }
+ else
+ { // we must check this corner case; it can not be tested in loop above
+ TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend());
+ TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end());
+ }
+ }
+}
+
+// should provide minimal requirements only
+struct OnlyLessCompare
+{
+ int32_t val;
+ OnlyLessCompare() : val(0) {}
+ OnlyLessCompare(int32_t val_) : val(val_) {}
+ bool
+ operator<(const OnlyLessCompare& other) const
+ {
+ return val < other.val;
+ }
+};
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ max_element(exec, iter, iter, non_const(std::less<T>()));
+ min_element(exec, iter, iter, non_const(std::less<T>()));
+ minmax_element(exec, iter, iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+main()
+{
+ using TestUtils::float64_t;
+ const std::size_t N = 100000;
+
+ for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n))
+ {
+ test_by_type<float64_t>(n);
+ test_by_type<OnlyLessCompare>(n);
+ }
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << TestUtils::done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp b/pstl/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp
new file mode 100644
index 00000000000..b18bb5f69f0
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//===-- includes.pass.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include <cmath>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct Num
+{
+ T val;
+ explicit Num(const T& v) : val(v) {}
+
+ //for "includes" checks
+ template <typename T1>
+ bool
+ operator<(const Num<T1>& v1) const
+ {
+ return val < v1.val;
+ }
+
+ //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them
+ template <typename T1>
+ operator Num<T1>() const
+ {
+ return Num<T1>((T1)val);
+ }
+};
+
+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)
+ {
+
+ auto expect_res = std::includes(first1, last1, first2, last2, comp);
+ auto res = std::includes(exec, first1, last1, first2, last2, comp);
+
+ EXPECT_TRUE(expect_res == res, "wrong result for includes");
+ }
+
+ 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)
+ {
+ }
+};
+
+template <typename T1, typename T2, typename Compare>
+void
+test_includes(Compare compare)
+{
+
+ const std::size_t n_max = 1000000;
+
+ // The rand()%(2*n+1) encourages generation of some duplicates.
+ std::srand(42);
+
+ for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ 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, [](std::size_t k) { return rand() % (2 * k + 1); });
+ Sequence<T2> in2(m, [](std::size_t k) { return 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);
+
+ //test w/ non constant predicate
+ if (n < 5 && m < 5)
+ invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(),
+ non_const(compare));
+ }
+ }
+}
+
+int32_t
+main()
+{
+
+ test_includes<float64_t, float64_t>(__pstl::internal::pstl_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;
+
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp b/pstl/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp
new file mode 100644
index 00000000000..33b7542d4fa
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp
@@ -0,0 +1,167 @@
+// -*- C++ -*-
+//===-- set.pass.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include <cmath>
+#include <chrono>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct Num
+{
+ T val;
+
+ Num() : val{} {}
+ Num(const T& v) : val(v) {}
+
+ //for "includes" checks
+ template <typename T1>
+ bool
+ operator<(const Num<T1>& v1) const
+ {
+ return val < v1.val;
+ }
+
+ //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them
+ template <typename T1>
+ operator Num<T1>() const
+ {
+ return Num<T1>((T1)val);
+ }
+
+ friend bool
+ operator==(const Num& v1, const Num& v2)
+ {
+ return v1.val == v2.val;
+ }
+};
+
+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)
+ {
+ 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);
+
+ //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");
+
+ //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);
+
+ 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");
+
+ //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);
+
+ 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");
+
+ //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);
+
+ 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),
+ "wrong set_symmetric_difference effect");
+ }
+
+ 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)
+ {
+ }
+};
+
+template <typename T1, typename T2, typename Compare>
+void
+test_set(Compare compare)
+{
+
+ const std::size_t n_max = 100000;
+
+ // The rand()%(2*n+1) encourages generation of some duplicates.
+ std::srand(4200);
+
+ for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ 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<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);
+ }
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ 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>()));
+
+ set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
+
+ set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter,
+ non_const(std::less<T>()));
+
+ set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+main()
+{
+
+ test_set<float64_t, float64_t>(__pstl::internal::pstl_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>>());
+
+ std::cout << done() << std::endl;
+
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/is_sorted.pass.cpp b/pstl/test/std/algorithms/alg.sorting/is_sorted.pass.cpp
new file mode 100644
index 00000000000..a5219f79669
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/is_sorted.pass.cpp
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//===-- is_sorted.pass.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+struct test_is_sorted
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator first, Iterator last, bool exam)
+ {
+ using namespace std;
+ typedef typename std::iterator_traits<Iterator>::value_type T;
+
+ //try random-access iterator
+ bool res = is_sorted(exec, first, last);
+ EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator");
+ auto iexam = is_sorted_until(first, last);
+ auto ires = is_sorted_until(exec, first, last);
+ EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator");
+
+ //try random-access iterator with a predicate
+ res = is_sorted(exec, first, last, std::less<T>());
+ EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator");
+ iexam = is_sorted_until(first, last, std::less<T>());
+ ires = is_sorted_until(exec, first, last, std::less<T>());
+ EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator");
+ }
+};
+
+template <typename T>
+void
+test_is_sorted_by_type()
+{
+
+ Sequence<T> in(99999, [](size_t v) -> T { return T(v); }); //fill 0..n
+
+ invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end()));
+ invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end()));
+
+ in[in.size() / 2] = -1;
+ invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end()));
+ invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end()));
+
+ in[1] = -1;
+ invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end()));
+ invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end()));
+
+ //an empty container
+ Sequence<T> in0(0);
+ invoke_on_all_policies(test_is_sorted(), in0.begin(), in0.end(), std::is_sorted(in0.begin(), in0.end()));
+ 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); });
+ 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()));
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ is_sorted(exec, iter, iter, std::less<T>());
+ is_sorted_until(exec, iter, iter, std::less<T>());
+ }
+};
+
+int32_t
+main()
+{
+
+ test_is_sorted_by_type<int32_t>();
+ test_is_sorted_by_type<float64_t>();
+
+ test_is_sorted_by_type<Wrapper<int32_t>>();
+
+ test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/partial_sort.pass.cpp b/pstl/test/std/algorithms/alg.sorting/partial_sort.pass.cpp
new file mode 100644
index 00000000000..6e9d7d21d66
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/partial_sort.pass.cpp
@@ -0,0 +1,156 @@
+// -*- C++ -*-
+//===-- partial_sort.pass.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include <cmath>
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+static std::atomic<int32_t> count_val;
+static std::atomic<int32_t> count_comp;
+
+template <typename T>
+struct Num
+{
+ T val;
+
+ Num() { ++count_val; }
+ Num(T v) : val(v) { ++count_val; }
+ Num(const Num<T>& v) : val(v.val) { ++count_val; }
+ Num(Num<T>&& v) : val(v.val) { ++count_val; }
+ ~Num() { --count_val; }
+ Num<T>&
+ operator=(const Num<T>& v)
+ {
+ val = v.val;
+ return *this;
+ }
+ operator T() const { return val; }
+ bool
+ operator<(const Num<T>& v) const
+ {
+ ++count_comp;
+ return val < v.val;
+ }
+};
+
+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)
+ {
+
+ typedef typename std::iterator_traits<InputIterator>::value_type T;
+
+ // The rand()%(2*n+1) encourages generation of some duplicates.
+ std::srand(42);
+ const std::size_t n = last - first;
+ for (std::size_t k = 0; k < n; ++k)
+ {
+ first[k] = T(rand() % (2 * n + 1));
+ }
+ std::copy(first, last, exp_first);
+
+ for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p))
+ {
+ auto m1 = first + p;
+ auto m2 = exp_first + p;
+
+ std::partial_sort(exp_first, m2, exp_last, compare);
+ count_comp = 0;
+ std::partial_sort(exec, first, m1, last, compare);
+ EXPECT_EQ_N(exp_first, first, p, "wrong effect from 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 defined(__PSTL_PAR_BACKEND_TBB)
+ auto p = tbb::this_task_arena::max_concurrency();
+#else
+ auto p = 1;
+#endif
+
+#ifdef _DEBUG
+ if (count_comp > complex * p)
+ {
+ std::cout << "complexity exceeded" << std::endl;
+ }
+#endif
+ }
+ }
+ }
+
+ 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)
+ {
+ }
+};
+
+template <typename T, typename Compare>
+void
+test_partial_sort(Compare compare)
+{
+
+ const std::size_t n_max = 100000;
+ Sequence<T> in(n_max);
+ Sequence<T> exp(n_max);
+ for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n,
+ compare);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ partial_sort(exec, iter, iter, iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+main()
+{
+ count_val = 0;
+
+ test_partial_sort<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; });
+
+ EXPECT_TRUE(count_val == 0, "cleanup error");
+
+ test_partial_sort<int32_t>(
+ [](int32_t x, int32_t y) { return x > y; }); // Reversed so accidental use of < will be detected.
+
+ test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp b/pstl/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp
new file mode 100644
index 00000000000..8f132022c64
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp
@@ -0,0 +1,195 @@
+// -*- C++ -*-
+//===-- partial_sort_copy.pass.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Tests for partial_sort_copy
+
+#include <cmath>
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+
+template <typename T>
+struct Num
+{
+ T val;
+
+ Num() : val(0) {}
+ Num(T v) : val(v) {}
+ Num(const Num<T>& v) : val(v.val) {}
+ Num(Num<T>&& v) : val(v.val) {}
+ Num<T>&
+ operator=(const Num<T>& v)
+ {
+ val = v.val;
+ return *this;
+ }
+ operator T() const { return val; }
+ bool
+ operator<(const Num<T>& v) const
+ {
+ return val < v.val;
+ }
+};
+
+template <typename RandomAccessIterator>
+struct test_one_policy
+{
+ RandomAccessIterator d_first;
+ RandomAccessIterator d_last;
+ RandomAccessIterator exp_first;
+ RandomAccessIterator exp_last;
+ // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed)
+ test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2)
+ : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2)
+ {
+ }
+#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \
+ __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+ template <typename InputIterator, typename Size, typename T, typename Compare>
+ void
+ 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,
+ 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,
+ 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,
+ const T& trash)
+ {
+ }
+#endif
+
+ template <typename Policy, typename InputIterator, typename Size, typename T, typename Compare>
+ void
+ operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash,
+ Compare compare)
+ {
+ prepare_data(first, last, n1, trash);
+ RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare);
+ RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare);
+
+ EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate");
+ EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate");
+ }
+
+ template <typename Policy, typename InputIterator, typename Size, typename T>
+ void
+ operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash)
+ {
+ prepare_data(first, last, n1, trash);
+ RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last);
+ RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last);
+
+ EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate");
+ EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate");
+ }
+
+ private:
+ template <typename InputIterator, typename Size, typename T>
+ void
+ prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash)
+ {
+ // The rand()%(2*n+1) encourages generation of some duplicates.
+ std::srand(42);
+ std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); });
+
+ std::fill(exp_first, exp_last, trash);
+ std::fill(d_first, d_last, trash);
+ }
+};
+
+template <typename T, typename Compare>
+void
+test_partial_sort_copy(Compare compare)
+{
+
+ typedef typename Sequence<T>::iterator iterator_type;
+ const std::size_t n_max = 100000;
+ Sequence<T> in(n_max);
+ Sequence<T> out(2 * n_max);
+ Sequence<T> exp(2 * n_max);
+ std::size_t n1 = 0;
+ std::size_t n2;
+ T trash = T(-666);
+ for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
+ {
+ // If both sequences are equal
+ n2 = n1;
+ invoke_on_all_policies(
+ test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
+ in.begin() + n1, n1, n2, trash, compare);
+
+ // If first sequence is greater than second
+ n2 = n1 / 3;
+ invoke_on_all_policies(
+ test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
+ in.begin() + n1, n1, n2, trash, compare);
+
+ // If first sequence is less than second
+ n2 = 2 * n1;
+ invoke_on_all_policies(
+ test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(),
+ in.begin() + n1, n1, n2, trash, compare);
+ }
+ // Test partial_sort_copy without predicate
+ n1 = n_max;
+ n2 = 2 * n1;
+ invoke_on_all_policies(test_one_policy<iterator_type>(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2),
+ in.begin(), in.begin() + n1, n1, n2, trash);
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename InputIterator, typename OutputInterator>
+ void
+ operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+ {
+ invoke_if(exec, [&]() {
+ partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less<T>()));
+ });
+ }
+};
+
+int32_t
+main()
+{
+ test_partial_sort_copy<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; });
+ test_partial_sort_copy<int32_t>([](int32_t x, int32_t y) { return x > y; });
+
+ test_algo_basic_double<int32_t>(run_for_rnd<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
diff --git a/pstl/test/std/algorithms/alg.sorting/sort.pass.cpp b/pstl/test/std/algorithms/alg.sorting/sort.pass.cpp
new file mode 100644
index 00000000000..e2eb9cecd2d
--- /dev/null
+++ b/pstl/test/std/algorithms/alg.sorting/sort.pass.cpp
@@ -0,0 +1,251 @@
+// -*- C++ -*-
+//===-- sort.pass.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "support/pstl_test_config.h"
+
+#ifdef PSTL_STANDALONE_TESTS
+
+#include "pstl/execution"
+#include "pstl/algorithm"
+#else
+#include <execution>
+#include <algorithm>
+#endif // PSTL_STANDALONE_TESTS
+
+#include "support/utils.h"
+
+using namespace TestUtils;
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <atomic>
+
+static bool Stable;
+
+//! Number of extant keys
+static std::atomic<int32_t> KeyCount;
+
+//! One more than highest index in array to be sorted.
+static uint32_t LastIndex;
+
+//! Keeping Equal() static and a friend of ParanoidKey class (C++, paragraphs 3.5/7.1.1)
+class ParanoidKey;
+static bool
+Equal(const ParanoidKey& x, const ParanoidKey& y);
+
+//! A key to be sorted, with lots of checking.
+class ParanoidKey
+{
+ //! Value used by comparator
+ int32_t value;
+ //! Original position or special value (Empty or Dead)
+ int32_t index;
+ //! Special value used to mark object without a comparable value, e.g. after being moved from.
+ static const int32_t Empty = -1;
+ //! Special value used to mark destroyed objects.
+ static const int32_t Dead = -2;
+ // True if key object has comparable value
+ bool
+ isLive() const
+ {
+ return (uint32_t)(index) < LastIndex;
+ }
+ // True if key object has been constructed.
+ bool
+ isConstructed() const
+ {
+ return isLive() || index == Empty;
+ }
+
+ public:
+ ParanoidKey()
+ {
+ ++KeyCount;
+ index = Empty;
+ value = Empty;
+ }
+ ParanoidKey(const ParanoidKey& k) : value(k.value), index(k.index)
+ {
+ EXPECT_TRUE(k.isLive(), "source for copy-constructor is dead");
+ ++KeyCount;
+ }
+ ~ParanoidKey()
+ {
+ EXPECT_TRUE(isConstructed(), "double destruction");
+ index = Dead;
+ --KeyCount;
+ }
+ ParanoidKey&
+ operator=(const ParanoidKey& k)
+ {
+ EXPECT_TRUE(k.isLive(), "source for copy-assignment is dead");
+ EXPECT_TRUE(isConstructed(), "destination for copy-assignment is dead");
+ value = k.value;
+ index = k.index;
+ return *this;
+ }
+ ParanoidKey(int32_t index, int32_t value, OddTag) : index(index), value(value) {}
+ ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index)
+ {
+ EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead");
+// std::stable_sort() fails in move semantics on paranoid test before VS2015
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+ k.index = Empty;
+#endif
+ ++KeyCount;
+ }
+ ParanoidKey&
+ operator=(ParanoidKey&& k)
+ {
+ EXPECT_TRUE(k.isConstructed(), "source for move-assignment is dead");
+ EXPECT_TRUE(isConstructed(), "destination for move-assignment is dead");
+ value = k.value;
+ index = k.index;
+// std::stable_sort() fails in move semantics on paranoid test before VS2015
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+ k.index = Empty;
+#endif
+ return *this;
+ }
+ friend class KeyCompare;
+ friend bool
+ Equal(const ParanoidKey& x, const ParanoidKey& y);
+};
+
+class KeyCompare
+{
+ enum statusType
+ {
+ //! Special value used to mark defined object.
+ Live = 0xabcd,
+ //! Special value used to mark destroyed objects.
+ Dead = -1
+ } status;
+
+ public:
+ KeyCompare(OddTag) : status(Live) {}
+ ~KeyCompare() { status = Dead; }
+ bool
+ operator()(const ParanoidKey& j, const ParanoidKey& k) const
+ {
+ EXPECT_TRUE(status == Live, "key comparison object not defined");
+ EXPECT_TRUE(j.isLive(), "first key to operator() is not live");
+ EXPECT_TRUE(k.isLive(), "second key to operator() is not live");
+ return j.value < k.value;
+ }
+};
+
+// Equal is equality comparison used for checking result of sort against expected result.
+static bool
+Equal(const ParanoidKey& x, const ParanoidKey& y)
+{
+ return (x.value == y.value && !Stable) || (x.index == y.index);
+}
+
+static bool
+Equal(float32_t x, float32_t y)
+{
+ return x == y;
+}
+
+static bool
+Equal(int32_t x, int32_t y)
+{
+ return x == y;
+}
+
+struct test_sort_with_compare
+{
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ using namespace std;
+ copy_n(first, n, expected_first);
+ copy_n(first, n, tmp_first);
+ if (Stable)
+ std::stable_sort(expected_first + 1, expected_last - 1, compare);
+ else
+ std::sort(expected_first + 1, expected_last - 1, compare);
+ int32_t count0 = KeyCount;
+ if (Stable)
+ stable_sort(exec, tmp_first + 1, tmp_last - 1, compare);
+ else
+ sort(exec, tmp_first + 1, tmp_last - 1, compare);
+
+ for (size_t i = 0; i < n; ++i, ++expected_first, ++tmp_first)
+ {
+ // Check that expected[i] is equal to tmp[i]
+ EXPECT_TRUE(Equal(*expected_first, *tmp_first), "bad sort");
+ }
+ int32_t count1 = KeyCount;
+ EXPECT_EQ(count0, count1, "key cleanup error");
+ }
+ template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
+ 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)
+ {
+ }
+};
+
+template <typename T, typename Compare, typename Convert>
+void
+test_sort(Compare compare, Convert convert)
+{
+ for (size_t n = 0; n < 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
+ {
+ LastIndex = n + 2;
+ // The rand()%(2*n+1) encourages generation of some duplicates.
+ // Sequence is padded with an extra element at front and back, to detect overwrite bugs.
+ Sequence<T> in(n + 2, [=](size_t k) { return convert(k, rand() % (2 * n + 1)); });
+ Sequence<T> expected(in);
+ Sequence<T> tmp(in);
+ invoke_on_all_policies(test_sort_with_compare(), tmp.begin(), tmp.end(), expected.begin(), expected.end(),
+ in.begin(), in.end(), in.size(), compare);
+ }
+}
+
+template <typename T>
+struct test_non_const
+{
+ template <typename Policy, typename Iterator>
+ void
+ operator()(Policy&& exec, Iterator iter)
+ {
+ sort(exec, iter, iter, non_const(std::less<T>()));
+ stable_sort(exec, iter, iter, non_const(std::less<T>()));
+ }
+};
+
+int32_t
+main()
+{
+ std::srand(42);
+ for (int32_t kind = 0; kind < 2; ++kind)
+ {
+ Stable = kind != 0;
+ test_sort<ParanoidKey>(KeyCompare(OddTag()),
+ [](size_t k, size_t val) { return ParanoidKey(k, val, OddTag()); });
+ test_sort<float32_t>([](float32_t x, float32_t y) { return x < y; },
+ [](size_t, size_t val) { return float32_t(val); });
+ test_sort<int32_t>(
+ [](int32_t x, int32_t y) { return x > y; }, // Reversed so accidental use of < will be detected.
+ [](size_t, size_t val) { return int32_t(val); });
+ }
+
+ test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>());
+
+ std::cout << done() << std::endl;
+ return 0;
+}
OpenPOWER on IntegriCloud