diff options
author | Louis Dionne <ldionne@apple.com> | 2019-03-27 21:28:24 +0000 |
---|---|---|
committer | Louis Dionne <ldionne@apple.com> | 2019-03-27 21:28:24 +0000 |
commit | 3b62047b8b2209bed57d239f581bdbfc91a10b94 (patch) | |
tree | e321a0dea2d7355c3eca7c9cf9ae1f2b89823c1d /pstl/test/std/algorithms/alg.modifying.operations | |
parent | 4bc38cfe297746858a7159bd4a537261d628b47e (diff) | |
download | bcm5719-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/alg.modifying.operations')
20 files changed, 2719 insertions, 0 deletions
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; +} |