Index: pstl/trunk/CMakeLists.txt =================================================================== --- pstl/trunk/CMakeLists.txt +++ pstl/trunk/CMakeLists.txt @@ -31,11 +31,13 @@ add_library(pstl::ParallelSTL ALIAS ParallelSTL) if (PARALLELSTL_USE_PARALLEL_POLICIES) + message(STATUS "Using Parallel Policies") if (PARALLELSTL_BACKEND STREQUAL "tbb") find_package(TBB 2018 REQUIRED tbb OPTIONAL_COMPONENTS tbbmalloc) message(STATUS "Parallel STL uses TBB ${TBB_VERSION} (interface version: ${TBB_INTERFACE_VERSION})") target_link_libraries(ParallelSTL INTERFACE TBB::tbb) - else() + else() + message(STATUS "Using Parallel Policies, but not tbb") if (TARGET ${PARALLELSTL_BACKEND}) target_link_libraries(ParallelSTL INTERFACE ${PARALLELSTL_BACKEND}) else() Index: pstl/trunk/include/pstl/internal/parallel_backend_utils.h =================================================================== --- pstl/trunk/include/pstl/internal/parallel_backend_utils.h +++ pstl/trunk/include/pstl/internal/parallel_backend_utils.h @@ -12,6 +12,7 @@ #include #include +#include #include "utils.h" namespace __pstl Index: pstl/trunk/test/CMakeLists.txt =================================================================== --- pstl/trunk/test/CMakeLists.txt +++ pstl/trunk/test/CMakeLists.txt @@ -18,14 +18,17 @@ DEPENDS pstl-build-tests COMMENT "Build and run all the unit tests.") -file(GLOB_RECURSE UNIT_TESTS "test_*.cpp") +file(GLOB_RECURSE UNIT_TESTS "*.pass.cpp") foreach(_file IN LISTS UNIT_TESTS) file(RELATIVE_PATH _target "${CMAKE_CURRENT_SOURCE_DIR}" "${_file}") string(REPLACE ".cpp" "" _target "${_target}") + string(REPLACE "/" "-" _target "${_target}") set(_target "pstl-${_target}") add_executable(${_target} EXCLUDE_FROM_ALL "${_file}") + target_include_directories(${_target} PRIVATE "${CMAKE_CURRENT_LIST_DIR}") target_link_libraries(${_target} PRIVATE pstl::ParallelSTL) + target_compile_definitions(${_target} PRIVATE -DPSTL_STANDALONE_TESTS) set_target_properties(${_target} PROPERTIES CXX_EXTENSIONS NO RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") add_test(${_target} "${CMAKE_CURRENT_BINARY_DIR}/${_target}") Index: pstl/trunk/test/pstl_test_config.h =================================================================== --- pstl/trunk/test/pstl_test_config.h +++ pstl/trunk/test/pstl_test_config.h @@ -1,49 +0,0 @@ -// -*- C++ -*- -//===-- pstl_test_config.h ------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef __PSTL_TEST_config_H -#define __PSTL_TEST_config_H - -#if defined(_MSC_VER) && defined(_DEBUG) -#define _SCL_SECURE_NO_WARNINGS //to prevent the compilation warning. Microsoft STL implementation has specific checking of an iterator range in DEBUG mode for the containers from the standard library. -#endif - -#define __PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN \ - (__x86_64 && !_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER <= 1700 && !__APPLE__) -#define __PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN \ - (!_DEBUG && __INTEL_COMPILER && \ - (__INTEL_COMPILER < 1800 || (__INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1))) -#define __PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN \ - (__x86_64 && !_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1) -#define __PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN \ - (__i386__ && !_DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && __APPLE__) -#define __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN \ - (!_DEBUG && __INTEL_COMPILER >= 1800 && __INTEL_COMPILER < 1900 && _MSC_VER == 1910) -#define __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN \ - (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && _MSC_VER >= 1900) -#define __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN \ - (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1600 && __INTEL_COMPILER < 1700 && _MSC_VER == 1900) -#define __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN \ - (__PSTL_USE_PAR_POLICIES && ((_M_X64 && _MSC_VER == 1900) || __x86_64) && !_DEBUG && __INTEL_COMPILER < 1700) -#define __PSTL_ICC_16_17_TEST_64_TIMEOUT (__x86_64 && __INTEL_COMPILER && __INTEL_COMPILER < 1800 && !__APPLE__) -#define __PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN (!_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER == 1800) -#define __PSTL_CLANG_TEST_BIG_OBJ_DEBUG_32_BROKEN \ - (__i386__ && PSTL_USE_DEBUG && __clang__ && __PSTL_CLANG_VERSION <= 90000) -#define __PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN \ - (!_DEBUG && __INTEL_COMPILER && \ - (__INTEL_COMPILER < 1800 || (__INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 3))) -#define __PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN \ - (!_DEBUG && __INTEL_COMPILER == 1800 && __AVX__ && !__AVX2__ && !__AVX512__) -#define __PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN \ - (!PSTL_USE_DEBUG && (__linux__ || __APPLE__) && __INTEL_COMPILER == 1900) -#define __PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN \ - (__INTEL_COMPILER == 1900 && _MSC_VER >= 1900 && _MSC_VER <= 1910) -#define __PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN (__INTEL_COMPILER == 1900 && _MSC_VER && !_DEBUG) - -#endif /* __PSTL_TEST_config_H */ Index: pstl/trunk/test/std/algorithms/alg.merge/inplace_merge.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.merge/inplace_merge.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.merge/inplace_merge.pass.cpp @@ -0,0 +1,160 @@ +// -*- C++ -*- +//===-- inplace_merge.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include +#include "pstl/execution" +#include "pstl/algorithm" + +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, + Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, + BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } +#endif + + // inplace_merge works with bidirectional iterators at least + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + + using T = typename std::iterator_traits::value_type; + const BiDirIt1 mid1 = std::next(first1, m); + fill_data(first1, mid1, generator1); + fill_data(mid1, last1, generator2); + + const BiDirIt1 mid2 = std::next(first2, m); + fill_data(first2, mid2, generator1); + fill_data(mid2, last2, generator2); + + std::inplace_merge(first1, mid1, last1, comp); + std::inplace_merge(exec, first2, mid2, last2, comp); + EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + } +}; + +template +void +test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) +{ + using namespace std; + size_t max_size = 100000; + Sequence in1(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + size_t m; + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + m = 0; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + + m = n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + + m = 2 * n / 3; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, + generator1, generator2, comp); + } +} + +template +struct LocalWrapper +{ + explicit LocalWrapper(int32_t k) : my_val(k) {} + LocalWrapper(LocalWrapper&& input) { my_val = std::move(input.my_val); } + LocalWrapper& + operator=(LocalWrapper&& input) + { + my_val = std::move(input.my_val); + return *this; + } + bool + operator<(const LocalWrapper& w) const + { + return my_val < w.my_val; + } + friend bool + operator==(const LocalWrapper& x, const LocalWrapper& y) + { + return x.my_val == y.my_val; + } + friend std::ostream& + operator<<(std::ostream& stream, const LocalWrapper& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { inplace_merge(exec, iter, iter, iter, non_const(std::less())); }); + } +}; + +int32_t +main() +{ + test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, + [](const float64_t x, const float64_t y) { return x > y; }); + + test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); + + test_by_type>([](int32_t i) { return LocalWrapper(2 * i + 1); }, + [](int32_t i) { return LocalWrapper(2 * i); }, + std::less>()); + + test_algo_basic_single(run_for_rnd_bi>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.merge/merge.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.merge/merge.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.merge/merge.pass.cpp @@ -0,0 +1,119 @@ +// -*- C++ -*- +//===-- merge.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include +#include +#include "pstl/execution" +#include "pstl/algorithm" + +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_merge +{ + template + void + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + OutputIterator out_first, OutputIterator out_last, Compare comp) + { + using namespace std; + { + const auto res = merge(exec, first1, last1, first2, last2, out_first, comp); + EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); + EXPECT_TRUE(is_sorted(out_first, res, comp), "wrong result from merge with predicate"); + EXPECT_TRUE(includes(out_first, res, first1, last1, comp), "first sequence is not a part of result"); + EXPECT_TRUE(includes(out_first, res, first2, last2, comp), "second sequence is not a part of result"); + } + { + const auto res = merge(exec, first1, last1, first2, last2, out_first); + EXPECT_TRUE(res == out_last, "wrong return result from merge"); + EXPECT_TRUE(is_sorted(out_first, res), "wrong result from merge"); + } + } + + // for reverse iterators + template + void + operator()(Policy&& exec, std::reverse_iterator first1, std::reverse_iterator last1, + std::reverse_iterator first2, std::reverse_iterator last2, + std::reverse_iterator out_first, std::reverse_iterator out_last, + Compare comp) + { + using namespace std; + typedef typename std::iterator_traits>::value_type T; + const auto res = merge(exec, first1, last1, first2, last2, out_first, std::greater()); + + EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); + EXPECT_TRUE(is_sorted(out_first, res, std::greater()), "wrong result from merge with predicate"); + EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater()), + "first sequence is not a part of result"); + EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater()), + "second sequence is not a part of result"); + } +}; + +template +void +test_merge_by_type(Generator1 generator1, Generator2 generator2) +{ + using namespace std; + size_t max_size = 100000; + Sequence in1(max_size, generator1); + Sequence in2(max_size / 2, generator2); + Sequence out(in1.size() + in2.size()); + std::sort(in1.begin(), in1.end()); + std::sort(in2.begin(), in2.end()); + + for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) + { + invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2, + out.begin(), out.begin() + 1.5 * size, std::less()); + invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2, + out.begin(), out.begin() + 3 * size / 2, std::less()); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) + { + merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + test_merge_by_type([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; }); + test_merge_by_type([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); }); + +#if !__PSTL_ICC_16_17_TEST_64_TIMEOUT + test_merge_by_type>([](size_t v) { return Wrapper(v % 100); }, + [](size_t v) { return Wrapper(v % 10); }); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.copy/copy_if.pass.cpp +++ pstl/trunk/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 +#include +#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 + 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 + 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 + 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 +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 in(n, [&](size_t k) -> T { + T val = convert(n ^ k); + count += pred(val) ? 1 : 0; + return val; + }); + + Sequence out(count, [=](size_t) { return trash; }); + Sequence 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 + 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(-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(-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(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); +#endif + +#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(-666, [](const int32_t& x) { return true; }, [](size_t j) { return j; }, false); +#endif + + test_algo_basic_double(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/is_partitioned.pass.cpp +++ pstl/trunk/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 +#include +#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 + void + operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) + { + } +#endif + + template + 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 +void +test(Predicate pred) +{ + + const std::size_t max_n = 1000000; + Sequence 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 +struct LocalWrapper +{ + explicit LocalWrapper(std::size_t k) : my_val(k) {} + + private: + T my_val; +}; + +struct test_non_const +{ + template + 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([](const float64_t x) { return x < 0; }); + test([](const int32_t x) { return x > 1000; }); + test([](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>([](const LocalWrapper& x) { return true; }); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/partition.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +#include +#include + +using namespace TestUtils; + +template +struct DataType +{ + explicit DataType(int32_t k) : my_val(k) {} + DataType(DataType&& input) { my_val = std::move(input.my_val); } + DataType& + operator=(DataType&& input) + { + my_val = std::move(input.my_val); + return *this; + } + T + get_val() const + { + return my_val; + } + + friend std::ostream& + operator<<(std::ostream& stream, const DataType& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +typename std::enable_if::value_type>::value, bool>::type +is_equal(Iterator first, Iterator last, Iterator d_first) +{ + return std::equal(first, last, d_first); +} + +template +typename std::enable_if::value_type>::value, bool>::type +is_equal(Iterator first, Iterator last, Iterator d_first) +{ + return true; +} + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, + Size n, UnaryOp unary_op, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, + BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) + { + } +#elif __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specializations to skip testing in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, + Size n, UnaryOp unary_op, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, + BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) + { + } +#endif + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, + UnaryOp unary_op, Generator generator) + { + // partition + { + fill_data(first, last, generator); + BiDirIt actual_ret = std::partition(exec, first, last, unary_op); + EXPECT_TRUE(std::all_of(first, actual_ret, unary_op) && !std::any_of(actual_ret, last, unary_op), + "wrong effect from partition"); + } + // stable_partition + { + fill_data(exp_first, exp_last, generator); + BiDirIt exp_ret = std::stable_partition(exp_first, exp_last, unary_op); + fill_data(first, last, generator); + BiDirIt actual_ret = std::stable_partition(exec, first, last, unary_op); + + EXPECT_TRUE(std::distance(first, actual_ret) == std::distance(exp_first, exp_ret), + "wrong result from stable_partition"); + EXPECT_TRUE((is_equal(exp_first, exp_last, first)), "wrong effect from stable_partition"); + } + } + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, + UnaryOp unary_op, Generator generator) + { + } +}; + +template +void +test_by_type(Generator generator, UnaryPred pred) +{ + + using namespace std; + size_t max_size = 100000; + Sequence in(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, n, pred, + generator); + } +} + +struct test_non_const +{ + template + 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 i) { return i; }, [](int32_t) { return true; }); +#endif + test_by_type([](int32_t i) { return -i; }, [](const float64_t x) { return x < 0; }); + test_by_type([](int32_t i) { return i + 1; }, [](int64_t x) { return x % 3 == 0; }); + test_by_type>([](int32_t i) { return DataType(2 * i + 1); }, + [](const DataType& x) { return x.get_val() < 0; }); + + test_algo_basic_single(run_for_rnd_bi()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.partitions/partition_copy.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +#include +#include + +using namespace TestUtils; + +struct test_partition_copy +{ + template + 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(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 + void + operator()(pstl::execution::unsequenced_policy, std::reverse_iterator first, + std::reverse_iterator last, std::reverse_iterator true_first, + std::reverse_iterator true_last, std::reverse_iterator false_first, + OutputIterator2 false_last, UnaryOp unary_op) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, std::reverse_iterator first, + std::reverse_iterator last, std::reverse_iterator true_first, + std::reverse_iterator true_last, std::reverse_iterator false_first, + OutputIterator2 false_last, UnaryOp unary_op) + { + } +#endif +}; + +template +void +test(UnaryPred pred) +{ + + const std::size_t max_size = 100000; + Sequence in(max_size, [](std::size_t v) -> T { return T(v); }); + Sequence actual_true(max_size); + Sequence 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 + 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([](const int32_t value) { return value % 2; }); + +#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test([](const int32_t value) { return true; }); +#endif + + test([](const float64_t value) { return value > 2 << 6; }); + test>([](const Wrapper& value) -> bool { return value.get_my_field() != nullptr; }); + + test_algo_basic_double(run_for_rnd_bi()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#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 std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e) + { + } +#endif + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) + { + using namespace std; + + copy(data_b, data_e, actual_b); + + reverse(exec, actual_b, actual_e); + + bool check = equal(data_b, data_e, reverse_iterator(actual_e)); + + EXPECT_TRUE(check, "wrong result of reverse"); + } + + template + typename std::enable_if::value>::type + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) + { + } +}; + +template +void +test() +{ + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { return T(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len); + } +} + +template +struct wrapper +{ + T t; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + bool + operator==(const wrapper& a) const + { + return t == a.t; + } +}; + +int32_t +main() +{ + test(); + test(); + test(); +#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + test>(); +#endif + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/alg.reverse/reverse_copy.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +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 +bool +eq(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +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 +struct test_one_policy +{ + Iterator data_b; + Iterator data_e; + test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {} + +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e) + { + using namespace std; + using T = typename iterator_traits::value_type; + using DifferenceType = typename iterator_traits::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 res(n); + std::copy(std::reverse_iterator(data_e), std::reverse_iterator(data_b), res.begin()); + + EXPECT_EQ_N(res.begin(), actual_b, n, "wrong effect of reverse_copy"); + } +}; + +template +void +test() +{ + typedef typename Sequence::iterator iterator_type; + typedef typename Sequence::const_bidirectional_iterator cbi_iterator_type; + + const std::size_t max_len = 100000; + + Sequence actual(max_len); + + Sequence data(max_len, [](std::size_t i) { return T1(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(data.begin(), data.begin() + len), actual.begin(), + actual.begin() + len); + invoke_on_all_policies(test_one_policy(data.cbibegin(), std::next(data.cbibegin(), len)), + actual.begin(), actual.begin() + len); + } +} + +int32_t +main() +{ + // 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(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/copy_move.pass.cpp +++ pstl/trunk/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 +#include +#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 + 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 + 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 + 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 +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 + 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 + 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 + 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 +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 + 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 trash) + { + } + + template + 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 trash) + { + } +#endif + + template + 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 trash) + { + // Cleaning + std::fill_n(out_first, size, trash); + Wrapper::SetMoveCount(0); + + // Run move + auto k = move(exec, first, last, out_first); + for (size_t j = 0; j < GuardSize; ++j) + ++k; + EXPECT_TRUE(Wrapper::MoveCount() == size, "wrong effect from move"); + EXPECT_TRUE(out_last == k, "wrong return value from move"); + } +}; + +template +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 in(n, [&](size_t k) -> T { + T val = convert(n ^ k); + return val; + }); + + const size_t outN = n + GuardSize; + Sequence out(outN, [=](size_t) { return trash; }); + Sequence 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(), 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(-666, [](size_t j) { return int32_t(j); }); + test>(Wrapper(-666.0), [](int32_t j) { return Wrapper(j); }); + +#if !__PSTL_ICC_16_17_TEST_64_TIMEOUT + test(-666.0, [](size_t j) { return float64_t(j); }); + test(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); +#endif + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/fill.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/fill.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_fill +{ + template + bool + check(It first, It last, const T& value) + { + for (; first != last; ++first) + if (*first != value) + return false; + return true; + } + + template + 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 + 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 + 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 +void +test_fill_by_type(std::size_t n) +{ + Sequence 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(n); + test_fill_by_type(n); + } + + std::cout << done() << std::endl; + + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/generate.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/generate.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +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 + void + operator()(Policy&& exec, Iterator first, Iterator last, Size n) + { + using namespace std; + typedef typename std::iterator_traits::value_type T; + + // Try random-access iterator + { + Generator_count 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 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 +void +test_generate_by_type() +{ + for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence 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 +struct test_non_const +{ + template + 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(); + test_generate_by_type(); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/remove.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/remove.pass.cpp +++ pstl/trunk/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 +#include +#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 + 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 + 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 + 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 + 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 + 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 + 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 +void +test(T trash, const T& value, Predicate pred, Convert convert) +{ + const std::size_t max_size = 100000; + Sequence out(max_size, [trash](size_t) { return trash; }); + Sequence 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 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 + 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(666, 42, [](int32_t val) { return true; }, [](size_t j) { return j; }); +#endif + + test(666, 2001, [](const int32_t& val) { return val != 2001; }, + [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 2001 : -1 - int32_t(j); }); + test(-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(-666, OddTag()), Number(42, OddTag()), IsMultiple(3, OddTag()), + [](int32_t j) { return Number(j, OddTag()); }); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/remove_copy.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct run_remove_copy +{ + template + 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 +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 in(n, [&](size_t k) -> T { + T x = convert(n ^ k); + count += !(x == value) ? 1 : 0; + return x; + }); + using namespace std; + + Sequence out(count, [=](size_t) { return trash; }); + Sequence 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(-666.0, 8.5, [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); + + test(-666, 42, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); }); + + test(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; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/replace.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/replace.pass.cpp +++ pstl/trunk/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 +#include +#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 +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 + 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(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 + bool + check(Iterator1 b, Iterator1 e) + { + return true; + } + + template + typename std::enable_if::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 +void +test(Pred pred) +{ + typedef typename Sequence::iterator iterator_type; + + const std::size_t max_len = 100000; + + const T1 value = T1(0); + const T1 new_value = T1(666); + + Sequence expected(max_len); + Sequence actual(max_len); + + Sequence 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 temp(data.begin(), len); + + invoke_on_all_policies(temp, expected.begin(), expected.begin() + len, actual.begin(), actual.begin() + len, + pred, new_value, value); + } +} + +template +struct test_non_const +{ + template + 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(__pstl::internal::equal_value(666)); + test([](const uint16_t& elem) { return elem % 3 < 2; }); + test([](const float64_t& elem) { return elem * elem - 3.5 * elem > 10; }); + test([](const copy_int& val) { return val.value / 5 > 2; }); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/replace_copy.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_replace_copy +{ + template + 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 +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 in(n, [&](size_t k) -> T { return convert(n ^ k); }); + Sequence out(n, [=](size_t) { return trash; }); + Sequence 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 +struct test_non_const +{ + template + 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(-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(-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(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(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/rotate.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +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& a) : move_count(0) { t = a.t; } + + wrapper& + operator=(wrapper& a) + { + t = a.t; + return *this; + } + + wrapper& + operator=(wrapper&& a) + { + t = a.t; + move_count += 1; + return *this; + } +}; + +template +struct compare +{ + bool + operator()(const T& a, const T& b) + { + return a == b; + } +}; + +template +struct compare> +{ + bool + operator()(const wrapper& a, const wrapper& b) + { + return a.t == b.t; + } +}; +#include + +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 + void + operator()(pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, + Iterator actual_e, Size shift) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, + Iterator actual_e, Size shift) + { + } +#endif + + template + 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::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(); + 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 std::enable_if< + is_same_iterator_category::value && + !std::is_same::value && + std::is_same::value_type, wrapper>::value, + bool>::type + check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) + { + bool result = all_of(b, e, [](wrapper& a) { + bool temp = a.move_count > 0; + a.move_count = 0; + return temp; + }); + return shift == 0 || result; + } + + template + typename std::enable_if< + !(is_same_iterator_category::value && + !std::is_same::value && + std::is_same::value_type, wrapper>::value), + bool>::type + check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) + { + return true; + } +}; + +template +void +test() +{ + const int32_t max_len = 100000; + + Sequence actual(max_len, [](std::size_t i) { return T(i); }); + Sequence 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(); + test>(); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/rotate_copy.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper; + +template +bool +compare(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +bool +compare(const T& a, const T& b) +{ + return a == b; +} + +template +struct wrapper +{ + explicit wrapper(T t_) : t(t_) {} + wrapper& + operator=(const T& t_) + { + t = t_; + return *this; + } + friend bool + compare(const wrapper& a, const wrapper& b); + + private: + T t; +}; + +template +struct comparator +{ + using T1 = typename std::iterator_traits::value_type; + using T2 = typename std::iterator_traits::value_type; + bool + operator()(T1 a, T2 b) + { + T temp = a; + return compare(temp, b); + } +}; + +struct test_one_policy +{ + +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, std::size_t shift) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, std::size_t shift) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, + std::size_t shift) + { + using namespace std; + using T = typename iterator_traits::value_type; + Iterator1 data_m = std::next(data_b, shift); + + fill(actual_b, actual_e, T(-123)); + Iterator2 actual_return = rotate_copy(exec, data_b, data_m, data_e, actual_b); + + EXPECT_TRUE(actual_return == actual_e, "wrong result of rotate_copy"); + auto comparer = comparator(); + bool check = std::equal(data_m, data_e, actual_b, comparer); + check = check && std::equal(data_b, data_m, std::next(actual_b, std::distance(data_m, data_e)), comparer); + + EXPECT_TRUE(check, "wrong effect of rotate_copy"); + } +}; + +template +void +test() +{ + + const std::size_t max_len = 100000; + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [](std::size_t i) { return T1(i); }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + std::size_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; + for (std::size_t shift : shifts) + { + if (shift > 0 && shift < len) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len, shift); + invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), + actual.begin() + len, shift); + } + } + } +} + +int32_t +main() +{ + test(); + test(); + test(); + test, wrapper>(); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/swap_ranges.pass.cpp +++ pstl/trunk/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 + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + std::size_t number_of_swaps = 0; + wrapper() {} + explicit wrapper(T t_) : t(t_) {} + template + void + operator=(const U& b) + { + t = b; + } + bool + operator==(const wrapper& a) const + { + return t == a.t; + } +}; + +template +void +swap(wrapper& a, wrapper& b) +{ + std::swap(a.t, b.t); + a.number_of_swaps++; + b.number_of_swaps++; +} + +template +struct check_swap +{ + bool + operator()(T& a) + { + return true; + } +}; + +template +struct check_swap> +{ + bool + operator()(wrapper& a) + { + bool temp = (a.number_of_swaps == 1); + a.number_of_swaps = 0; + return temp; + } +}; + +struct test_one_policy +{ + template + 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::reference; + using T = typename iterator_traits::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()) && all_of(actual_b, actual_e, check_swap()); + EXPECT_TRUE(swap_check, "wrong effect of swap_ranges swap check"); + } + } + } +}; + +template +void +test() +{ + const std::size_t max_len = 100000; + + Sequence data(max_len); + Sequence 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>(); + test>(); + test(); + test(); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/transform_binary.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +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 +void +check_and_reset(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator out_first) +{ + typedef typename std::iterator_traits::value_type Out; + typename std::iterator_traits::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::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 + 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 +void +test(Predicate pred) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in1(n, [](size_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); + Sequence in2(n, [](size_t k) { return k % 7 != 2 ? 5 * k - 5 : 0; }); + + Sequence 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 +struct test_non_const +{ + template + 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())); + }); + } +}; + +int32_t +main() +{ + //const operator() + test(TheOperation(1)); + test(TheOperation(1.5)); + //non-const operator() + test(non_const(TheOperation(1.5))); + test(non_const(TheOperation(1.5))); + //lambda + test([](const int8_t& x, const float64_t& y) { return int8_t(int8_t(1.5) + x - y); }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/transform_unary.pass.cpp +++ pstl/trunk/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 +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +void +check_and_reset(InputIterator first, InputIterator last, OutputIterator out_first) +{ + typedef typename std::iterator_traits::value_type Out; + typename std::iterator_traits::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 + 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 +void +test() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](int32_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); + + Sequence out(n); + + const auto flip = Complement(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 +struct test_non_const +{ + template + 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())); }); + } +}; + +int32_t +main() +{ + test(); + test(); + test(); + test(); + test(); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/unique.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/unique.pass.cpp +++ pstl/trunk/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 +#include +#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 + void + operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, Generator generator) + { + } + + template + void + operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, BinaryPred pred, Generator generator) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, + ForwardIt last2, BinaryPred pred, Generator generator) + { + } +#endif + + template + 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 + 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 +void +test(Generator generator, Predicate pred) +{ + const std::size_t max_size = 1000000; + Sequence in(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(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 +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& x, const LocalWrapper& y) + { + return x.my_val == y.my_val; + } +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { unique(exec, iter, iter, non_const(std::equal_to())); }); + } +}; + +int32_t +main() +{ +#if !__PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN + test([](size_t j) { return j / 3; }, + [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; }); + test([](size_t) { return float64_t(1); }, + [](const float64_t& val1, const float64_t& val2) { return val1 != val2; }); +#endif + test>([](size_t j) { return LocalWrapper(j); }, + [](const LocalWrapper& val1, const LocalWrapper& val2) { + return val1.my_val != val2.my_val; + }); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.modifying.operations/unique_copy_equal.pass.cpp +++ pstl/trunk/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 +#include +#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 + 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 + 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 + 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 +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 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 out(count, [=](size_t) { return trash; }); + Sequence 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 +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + unique_copy(exec, input_iter, input_iter, out_iter, non_const(std::equal_to())); + } +}; + +int32_t +main(int32_t argc, char* argv[]) +{ + test(Number(42, OddTag()), std::equal_to(), + [](int32_t j) { return Number(3 * j / 13 ^ (j & 8), OddTag()); }); + + test(float32_t(42), std::equal_to(), + [](int32_t j) { return float32_t(5 * j / 23 ^ (j / 7)); }); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(float32_t(42), [](float32_t x, float32_t y) { return false; }, + [](int32_t j) { return float32_t(j); }, false); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/adjacent_find.pass.cpp @@ -0,0 +1,118 @@ +// -*- C++ -*- +//===-- adjacent_find.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_adjacent_find +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Pred pred) + { + using namespace std; + + auto k = std::adjacent_find(first, last, pred); + auto i = adjacent_find(exec, first, last, pred); + EXPECT_TRUE(i == k, "wrong return value from adjacent_find with predicate"); + + i = adjacent_find(exec, first, last); + EXPECT_TRUE(i == k, "wrong return value from adjacent_find without predicate"); + } +}; + +template +void +test_adjacent_find_by_type() +{ + + size_t counts[] = {2, 3, 500}; + for (int32_t c = 0; c < const_size(counts); ++c) + { + + for (int32_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e) + { + Sequence in(counts[c], [](int32_t v) -> T { return T(v); }); //fill 0...n + in[e] = in[e + 1] = -1; //make an adjacent pair + + auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); + EXPECT_TRUE(i == in.cbegin() + e, "std::adjacent_find returned wrong result"); + + invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); + } + } + + //special cases: size=0, size=1; + for (int32_t expect = 0; expect < 1; ++expect) + { + Sequence in(expect, [](int32_t v) -> T { return T(v); }); //fill 0...n + auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); + EXPECT_TRUE(i == in.cbegin() + expect, "std::adjacent_find returned wrong result"); + + invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); + } + + //special cases: + Sequence a1 = {5, 5, 5, 6, 7, 8, 9}; + invoke_on_all_policies(test_adjacent_find(), a1.begin(), a1.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a1.begin() + 1, a1.end(), std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a1.cbegin(), a1.cend(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a1.cbegin() + 1, a1.cend(), std::equal_to()); + + Sequence a2 = {5, 6, 7, 8, 9, 9}; + invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end() - 1, std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend(), std::equal_to()); + invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend() - 1, std::equal_to()); + + Sequence a3 = {5, 6, 6, 6, 7, 9, 9, 9, 9}; + invoke_on_all_policies(test_adjacent_find(), a3.begin(), a3.end(), std::equal_to()); + + invoke_on_all_policies(test_adjacent_find(), a3.cbegin(), a3.cend(), std::equal_to()); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + adjacent_find(exec, iter, iter, non_const(std::equal_to())); + } +}; + +int32_t +main() +{ + + test_adjacent_find_by_type(); + test_adjacent_find_by_type(); + + test_algo_basic_single(run_for_rnd_bi>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/all_of.pass.cpp @@ -0,0 +1,120 @@ +// -*- C++ -*- +//===-- all_of.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_all_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::all_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for all_of"); + } +}; + +template +struct Parity +{ + bool parity; + + public: + Parity(bool parity_) : parity(parity_) {} + bool + operator()(T value) const + { + return (size_t(value) ^ parity) % 2 == 0; + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + Sequence inCopy(in); + + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), true); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), true); + EXPECT_EQ(in, inCopy, "all_of modified input sequence"); + if (n > 0) + { + // Sprinkle in a miss + in[2 * n / 3] = spike; + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); + + // Sprinkle in a few more misses + in[n / 2] = spike; + in[n / 3] = spike; + invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); + invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + all_of(exec, iter, iter, non_const(is_even)); + } +}; + +int32_t +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/any_of.pass.cpp @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===-- any_of.pass.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_any_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::any_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for any_of"); + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + Sequence inCopy(in); + + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + EXPECT_EQ(in, inCopy, "any_of modified input sequence"); + if (n > 0) + { + // Sprinkle in a hit + in[2 * n / 3] = spike; + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + + // Sprinkle in a few more hits + in[n / 2] = spike; + in[n / 3] = spike; + invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + any_of(exec, iter, iter, non_const(is_even)); + } +}; + +int32_t +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/count.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/count.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/count.pass.cpp @@ -0,0 +1,111 @@ +// -*- C++ -*- +//===-- count.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Tests for count and count_if +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_count +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, T needle) + { + auto expected = std::count(first, last, needle); + auto result = std::count(exec, first, last, needle); + EXPECT_EQ(expected, result, "wrong count result"); + } +}; + +struct test_count_if +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + { + auto expected = std::count_if(first, last, pred); + auto result = std::count_if(exec, first, last, pred); + EXPECT_EQ(expected, result, "wrong count_if result"); + } +}; + +template +class IsEqual +{ + T value; + + public: + IsEqual(T value_, OddTag) : value(value_) {} + bool + operator()(const T& x) const + { + return x == value; + } +}; + +template +void +test(T needle, Predicate pred, Convert convert) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [=](size_t k) -> In { + // Sprinkle "42" and "50" early, so that short sequences have non-zero count. + return convert((n - k - 1) % 3 == 0 ? 42 : (n - k - 2) % 5 == 0 ? 50 : 3 * (int(k) % 1000 - 500)); + }); + invoke_on_all_policies(test_count(), in.begin(), in.end(), needle); + invoke_on_all_policies(test_count_if(), in.begin(), in.end(), pred); + + invoke_on_all_policies(test_count(), in.cbegin(), in.cend(), needle); + invoke_on_all_policies(test_count_if(), in.cbegin(), in.cend(), pred); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + count_if(exec, iter, iter, non_const(is_even)); + } +}; + +int32_t +main() +{ + test(42, IsEqual(50, OddTag()), [](int32_t j) { return j; }); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN + test(42, [](const int32_t& x) { return true; }, [](int32_t j) { return j; }); +#endif + test(42, IsEqual(50, OddTag()), [](int32_t j) { return float64_t(j); }); + test(Number(42, OddTag()), IsEqual(Number(50, OddTag()), OddTag()), + [](int32_t j) { return Number(j, OddTag()); }); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/equal.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/equal.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/equal.pass.cpp @@ -0,0 +1,171 @@ +// -*- C++ -*- +//===-- equal.pass.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +#define CPP14_ENABLED 0 + +struct UserType +{ + float32_t f; + float64_t d; + int32_t i; + size_t key; + + bool + operator()(UserType a, UserType b) + { + return a.key < b.key; + } + bool + operator<(UserType a) + { + return a.key < key; + } + bool + operator>=(UserType a) + { + return a.key <= key; + } + bool + operator<=(UserType a) + { + return a.key >= key; + } + bool + operator==(UserType a) + { + return a.key == key; + } + bool + operator==(UserType a) const + { + return a.key == key; + } + bool + operator!=(UserType a) + { + return a.key != key; + } + UserType operator!() + { + UserType tmp; + tmp.key = !key; + return tmp; + } + friend std::ostream& + operator<<(std::ostream& stream, const UserType a) + { + stream << a.key; + return stream; + } + + UserType() : key(-1), f(0.0f), d(0.0), i(0) {} + UserType(size_t Number) : key(Number), f(0.0f), d(0.0), i(0) {} + UserType& + operator=(const UserType& other) + { + key = other.key; + return *this; + } + UserType(const UserType& other) : key(other.key), f(other.f), d(other.d), i(other.i) {} + UserType(UserType&& other) : key(other.key), f(other.f), d(other.d), i(other.i) + { + other.key = -1; + other.f = 0.0f; + other.d = 0.0; + other.i = 0; + } +}; + +struct test_one_policy +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, bool is_true_equal) + { + using namespace std; + + auto expected = equal(first1, last1, first2); + auto actual = equal(exec, first1, last1, first2); + EXPECT_EQ(expected, actual, "result for equal for random-access iterator, checking against std::equal()"); + + // testing bool + EXPECT_TRUE(is_true_equal == actual, "result for equal for random-access iterator, bool"); + +//add C++14 equal symantics tests +//add more cases for inCopy size less than in +#if CPP14_ENABLED + auto actualr14 = std::equal(in.cbegin(), in.cend(), inCopy.cbegin(), inCopy.cend()); + EXPECT_EQ(expected, actualr14, "result for equal for random-access iterator"); +#endif + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 1; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [bits](size_t k) { return T(2 * HashBits(k, bits - 1) ^ 1); }); + Sequence inCopy(in); + + invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), true); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), true); + + // testing bool !equal() + inCopy[0] = !inCopy[0]; + invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), false); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), false); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + equal(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + } +}; + +int32_t +main() +{ + + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + test(256); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/find.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/find.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/find.pass.cpp @@ -0,0 +1,99 @@ +// -*- C++ -*- +//===-- find.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Tests for find +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_find +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Value value) + { + auto i = std::find(first, last, value); + auto j = find(exec, first, last, value); + EXPECT_TRUE(i == j, "wrong return value from find"); + } +}; + +template +void +test(Value value, Hit hit, Miss miss) +{ + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); + // Try different find positions, including not found. + // By going backwards, we can add extra matches that are *not* supposed to be found. + // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. + for (size_t m = n; m > 0; m *= 0.6) + { + if (m < n) + in[m] = hit(n ^ m); + invoke_on_all_policies(test_find(), in.begin(), in.end(), value); + invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value); + } + } +} + +// Type defined for sake of checking that std::find works with asymmetric ==. +class Weird +{ + Number value; + + public: + friend bool + operator==(Number x, Weird y) + { + return x == y.value; + } + Weird(int32_t val, OddTag) : value(val, OddTag()) {} +}; + +int32_t +main() +{ + // Note that the "hit" and "miss" functions here avoid overflow issues. + test(Weird(42, OddTag()), [](int32_t j) { return Number(42, OddTag()); }, // hit + [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss + + // Test with value that is equal to two different bit patterns (-0.0 and 0.0) + test(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit + [](int32_t j) { return j == 0 ? ~j : j; }); // miss + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/find_end.pass.cpp @@ -0,0 +1,126 @@ +// -*- C++ -*- +//===-- find_end.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) + { + using namespace std; + // For find_end + { + auto expected = find_end(b, e, bsub, esub, pred); + auto actual = find_end(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from find_end"); + + actual = find_end(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from find_end with a predicate"); + } + + // For search + { + auto expected = search(b, e, bsub, esub, pred); + auto actual = search(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from search"); + + actual = search(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from search with a predicate"); + } + } +}; + +template +void +test(const std::size_t bits) +{ + + const std::size_t max_n1 = 1000; + const std::size_t max_n2 = (max_n1 * 10) / 8; + Sequence in(max_n1, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); }); + Sequence sub(max_n2, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1)); }); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; + std::size_t res[] = {0, 1, n1 / 2, n1}; + for (auto n2 : sub_n) + { + for (auto r : res) + { + std::size_t i = r, isub = 0; + for (; i < n1 & isub < n2; ++i, ++isub) + in[i] = sub[isub]; + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2, + std::equal_to()); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(), + sub.cbegin() + n2, std::equal_to()); + } + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + }); + } +}; + +int32_t +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/find_first_of.pass.cpp @@ -0,0 +1,115 @@ +// -*- C++ -*- +//===-- find_first_of.pass.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) + { + using namespace std; + Iterator1 expected = find_first_of(b, e, bsub, esub, pred); + Iterator1 actual = find_first_of(exec, b, e, bsub, esub, pred); + EXPECT_TRUE(actual == expected, "wrong return result from find_first_of with a predicate"); + + expected = find_first_of(b, e, bsub, esub); + actual = find_first_of(exec, b, e, bsub, esub); + EXPECT_TRUE(actual == expected, "wrong return result from find_first_of"); + } +}; + +template +void +test(Predicate pred) +{ + + const std::size_t max_n1 = 1000; + const std::size_t max_n2 = (max_n1 * 10) / 8; + Sequence in1(max_n1, [](std::size_t k) { return T(1); }); + Sequence in2(max_n2, [](std::size_t k) { return T(0); }); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8}; + for (const auto n2 : sub_n) + { + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.data(), in2.data() + n2, pred); + + in2[n2 / 2] = T(1); + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2, + pred); + + if (n2 >= 3) + { + in2[2 * n2 / 3] = T(1); + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(), + in2.begin() + n2, pred); + in2[2 * n2 / 3] = T(0); + } + in2[n2 / 2] = T(0); + } + } + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(), + in1.data() + max_n1 / 10, pred); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + find_first_of(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); + }); + } +}; + +int32_t +main() +{ + test(std::equal_to()); + test(std::not_equal_to()); + test([](const float64_t x, const float64_t y) { return x * x == y * y; }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/find_if.pass.cpp @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===-- find_if.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Tests for find_if and find_if_not +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_find_if +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, + NotPredicate not_pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, + NotPredicate not_pred) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) + { + auto i = std::find_if(first, last, pred); + auto j = find_if(exec, first, last, pred); + EXPECT_TRUE(i == j, "wrong return value from find_if"); + auto i_not = find_if_not(exec, first, last, not_pred); + EXPECT_TRUE(i_not == i, "wrong return value from find_if_not"); + } +}; + +template +void +test(Predicate pred, Hit hit, Miss miss) +{ + auto not_pred = [pred](T x) { return !pred(x); }; + // Try sequences of various lengths. + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); + // Try different find positions, including not found. + // By going backwards, we can add extra matches that are *not* supposed to be found. + // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. + for (size_t m = n; m > 0; m *= 0.6) + { + if (m < n) + in[m] = hit(n ^ m); + invoke_on_all_policies(test_find_if(), in.begin(), in.end(), pred, not_pred); + invoke_on_all_policies(test_find_if(), in.cbegin(), in.cend(), pred, not_pred); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + + invoke_if(exec, [&]() { + find_if(exec, iter, iter, non_const(is_even)); + find_if_not(exec, iter, iter, non_const(is_even)); + }); + } +}; + +int32_t +main() +{ +#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN + // Note that the "hit" and "miss" functions here avoid overflow issues. + test(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit + [](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); }); // miss +#endif + + // Try type for which algorithm can really be vectorized. + test([](float32_t x) { return x >= 0; }, [](float32_t j) { return j * j; }, + [](float32_t j) { return -1 - j * j; }); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/for_each.pass.cpp @@ -0,0 +1,105 @@ +// -*- C++ -*- +//===-- for_each.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Gen +{ + Type + operator()(std::size_t k) + { + return Type(k % 5 != 1 ? 3 * k - 7 : 0); + }; +}; + +template +struct Flip +{ + int32_t val; + Flip(int32_t y) : val(y) {} + T + operator()(T& x) const + { + return x = val - x; + } +}; + +struct test_one_policy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n) + { + typedef typename std::iterator_traits::value_type T; + + // Try for_each + std::for_each(expected_first, expected_last, Flip(1)); + for_each(exec, first, last, Flip(1)); + EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each"); + + // Try for_each_n + std::for_each_n(pstl::execution::seq, expected_first, n, Flip(1)); + for_each_n(exec, first, n, Flip(1)); + EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n"); + } +}; + +template +void +test() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence inout(n, Gen()); + Sequence expected(n, Gen()); + invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(), + inout.size()); + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { + auto f = [](typename std::iterator_traits::reference x) { x = x + 1; }; + + for_each(exec, iter, iter, non_const(f)); + for_each_n(exec, iter, 0, non_const(f)); + }); + } +}; + +int32_t +main() +{ + test(); + test(); + test(); + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/mismatch.pass.cpp @@ -0,0 +1,139 @@ +// -*- C++ -*- +//===-- mismatch.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include "pstl/execution" +#include "pstl/algorithm" +#include "pstl/numeric" +#include "pstl/memory" + +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_mismatch +{ + template + void + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2) + { + using namespace std; + typedef typename iterator_traits::value_type T; + { + const auto expected = std::mismatch(first1, last1, first2, std::equal_to()); + const auto res3 = mismatch(exec, first1, last1, first2, std::equal_to()); + EXPECT_TRUE(expected == res3, "wrong return result from mismatch"); + const auto res4 = mismatch(exec, first1, last1, first2); + EXPECT_TRUE(expected == res4, "wrong return result from mismatch"); + } + } + template + void + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) + { + using namespace std; + typedef typename iterator_traits::value_type T; + { + const auto expected = mismatch(pstl::execution::seq, first1, last1, first2, last2, std::equal_to()); + const auto res1 = mismatch(exec, first1, last1, first2, last2, std::equal_to()); + EXPECT_TRUE(expected == res1, "wrong return result from mismatch"); + const auto res2 = mismatch(exec, first1, last1, first2, last2); + EXPECT_TRUE(expected == res2, "wrong return result from mismatch"); + } + } +}; + +template +void +test_mismatch_by_type() +{ + using namespace std; + for (size_t size = 0; size <= 100000; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) + { + const T val = T(-1); + Sequence in(size, [](size_t v) -> T { return T(v % 100); }); + { + Sequence in2(in); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); + + const size_t min_size = 3; + if (size > min_size) + { + const size_t idx_for_1 = size / min_size; + in[idx_for_1] = val, in[idx_for_1 + 1] = val, in[idx_for_1 + 2] = val; + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); + invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); + } + + const size_t idx_for_2 = 500; + if (size >= idx_for_2 - 1) + { + in2[size / idx_for_2] = val; + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + } + { + Sequence in2(100, [](size_t v) -> T { return T(v); }); + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); + // We can't call std::mismatch with semantic below when size of second sequence less than size of first sequence + if (in2.size() <= in.size()) + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin()); + + const size_t idx = 97; + in2[idx] = val; + in2[idx + 1] = val; + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + if (in.size() <= in2.size()) + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + { + Sequence in2({}); + invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); + + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); + if (in.size() == 0) + invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + mismatch(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + + test_mismatch_by_type(); + test_mismatch_by_type(); + test_mismatch_by_type>(); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/none_of.pass.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===-- none_of.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +/* + TODO: consider implementing the following tests for a better code coverage + - correctness + - bad input argument (if applicable) + - data corruption around/of input and output + - correctly work with nested parallelism + - check that algorithm does not require anything more than is described in its requirements section +*/ + +using namespace TestUtils; + +struct test_none_of +{ + template + void + operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) + { + + auto actualr = std::none_of(exec, begin, end, pred); + EXPECT_EQ(expected, actualr, "result for none_of"); + } +}; + +template +void +test(size_t bits) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + + // Sequence of odd values + Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); + + // Even value, or false when T is bool. + T spike(2 * HashBits(n, bits - 1)); + + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), true); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); + if (n > 0) + { + // Sprinkle in a hit + in[2 * n / 3] = spike; + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + + // Sprinkle in a few more hits + in[n / 3] = spike; + in[n / 2] = spike; + invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); + invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); + } + } +} + +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + auto is_even = [&](float64_t v) { + uint32_t i = (uint32_t)v; + return i % 2 == 0; + }; + none_of(exec, iter, iter, non_const(is_even)); + } +}; + +int32_t +main() +{ + test(8 * sizeof(int32_t)); + test(8 * sizeof(uint16_t)); + test(53); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(1); +#endif + + test_algo_basic_single(run_for_rnd_fw()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/nth_element.pass.cpp @@ -0,0 +1,181 @@ +// -*- C++ -*- +//===-- nth_element.pass.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include +#include +#include "pstl/execution" +#include "pstl/algorithm" + +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// User defined type with minimal requirements +template +struct DataType +{ + explicit DataType(int32_t k) : my_val(k) {} + DataType(DataType&& input) + { + my_val = std::move(input.my_val); + input.my_val = T(0); + } + DataType& + operator=(DataType&& input) + { + my_val = std::move(input.my_val); + input.my_val = T(0); + return *this; + } + T + get_val() const + { + return my_val; + } + + friend std::ostream& + operator<<(std::ostream& stream, const DataType& input) + { + return stream << input.my_val; + } + + private: + T my_val; +}; + +template +bool +is_equal(const DataType& x, const DataType& y) +{ + return x.get_val() == y.get_val(); +} + +template +bool +is_equal(const T& x, const T& y) +{ + return x == y; +} + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, + Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) + { + } +#endif + + // nth_element works only with random access iterators + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + + using T = typename std::iterator_traits::value_type; + const Iterator1 mid1 = std::next(first1, m); + const Iterator1 mid2 = std::next(first2, m); + + fill_data(first1, mid1, generator1); + fill_data(mid1, last1, generator2); + fill_data(first2, mid2, generator1); + fill_data(mid2, last2, generator2); + std::nth_element(first1, mid1, last1, comp); + std::nth_element(exec, first2, mid2, last2, comp); + if (m > 0 && m < n) + { + EXPECT_TRUE(is_equal(*mid1, *mid2), "wrong result from nth_element with predicate"); + } + EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2, [comp](T& x, T& y) { return comp(y, x); }) == mid2, + "wrong effect from nth_element with predicate"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, + Generator1 generator1, Generator2 generator2, Compare comp) + { + } +}; + +template +void +test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) +{ + using namespace std; + size_t max_size = 10000; + Sequence in1(max_size, [](size_t v) { return T(v); }); + Sequence exp(max_size, [](size_t v) { return T(v); }); + size_t m; + + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + m = 0; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + m = n / 7; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + m = 3 * n / 5; + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, + generator1, generator2, comp); + } + invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + max_size, in1.begin(), in1.begin() + max_size, + max_size, max_size, generator1, generator2, comp); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { nth_element(exec, iter, iter, iter, non_const(std::less())); }); + } +}; + +int32_t +main() +{ + test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); + test_by_type([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less()); + + test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, + [](const float64_t x, const float64_t y) { return x > y; }); + + test_by_type>( + [](int32_t i) { return DataType(2 * i + 1); }, [](int32_t i) { return DataType(2 * i); }, + [](const DataType& x, const DataType& y) { return x.get_val() < y.get_val(); }); + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.nonmodifying/search_n.pass.cpp @@ -0,0 +1,112 @@ +// -*- C++ -*- +//===-- search_n.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, + Predicate pred) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator b, Iterator e, Size count, const T& value, Predicate pred) + { + using namespace std; + auto expected = search_n(b, e, count, value, pred); + auto actual = search_n(exec, b, e, count, value); + EXPECT_TRUE(actual == expected, "wrong return result from search_n"); + + actual = search_n(exec, b, e, count, value, pred); + EXPECT_TRUE(actual == expected, "wrong return result from search_n with a predicate"); + } +}; + +template +void +test() +{ + + const std::size_t max_n1 = 100000; + const T value = T(1); + for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; + std::size_t res[] = {0, 1, n1 / 2, n1}; + for (auto n2 : sub_n) + { + // Some of standard libraries return "first" in this case. We return "last" according to the standard + if (n2 == 0) + { + continue; + } + for (auto r : res) + { + Sequence in(n1, [n1](std::size_t k) { return T(0); }); + std::size_t i = r, isub = 0; + for (; i < n1 & isub < n2; ++i, ++isub) + in[i] = value; + + invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, n2, value, std::equal_to()); + invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, n2, value, std::equal_to()); + } + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { search_n(exec, iter, iter, 0, T(0), non_const(std::equal_to())); }); + } +}; + +int32_t +main() +{ + test(); + test(); + test(); +#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN + test(); +#endif + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/alg.heap.operations/is_heap.pass.cpp @@ -0,0 +1,148 @@ +// -*- C++ -*- +//===-- is_heap.pass.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Tests for is_heap, is_heap_until +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" +#include + +using namespace TestUtils; + +struct WithCmpOp +{ + int32_t _first; + int32_t _second; + WithCmpOp() : _first(0), _second(0){}; + explicit WithCmpOp(int32_t x) : _first(x), _second(x){}; + bool + operator<(const WithCmpOp& rhs) const + { + return this->_first < rhs._first; + } +}; + +struct test_is_heap +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) + { + } +#endif + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + { + using namespace std; + // is_heap + { + bool expected = is_heap(first, last); + bool actual = is_heap(exec, first, last); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap"); + } + // is_heap with predicate + { + bool expected = is_heap(first, last, pred); + bool actual = is_heap(exec, first, last, pred); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap with predicate"); + } + // is_heap_until + { + Iterator expected = is_heap_until(first, last); + Iterator actual = is_heap_until(exec, first, last); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until"); + } + // is_heap_until with predicate + { + const Iterator expected = is_heap_until(first, last, pred); + const auto y = std::distance(first, expected); + const Iterator actual = is_heap_until(exec, first, last, pred); + const auto x = std::distance(first, actual); + EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate"); + } + } + + // is_heap, is_heap_until works only with random access iterators + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) + { + } +}; + +template +void +test_is_heap_by_type(Comp comp) +{ + using namespace std; + + const size_t max_size = 100000; + for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t v) -> T { return T(v); }); + + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); + + std::make_heap(in.begin(), in.begin() + n / 4, comp); + invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); + + std::make_heap(in.begin(), in.begin() + n / 3, comp); + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); + + std::make_heap(in.begin(), in.end(), comp); + invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); + } + + Sequence in(max_size / 10, [](size_t v) -> T { return T(1); }); + invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + invoke_if(exec, [&]() { + is_heap(exec, iter, iter, non_const(std::less())); + is_heap_until(exec, iter, iter, non_const(std::less())); + }); + } +}; + +int32_t +main() +{ + test_is_heap_by_type(std::greater()); + test_is_heap_by_type(std::less()); + test_is_heap_by_type([](uint64_t x, uint64_t y) { return x % 100 < y % 100; }); + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/alg.lex.comparison/lexicographical_compare.pass.cpp @@ -0,0 +1,179 @@ +// -*- C++ -*- +//===-- lexicographical_compare.pass.cpp ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_one_policy +{ + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2, + Predicate pred) + { + const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2, pred); + const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2, pred); + EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare with predicate"); + } + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) + { + const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2); + const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2); + EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare without predicate"); + } +}; + +template +void +test(Predicate pred) +{ + + const std::size_t max_n = 1000000; + Sequence in1(max_n, [](std::size_t k) { return T1(k); }); + Sequence in2(2 * max_n, [](std::size_t k) { return T2(k); }); + + std::size_t n2; + + // Test case: Call algorithm's version without predicate. + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, + in2.cbegin() + 5 * max_n / 10); + + // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. + std::size_t max_n2 = max_n / 10; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2, + pred); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2, + in2.begin() + 3 * max_n2, pred); + + // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. + max_n2 = 2 * max_n; + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2, + pred); + + for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) + { + // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. + n2 = n1; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + n2 = n1; + // Test case: two ranges have different elements and are of the same length (second sequence less than first) + std::size_t ind = n1 / 2; + in2[ind] = T2(-1); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + in2[ind] = T2(ind); + + // Test case: two ranges have different elements and are of the same length (first sequence less than second) + ind = n1 / 5; + in1[ind] = T1(-1); + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); + in1[ind] = T1(ind); + } +} + +template +void +test_string(Predicate pred) +{ + + const std::size_t max_n = 1000000; + std::string in1 = ""; + std::string in2 = ""; + for (std::size_t n1 = 0; n1 <= max_n; ++n1) + { + in1 += n1; + } + + for (std::size_t n1 = 0; n1 <= 2 * max_n; ++n1) + { + in2 += n1; + } + + std::size_t n2; + + for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) + { + // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. + n2 = n1; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + n2 = n1; + // Test case: two ranges have different elements and are of the same length (second sequence less than first) + in2[n1 / 2] = 'a'; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); + + // Test case: two ranges have different elements and are of the same length (first sequence less than second) + in1[n1 / 5] = 'a'; + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); + } + invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, + in2.cbegin() + 5 * max_n / 10); +} + +template +struct LocalWrapper +{ + explicit LocalWrapper(std::size_t k) : my_val(k) {} + bool + operator<(const LocalWrapper& w) const + { + return my_val < w.my_val; + } + + private: + T my_val; +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) + { + invoke_if(exec, [&]() { + lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); + }); + } +}; + +int32_t +main() +{ + test(std::less()); + test(std::greater()); +#if !__PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN + test([](const float64_t x, const int32_t y) { return x * x < y * y; }); +#endif + test, LocalWrapper>( + [](const LocalWrapper& x, const LocalWrapper& y) { return x < y; }); + test_string([](const char x, const char y) { return x < y; }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/alg.min.max/minmax_element.pass.cpp @@ -0,0 +1,198 @@ +// -*- C++ -*- +//===-- minmax_element.pass.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +#include +#include +#include + +using namespace TestUtils; + +struct check_minelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const Iterator expect = std::min_element(begin, end); + const Iterator result = std::min_element(exec, begin, end); + const Iterator result_pred = std::min_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect == result, "wrong return result from min_element"); + EXPECT_TRUE(expect == result_pred, "wrong return result from min_element"); + } +}; + +struct check_maxelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const Iterator expect = std::max_element(begin, end); + const Iterator result = std::max_element(exec, begin, end); + const Iterator result_pred = std::max_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect == result, "wrong return result from max_element"); + EXPECT_TRUE(expect == result_pred, "wrong return result from max_element"); + } +}; + +struct check_minmaxelement +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end) + { + typedef typename std::iterator_traits::value_type T; + const std::pair expect = std::minmax_element(begin, end); + const std::pair got = std::minmax_element(exec, begin, end); + const std::pair got_pred = std::minmax_element(exec, begin, end, std::less()); + EXPECT_TRUE(expect.first == got.first, "wrong return result from minmax_element (min part)"); + EXPECT_TRUE(expect.second == got.second, "wrong return result from minmax_element (max part)"); + EXPECT_TRUE(expect == got_pred, "wrong return result from minmax_element"); + } +}; + +template +struct sequence_wrapper +{ + TestUtils::Sequence seq; + const T min_value; + const T max_value; + static const std::size_t bits = 30; // We assume that T can handle signed 2^bits+1 value + + // TestUtils::HashBits returns value between 0 and (1< T { return T(TestUtils::HashBits(i, bits)); }); + } + + // sets first one at position `at` and bunch of them farther + void + set_desired_value(std::size_t at, T value) + { + if (seq.size() == 0) + return; + seq[at] = value; + + //Producing serveral red herrings + for (std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5)) + seq[i] = value; + } +}; + +template +void +test_by_type(std::size_t n) +{ + sequence_wrapper wseq(n); + + // to avoid overtesing we use std::set to leave only unique indexes + std::set targets{0}; + if (n > 1) + { + targets.insert(1); + targets.insert(2.718282 * n / 3); + targets.insert(n / 2); + targets.insert(n / 7.389056); + targets.insert(n - 1); // last + } + + for (std::set::iterator it = targets.begin(); it != targets.end(); ++it) + { + wseq.pattern_fill(); + wseq.set_desired_value(*it, wseq.min_value); + TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.begin(), wseq.seq.end()); + + wseq.set_desired_value(*it, wseq.max_value); + TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.begin(), wseq.seq.end()); + + if (targets.size() > 1) + { + for (std::set::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit) + { + if (*rit == *it) // we requires at least 2 unique indexes in targets + break; + wseq.pattern_fill(); + wseq.set_desired_value(*it, wseq.min_value); // setting minimum element + wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); + } + } + else + { // we must check this corner case; it can not be tested in loop above + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); + TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); + } + } +} + +// should provide minimal requirements only +struct OnlyLessCompare +{ + int32_t val; + OnlyLessCompare() : val(0) {} + OnlyLessCompare(int32_t val_) : val(val_) {} + bool + operator<(const OnlyLessCompare& other) const + { + return val < other.val; + } +}; + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + max_element(exec, iter, iter, non_const(std::less())); + min_element(exec, iter, iter, non_const(std::less())); + minmax_element(exec, iter, iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + using TestUtils::float64_t; + const std::size_t N = 100000; + + for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n)) + { + test_by_type(n); + test_by_type(n); + } + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << TestUtils::done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/includes.pass.cpp @@ -0,0 +1,111 @@ +// -*- C++ -*- +//===-- includes.pass.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + explicit Num(const T& v) : val(v) {} + + //for "includes" checks + template + bool + operator<(const Num& v1) const + { + return val < v1.val; + } + + //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them + template + operator Num() const + { + return Num((T1)val); + } +}; + +struct test_one_policy +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + + auto expect_res = std::includes(first1, last1, first2, last2, comp); + auto res = std::includes(exec, first1, last1, first2, last2, comp); + + EXPECT_TRUE(expect_res == res, "wrong result for includes"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + } +}; + +template +void +test_includes(Compare compare) +{ + + const std::size_t n_max = 1000000; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) + { + //prepare the input ranges + Sequence in1(n, [](std::size_t k) { return rand() % (2 * k + 1); }); + Sequence in2(m, [](std::size_t k) { return rand() % (k + 1); }); + + std::sort(in1.begin(), in1.end(), compare); + std::sort(in2.begin(), in2.end(), compare); + + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); + + //test w/ non constant predicate + if (n < 5 && m < 5) + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), + non_const(compare)); + } + } +} + +int32_t +main() +{ + + test_includes(__pstl::internal::pstl_less()); + test_includes, Num>([](const Num& x, const Num& y) { return x < y; }); + std::cout << done() << std::endl; + + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/alg.set.operations/set.pass.cpp @@ -0,0 +1,167 @@ +// -*- C++ -*- +//===-- set.pass.cpp ------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + + Num() : val{} {} + Num(const T& v) : val(v) {} + + //for "includes" checks + template + bool + operator<(const Num& v1) const + { + return val < v1.val; + } + + //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them + template + operator Num() const + { + return Num((T1)val); + } + + friend bool + operator==(const Num& v1, const Num& v2) + { + return v1.val == v2.val; + } +}; + +struct test_one_policy +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + using T1 = typename std::iterator_traits::value_type; + + auto n1 = std::distance(first1, last1); + auto n2 = std::distance(first2, last2); + auto n = n1 + n2; + Sequence expect(n); + Sequence out(n); + + //1. set_union + auto expect_res = std::set_union(first1, last1, first2, last2, expect.begin(), comp); + auto res = std::set_union(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_union"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_union effect"); + + //2. set_intersection + expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp); + res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_intersection"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_intersection effect"); + + //3. set_difference + expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp); + res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_difference"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_difference effect"); + + //4. set_symmetric_difference + expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp); + res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp); + + EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_symmetric_difference"); + EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), + "wrong set_symmetric_difference effect"); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + Compare comp) + { + } +}; + +template +void +test_set(Compare compare) +{ + + const std::size_t n_max = 100000; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(4200); + + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) + { + //prepare the input ranges + Sequence in1(n, [n](std::size_t k) { return rand() % (2 * k + 1); }); + Sequence in2(m, [m](std::size_t k) { return (m % 2) * rand() + rand() % (k + 1); }); + + std::sort(in1.begin(), in1.end(), compare); + std::sort(in2.begin(), in2.end(), compare); + + invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); + } + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + set_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + + set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + + set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, + non_const(std::less())); + + set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + + test_set(__pstl::internal::pstl_less()); + test_set, Num>([](const Num& x, const Num& y) { return x < y; }); + + test_algo_basic_double(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/is_sorted.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/is_sorted.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/is_sorted.pass.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===-- is_sorted.pass.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_is_sorted +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, bool exam) + { + using namespace std; + typedef typename std::iterator_traits::value_type T; + + //try random-access iterator + bool res = is_sorted(exec, first, last); + EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); + auto iexam = is_sorted_until(first, last); + auto ires = is_sorted_until(exec, first, last); + EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); + + //try random-access iterator with a predicate + res = is_sorted(exec, first, last, std::less()); + EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); + iexam = is_sorted_until(first, last, std::less()); + ires = is_sorted_until(exec, first, last, std::less()); + EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); + } +}; + +template +void +test_is_sorted_by_type() +{ + + Sequence in(99999, [](size_t v) -> T { return T(v); }); //fill 0..n + + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + in[in.size() / 2] = -1; + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + in[1] = -1; + invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); + invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); + + //an empty container + Sequence in0(0); + invoke_on_all_policies(test_is_sorted(), in0.begin(), in0.end(), std::is_sorted(in0.begin(), in0.end())); + invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end())); + + //non-descending order + Sequence in1(9, [](size_t v) -> T { return T(0); }); + invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end())); + invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end())); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + is_sorted(exec, iter, iter, std::less()); + is_sorted_until(exec, iter, iter, std::less()); + } +}; + +int32_t +main() +{ + + test_is_sorted_by_type(); + test_is_sorted_by_type(); + + test_is_sorted_by_type>(); + + test_algo_basic_single(run_for_rnd_fw>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/partial_sort.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/partial_sort.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/partial_sort.pass.cpp @@ -0,0 +1,156 @@ +// -*- C++ -*- +//===-- partial_sort.pass.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +static std::atomic count_val; +static std::atomic count_comp; + +template +struct Num +{ + T val; + + Num() { ++count_val; } + Num(T v) : val(v) { ++count_val; } + Num(const Num& v) : val(v.val) { ++count_val; } + Num(Num&& v) : val(v.val) { ++count_val; } + ~Num() { --count_val; } + Num& + operator=(const Num& v) + { + val = v.val; + return *this; + } + operator T() const { return val; } + bool + operator<(const Num& v) const + { + ++count_comp; + return val < v.val; + } +}; + +struct test_brick_partial_sort +{ + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, + Compare compare) + { + + typedef typename std::iterator_traits::value_type T; + + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + const std::size_t n = last - first; + for (std::size_t k = 0; k < n; ++k) + { + first[k] = T(rand() % (2 * n + 1)); + } + std::copy(first, last, exp_first); + + for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p)) + { + auto m1 = first + p; + auto m2 = exp_first + p; + + std::partial_sort(exp_first, m2, exp_last, compare); + count_comp = 0; + std::partial_sort(exec, first, m1, last, compare); + EXPECT_EQ_N(exp_first, first, p, "wrong effect from partial_sort"); + + //checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads; + if (m1 - first > 1) + { + auto complex = std::ceil(n * std::log(float32_t(m1 - first))); +#if defined(__PSTL_PAR_BACKEND_TBB) + auto p = tbb::this_task_arena::max_concurrency(); +#else + auto p = 1; +#endif + +#ifdef _DEBUG + if (count_comp > complex * p) + { + std::cout << "complexity exceeded" << std::endl; + } +#endif + } + } + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, + Compare compare) + { + } +}; + +template +void +test_partial_sort(Compare compare) +{ + + const std::size_t n_max = 100000; + Sequence in(n_max); + Sequence exp(n_max); + for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, + compare); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + partial_sort(exec, iter, iter, iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + count_val = 0; + + test_partial_sort>([](Num x, Num y) { return x < y; }); + + EXPECT_TRUE(count_val == 0, "cleanup error"); + + test_partial_sort( + [](int32_t x, int32_t y) { return x > y; }); // Reversed so accidental use of < will be detected. + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/partial_sort_copy.pass.cpp @@ -0,0 +1,195 @@ +// -*- C++ -*- +//===-- partial_sort_copy.pass.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Tests for partial_sort_copy + +#include +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct Num +{ + T val; + + Num() : val(0) {} + Num(T v) : val(v) {} + Num(const Num& v) : val(v.val) {} + Num(Num&& v) : val(v.val) {} + Num& + operator=(const Num& v) + { + val = v.val; + return *this; + } + operator T() const { return val; } + bool + operator<(const Num& v) const + { + return val < v.val; + } +}; + +template +struct test_one_policy +{ + RandomAccessIterator d_first; + RandomAccessIterator d_last; + RandomAccessIterator exp_first; + RandomAccessIterator exp_last; + // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed) + test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2) + : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2) + { + } +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash, Compare compare) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash, Compare compare) + { + } + + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash) + { + } + + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, + const T& trash) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, + Compare compare) + { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate"); + } + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) + { + prepare_data(first, last, n1, trash); + RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last); + RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last); + + EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate"); + EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate"); + } + + private: + template + void + prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash) + { + // The rand()%(2*n+1) encourages generation of some duplicates. + std::srand(42); + std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); }); + + std::fill(exp_first, exp_last, trash); + std::fill(d_first, d_last, trash); + } +}; + +template +void +test_partial_sort_copy(Compare compare) +{ + + typedef typename Sequence::iterator iterator_type; + const std::size_t n_max = 100000; + Sequence in(n_max); + Sequence out(2 * n_max); + Sequence exp(2 * n_max); + std::size_t n1 = 0; + std::size_t n2; + T trash = T(-666); + for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) + { + // If both sequences are equal + n2 = n1; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is greater than second + n2 = n1 / 3; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + + // If first sequence is less than second + n2 = 2 * n1; + invoke_on_all_policies( + test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), + in.begin() + n1, n1, n2, trash, compare); + } + // Test partial_sort_copy without predicate + n1 = n_max; + n2 = 2 * n1; + invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), + in.begin(), in.begin() + n1, n1, n2, trash); +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) + { + invoke_if(exec, [&]() { + partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less())); + }); + } +}; + +int32_t +main() +{ + test_partial_sort_copy>([](Num x, Num y) { return x < y; }); + test_partial_sort_copy([](int32_t x, int32_t y) { return x > y; }); + + test_algo_basic_double(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/algorithms/alg.sorting/sort.pass.cpp =================================================================== --- pstl/trunk/test/std/algorithms/alg.sorting/sort.pass.cpp +++ pstl/trunk/test/std/algorithms/alg.sorting/sort.pass.cpp @@ -0,0 +1,251 @@ +// -*- C++ -*- +//===-- sort.pass.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS + +#include "pstl/execution" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; +#define _CRT_SECURE_NO_WARNINGS + +#include + +static bool Stable; + +//! Number of extant keys +static std::atomic KeyCount; + +//! One more than highest index in array to be sorted. +static uint32_t LastIndex; + +//! Keeping Equal() static and a friend of ParanoidKey class (C++, paragraphs 3.5/7.1.1) +class ParanoidKey; +static bool +Equal(const ParanoidKey& x, const ParanoidKey& y); + +//! A key to be sorted, with lots of checking. +class ParanoidKey +{ + //! Value used by comparator + int32_t value; + //! Original position or special value (Empty or Dead) + int32_t index; + //! Special value used to mark object without a comparable value, e.g. after being moved from. + static const int32_t Empty = -1; + //! Special value used to mark destroyed objects. + static const int32_t Dead = -2; + // True if key object has comparable value + bool + isLive() const + { + return (uint32_t)(index) < LastIndex; + } + // True if key object has been constructed. + bool + isConstructed() const + { + return isLive() || index == Empty; + } + + public: + ParanoidKey() + { + ++KeyCount; + index = Empty; + value = Empty; + } + ParanoidKey(const ParanoidKey& k) : value(k.value), index(k.index) + { + EXPECT_TRUE(k.isLive(), "source for copy-constructor is dead"); + ++KeyCount; + } + ~ParanoidKey() + { + EXPECT_TRUE(isConstructed(), "double destruction"); + index = Dead; + --KeyCount; + } + ParanoidKey& + operator=(const ParanoidKey& k) + { + EXPECT_TRUE(k.isLive(), "source for copy-assignment is dead"); + EXPECT_TRUE(isConstructed(), "destination for copy-assignment is dead"); + value = k.value; + index = k.index; + return *this; + } + ParanoidKey(int32_t index, int32_t value, OddTag) : index(index), value(value) {} + ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index) + { + EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead"); +// std::stable_sort() fails in move semantics on paranoid test before VS2015 +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + k.index = Empty; +#endif + ++KeyCount; + } + ParanoidKey& + operator=(ParanoidKey&& k) + { + EXPECT_TRUE(k.isConstructed(), "source for move-assignment is dead"); + EXPECT_TRUE(isConstructed(), "destination for move-assignment is dead"); + value = k.value; + index = k.index; +// std::stable_sort() fails in move semantics on paranoid test before VS2015 +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + k.index = Empty; +#endif + return *this; + } + friend class KeyCompare; + friend bool + Equal(const ParanoidKey& x, const ParanoidKey& y); +}; + +class KeyCompare +{ + enum statusType + { + //! Special value used to mark defined object. + Live = 0xabcd, + //! Special value used to mark destroyed objects. + Dead = -1 + } status; + + public: + KeyCompare(OddTag) : status(Live) {} + ~KeyCompare() { status = Dead; } + bool + operator()(const ParanoidKey& j, const ParanoidKey& k) const + { + EXPECT_TRUE(status == Live, "key comparison object not defined"); + EXPECT_TRUE(j.isLive(), "first key to operator() is not live"); + EXPECT_TRUE(k.isLive(), "second key to operator() is not live"); + return j.value < k.value; + } +}; + +// Equal is equality comparison used for checking result of sort against expected result. +static bool +Equal(const ParanoidKey& x, const ParanoidKey& y) +{ + return (x.value == y.value && !Stable) || (x.index == y.index); +} + +static bool +Equal(float32_t x, float32_t y) +{ + return x == y; +} + +static bool +Equal(int32_t x, int32_t y) +{ + return x == y; +} + +struct test_sort_with_compare +{ + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) + { + using namespace std; + copy_n(first, n, expected_first); + copy_n(first, n, tmp_first); + if (Stable) + std::stable_sort(expected_first + 1, expected_last - 1, compare); + else + std::sort(expected_first + 1, expected_last - 1, compare); + int32_t count0 = KeyCount; + if (Stable) + stable_sort(exec, tmp_first + 1, tmp_last - 1, compare); + else + sort(exec, tmp_first + 1, tmp_last - 1, compare); + + for (size_t i = 0; i < n; ++i, ++expected_first, ++tmp_first) + { + // Check that expected[i] is equal to tmp[i] + EXPECT_TRUE(Equal(*expected_first, *tmp_first), "bad sort"); + } + int32_t count1 = KeyCount; + EXPECT_EQ(count0, count1, "key cleanup error"); + } + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, + OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) + { + } +}; + +template +void +test_sort(Compare compare, Convert convert) +{ + for (size_t n = 0; n < 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + LastIndex = n + 2; + // The rand()%(2*n+1) encourages generation of some duplicates. + // Sequence is padded with an extra element at front and back, to detect overwrite bugs. + Sequence in(n + 2, [=](size_t k) { return convert(k, rand() % (2 * n + 1)); }); + Sequence expected(in); + Sequence tmp(in); + invoke_on_all_policies(test_sort_with_compare(), tmp.begin(), tmp.end(), expected.begin(), expected.end(), + in.begin(), in.end(), in.size(), compare); + } +} + +template +struct test_non_const +{ + template + void + operator()(Policy&& exec, Iterator iter) + { + sort(exec, iter, iter, non_const(std::less())); + stable_sort(exec, iter, iter, non_const(std::less())); + } +}; + +int32_t +main() +{ + std::srand(42); + for (int32_t kind = 0; kind < 2; ++kind) + { + Stable = kind != 0; + test_sort(KeyCompare(OddTag()), + [](size_t k, size_t val) { return ParanoidKey(k, val, OddTag()); }); + test_sort([](float32_t x, float32_t y) { return x < y; }, + [](size_t, size_t val) { return float32_t(val); }); + test_sort( + [](int32_t x, int32_t y) { return x > y; }, // Reversed so accidental use of < will be detected. + [](size_t, size_t val) { return int32_t(val); }); + } + + test_algo_basic_single(run_for_rnd>()); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/numerics/numeric.ops/adjacent_difference.pass.cpp =================================================================== --- pstl/trunk/test/std/numerics/numeric.ops/adjacent_difference.pass.cpp +++ pstl/trunk/test/std/numerics/numeric.ops/adjacent_difference.pass.cpp @@ -0,0 +1,175 @@ +// -*- C++ -*- +//===-- adjacent_difference.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 + +#include "pstl/execution" +#include "pstl/algorithm" +#include "pstl/numeric" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +template +struct wrapper +{ + T t; + explicit wrapper(T t_) : t(t_) {} + template + wrapper(const wrapper& a) + { + t = a.t; + } + template + void + operator=(const wrapper& a) + { + t = a.t; + } + wrapper + operator-(const wrapper& a) const + { + return wrapper(t - a.t); + } +}; + +template +bool +compare(const T& a, const T& b) +{ + return a == b; +} + +template +bool +compare(const wrapper& a, const wrapper& b) +{ + return a.t == b.t; +} + +template +typename std::enable_if::value, bool>::type +compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function f) +{ + using T2 = typename std::iterator_traits::value_type; + + if (first == last) + return true; + + T2 temp(*first); + if (!compare(temp, *d_first)) + return false; + Iterator1 second = std::next(first); + + ++d_first; + for (; second != last; ++first, ++second, ++d_first) + { + T2 temp(f(*second, *first)); + if (!compare(temp, *d_first)) + return false; + } + + return true; +} + +// we don't want to check equality here +// because we can't be sure it will be strictly equal for floating point types +template +typename std::enable_if::value, bool>::type +compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function) +{ + return true; +} + +struct test_one_policy +{ +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ + __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, T trash, Function f) + { + } + template + typename std::enable_if::value, void>::type + operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, + Iterator2 actual_e, T trash, Function f) + { + } +#endif + + template + void + operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, + T trash, Function f) + { + using namespace std; + using T2 = typename std::iterator_traits::value_type; + + fill(actual_b, actual_e, trash); + + Iterator2 actual_return = adjacent_difference(exec, data_b, data_e, actual_b); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), std::minus()), + "wrong effect of adjacent_difference"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference"); + + fill(actual_b, actual_e, trash); + + actual_return = adjacent_difference(exec, data_b, data_e, actual_b, f); + EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), f), + "wrong effect of adjacent_difference with functor"); + EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference with functor"); + } +}; + +template +void +test(Pred pred) +{ + typedef typename Sequence::iterator iterator_type; + + const std::size_t max_len = 100000; + + const T2 value = T2(77); + const T1 trash = T1(31); + + Sequence actual(max_len, [](std::size_t i) { return T1(i); }); + + Sequence data(max_len, [&value](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; }); + + for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) + { + invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), + actual.begin() + len, trash, pred); + invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), + actual.begin() + len, trash, pred); + } +} + +int32_t +main() +{ + test([](uint32_t a, uint32_t b) { return a - b; }); + test([](int64_t a, int64_t b) { return a / (b + 1); }); + test([](float32_t a, float32_t b) { return (a + b) / 2; }); + test, wrapper>( + [](const wrapper& a, const wrapper& b) { return a - b; }); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/numerics/numeric.ops/reduce.pass.cpp =================================================================== --- pstl/trunk/test/std/numerics/numeric.ops/reduce.pass.cpp +++ pstl/trunk/test/std/numerics/numeric.ops/reduce.pass.cpp @@ -0,0 +1,117 @@ +// -*- C++ -*- +//===-- reduce.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/numeric" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_long_forms_for_one_policy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, T init, BinaryOp binary, T expected) + { + T result_r = std::reduce(exec, first, last, init, binary); + EXPECT_EQ(expected, result_r, "bad result from reduce(exec, first, last, init, binary_op)"); + } +}; + +template +void +test_long_form(T init, BinaryOp binary_op, F f) +{ + // Try sequences of various lengths + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + T expected(init); + Sequence in(n, [n, f](size_t k) { return f((int32_t(k ^ n) % 1000 - 500)); }); + for (size_t k = 0; k < n; ++k) + expected = binary_op(expected, in[k]); + + using namespace std; + + T result = transform_reduce_serial(in.cfbegin(), in.cfend(), init, binary_op, [](const T& t) { return t; }); + EXPECT_EQ(expected, result, "bad result from reduce(first, last, init, binary_op_op)"); + + invoke_on_all_policies(test_long_forms_for_one_policy(), in.begin(), in.end(), init, binary_op, expected); + invoke_on_all_policies(test_long_forms_for_one_policy(), in.cbegin(), in.cend(), init, binary_op, expected); + } +} + +struct test_two_short_forms +{ + +#if __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specialization by policy type, in case of broken configuration + template + void + operator()(pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Sum init, Sum expected) + { + } +#endif + + template + void + operator()(Policy&& exec, Iterator first, Iterator last, Sum init, Sum expected) + { + using namespace std; + + Sum r0 = init + reduce(exec, first, last); + EXPECT_EQ(expected, r0, "bad result from reduce(exec, first, last)"); + + Sum r1 = reduce(exec, first, last, init); + EXPECT_EQ(expected, r1, "bad result from reduce(exec, first, last, init)"); + } +}; + +// Test forms of reduce(...) that omit the binary_op or init operands. +void +test_short_forms() +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sum init(42, OddTag()); + Sum expected(init); + Sequence in(n, [n](size_t k) { return Sum((int32_t(k ^ n) % 1000 - 500), OddTag()); }); + for (size_t k = 0; k < n; ++k) + expected = expected + in[k]; + invoke_on_all_policies(test_two_short_forms(), in.begin(), in.end(), init, expected); + invoke_on_all_policies(test_two_short_forms(), in.cbegin(), in.cend(), init, expected); + } +} + +int32_t +main() +{ + // Test for popular types + test_long_form(42, std::plus(), [](int32_t x) { return x; }); + test_long_form(42.0, std::plus(), [](float64_t x) { return x; }); + + // Test for strict types + test_long_form(Number(42, OddTag()), Add(OddTag()), [](int32_t x) { return Number(x, OddTag()); }); + + // Short forms are just facade for long forms, so just test with a single type. + test_short_forms(); + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/numerics/numeric.ops/scan.pass.cpp =================================================================== --- pstl/trunk/test/std/numerics/numeric.ops/scan.pass.cpp +++ pstl/trunk/test/std/numerics/numeric.ops/scan.pass.cpp @@ -0,0 +1,203 @@ +// -*- C++ -*- +//===-- scan.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/numeric" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// We provide the no execution policy versions of the exclusive_scan and inclusive_scan due checking correctness result of the versions with execution policies. +//TODO: to add a macro for availability of ver implementations +template +OutputIterator +exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init) +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = init + *first; + } + return result; +} + +template +OutputIterator +exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op) +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = binary_op(init, *first); + } + return result; +} + +// Note: N4582 is missing the ", class T". Issue was reported 2016-Apr-11 to cxxeditor@gmail.com +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, T init) +{ + for (; first != last; ++first, ++result) + { + init = binary_op(init, *first); + *result = init; + } + return result; +} + +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) +{ + if (first != last) + { + auto tmp = *first; + *result = tmp; + return inclusive_scan_serial(++first, last, ++result, binary_op, tmp); + } + else + { + return result; + } +} + +template +OutputIterator +inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result) +{ + typedef typename std::iterator_traits::value_type input_type; + return inclusive_scan_serial(first, last, result, std::plus()); +} + +// Most of the framework required for testing inclusive and exclusive scan is identical, +// so the tests for both are in this file. Which is being tested is controlled by the global +// flag inclusive, which is set to each alternative by main(). +static bool inclusive; + +template +void +check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) +{ + EXPECT_EQ_N(expected_first, out_first, n, + inclusive ? "wrong result from inclusive_scan" : "wrong result from exclusive_scan"); + std::fill_n(out_first, n, trash); +} + +struct test_scan_with_plus +{ + template + void + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, + Iterator3 expected_first, Iterator3 expected_last, Size n, T init, T trash) + { + using namespace std; + + auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first) + : exclusive_scan_serial(in_first, in_last, expected_first, init); + auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first) + : exclusive_scan(exec, in_first, in_last, out_first, init); + EXPECT_TRUE(out_last == orr, + inclusive ? "inclusive_scan returned wrong iterator" : "exclusive_scan returned wrong iterator"); + + check_and_reset(expected_first, out_first, n, trash); + fill(out_first, out_last, trash); + } +}; + +template +void +test_with_plus(T init, T trash, Convert convert) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, convert); + Sequence expected(in); + Sequence out(n, [&](int32_t) { return trash; }); + + invoke_on_all_policies(test_scan_with_plus(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), init, trash); + invoke_on_all_policies(test_scan_with_plus(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), init, trash); + } +} +struct test_scan_with_binary_op +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, + Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) + { + using namespace std; + + auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first, binary_op, init) + : exclusive_scan_serial(in_first, in_last, expected_first, init, binary_op); + auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first, binary_op, init) + : exclusive_scan(exec, in_first, in_last, out_first, init, binary_op); + + EXPECT_TRUE(out_last == orr, "scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, + Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) + { + } +}; + +template +void +test_matrix(Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k, k + 1); }); + + Sequence out(n, [&](size_t) { return trash; }); + Sequence expected(n, [&](size_t) { return trash; }); + + invoke_on_all_policies(test_scan_with_binary_op(), in.begin(), in.end(), out.begin(), out.end(), + expected.begin(), expected.end(), in.size(), init, binary_op, trash); + invoke_on_all_policies(test_scan_with_binary_op(), in.cbegin(), in.cend(), out.begin(), out.end(), + expected.begin(), expected.end(), in.size(), init, binary_op, trash); + } +} + +int32_t +main() +{ + for (int32_t mode = 0; mode < 2; ++mode) + { + inclusive = mode != 0; +#if !__PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN + // Test with highly restricted type and associative but not commutative operation + test_matrix, Matrix2x2>(Matrix2x2(), multiply_matrix, + Matrix2x2(-666, 666)); +#endif + + // Since the implict "+" forms of the scan delegate to the generic forms, + // there's little point in using a highly restricted type, so just use double. + test_with_plus(inclusive ? 0.0 : -1.0, -666.0, + [](uint32_t k) { return float64_t((k % 991 + 1) ^ (k % 997 + 2)); }); + } + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/numerics/numeric.ops/transform_reduce.pass.cpp =================================================================== --- pstl/trunk/test/std/numerics/numeric.ops/transform_reduce.pass.cpp +++ pstl/trunk/test/std/numerics/numeric.ops/transform_reduce.pass.cpp @@ -0,0 +1,140 @@ +// -*- C++ -*- +//===-- transform_reduce.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/numeric" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// Equal for all types +template +static bool +Equal(T x, T y) +{ + return x == y; +} + +// Functor for xor-operation for modeling binary operations in inner_product +class XOR +{ + public: + template + T + operator()(const T& left, const T& right) const + { + return left ^ right; + } +}; + +// Model of User-defined class +class MyClass +{ + public: + int32_t my_field; + MyClass() { my_field = 0; } + MyClass(int32_t in) { my_field = in; } + MyClass(const MyClass& in) { my_field = in.my_field; } + + friend MyClass + operator+(const MyClass& x, const MyClass& y) + { + return MyClass(x.my_field + y.my_field); + } + friend MyClass + operator-(const MyClass& x) + { + return MyClass(-x.my_field); + } + friend MyClass operator*(const MyClass& x, const MyClass& y) { return MyClass(x.my_field * y.my_field); } + bool + operator==(const MyClass& in) + { + return my_field == in.my_field; + } +}; + +template +void +CheckResults(const T& expected, const T& in) +{ + EXPECT_TRUE(Equal(expected, in), "wrong result of transform_reduce"); +} + +// We need to check correctness only for "int" (for example) except cases +// if we have "floating-point type"-specialization +void +CheckResults(const float32_t& expected, const float32_t& in) +{ +} + +// Test for different types and operations with different iterators +struct test_transform_reduce +{ + template + void + operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, + T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU) + { + + auto expectedB = std::inner_product(first1, last1, first2, init, opB1, opB2); + auto expectedU = transform_reduce_serial(first1, last1, init, opB1, opU); + T resRA = std::transform_reduce(exec, first1, last1, first2, init, opB1, opB2); + CheckResults(expectedB, resRA); + resRA = std::transform_reduce(exec, first1, last1, init, opB1, opU); + CheckResults(expectedU, resRA); + } +}; + +template +void +test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU, Initializer initObj) +{ + + std::size_t maxSize = 100000; + Sequence in1(maxSize, initObj); + Sequence in2(maxSize, initObj); + + for (std::size_t n = 0; n < maxSize; n = n < 16 ? n + 1 : size_t(3.1415 * n)) + { + invoke_on_all_policies(test_transform_reduce(), in1.begin(), in1.begin() + n, in2.begin(), in2.begin() + n, + init, opB1, opB2, opU); + invoke_on_all_policies(test_transform_reduce(), in1.cbegin(), in1.cbegin() + n, in2.cbegin(), in2.cbegin() + n, + init, opB1, opB2, opU); + } +} + +int32_t +main() +{ + test_by_type(42, std::plus(), std::multiplies(), std::negate(), + [](std::size_t a) -> int32_t { return int32_t(rand() % 1000); }); + test_by_type(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(), + [](const int64_t& x) -> int64_t { return x * 2; }, + [](std::size_t a) -> int64_t { return int64_t(rand() % 1000); }); + test_by_type(1.0f, std::multiplies(), + [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, + [](const float32_t& x) -> float32_t { return x + 2; }, + [](std::size_t a) -> float32_t { return rand() % 1000; }); + test_by_type(MyClass(), std::plus(), std::multiplies(), std::negate(), + [](std::size_t a) -> MyClass { return MyClass(rand() % 1000); }); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/numerics/numeric.ops/transform_scan.pass.cpp =================================================================== --- pstl/trunk/test/std/numerics/numeric.ops/transform_scan.pass.cpp +++ pstl/trunk/test/std/numerics/numeric.ops/transform_scan.pass.cpp @@ -0,0 +1,180 @@ +// -*- C++ -*- +//===-- transform_scan.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/numeric" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// Most of the framework required for testing inclusive and exclusive transform-scans is identical, +// so the tests for both are in this file. Which is being tested is controlled by the global +// flag inclusive, which is set to each alternative by main(). +static bool inclusive; + +template +void +check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) +{ + EXPECT_EQ_N(expected_first, out_first, n, + inclusive ? "wrong result from transform_inclusive_scan" + : "wrong result from transform_exclusive_scan"); + std::fill_n(out_first, n, trash); +} + +struct test_transform_scan +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, + UnaryOp unary_op, T init, BinaryOp binary_op, T trash) + { + using namespace std; + + auto orr1 = inclusive ? transform_inclusive_scan(pstl::execution::seq, first, last, expected_first, binary_op, + unary_op, init) + : transform_exclusive_scan(pstl::execution::seq, first, last, expected_first, init, + binary_op, unary_op); + auto orr2 = inclusive ? transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op, init) + : transform_exclusive_scan(exec, first, last, out_first, init, binary_op, unary_op); + EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + + // Checks inclusive scan if init is not provided + if (inclusive && n > 0) + { + orr1 = transform_inclusive_scan(pstl::execution::seq, first, last, expected_first, binary_op, unary_op); + orr2 = transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op); + EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); + check_and_reset(expected_first, out_first, n, trash); + } + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, + OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, + UnaryOp unary_op, T init, BinaryOp binary_op, T trash) + { + } +}; + +const uint32_t encryption_mask = 0x314; + +template +std::pair +transform_inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, + T init, BinaryOperation binary_op) noexcept +{ + for (; first != last; ++first, ++result) + { + init = binary_op(init, unary_op(*first)); + *result = init; + } + return std::make_pair(result, init); +} + +template +std::pair +transform_exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, + T init, BinaryOperation binary_op) noexcept +{ + for (; first != last; ++first, ++result) + { + *result = init; + init = binary_op(init, unary_op(*first)); + } + return std::make_pair(result, init); +} + +template +void +test(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k ^ encryption_mask); }); + + Out tmp = init; + Sequence expected(n, [&](size_t k) -> Out { + if (inclusive) + { + tmp = binary_op(tmp, unary_op(in[k])); + return tmp; + } + else + { + Out val = tmp; + tmp = binary_op(tmp, unary_op(in[k])); + return val; + } + }); + + Sequence out(n, [&](size_t) { return trash; }); + + auto result = + inclusive + ? transform_inclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op) + : transform_exclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op); + check_and_reset(expected.begin(), out.begin(), out.size(), trash); + + invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + } +} + +template +void +test_matrix(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) +{ + for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [](size_t k) { return In(k, k + 1); }); + + Sequence out(n, [&](size_t) { return trash; }); + Sequence expected(n, [&](size_t) { return trash; }); + + invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), + expected.end(), in.size(), unary_op, init, binary_op, trash); + } +} + +int32_t +main() +{ + for (int32_t mode = 0; mode < 2; ++mode) + { + inclusive = mode != 0; +#if !__PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN + test_matrix, Matrix2x2>([](const Matrix2x2 x) { return x; }, + Matrix2x2(), multiply_matrix, + Matrix2x2(-666, 666)); +#endif + test([](int32_t x) { return x++; }, -123, [](int32_t x, int32_t y) { return x + y; }, 666); + } + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp =================================================================== --- pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp +++ pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_construct.pass.cpp @@ -0,0 +1,126 @@ +// -*- C++ -*- +//===-- uninitialized_construct.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 uninitialized_default_construct, uninitialized_default_construct_n, +// uninitialized_value_construct, uninitialized_value_construct_n + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/memory" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// function of checking correctness for uninitialized.construct.value +template +bool +IsCheckValueCorrectness(Iterator begin, Iterator end) +{ + for (; begin != end; ++begin) + { + if (*begin != T()) + { + return false; + } + } + return true; +} + +struct test_uninit_construct +{ + template + void + operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::false_type) + { + typedef typename std::iterator_traits::value_type T; + // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) + // and for cleaning memory after last calling of uninitialized_value_construct_n. + // It is important for non-trivial types + std::destroy_n(exec, begin, n); + + // reset counter of constructors + T::SetCount(0); + // run algorithm + std::uninitialized_default_construct(exec, begin, end); + // compare counter of constructors to length of container + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct"); + // destroy objects for testing new algorithms on same memory + std::destroy(exec, begin, end); + + std::uninitialized_default_construct_n(exec, begin, n); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct_n"); + std::destroy_n(exec, begin, n); + + std::uninitialized_value_construct(exec, begin, end); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct"); + std::destroy(exec, begin, end); + + std::uninitialized_value_construct_n(exec, begin, n); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct_n"); + } + + template + void + operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::true_type) + { + typedef typename std::iterator_traits::value_type T; + + std::uninitialized_default_construct(exec, begin, end); + std::destroy(exec, begin, end); + + std::uninitialized_default_construct_n(exec, begin, n); + std::destroy_n(exec, begin, n); + + std::uninitialized_value_construct(exec, begin, end); + // check correctness for uninitialized.construct.value + EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct"); + std::destroy(exec, begin, end); + + std::uninitialized_value_construct_n(exec, begin, n); + EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct_n"); + std::destroy_n(exec, begin, n); + } +}; + +template +void +test_uninit_construct_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninit_construct(), p.get(), std::next(p.get(), n), n, std::is_trivial()); + } +} + +int32_t +main() +{ + + // for user-defined types +#if !__PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN + test_uninit_construct_by_type>(); + test_uninit_construct_by_type>>(); +#endif + + // for trivial types + test_uninit_construct_by_type(); + test_uninit_construct_by_type(); + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp =================================================================== --- pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp +++ pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_copy_move.pass.cpp @@ -0,0 +1,148 @@ +// -*- C++ -*- +//===-- uninitialized_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 uninitialized_copy, uninitialized_copy_n, uninitialized_move, uninitialized_move_n + +#include "support/pstl_test_config.h" + +#ifdef PSTL_STANDALONE_TESTS +#include "pstl/execution" +#include "pstl/memory" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +// function of checking correctness for uninitialized.construct.value +template +bool +IsCheckValueCorrectness(InputIterator first1, OutputIterator first2, Size n) +{ + for (Size i = 0; i < n; ++i, ++first1, ++first2) + { + if (*first1 != *first2) + { + return false; + } + } + return true; +} + +struct test_uninitialized_copy_move +{ + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, + /*is_trivial=*/std::false_type) + { + typedef typename std::iterator_traits::value_type T; + // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) + // and for cleaning memory after last calling of uninitialized_value_construct_n. + // It is important for non-trivial types + std::destroy_n(exec, out_first, n); + + // reset counter of constructors + T::SetCount(0); + // run algorithm + std::uninitialized_copy(exec, first, last, out_first); + // compare counter of constructors to length of container + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy"); + // destroy objects for testing new algorithms on same memory + std::destroy_n(exec, out_first, n); + + std::uninitialized_copy_n(exec, first, n, out_first); + EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy_n"); + std::destroy_n(exec, out_first, n); + + // For move + std::uninitialized_move(exec, first, last, out_first); + // compare counter of constructors to length of container + EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move"); + // destroy objects for testing new algorithms on same memory + std::destroy_n(exec, out_first, n); + + std::uninitialized_move_n(exec, first, n, out_first); + EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move_n"); + std::destroy_n(exec, out_first, n); + } + +#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN + template + void + operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, + size_t n, /*is_trivial=*/std::true_type) + { + } + template + void + operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, + OutputIterator out_first, size_t n, /*is_trivial=*/std::true_type) + { + } +#endif + + template + void + operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, + /*is_trivial=*/std::true_type) + { + typedef typename std::iterator_traits::value_type T; + + std::uninitialized_copy(exec, first, last, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_copy_n(exec, first, n, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy_n"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_move(exec, first, last, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move"); + std::destroy_n(exec, out_first, n); + + std::uninitialized_move_n(exec, first, n, out_first); + EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move_n"); + std::destroy_n(exec, out_first, n); + } +}; + +template +void +test_uninitialized_copy_move_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + Sequence in(n, [=](size_t k) -> T { return T(k); }); + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninitialized_copy_move(), in.begin(), in.end(), p.get(), n, std::is_trivial()); + } +} + +int32_t +main() +{ + + // for trivial types + test_uninitialized_copy_move_by_type(); + test_uninitialized_copy_move_by_type(); + + // for user-defined types +#if !__PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && !__PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && \ + !__PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN + test_uninitialized_copy_move_by_type>(); +#endif + + std::cout << done() << std::endl; + return 0; +} Index: pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp =================================================================== --- pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp +++ pstl/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized_fill_destroy.pass.cpp @@ -0,0 +1,98 @@ +// -*- C++ -*- +//===-- uninitialized_fill_destroy.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/memory" +#include "pstl/algorithm" +#else +#include +#include +#endif // PSTL_STANDALONE_TESTS + +#include "support/utils.h" + +using namespace TestUtils; + +struct test_uninitialized_fill_destroy +{ + template + void + operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::false_type) + { + using namespace std; + { + T::SetCount(0); + uninitialized_fill(exec, first, last, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_TRUE(n == count, "wrong work of uninitialized_fill"); + destroy(exec, first, last); + EXPECT_TRUE(T::Count() == 0, "wrong work of destroy"); + } + + { + auto res = uninitialized_fill_n(exec, first, n, in); + EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_TRUE(n == count, "wrong work of uninitialized_fill_n"); + destroy_n(exec, first, n); + EXPECT_TRUE(T::Count() == 0, "wrong work of destroy_n"); + } + } + template + void + operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::true_type) + { + using namespace std; + { + destroy(exec, first, last); + uninitialized_fill(exec, first, last, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_EQ(n, count, "wrong work of uninitialized:_fill"); + } + { + destroy_n(exec, first, n); + auto res = uninitialized_fill_n(exec, first, n, in); + size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); + EXPECT_EQ(n, count, "wrong work of uninitialized_fill_n"); + EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); + } + } +}; + +template +void +test_uninitialized_fill_destroy_by_type() +{ + std::size_t N = 100000; + for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) + { + std::unique_ptr p(new T[n]); + invoke_on_all_policies(test_uninitialized_fill_destroy(), p.get(), std::next(p.get(), n), T(), n, + std::is_trivial()); + } +} + +int32_t +main() +{ + // for trivial types + test_uninitialized_fill_destroy_by_type(); + test_uninitialized_fill_destroy_by_type(); + + // for user-defined types + test_uninitialized_fill_destroy_by_type>(); + test_uninitialized_fill_destroy_by_type>(); + std::cout << done() << std::endl; + + return 0; +} Index: pstl/trunk/test/support/pstl_test_config.h =================================================================== --- pstl/trunk/test/support/pstl_test_config.h +++ pstl/trunk/test/support/pstl_test_config.h @@ -0,0 +1,49 @@ +// -*- C++ -*- +//===-- pstl_test_config.h ------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef __PSTL_TEST_config_H +#define __PSTL_TEST_config_H + +#if defined(_MSC_VER) && defined(_DEBUG) +#define _SCL_SECURE_NO_WARNINGS //to prevent the compilation warning. Microsoft STL implementation has specific checking of an iterator range in DEBUG mode for the containers from the standard library. +#endif + +#define __PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN \ + (__x86_64 && !_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER <= 1700 && !__APPLE__) +#define __PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN \ + (!_DEBUG && __INTEL_COMPILER && \ + (__INTEL_COMPILER < 1800 || (__INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1))) +#define __PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN \ + (__x86_64 && !_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 1) +#define __PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN \ + (__i386__ && !_DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && __APPLE__) +#define __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN \ + (!_DEBUG && __INTEL_COMPILER >= 1800 && __INTEL_COMPILER < 1900 && _MSC_VER == 1910) +#define __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN \ + (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1700 && __INTEL_COMPILER < 1800 && _MSC_VER >= 1900) +#define __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN \ + (_M_IX86 && _DEBUG && __INTEL_COMPILER >= 1600 && __INTEL_COMPILER < 1700 && _MSC_VER == 1900) +#define __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN \ + (__PSTL_USE_PAR_POLICIES && ((_M_X64 && _MSC_VER == 1900) || __x86_64) && !_DEBUG && __INTEL_COMPILER < 1700) +#define __PSTL_ICC_16_17_TEST_64_TIMEOUT (__x86_64 && __INTEL_COMPILER && __INTEL_COMPILER < 1800 && !__APPLE__) +#define __PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN (!_DEBUG && __INTEL_COMPILER && __INTEL_COMPILER == 1800) +#define __PSTL_CLANG_TEST_BIG_OBJ_DEBUG_32_BROKEN \ + (__i386__ && PSTL_USE_DEBUG && __clang__ && __PSTL_CLANG_VERSION <= 90000) +#define __PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN \ + (!_DEBUG && __INTEL_COMPILER && \ + (__INTEL_COMPILER < 1800 || (__INTEL_COMPILER == 1800 && __INTEL_COMPILER_UPDATE < 3))) +#define __PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN \ + (!_DEBUG && __INTEL_COMPILER == 1800 && __AVX__ && !__AVX2__ && !__AVX512__) +#define __PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN \ + (!PSTL_USE_DEBUG && (__linux__ || __APPLE__) && __INTEL_COMPILER == 1900) +#define __PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN \ + (__INTEL_COMPILER == 1900 && _MSC_VER >= 1900 && _MSC_VER <= 1910) +#define __PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN (__INTEL_COMPILER == 1900 && _MSC_VER && !_DEBUG) + +#endif /* __PSTL_TEST_config_H */ Index: pstl/trunk/test/support/utils.h =================================================================== --- pstl/trunk/test/support/utils.h +++ pstl/trunk/test/support/utils.h @@ -0,0 +1,1247 @@ +// -*- C++ -*- +//===-- utils.h -----------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// File contains common utilities that tests rely on + +// Do not #include , because if we do we will not detect accidental dependencies. +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pstl_test_config.h" + +namespace TestUtils +{ + +typedef double float64_t; +typedef float float32_t; + +template +constexpr size_t +const_size(const T (&array)[N]) noexcept +{ + return N; +} + +template +class Sequence; + +// Handy macros for error reporting +#define EXPECT_TRUE(condition, message) ::TestUtils::expect(true, condition, __FILE__, __LINE__, message) +#define EXPECT_FALSE(condition, message) ::TestUtils::expect(false, condition, __FILE__, __LINE__, message) + +// Check that expected and actual are equal and have the same type. +#define EXPECT_EQ(expected, actual, message) ::TestUtils::expect_equal(expected, actual, __FILE__, __LINE__, message) + +// Check that sequences started with expected and actual and have had size n are equal and have the same type. +#define EXPECT_EQ_N(expected, actual, n, message) \ + ::TestUtils::expect_equal(expected, actual, n, __FILE__, __LINE__, message) + +// Issue error message from outstr, adding a newline. +// Real purpose of this routine is to have a place to hang a breakpoint. +inline void +issue_error_message(std::stringstream& outstr) +{ + outstr << std::endl; + std::cerr << outstr.str(); + std::exit(EXIT_FAILURE); +} + +inline void +expect(bool expected, bool condition, const char* file, int32_t line, const char* message) +{ + if (condition != expected) + { + std::stringstream outstr; + outstr << "error at " << file << ":" << line << " - " << message; + issue_error_message(outstr); + } +} + +// Do not change signature to const T&. +// Function must be able to detect const differences between expected and actual. +template +void +expect_equal(T& expected, T& actual, const char* file, int32_t line, const char* message) +{ + if (!(expected == actual)) + { + std::stringstream outstr; + outstr << "error at " << file << ":" << line << " - " << message << ", expected " << expected << " got " + << actual; + issue_error_message(outstr); + } +} + +template +void +expect_equal(Sequence& expected, Sequence& actual, const char* file, int32_t line, const char* message) +{ + size_t n = expected.size(); + size_t m = actual.size(); + if (n != m) + { + std::stringstream outstr; + outstr << "error at " << file << ":" << line << " - " << message << ", expected sequence of size " << n + << " got sequence of size " << m; + issue_error_message(outstr); + return; + } + size_t error_count = 0; + for (size_t k = 0; k < n && error_count < 10; ++k) + { + if (!(expected[k] == actual[k])) + { + std::stringstream outstr; + outstr << "error at " << file << ":" << line << " - " << message << ", at index " << k << " expected " + << expected[k] << " got " << actual[k]; + issue_error_message(outstr); + ++error_count; + } + } +} + +template +void +expect_equal(Iterator1 expected_first, Iterator2 actual_first, Size n, const char* file, int32_t line, + const char* message) +{ + size_t error_count = 0; + for (size_t k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first) + { + if (!(*expected_first == *actual_first)) + { + std::stringstream outstr; + outstr << "error at " << file << ":" << line << " - " << message << ", at index " << k; + issue_error_message(outstr); + ++error_count; + } + } +} + +// ForwardIterator is like type Iterator, but restricted to be a forward iterator. +// Only the forward iterator signatures that are necessary for tests are present. +// Post-increment in particular is deliberatly omitted since our templates should avoid using it +// because of efficiency considerations. +template +class ForwardIterator +{ + public: + typedef IteratorTag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + + protected: + Iterator my_iterator; + typedef value_type element_type; + + public: + ForwardIterator() = default; + explicit ForwardIterator(Iterator i) : my_iterator(i) {} + reference operator*() const { return *my_iterator; } + Iterator operator->() const { return my_iterator; } + ForwardIterator + operator++() + { + ++my_iterator; + return *this; + } + ForwardIterator operator++(int32_t) + { + auto retval = *this; + my_iterator++; + return retval; + } + friend bool + operator==(const ForwardIterator& i, const ForwardIterator& j) + { + return i.my_iterator == j.my_iterator; + } + friend bool + operator!=(const ForwardIterator& i, const ForwardIterator& j) + { + return i.my_iterator != j.my_iterator; + } + + Iterator + iterator() const + { + return my_iterator; + } +}; + +template +class BidirectionalIterator : public ForwardIterator +{ + typedef ForwardIterator base_type; + + public: + BidirectionalIterator() = default; + explicit BidirectionalIterator(Iterator i) : base_type(i) {} + BidirectionalIterator(const base_type& i) : base_type(i.iterator()) {} + + BidirectionalIterator + operator++() + { + ++base_type::my_iterator; + return *this; + } + BidirectionalIterator + operator--() + { + --base_type::my_iterator; + return *this; + } + BidirectionalIterator operator++(int32_t) + { + auto retval = *this; + base_type::my_iterator++; + return retval; + } + BidirectionalIterator operator--(int32_t) + { + auto retval = *this; + base_type::my_iterator--; + return retval; + } +}; + +template +void +fill_data(Iterator first, Iterator last, F f) +{ + typedef typename std::iterator_traits::value_type T; + for (std::size_t i = 0; first != last; ++first, ++i) + { + *first = T(f(i)); + } +} + +// Sequence is a container of a sequence of T with lots of kinds of iterators. +// Prefixes on begin/end mean: +// c = "const" +// f = "forward" +// No prefix indicates non-const random-access iterator. +template +class Sequence +{ + std::vector m_storage; + + public: + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef ForwardIterator forward_iterator; + typedef ForwardIterator const_forward_iterator; + + typedef BidirectionalIterator bidirectional_iterator; + typedef BidirectionalIterator const_bidirectional_iterator; + + typedef T value_type; + explicit Sequence(size_t size) : m_storage(size) {} + + // Construct sequence [f(0), f(1), ... f(size-1)] + // f can rely on its invocations being sequential from 0 to size-1. + template + Sequence(size_t size, Func f) + { + m_storage.reserve(size); + // Use push_back because T might not have a default constructor + for (size_t k = 0; k < size; ++k) + m_storage.push_back(T(f(k))); + } + Sequence(const std::initializer_list& data) : m_storage(data) {} + + const_iterator + begin() const + { + return m_storage.begin(); + } + const_iterator + end() const + { + return m_storage.end(); + } + iterator + begin() + { + return m_storage.begin(); + } + iterator + end() + { + return m_storage.end(); + } + const_iterator + cbegin() const + { + return m_storage.cbegin(); + } + const_iterator + cend() const + { + return m_storage.cend(); + } + forward_iterator + fbegin() + { + return forward_iterator(m_storage.begin()); + } + forward_iterator + fend() + { + return forward_iterator(m_storage.end()); + } + const_forward_iterator + cfbegin() const + { + return const_forward_iterator(m_storage.cbegin()); + } + const_forward_iterator + cfend() const + { + return const_forward_iterator(m_storage.cend()); + } + const_forward_iterator + fbegin() const + { + return const_forward_iterator(m_storage.cbegin()); + } + const_forward_iterator + fend() const + { + return const_forward_iterator(m_storage.cend()); + } + + const_bidirectional_iterator + cbibegin() const + { + return const_bidirectional_iterator(m_storage.cbegin()); + } + const_bidirectional_iterator + cbiend() const + { + return const_bidirectional_iterator(m_storage.cend()); + } + + bidirectional_iterator + bibegin() + { + return bidirectional_iterator(m_storage.begin()); + } + bidirectional_iterator + biend() + { + return bidirectional_iterator(m_storage.end()); + } + + std::size_t + size() const + { + return m_storage.size(); + } + const T* + data() const + { + return m_storage.data(); + } + typename std::vector::reference operator[](size_t j) { return m_storage[j]; } + const T& operator[](size_t j) const { return m_storage[j]; } + + // Fill with given value + void + fill(const T& value) + { + for (size_t i = 0; i < m_storage.size(); i++) + m_storage[i] = value; + } + + void + print() const; + + template + void + fill(Func f) + { + fill_data(m_storage.begin(), m_storage.end(), f); + } +}; + +template +void +Sequence::print() const +{ + std::cout << "size = " << size() << ": { "; + std::copy(begin(), end(), std::ostream_iterator(std::cout, " ")); + std::cout << " } " << std::endl; +} + +// Predicates for algorithms +template +struct is_equal_to +{ + is_equal_to(const DataType& expected) : m_expected(expected) {} + bool + operator()(const DataType& actual) const + { + return actual == m_expected; + } + + private: + DataType m_expected; +}; + +// Low-quality hash function, returns value between 0 and (1<= 8 * sizeof(size_t) ? ~size_t(0) : (size_t(1) << bits) - 1; + return (424157 * i ^ 0x24aFa) & mask; +} + +// Stateful unary op +template +class Complement +{ + int32_t val; + + public: + Complement(T v) : val(v) {} + U + operator()(const T& x) const + { + return U(val - x); + } +}; + +// Tag used to prevent accidental use of converting constructor, even if use is explicit. +struct OddTag +{ +}; + +class Sum; + +// Type with limited set of operations. Not default-constructible. +// Only available operator is "==". +// Typically used as value type in tests. +class Number +{ + int32_t value; + friend class Add; + friend class Sum; + friend class IsMultiple; + friend class Congruent; + friend Sum + operator+(const Sum& x, const Sum& y); + + public: + Number(int32_t val, OddTag) : value(val) {} + friend bool + operator==(const Number& x, const Number& y) + { + return x.value == y.value; + } + friend std::ostream& + operator<<(std::ostream& o, const Number& d) + { + return o << d.value; + } +}; + +// Stateful predicate for Number. Not default-constructible. +class IsMultiple +{ + long modulus; + + public: + // True if x is multiple of modulus + bool + operator()(Number x) const + { + return x.value % modulus == 0; + } + IsMultiple(long modulus_, OddTag) : modulus(modulus_) {} +}; + +// Stateful equivalence-class predicate for Number. Not default-constructible. +class Congruent +{ + long modulus; + + public: + // True if x and y have same remainder for the given modulus. + // Note: this is not quite the same as "equivalent modulo modulus" when x and y have different + // sign, but nonetheless AreCongruent is still an equivalence relationship, which is all + // we need for testing. + bool + operator()(Number x, Number y) const + { + return x.value % modulus == y.value % modulus; + } + Congruent(long modulus_, OddTag) : modulus(modulus_) {} +}; + +// Stateful reduction operation for Number +class Add +{ + long bias; + + public: + explicit Add(OddTag) : bias(1) {} + Number + operator()(Number x, const Number& y) + { + return Number(x.value + y.value + (bias - 1), OddTag()); + } +}; + +// Class similar to Number, but has default constructor and +. +class Sum : public Number +{ + public: + Sum() : Number(0, OddTag()) {} + Sum(long x, OddTag) : Number(x, OddTag()) {} + friend Sum + operator+(const Sum& x, const Sum& y) + { + return Sum(x.value + y.value, OddTag()); + } +}; + +// Type with limited set of operations, which includes an associative but not commutative operation. +// Not default-constructible. +// Typically used as value type in tests involving "GENERALIZED_NONCOMMUTATIVE_SUM". +class MonoidElement +{ + size_t a, b; + + public: + MonoidElement(size_t a_, size_t b_, OddTag) : a(a_), b(b_) {} + friend bool + operator==(const MonoidElement& x, const MonoidElement& y) + { + return x.a == y.a && x.b == y.b; + } + friend std::ostream& + operator<<(std::ostream& o, const MonoidElement& x) + { + return o << "[" << x.a << ".." << x.b << ")"; + } + friend class AssocOp; +}; + +// Stateful associative op for MonoidElement +// It's not really a monoid since the operation is not allowed for any two elements. +// But it's good enough for testing. +class AssocOp +{ + unsigned c; + + public: + explicit AssocOp(OddTag) : c(5) {} + MonoidElement + operator()(const MonoidElement& x, const MonoidElement& y) + { + unsigned d = 5; + EXPECT_EQ(d, c, "state lost"); + EXPECT_EQ(x.b, y.a, "commuted?"); + + return MonoidElement(x.a, y.b, OddTag()); + } +}; + +// Multiplication of matrix is an associative but not commutative operation +// Typically used as value type in tests involving "GENERALIZED_NONCOMMUTATIVE_SUM". +template +struct Matrix2x2 +{ + T a[2][2]; + Matrix2x2() : a{{1, 0}, {0, 1}} {} + Matrix2x2(T x, T y) : a{{0, x}, {x, y}} {} +#if !__PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN + Matrix2x2(const Matrix2x2& m) : a{{m.a[0][0], m.a[0][1]}, {m.a[1][0], m.a[1][1]}} {} + Matrix2x2& + operator=(const Matrix2x2& m) + { + a[0][0] = m.a[0][0], a[0][1] = m.a[0][1], a[1][0] = m.a[1][0], a[1][1] = m.a[1][1]; + return *this; + } +#endif +}; + +template +bool +operator==(const Matrix2x2& left, const Matrix2x2& right) +{ + return left.a[0][0] == right.a[0][0] && left.a[0][1] == right.a[0][1] && left.a[1][0] == right.a[1][0] && + left.a[1][1] == right.a[1][1]; +} + +template +Matrix2x2 +multiply_matrix(const Matrix2x2& left, const Matrix2x2& right) +{ + Matrix2x2 result; + for (int32_t i = 0; i < 2; ++i) + { + for (int32_t j = 0; j < 2; ++j) + { + result.a[i][j] = left.a[i][0] * right.a[0][j] + left.a[i][1] * right.a[1][j]; + } + } + return result; +} + +// Check that Intel(R) Threading Building Blocks header files are not used when parallel policies are off +#if !__PSTL_USE_PAR_POLICIES +#if defined(TBB_INTERFACE_VERSION) +#error The parallel backend is used while it should not (__PSTL_USE_PAR_POLICIES==0) +#endif +#endif + +//============================================================================ +// Adapters for creating different types of iterators. +// +// In this block we implemented some adapters for creating differnet types of iterators. +// It's needed for extending the unit testing of Parallel STL algorithms. +// We have adapters for iterators with different tags (forward_iterator_tag, bidirectional_iterator_tag), reverse iterators. +// The input iterator should be const or non-const, non-reverse random access iterator. +// Iterator creates in "MakeIterator": +// firstly, iterator is "packed" by "IteratorTypeAdapter" (creating forward or bidirectional iterator) +// then iterator is "packed" by "ReverseAdapter" (if it's possible) +// So, from input iterator we may create, for example, reverse bidirectional iterator. +// "Main" functor for testing iterators is named "invoke_on_all_iterator_types". + +// Base adapter +template +struct BaseAdapter +{ + typedef Iterator iterator_type; + iterator_type + operator()(Iterator it) + { + return it; + } +}; + +// Check if the iterator is reverse iterator +// Note: it works only for iterators that created by std::reverse_iterator +template +struct isReverse : std::false_type +{ +}; + +template +struct isReverse> : std::true_type +{ +}; + +// Reverse adapter +template +struct ReverseAdapter +{ + typedef std::reverse_iterator iterator_type; + iterator_type + operator()(Iterator it) + { +#if __PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT + return std::make_reverse_iterator(it); +#else + return iterator_type(it); +#endif + } +}; + +// Non-reverse adapter +template +struct ReverseAdapter : BaseAdapter +{ +}; + +// Iterator adapter by type (by default std::random_access_iterator_tag) +template +struct IteratorTypeAdapter : BaseAdapter +{ +}; + +// Iterator adapter for forward iterator +template +struct IteratorTypeAdapter +{ + typedef ForwardIterator iterator_type; + iterator_type + operator()(Iterator it) + { + return iterator_type(it); + } +}; + +// Iterator adapter for bidirectional iterator +template +struct IteratorTypeAdapter +{ + typedef BidirectionalIterator iterator_type; + iterator_type + operator()(Iterator it) + { + return iterator_type(it); + } +}; + +//For creating iterator with new type +template +struct MakeIterator +{ + typedef IteratorTypeAdapter IterByType; + typedef ReverseAdapter ReverseIter; + + typename ReverseIter::iterator_type + operator()(InputIterator it) + { + return ReverseIter()(IterByType()(it)); + } +}; + +// Useful constant variables +constexpr std::size_t GuardSize = 5; +constexpr std::ptrdiff_t sizeLimit = 1000; + +template // local iterator_traits for non-iterators +struct iterator_traits_ +{ +}; + +template // For iterators +struct iterator_traits_::value, void>::type> +{ + typedef typename Iter::iterator_category iterator_category; +}; + +template // For pointers +struct iterator_traits_ +{ + typedef std::random_access_iterator_tag iterator_category; +}; + +// is iterator Iter has tag Tag +template +using is_same_iterator_category = std::is_same::iterator_category, Tag>; + +// if we run with reverse or const iterators we shouldn't test the large range +template +struct invoke_if_ +{ + template + void + operator()(bool is_allow, Op op, Rest&&... rest) + { + if (is_allow) + op(std::forward(rest)...); + } +}; +template <> +struct invoke_if_ +{ + template + void + operator()(bool is_allow, Op op, Rest&&... rest) + { + op(std::forward(rest)...); + } +}; + +// Base non_const_wrapper struct. It is used to distinguish non_const testcases +// from a regular one. For non_const testcases only compilation is checked. +struct non_const_wrapper +{ +}; + +// Generic wrapper to specify iterator type to execute callable Op on. +// The condition can be either positive(Op is executed only with IteratorTag) +// or negative(Op is executed with every type of iterators except IteratorTag) +template +struct non_const_wrapper_tagged : non_const_wrapper +{ + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator iter) + { + Op()(exec, iter); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) + { + Op()(exec, input_iter, out_iter); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Iterator iter) + { + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) + { + } +}; + +// These run_for_* structures specify with which types of iterators callable object Op +// should be executed. +template +struct run_for_rnd : non_const_wrapper_tagged +{ +}; + +template +struct run_for_rnd_bi : non_const_wrapper_tagged +{ +}; + +template +struct run_for_rnd_fw : non_const_wrapper_tagged +{ +}; + +// Invoker for different types of iterators. +template +struct iterator_invoker +{ + template + using make_iterator = MakeIterator; + template + using IsConst = typename std::is_const< + typename std::remove_pointer::pointer>::type>::type; + template + using invoke_if = invoke_if_>; + + // A single iterator version which is used for non_const testcases + template + typename std::enable_if::value && + std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, Iterator iter) + { + op(std::forward(exec), make_iterator()(iter)); + } + + // A version with 2 iterators which is used for non_const testcases + template + typename std::enable_if::value && + std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator input_iter, OutputIterator out_iter) + { + op(std::forward(exec), make_iterator()(input_iter), + make_iterator()(out_iter)); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Op op, Iterator begin, Size n, Rest&&... rest) + { + invoke_if()(n <= sizeLimit, op, exec, make_iterator()(begin), n, + std::forward(rest)...); + } + + template + typename std::enable_if::value && + !std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, Iterator inputBegin, Iterator inputEnd, Rest&&... rest) + { + invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, + make_iterator()(inputBegin), make_iterator()(inputEnd), + std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, + Rest&&... rest) + { + invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, + make_iterator()(inputBegin), make_iterator()(inputEnd), + make_iterator()(outputBegin), std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, + OutputIterator outputEnd, Rest&&... rest) + { + invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, + make_iterator()(inputBegin), make_iterator()(inputEnd), + make_iterator()(outputBegin), + make_iterator()(outputEnd), std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator1 inputBegin1, InputIterator1 inputEnd1, InputIterator2 inputBegin2, + InputIterator2 inputEnd2, OutputIterator outputBegin, OutputIterator outputEnd, Rest&&... rest) + { + invoke_if()( + std::distance(inputBegin1, inputEnd1) <= sizeLimit, op, exec, make_iterator()(inputBegin1), + make_iterator()(inputEnd1), make_iterator()(inputBegin2), + make_iterator()(inputEnd2), make_iterator()(outputBegin), + make_iterator()(outputEnd), std::forward(rest)...); + } +}; + +// Invoker for reverse iterators only +// Note: if we run with reverse iterators we shouldn't test the large range +template +struct iterator_invoker +{ + + template + using make_iterator = MakeIterator; + + // A single iterator version which is used for non_const testcases + template + typename std::enable_if::value && + std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, Iterator iter) + { + op(std::forward(exec), make_iterator()(iter)); + } + + // A version with 2 iterators which is used for non_const testcases + template + typename std::enable_if::value && + std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator input_iter, OutputIterator out_iter) + { + op(std::forward(exec), make_iterator()(input_iter), + make_iterator()(out_iter)); + } + + template + typename std::enable_if::value, void>::type + operator()(Policy&& exec, Op op, Iterator begin, Size n, Rest&&... rest) + { + if (n <= sizeLimit) + op(exec, make_iterator()(begin + n), n, std::forward(rest)...); + } + + template + typename std::enable_if::value && + !std::is_base_of::value, + void>::type + operator()(Policy&& exec, Op op, Iterator inputBegin, Iterator inputEnd, Rest&&... rest) + { + if (std::distance(inputBegin, inputEnd) <= sizeLimit) + op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), + std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, + Rest&&... rest) + { + if (std::distance(inputBegin, inputEnd) <= sizeLimit) + op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), + make_iterator()(outputBegin + (inputEnd - inputBegin)), std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, + OutputIterator outputEnd, Rest&&... rest) + { + if (std::distance(inputBegin, inputEnd) <= sizeLimit) + op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), + make_iterator()(outputEnd), make_iterator()(outputBegin), + std::forward(rest)...); + } + + template + typename std::enable_if::value, + void>::type + operator()(Policy&& exec, Op op, InputIterator1 inputBegin1, InputIterator1 inputEnd1, InputIterator2 inputBegin2, + InputIterator2 inputEnd2, OutputIterator outputBegin, OutputIterator outputEnd, Rest&&... rest) + { + if (std::distance(inputBegin1, inputEnd1) <= sizeLimit) + op(exec, make_iterator()(inputEnd1), make_iterator()(inputBegin1), + make_iterator()(inputEnd2), make_iterator()(inputBegin2), + make_iterator()(outputEnd), make_iterator()(outputBegin), + std::forward(rest)...); + } +}; + +// We can't create reverse iterator from forward iterator +template <> +struct iterator_invoker +{ + template + void + operator()(Rest&&... rest) + { + } +}; + +template +struct reverse_invoker +{ + template + void + operator()(Rest&&... rest) + { + // Random-access iterator + iterator_invoker()(std::forward(rest)...); + + // Forward iterator + iterator_invoker()(std::forward(rest)...); + + // Bidirectional iterator + iterator_invoker()(std::forward(rest)...); + } +}; + +struct invoke_on_all_iterator_types +{ + template + void + operator()(Rest&&... rest) + { + reverse_invoker()(std::forward(rest)...); + reverse_invoker()(std::forward(rest)...); + } +}; +//============================================================================ + +// Invoke op(policy,rest...) for each possible policy. +template +void +invoke_on_all_policies(Op op, T&&... rest) +{ + using namespace __pstl::execution; + + // Try static execution policies + invoke_on_all_iterator_types()(seq, op, std::forward(rest)...); + invoke_on_all_iterator_types()(unseq, op, std::forward(rest)...); +#if __PSTL_USE_PAR_POLICIES + invoke_on_all_iterator_types()(par, op, std::forward(rest)...); + invoke_on_all_iterator_types()(par_unseq, op, std::forward(rest)...); +#endif +} + +template +struct NonConstAdapter +{ + F my_f; + NonConstAdapter(const F& f) : my_f(f) {} + + template + auto + operator()(Types&&... args) -> decltype(std::declval(). + operator()(std::forward(args)...)) + { + return my_f(std::forward(args)...); + } +}; + +template +NonConstAdapter +non_const(const F& f) +{ + return NonConstAdapter(f); +} + +// Wrapper for types. It's need for counting of constructing and destructing objects +template +class Wrapper +{ + public: + Wrapper() + { + my_field = std::shared_ptr(new T()); + ++my_count; + } + Wrapper(const T& input) + { + my_field = std::shared_ptr(new T(input)); + ++my_count; + } + Wrapper(const Wrapper& input) + { + my_field = input.my_field; + ++my_count; + } + Wrapper(Wrapper&& input) + { + my_field = input.my_field; + input.my_field = nullptr; + ++move_count; + } + Wrapper& + operator=(const Wrapper& input) + { + my_field = input.my_field; + return *this; + } + Wrapper& + operator=(Wrapper&& input) + { + my_field = input.my_field; + input.my_field = nullptr; + ++move_count; + return *this; + } + bool + operator==(const Wrapper& input) const + { + return my_field == input.my_field; + } + bool + operator<(const Wrapper& input) const + { + return *my_field < *input.my_field; + } + bool + operator>(const Wrapper& input) const + { + return *my_field > *input.my_field; + } + friend std::ostream& + operator<<(std::ostream& stream, const Wrapper& input) + { + return stream << *(input.my_field); + } + ~Wrapper() + { + --my_count; + if (move_count > 0) + { + --move_count; + } + } + T* + get_my_field() const + { + return my_field.get(); + }; + static size_t + Count() + { + return my_count; + } + static size_t + MoveCount() + { + return move_count; + } + static void + SetCount(const size_t& n) + { + my_count = n; + } + static void + SetMoveCount(const size_t& n) + { + move_count = n; + } + + private: + static std::atomic my_count; + static std::atomic move_count; + std::shared_ptr my_field; +}; + +template +std::atomic Wrapper::my_count = {0}; + +template +std::atomic Wrapper::move_count = {0}; + +template +T +transform_reduce_serial(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, + UnaryOperation unary_op) noexcept +{ + for (; first != last; ++first) + { + init = binary_op(init, unary_op(*first)); + } + return init; +} + +static const char* +done() +{ +#if __PSTL_TEST_SUCCESSFUL_KEYWORD + return "done"; +#else + return "passed"; +#endif +} + +// test_algo_basic_* functions are used to execute +// f on a very basic sequence of elements of type T. + +// Should be used with unary predicate +template +static void +test_algo_basic_single(F&& f) +{ + size_t N = 10; + Sequence in(N, [](size_t v) -> T { return T(v); }); + + invoke_on_all_policies(f, in.begin()); +} + +// Should be used with binary predicate +template +static void +test_algo_basic_double(F&& f) +{ + size_t N = 10; + Sequence in(N, [](size_t v) -> T { return T(v); }); + Sequence out(N, [](size_t v) -> T { return T(v); }); + + invoke_on_all_policies(f, in.begin(), out.begin()); +} + +template +static void +invoke_if(Policy&& p, F f) +{ +#if __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN + __pstl::internal::invoke_if_not(__pstl::internal::allow_unsequenced(), f); +#else + f(); +#endif +} + +} /* namespace TestUtils */ Index: pstl/trunk/test/test_adjacent_difference.cpp =================================================================== --- pstl/trunk/test/test_adjacent_difference.cpp +++ pstl/trunk/test/test_adjacent_difference.cpp @@ -1,169 +0,0 @@ -// -*- C++ -*- -//===-- test_adjacent_difference.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "pstl/numeric" -#include "utils.h" - -using namespace TestUtils; - -template -struct wrapper -{ - T t; - explicit wrapper(T t_) : t(t_) {} - template - wrapper(const wrapper& a) - { - t = a.t; - } - template - void - operator=(const wrapper& a) - { - t = a.t; - } - wrapper - operator-(const wrapper& a) const - { - return wrapper(t - a.t); - } -}; - -template -bool -compare(const T& a, const T& b) -{ - return a == b; -} - -template -bool -compare(const wrapper& a, const wrapper& b) -{ - return a.t == b.t; -} - -template -typename std::enable_if::value, bool>::type -compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function f) -{ - using T2 = typename std::iterator_traits::value_type; - - if (first == last) - return true; - - T2 temp(*first); - if (!compare(temp, *d_first)) - return false; - Iterator1 second = std::next(first); - - ++d_first; - for (; second != last; ++first, ++second, ++d_first) - { - T2 temp(f(*second, *first)); - if (!compare(temp, *d_first)) - return false; - } - - return true; -} - -// we don't want to check equality here -// because we can't be sure it will be strictly equal for floating point types -template -typename std::enable_if::value, bool>::type -compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function) -{ - return true; -} - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e, T trash, Function f) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e, T trash, Function f) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, - T trash, Function f) - { - using namespace std; - using T2 = typename std::iterator_traits::value_type; - - fill(actual_b, actual_e, trash); - - Iterator2 actual_return = adjacent_difference(exec, data_b, data_e, actual_b); - EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), std::minus()), - "wrong effect of adjacent_difference"); - EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference"); - - fill(actual_b, actual_e, trash); - - actual_return = adjacent_difference(exec, data_b, data_e, actual_b, f); - EXPECT_TRUE(compute_and_check(data_b, data_e, actual_b, T2(0), f), - "wrong effect of adjacent_difference with functor"); - EXPECT_TRUE(actual_return == actual_e, "wrong result of adjacent_difference with functor"); - } -}; - -template -void -test(Pred pred) -{ - typedef typename Sequence::iterator iterator_type; - - const std::size_t max_len = 100000; - - const T2 value = T2(77); - const T1 trash = T1(31); - - Sequence actual(max_len, [](std::size_t i) { return T1(i); }); - - Sequence data(max_len, [&value](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; }); - - for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) - { - invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), - actual.begin() + len, trash, pred); - invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), - actual.begin() + len, trash, pred); - } -} - -int32_t -main() -{ - test([](uint32_t a, uint32_t b) { return a - b; }); - test([](int64_t a, int64_t b) { return a / (b + 1); }); - test([](float32_t a, float32_t b) { return (a + b) / 2; }); - test, wrapper>( - [](const wrapper& a, const wrapper& b) { return a - b; }); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_adjacent_find.cpp =================================================================== --- pstl/trunk/test/test_adjacent_find.cpp +++ pstl/trunk/test/test_adjacent_find.cpp @@ -1,111 +0,0 @@ -// -*- C++ -*- -//===-- test_adjacent_find.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 adjacent_find - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_adjacent_find -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Pred pred) - { - using namespace std; - - auto k = std::adjacent_find(first, last, pred); - auto i = adjacent_find(exec, first, last, pred); - EXPECT_TRUE(i == k, "wrong return value from adjacent_find with predicate"); - - i = adjacent_find(exec, first, last); - EXPECT_TRUE(i == k, "wrong return value from adjacent_find without predicate"); - } -}; - -template -void -test_adjacent_find_by_type() -{ - - size_t counts[] = {2, 3, 500}; - for (int32_t c = 0; c < const_size(counts); ++c) - { - - for (int32_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e) - { - Sequence in(counts[c], [](int32_t v) -> T { return T(v); }); //fill 0...n - in[e] = in[e + 1] = -1; //make an adjacent pair - - auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); - EXPECT_TRUE(i == in.cbegin() + e, "std::adjacent_find returned wrong result"); - - invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); - } - } - - //special cases: size=0, size=1; - for (int32_t expect = 0; expect < 1; ++expect) - { - Sequence in(expect, [](int32_t v) -> T { return T(v); }); //fill 0...n - auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to()); - EXPECT_TRUE(i == in.cbegin() + expect, "std::adjacent_find returned wrong result"); - - invoke_on_all_policies(test_adjacent_find(), in.begin(), in.end(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), in.cbegin(), in.cend(), std::equal_to()); - } - - //special cases: - Sequence a1 = {5, 5, 5, 6, 7, 8, 9}; - invoke_on_all_policies(test_adjacent_find(), a1.begin(), a1.end(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), a1.begin() + 1, a1.end(), std::equal_to()); - - invoke_on_all_policies(test_adjacent_find(), a1.cbegin(), a1.cend(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), a1.cbegin() + 1, a1.cend(), std::equal_to()); - - Sequence a2 = {5, 6, 7, 8, 9, 9}; - invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), a2.begin(), a2.end() - 1, std::equal_to()); - - invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend(), std::equal_to()); - invoke_on_all_policies(test_adjacent_find(), a2.cbegin(), a2.cend() - 1, std::equal_to()); - - Sequence a3 = {5, 6, 6, 6, 7, 9, 9, 9, 9}; - invoke_on_all_policies(test_adjacent_find(), a3.begin(), a3.end(), std::equal_to()); - - invoke_on_all_policies(test_adjacent_find(), a3.cbegin(), a3.cend(), std::equal_to()); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - adjacent_find(exec, iter, iter, non_const(std::equal_to())); - } -}; - -int32_t -main() -{ - - test_adjacent_find_by_type(); - test_adjacent_find_by_type(); - - test_algo_basic_single(run_for_rnd_bi>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_all_of.cpp =================================================================== --- pstl/trunk/test/test_all_of.cpp +++ pstl/trunk/test/test_all_of.cpp @@ -1,114 +0,0 @@ -// -*- C++ -*- -//===-- test_all_of.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -/* - TODO: consider implementing the following tests for a better code coverage - - correctness - - bad input argument (if applicable) - - data corruption around/of input and output - - correctly work with nested parallelism - - check that algorithm does not require anything more than is described in its requirements section -*/ - -using namespace TestUtils; - -struct test_all_of -{ - template - void - operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) - { - - auto actualr = std::all_of(exec, begin, end, pred); - EXPECT_EQ(expected, actualr, "result for all_of"); - } -}; - -template -struct Parity -{ - bool parity; - - public: - Parity(bool parity_) : parity(parity_) {} - bool - operator()(T value) const - { - return (size_t(value) ^ parity) % 2 == 0; - } -}; - -template -void -test(size_t bits) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - - // Sequence of odd values - Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); - - // Even value, or false when T is bool. - T spike(2 * HashBits(n, bits - 1)); - Sequence inCopy(in); - - invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), true); - invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), true); - EXPECT_EQ(in, inCopy, "all_of modified input sequence"); - if (n > 0) - { - // Sprinkle in a miss - in[2 * n / 3] = spike; - invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); - invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); - - // Sprinkle in a few more misses - in[n / 2] = spike; - in[n / 3] = spike; - invoke_on_all_policies(test_all_of(), in.begin(), in.end(), Parity(1), false); - invoke_on_all_policies(test_all_of(), in.cbegin(), in.cend(), Parity(1), false); - } - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - auto is_even = [&](float64_t v) { - uint32_t i = (uint32_t)v; - return i % 2 == 0; - }; - all_of(exec, iter, iter, non_const(is_even)); - } -}; - -int32_t -main() -{ - test(8 * sizeof(int32_t)); - test(8 * sizeof(uint16_t)); - test(53); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(1); -#endif - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_any_of.cpp =================================================================== --- pstl/trunk/test/test_any_of.cpp +++ pstl/trunk/test/test_any_of.cpp @@ -1,100 +0,0 @@ -// -*- C++ -*- -//===-- test_any_of.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -/* - TODO: consider implementing the following tests for a better code coverage - - correctness - - bad input argument (if applicable) - - data corruption around/of input and output - - correctly work with nested parallelism - - check that algorithm does not require anything more than is described in its requirements section -*/ - -using namespace TestUtils; - -struct test_any_of -{ - template - void - operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) - { - - auto actualr = std::any_of(exec, begin, end, pred); - EXPECT_EQ(expected, actualr, "result for any_of"); - } -}; - -template -void -test(size_t bits) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - - // Sequence of odd values - Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); - - // Even value, or false when T is bool. - T spike(2 * HashBits(n, bits - 1)); - Sequence inCopy(in); - - invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), false); - invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); - EXPECT_EQ(in, inCopy, "any_of modified input sequence"); - if (n > 0) - { - // Sprinkle in a hit - in[2 * n / 3] = spike; - invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); - invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); - - // Sprinkle in a few more hits - in[n / 2] = spike; - in[n / 3] = spike; - invoke_on_all_policies(test_any_of(), in.begin(), in.end(), is_equal_to(spike), true); - invoke_on_all_policies(test_any_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); - } - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - auto is_even = [&](float64_t v) { - uint32_t i = (uint32_t)v; - return i % 2 == 0; - }; - any_of(exec, iter, iter, non_const(is_even)); - } -}; - -int32_t -main() -{ - test(8 * sizeof(int32_t)); - test(8 * sizeof(uint16_t)); - test(53); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(1); -#endif - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_copy_if.cpp =================================================================== --- pstl/trunk/test/test_copy_if.cpp +++ pstl/trunk/test/test_copy_if.cpp @@ -1,144 +0,0 @@ -// -*- C++ -*- -//===-- test_copy_if.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - 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 - 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 - 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 -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 in(n, [&](size_t k) -> T { - T val = convert(n ^ k); - count += pred(val) ? 1 : 0; - return val; - }); - - Sequence out(count, [=](size_t) { return trash; }); - Sequence 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 - 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(-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(-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(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); -#endif - -#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test(-666, [](const int32_t& x) { return true; }, [](size_t j) { return j; }, false); -#endif - - test_algo_basic_double(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_copy_move.cpp =================================================================== --- pstl/trunk/test/test_copy_move.cpp +++ pstl/trunk/test/test_copy_move.cpp @@ -1,198 +0,0 @@ -// -*- C++ -*- -//===-- test_copy_move.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - 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 - 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 - 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 -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 - 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 - 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 - 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 -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 - 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 trash) - { - } - - template - 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 trash) - { - } -#endif - - template - 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 trash) - { - // Cleaning - std::fill_n(out_first, size, trash); - Wrapper::SetMoveCount(0); - - // Run move - auto k = move(exec, first, last, out_first); - for (size_t j = 0; j < GuardSize; ++j) - ++k; - EXPECT_TRUE(Wrapper::MoveCount() == size, "wrong effect from move"); - EXPECT_TRUE(out_last == k, "wrong return value from move"); - } -}; - -template -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 in(n, [&](size_t k) -> T { - T val = convert(n ^ k); - return val; - }); - - const size_t outN = n + GuardSize; - Sequence out(outN, [=](size_t) { return trash; }); - Sequence 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(), 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(-666, [](size_t j) { return int32_t(j); }); - test>(Wrapper(-666.0), [](int32_t j) { return Wrapper(j); }); - -#if !__PSTL_ICC_16_17_TEST_64_TIMEOUT - test(-666.0, [](size_t j) { return float64_t(j); }); - test(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); }); -#endif - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_count.cpp =================================================================== --- pstl/trunk/test/test_count.cpp +++ pstl/trunk/test/test_count.cpp @@ -1,105 +0,0 @@ -// -*- C++ -*- -//===-- test_count.cpp ----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for count and count_if -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_count -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, T needle) - { - auto expected = std::count(first, last, needle); - auto result = std::count(exec, first, last, needle); - EXPECT_EQ(expected, result, "wrong count result"); - } -}; - -struct test_count_if -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) - { - auto expected = std::count_if(first, last, pred); - auto result = std::count_if(exec, first, last, pred); - EXPECT_EQ(expected, result, "wrong count_if result"); - } -}; - -template -class IsEqual -{ - T value; - - public: - IsEqual(T value_, OddTag) : value(value_) {} - bool - operator()(const T& x) const - { - return x == value; - } -}; - -template -void -test(T needle, Predicate pred, Convert convert) -{ - // Try sequences of various lengths. - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [=](size_t k) -> In { - // Sprinkle "42" and "50" early, so that short sequences have non-zero count. - return convert((n - k - 1) % 3 == 0 ? 42 : (n - k - 2) % 5 == 0 ? 50 : 3 * (int(k) % 1000 - 500)); - }); - invoke_on_all_policies(test_count(), in.begin(), in.end(), needle); - invoke_on_all_policies(test_count_if(), in.begin(), in.end(), pred); - - invoke_on_all_policies(test_count(), in.cbegin(), in.cend(), needle); - invoke_on_all_policies(test_count_if(), in.cbegin(), in.cend(), pred); - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - auto is_even = [&](float64_t v) { - uint32_t i = (uint32_t)v; - return i % 2 == 0; - }; - count_if(exec, iter, iter, non_const(is_even)); - } -}; - -int32_t -main() -{ - test(42, IsEqual(50, OddTag()), [](int32_t j) { return j; }); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test(42, [](const int32_t& x) { return true; }, [](int32_t j) { return j; }); -#endif - test(42, IsEqual(50, OddTag()), [](int32_t j) { return float64_t(j); }); - test(Number(42, OddTag()), IsEqual(Number(50, OddTag()), OddTag()), - [](int32_t j) { return Number(j, OddTag()); }); - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_equal.cpp =================================================================== --- pstl/trunk/test/test_equal.cpp +++ pstl/trunk/test/test_equal.cpp @@ -1,165 +0,0 @@ -// -*- C++ -*- -//===-- test_equal.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -#define CPP14_ENABLED 0 - -struct UserType -{ - float32_t f; - float64_t d; - int32_t i; - size_t key; - - bool - operator()(UserType a, UserType b) - { - return a.key < b.key; - } - bool - operator<(UserType a) - { - return a.key < key; - } - bool - operator>=(UserType a) - { - return a.key <= key; - } - bool - operator<=(UserType a) - { - return a.key >= key; - } - bool - operator==(UserType a) - { - return a.key == key; - } - bool - operator==(UserType a) const - { - return a.key == key; - } - bool - operator!=(UserType a) - { - return a.key != key; - } - UserType operator!() - { - UserType tmp; - tmp.key = !key; - return tmp; - } - friend std::ostream& - operator<<(std::ostream& stream, const UserType a) - { - stream << a.key; - return stream; - } - - UserType() : key(-1), f(0.0f), d(0.0), i(0) {} - UserType(size_t Number) : key(Number), f(0.0f), d(0.0), i(0) {} - UserType& - operator=(const UserType& other) - { - key = other.key; - return *this; - } - UserType(const UserType& other) : key(other.key), f(other.f), d(other.d), i(other.i) {} - UserType(UserType&& other) : key(other.key), f(other.f), d(other.d), i(other.i) - { - other.key = -1; - other.f = 0.0f; - other.d = 0.0; - other.i = 0; - } -}; - -struct test_one_policy -{ - template - void - operator()(ExecutionPolicy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, bool is_true_equal) - { - using namespace std; - - auto expected = equal(first1, last1, first2); - auto actual = equal(exec, first1, last1, first2); - EXPECT_EQ(expected, actual, "result for equal for random-access iterator, checking against std::equal()"); - - // testing bool - EXPECT_TRUE(is_true_equal == actual, "result for equal for random-access iterator, bool"); - -//add C++14 equal symantics tests -//add more cases for inCopy size less than in -#if CPP14_ENABLED - auto actualr14 = std::equal(in.cbegin(), in.cend(), inCopy.cbegin(), inCopy.cend()); - EXPECT_EQ(expected, actualr14, "result for equal for random-access iterator"); -#endif - } -}; - -template -void -test(size_t bits) -{ - for (size_t n = 1; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - - // Sequence of odd values - Sequence in(n, [bits](size_t k) { return T(2 * HashBits(k, bits - 1) ^ 1); }); - Sequence inCopy(in); - - invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), true); - invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), true); - - // testing bool !equal() - inCopy[0] = !inCopy[0]; - invoke_on_all_policies(test_one_policy(), in.begin(), in.end(), inCopy.begin(), false); - invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cend(), inCopy.cbegin(), false); - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) - { - equal(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); - } -}; - -int32_t -main() -{ - - test(8 * sizeof(int32_t)); - test(8 * sizeof(uint16_t)); - test(53); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(1); -#endif - test(256); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_fill.cpp =================================================================== --- pstl/trunk/test/test_fill.cpp +++ pstl/trunk/test/test_fill.cpp @@ -1,97 +0,0 @@ -// -*- C++ -*- -//===-- test_fill.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 fill/fill_n - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_fill -{ - template - bool - check(It first, It last, const T& value) - { - for (; first != last; ++first) - if (*first != value) - return false; - return true; - } - - template - 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 - 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 - 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 -void -test_fill_by_type(std::size_t n) -{ - Sequence 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(n); - test_fill_by_type(n); - } - - std::cout << done() << std::endl; - - return 0; -} Index: pstl/trunk/test/test_find.cpp =================================================================== --- pstl/trunk/test/test_find.cpp +++ pstl/trunk/test/test_find.cpp @@ -1,93 +0,0 @@ -// -*- C++ -*- -//===-- test_find.cpp -----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for find -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_find -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value) - { - } -#endif - - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Value value) - { - auto i = std::find(first, last, value); - auto j = find(exec, first, last, value); - EXPECT_TRUE(i == j, "wrong return value from find"); - } -}; - -template -void -test(Value value, Hit hit, Miss miss) -{ - // Try sequences of various lengths. - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); - // Try different find positions, including not found. - // By going backwards, we can add extra matches that are *not* supposed to be found. - // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. - for (size_t m = n; m > 0; m *= 0.6) - { - if (m < n) - in[m] = hit(n ^ m); - invoke_on_all_policies(test_find(), in.begin(), in.end(), value); - invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value); - } - } -} - -// Type defined for sake of checking that std::find works with asymmetric ==. -class Weird -{ - Number value; - - public: - friend bool - operator==(Number x, Weird y) - { - return x == y.value; - } - Weird(int32_t val, OddTag) : value(val, OddTag()) {} -}; - -int32_t -main() -{ - // Note that the "hit" and "miss" functions here avoid overflow issues. - test(Weird(42, OddTag()), [](int32_t j) { return Number(42, OddTag()); }, // hit - [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); }); // miss - - // Test with value that is equal to two different bit patterns (-0.0 and 0.0) - test(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit - [](int32_t j) { return j == 0 ? ~j : j; }); // miss - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_find_end.cpp =================================================================== --- pstl/trunk/test/test_find_end.cpp +++ pstl/trunk/test/test_find_end.cpp @@ -1,120 +0,0 @@ -// -*- C++ -*- -//===-- test_find_end.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) - { - using namespace std; - // For find_end - { - auto expected = find_end(b, e, bsub, esub, pred); - auto actual = find_end(exec, b, e, bsub, esub); - EXPECT_TRUE(actual == expected, "wrong return result from find_end"); - - actual = find_end(exec, b, e, bsub, esub, pred); - EXPECT_TRUE(actual == expected, "wrong return result from find_end with a predicate"); - } - - // For search - { - auto expected = search(b, e, bsub, esub, pred); - auto actual = search(exec, b, e, bsub, esub); - EXPECT_TRUE(actual == expected, "wrong return result from search"); - - actual = search(exec, b, e, bsub, esub, pred); - EXPECT_TRUE(actual == expected, "wrong return result from search with a predicate"); - } - } -}; - -template -void -test(const std::size_t bits) -{ - - const std::size_t max_n1 = 1000; - const std::size_t max_n2 = (max_n1 * 10) / 8; - Sequence in(max_n1, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); }); - Sequence sub(max_n2, [max_n1, bits](std::size_t k) { return T(2 * HashBits(max_n1, bits - 1)); }); - for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) - { - std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; - std::size_t res[] = {0, 1, n1 / 2, n1}; - for (auto n2 : sub_n) - { - for (auto r : res) - { - std::size_t i = r, isub = 0; - for (; i < n1 & isub < n2; ++i, ++isub) - in[i] = sub[isub]; - invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2, - std::equal_to()); - invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(), - sub.cbegin() + n2, std::equal_to()); - } - } - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) - { - invoke_if(exec, [&]() { - find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); - search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); - }); - } -}; - -int32_t -main() -{ - test(8 * sizeof(int32_t)); - test(8 * sizeof(uint16_t)); - test(53); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(1); -#endif - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_find_first_of.cpp =================================================================== --- pstl/trunk/test/test_find_first_of.cpp +++ pstl/trunk/test/test_find_first_of.cpp @@ -1,109 +0,0 @@ -// -*- C++ -*- -//===-- test_find_first_of.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, - Predicate pred) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred) - { - using namespace std; - Iterator1 expected = find_first_of(b, e, bsub, esub, pred); - Iterator1 actual = find_first_of(exec, b, e, bsub, esub, pred); - EXPECT_TRUE(actual == expected, "wrong return result from find_first_of with a predicate"); - - expected = find_first_of(b, e, bsub, esub); - actual = find_first_of(exec, b, e, bsub, esub); - EXPECT_TRUE(actual == expected, "wrong return result from find_first_of"); - } -}; - -template -void -test(Predicate pred) -{ - - const std::size_t max_n1 = 1000; - const std::size_t max_n2 = (max_n1 * 10) / 8; - Sequence in1(max_n1, [](std::size_t k) { return T(1); }); - Sequence in2(max_n2, [](std::size_t k) { return T(0); }); - for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) - { - std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8}; - for (const auto n2 : sub_n) - { - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.data(), in2.data() + n2, pred); - - in2[n2 / 2] = T(1); - invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.data(), in2.data() + n2, - pred); - - if (n2 >= 3) - { - in2[2 * n2 / 3] = T(1); - invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + n1, in2.begin(), - in2.begin() + n2, pred); - in2[2 * n2 / 3] = T(0); - } - in2[n2 / 2] = T(0); - } - } - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n1 / 10, in1.data(), - in1.data() + max_n1 / 10, pred); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) - { - invoke_if(exec, [&]() { - find_first_of(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to())); - }); - } -}; - -int32_t -main() -{ - test(std::equal_to()); - test(std::not_equal_to()); - test([](const float64_t x, const float64_t y) { return x * x == y * y; }); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_find_if.cpp =================================================================== --- pstl/trunk/test/test_find_if.cpp +++ pstl/trunk/test/test_find_if.cpp @@ -1,106 +0,0 @@ -// -*- C++ -*- -//===-- test_find_if.cpp --------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for find_if and find_if_not -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_find_if -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred, - NotPredicate not_pred) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred, - NotPredicate not_pred) - { - } -#endif - - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred, NotPredicate not_pred) - { - auto i = std::find_if(first, last, pred); - auto j = find_if(exec, first, last, pred); - EXPECT_TRUE(i == j, "wrong return value from find_if"); - auto i_not = find_if_not(exec, first, last, not_pred); - EXPECT_TRUE(i_not == i, "wrong return value from find_if_not"); - } -}; - -template -void -test(Predicate pred, Hit hit, Miss miss) -{ - auto not_pred = [pred](T x) { return !pred(x); }; - // Try sequences of various lengths. - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [&](size_t k) -> T { return miss(n ^ k); }); - // Try different find positions, including not found. - // By going backwards, we can add extra matches that are *not* supposed to be found. - // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time. - for (size_t m = n; m > 0; m *= 0.6) - { - if (m < n) - in[m] = hit(n ^ m); - invoke_on_all_policies(test_find_if(), in.begin(), in.end(), pred, not_pred); - invoke_on_all_policies(test_find_if(), in.cbegin(), in.cend(), pred, not_pred); - } - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - auto is_even = [&](float64_t v) { - uint32_t i = (uint32_t)v; - return i % 2 == 0; - }; - - invoke_if(exec, [&]() { - find_if(exec, iter, iter, non_const(is_even)); - find_if_not(exec, iter, iter, non_const(is_even)); - }); - } -}; - -int32_t -main() -{ -#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN - // Note that the "hit" and "miss" functions here avoid overflow issues. - test(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit - [](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); }); // miss -#endif - - // Try type for which algorithm can really be vectorized. - test([](float32_t x) { return x >= 0; }, [](float32_t j) { return j * j; }, - [](float32_t j) { return -1 - j * j; }); - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_for_each.cpp =================================================================== --- pstl/trunk/test/test_for_each.cpp +++ pstl/trunk/test/test_for_each.cpp @@ -1,97 +0,0 @@ -// -*- C++ -*- -//===-- test_for_each.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 "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct Gen -{ - Type - operator()(std::size_t k) - { - return Type(k % 5 != 1 ? 3 * k - 7 : 0); - }; -}; - -template -struct Flip -{ - int32_t val; - Flip(int32_t y) : val(y) {} - T - operator()(T& x) const - { - return x = val - x; - } -}; - -struct test_one_policy -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Iterator expected_first, Iterator expected_last, Size n) - { - typedef typename std::iterator_traits::value_type T; - - // Try for_each - std::for_each(expected_first, expected_last, Flip(1)); - for_each(exec, first, last, Flip(1)); - EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each"); - - // Try for_each_n - std::for_each_n(pstl::execution::seq, expected_first, n, Flip(1)); - for_each_n(exec, first, n, Flip(1)); - EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n"); - } -}; - -template -void -test() -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence inout(n, Gen()); - Sequence expected(n, Gen()); - invoke_on_all_policies(test_one_policy(), inout.begin(), inout.end(), expected.begin(), expected.end(), - inout.size()); - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { - auto f = [](typename std::iterator_traits::reference x) { x = x + 1; }; - - for_each(exec, iter, iter, non_const(f)); - for_each_n(exec, iter, 0, non_const(f)); - }); - } -}; - -int32_t -main() -{ - test(); - test(); - test(); - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_generate.cpp =================================================================== --- pstl/trunk/test/test_generate.cpp +++ pstl/trunk/test/test_generate.cpp @@ -1,100 +0,0 @@ -// -*- C++ -*- -//===-- test_generate.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 generate -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -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 - void - operator()(Policy&& exec, Iterator first, Iterator last, Size n) - { - using namespace std; - typedef typename std::iterator_traits::value_type T; - - // Try random-access iterator - { - Generator_count 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 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 -void -test_generate_by_type() -{ - for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence 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 -struct test_non_const -{ - template - 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(); - test_generate_by_type(); - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_includes.cpp =================================================================== --- pstl/trunk/test/test_includes.cpp +++ pstl/trunk/test/test_includes.cpp @@ -1,104 +0,0 @@ -// -*- C++ -*- -//===-- test_includes.cpp -------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for partial_sort - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct Num -{ - T val; - explicit Num(const T& v) : val(v) {} - - //for "includes" checks - template - bool - operator<(const Num& v1) const - { - return val < v1.val; - } - - //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them - template - operator Num() const - { - return Num((T1)val); - } -}; - -struct test_one_policy -{ - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) - { - - auto expect_res = std::includes(first1, last1, first2, last2, comp); - auto res = std::includes(exec, first1, last1, first2, last2, comp); - - EXPECT_TRUE(expect_res == res, "wrong result for includes"); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) - { - } -}; - -template -void -test_includes(Compare compare) -{ - - const std::size_t n_max = 1000000; - - // The rand()%(2*n+1) encourages generation of some duplicates. - std::srand(42); - - for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) - { - //prepare the input ranges - Sequence in1(n, [](std::size_t k) { return rand() % (2 * k + 1); }); - Sequence in2(m, [](std::size_t k) { return rand() % (k + 1); }); - - std::sort(in1.begin(), in1.end(), compare); - std::sort(in2.begin(), in2.end(), compare); - - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); - - //test w/ non constant predicate - if (n < 5 && m < 5) - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), - non_const(compare)); - } - } -} - -int32_t -main() -{ - - test_includes(__pstl::internal::pstl_less()); - test_includes, Num>([](const Num& x, const Num& y) { return x < y; }); - std::cout << done() << std::endl; - - return 0; -} Index: pstl/trunk/test/test_inplace_merge.cpp =================================================================== --- pstl/trunk/test/test_inplace_merge.cpp +++ pstl/trunk/test/test_inplace_merge.cpp @@ -1,154 +0,0 @@ -// -*- C++ -*- -//===-- test_inplace_merge.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 "pstl_test_config.h" - -#include -#include "pstl/execution" -#include "pstl/algorithm" - -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, - Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, - BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) - { - } -#endif - - // inplace_merge works with bidirectional iterators at least - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) - { - - using T = typename std::iterator_traits::value_type; - const BiDirIt1 mid1 = std::next(first1, m); - fill_data(first1, mid1, generator1); - fill_data(mid1, last1, generator2); - - const BiDirIt1 mid2 = std::next(first2, m); - fill_data(first2, mid2, generator1); - fill_data(mid2, last2, generator2); - - std::inplace_merge(first1, mid1, last1, comp); - std::inplace_merge(exec, first2, mid2, last2, comp); - EXPECT_EQ_N(first1, first2, n, "wrong effect from inplace_merge with predicate"); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) - { - } -}; - -template -void -test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) -{ - using namespace std; - size_t max_size = 100000; - Sequence in1(max_size, [](size_t v) { return T(v); }); - Sequence exp(max_size, [](size_t v) { return T(v); }); - size_t m; - - for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - m = 0; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, - generator1, generator2, comp); - - m = n / 3; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, - generator1, generator2, comp); - - m = 2 * n / 3; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n, exp.begin(), exp.begin() + n, n, m, - generator1, generator2, comp); - } -} - -template -struct LocalWrapper -{ - explicit LocalWrapper(int32_t k) : my_val(k) {} - LocalWrapper(LocalWrapper&& input) { my_val = std::move(input.my_val); } - LocalWrapper& - operator=(LocalWrapper&& input) - { - my_val = std::move(input.my_val); - return *this; - } - bool - operator<(const LocalWrapper& w) const - { - return my_val < w.my_val; - } - friend bool - operator==(const LocalWrapper& x, const LocalWrapper& y) - { - return x.my_val == y.my_val; - } - friend std::ostream& - operator<<(std::ostream& stream, const LocalWrapper& input) - { - return stream << input.my_val; - } - - private: - T my_val; -}; - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { inplace_merge(exec, iter, iter, iter, non_const(std::less())); }); - } -}; - -int32_t -main() -{ - test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, - [](const float64_t x, const float64_t y) { return x > y; }); - - test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); - - test_by_type>([](int32_t i) { return LocalWrapper(2 * i + 1); }, - [](int32_t i) { return LocalWrapper(2 * i); }, - std::less>()); - - test_algo_basic_single(run_for_rnd_bi>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_is_heap.cpp =================================================================== --- pstl/trunk/test/test_is_heap.cpp +++ pstl/trunk/test/test_is_heap.cpp @@ -1,142 +0,0 @@ -// -*- C++ -*- -//===-- test_is_heap.cpp --------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for is_heap, is_heap_until -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" -#include - -using namespace TestUtils; - -struct WithCmpOp -{ - int32_t _first; - int32_t _second; - WithCmpOp() : _first(0), _second(0){}; - explicit WithCmpOp(int32_t x) : _first(x), _second(x){}; - bool - operator<(const WithCmpOp& rhs) const - { - return this->_first < rhs._first; - } -}; - -struct test_is_heap -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) - { - } -#endif - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) - { - using namespace std; - // is_heap - { - bool expected = is_heap(first, last); - bool actual = is_heap(exec, first, last); - EXPECT_TRUE(expected == actual, "wrong return value from is_heap"); - } - // is_heap with predicate - { - bool expected = is_heap(first, last, pred); - bool actual = is_heap(exec, first, last, pred); - EXPECT_TRUE(expected == actual, "wrong return value from is_heap with predicate"); - } - // is_heap_until - { - Iterator expected = is_heap_until(first, last); - Iterator actual = is_heap_until(exec, first, last); - EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until"); - } - // is_heap_until with predicate - { - const Iterator expected = is_heap_until(first, last, pred); - const auto y = std::distance(first, expected); - const Iterator actual = is_heap_until(exec, first, last, pred); - const auto x = std::distance(first, actual); - EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate"); - } - } - - // is_heap, is_heap_until works only with random access iterators - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) - { - } -}; - -template -void -test_is_heap_by_type(Comp comp) -{ - using namespace std; - - const size_t max_size = 100000; - for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [](size_t v) -> T { return T(v); }); - - invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); - - std::make_heap(in.begin(), in.begin() + n / 4, comp); - invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); - - std::make_heap(in.begin(), in.begin() + n / 3, comp); - invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); - - std::make_heap(in.begin(), in.end(), comp); - invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); - } - - Sequence in(max_size / 10, [](size_t v) -> T { return T(1); }); - invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { - is_heap(exec, iter, iter, non_const(std::less())); - is_heap_until(exec, iter, iter, non_const(std::less())); - }); - } -}; - -int32_t -main() -{ - test_is_heap_by_type(std::greater()); - test_is_heap_by_type(std::less()); - test_is_heap_by_type([](uint64_t x, uint64_t y) { return x % 100 < y % 100; }); - - test_algo_basic_single(run_for_rnd>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_is_partitioned.cpp =================================================================== --- pstl/trunk/test/test_is_partitioned.cpp +++ pstl/trunk/test/test_is_partitioned.cpp @@ -1,98 +0,0 @@ -// -*- C++ -*- -//===-- test_is_partitioned.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - void - operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred) - { - } -#endif - - template - 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 -void -test(Predicate pred) -{ - - const std::size_t max_n = 1000000; - Sequence 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 -struct LocalWrapper -{ - explicit LocalWrapper(std::size_t k) : my_val(k) {} - - private: - T my_val; -}; - -struct test_non_const -{ - template - 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([](const float64_t x) { return x < 0; }); - test([](const int32_t x) { return x > 1000; }); - test([](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>([](const LocalWrapper& x) { return true; }); -#endif - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_is_sorted.cpp =================================================================== --- pstl/trunk/test/test_is_sorted.cpp +++ pstl/trunk/test/test_is_sorted.cpp @@ -1,97 +0,0 @@ -// -*- C++ -*- -//===-- test_is_sorted.cpp ------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for is_sorted, is_sorted_until - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_is_sorted -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, bool exam) - { - using namespace std; - typedef typename std::iterator_traits::value_type T; - - //try random-access iterator - bool res = is_sorted(exec, first, last); - EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); - auto iexam = is_sorted_until(first, last); - auto ires = is_sorted_until(exec, first, last); - EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); - - //try random-access iterator with a predicate - res = is_sorted(exec, first, last, std::less()); - EXPECT_TRUE(exam == res, "is_sorted wrong result for random-access iterator"); - iexam = is_sorted_until(first, last, std::less()); - ires = is_sorted_until(exec, first, last, std::less()); - EXPECT_TRUE(iexam == ires, "is_sorted_until wrong result for random-access iterator"); - } -}; - -template -void -test_is_sorted_by_type() -{ - - Sequence in(99999, [](size_t v) -> T { return T(v); }); //fill 0..n - - invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); - invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); - - in[in.size() / 2] = -1; - invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); - invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); - - in[1] = -1; - invoke_on_all_policies(test_is_sorted(), in.begin(), in.end(), std::is_sorted(in.begin(), in.end())); - invoke_on_all_policies(test_is_sorted(), in.cbegin(), in.cend(), std::is_sorted(in.begin(), in.end())); - - //an empty container - Sequence in0(0); - invoke_on_all_policies(test_is_sorted(), in0.begin(), in0.end(), std::is_sorted(in0.begin(), in0.end())); - invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end())); - - //non-descending order - Sequence in1(9, [](size_t v) -> T { return T(0); }); - invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end())); - invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end())); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - is_sorted(exec, iter, iter, std::less()); - is_sorted_until(exec, iter, iter, std::less()); - } -}; - -int32_t -main() -{ - - test_is_sorted_by_type(); - test_is_sorted_by_type(); - - test_is_sorted_by_type>(); - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_lexicographical_compare.cpp =================================================================== --- pstl/trunk/test/test_lexicographical_compare.cpp +++ pstl/trunk/test/test_lexicographical_compare.cpp @@ -1,173 +0,0 @@ -// -*- C++ -*- -//===-- test_lexicographical_compare.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 "pstl_test_config.h" -#include -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2, - Predicate pred) - { - const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2, pred); - const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2, pred); - EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare with predicate"); - } - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 begin1, Iterator1 end1, Iterator2 begin2, Iterator2 end2) - { - const bool expected = std::lexicographical_compare(begin1, end1, begin2, end2); - const bool actual = std::lexicographical_compare(exec, begin1, end1, begin2, end2); - EXPECT_TRUE(actual == expected, "wrong return result from lexicographical compare without predicate"); - } -}; - -template -void -test(Predicate pred) -{ - - const std::size_t max_n = 1000000; - Sequence in1(max_n, [](std::size_t k) { return T1(k); }); - Sequence in2(2 * max_n, [](std::size_t k) { return T2(k); }); - - std::size_t n2; - - // Test case: Call algorithm's version without predicate. - invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, - in2.cbegin() + 5 * max_n / 10); - - // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. - std::size_t max_n2 = max_n / 10; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.cbegin(), in2.cbegin() + max_n2, - pred); - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + max_n, in2.begin() + max_n2, - in2.begin() + 3 * max_n2, pred); - - // Test case: If one range is a prefix of another, the shorter range is lexicographically less than the other. - max_n2 = 2 * max_n; - invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.begin(), in2.begin() + max_n2, - pred); - - for (std::size_t n1 = 0; n1 <= max_n; n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) - { - // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. - n2 = n1; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); - - n2 = n1; - // Test case: two ranges have different elements and are of the same length (second sequence less than first) - std::size_t ind = n1 / 2; - in2[ind] = T2(-1); - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); - in2[ind] = T2(ind); - - // Test case: two ranges have different elements and are of the same length (first sequence less than second) - ind = n1 / 5; - in1[ind] = T1(-1); - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); - in1[ind] = T1(ind); - } -} - -template -void -test_string(Predicate pred) -{ - - const std::size_t max_n = 1000000; - std::string in1 = ""; - std::string in2 = ""; - for (std::size_t n1 = 0; n1 <= max_n; ++n1) - { - in1 += n1; - } - - for (std::size_t n1 = 0; n1 <= 2 * max_n; ++n1) - { - in2 += n1; - } - - std::size_t n2; - - for (std::size_t n1 = 0; n1 < in1.size(); n1 = n1 <= 16 ? n1 + 1 : std::size_t(3.1415 * n1)) - { - // Test case: If two ranges have equivalent elements and are of the same length, then the ranges are lexicographically equal. - n2 = n1; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); - - n2 = n1; - // Test case: two ranges have different elements and are of the same length (second sequence less than first) - in2[n1 / 2] = 'a'; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.begin(), in2.begin() + n2, pred); - - // Test case: two ranges have different elements and are of the same length (first sequence less than second) - in1[n1 / 5] = 'a'; - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.begin() + n1, in2.cbegin(), in2.cbegin() + n2, pred); - } - invoke_on_all_policies(test_one_policy(), in1.cbegin(), in1.cbegin() + max_n, in2.cbegin() + 3 * max_n / 10, - in2.cbegin() + 5 * max_n / 10); -} - -template -struct LocalWrapper -{ - explicit LocalWrapper(std::size_t k) : my_val(k) {} - bool - operator<(const LocalWrapper& w) const - { - return my_val < w.my_val; - } - - private: - T my_val; -}; - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) - { - invoke_if(exec, [&]() { - lexicographical_compare(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); - }); - } -}; - -int32_t -main() -{ - test(std::less()); - test(std::greater()); -#if !__PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN - test([](const float64_t x, const int32_t y) { return x * x < y * y; }); -#endif - test, LocalWrapper>( - [](const LocalWrapper& x, const LocalWrapper& y) { return x < y; }); - test_string([](const char x, const char y) { return x < y; }); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_merge.cpp =================================================================== --- pstl/trunk/test/test_merge.cpp +++ pstl/trunk/test/test_merge.cpp @@ -1,113 +0,0 @@ -// -*- C++ -*- -//===-- test_merge.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 "pstl_test_config.h" - -#include -#include -#include "pstl/execution" -#include "pstl/algorithm" - -#include "utils.h" - -using namespace TestUtils; - -struct test_merge -{ - template - void - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - OutputIterator out_first, OutputIterator out_last, Compare comp) - { - using namespace std; - { - const auto res = merge(exec, first1, last1, first2, last2, out_first, comp); - EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); - EXPECT_TRUE(is_sorted(out_first, res, comp), "wrong result from merge with predicate"); - EXPECT_TRUE(includes(out_first, res, first1, last1, comp), "first sequence is not a part of result"); - EXPECT_TRUE(includes(out_first, res, first2, last2, comp), "second sequence is not a part of result"); - } - { - const auto res = merge(exec, first1, last1, first2, last2, out_first); - EXPECT_TRUE(res == out_last, "wrong return result from merge"); - EXPECT_TRUE(is_sorted(out_first, res), "wrong result from merge"); - } - } - - // for reverse iterators - template - void - operator()(Policy&& exec, std::reverse_iterator first1, std::reverse_iterator last1, - std::reverse_iterator first2, std::reverse_iterator last2, - std::reverse_iterator out_first, std::reverse_iterator out_last, - Compare comp) - { - using namespace std; - typedef typename std::iterator_traits>::value_type T; - const auto res = merge(exec, first1, last1, first2, last2, out_first, std::greater()); - - EXPECT_TRUE(res == out_last, "wrong return result from merge with predicate"); - EXPECT_TRUE(is_sorted(out_first, res, std::greater()), "wrong result from merge with predicate"); - EXPECT_TRUE(includes(out_first, res, first1, last1, std::greater()), - "first sequence is not a part of result"); - EXPECT_TRUE(includes(out_first, res, first2, last2, std::greater()), - "second sequence is not a part of result"); - } -}; - -template -void -test_merge_by_type(Generator1 generator1, Generator2 generator2) -{ - using namespace std; - size_t max_size = 100000; - Sequence in1(max_size, generator1); - Sequence in2(max_size / 2, generator2); - Sequence out(in1.size() + in2.size()); - std::sort(in1.begin(), in1.end()); - std::sort(in2.begin(), in2.end()); - - for (size_t size = 0; size <= max_size; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) - { - invoke_on_all_policies(test_merge(), in1.cbegin(), in1.cbegin() + size, in2.data(), in2.data() + size / 2, - out.begin(), out.begin() + 1.5 * size, std::less()); - invoke_on_all_policies(test_merge(), in1.data(), in1.data() + size, in2.cbegin(), in2.cbegin() + size / 2, - out.begin(), out.begin() + 3 * size / 2, std::less()); - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) - { - merge(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - test_merge_by_type([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; }); - test_merge_by_type([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); }); - -#if !__PSTL_ICC_16_17_TEST_64_TIMEOUT - test_merge_by_type>([](size_t v) { return Wrapper(v % 100); }, - [](size_t v) { return Wrapper(v % 10); }); -#endif - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_minmax_element.cpp =================================================================== --- pstl/trunk/test/test_minmax_element.cpp +++ pstl/trunk/test/test_minmax_element.cpp @@ -1,191 +0,0 @@ -// -*- C++ -*- -//===-- test_minmax_element.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 min_element, max_element, minmax_element - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -#include -#include -#include - -using namespace TestUtils; - -struct check_minelement -{ - template - void - operator()(Policy&& exec, Iterator begin, Iterator end) - { - typedef typename std::iterator_traits::value_type T; - const Iterator expect = std::min_element(begin, end); - const Iterator result = std::min_element(exec, begin, end); - const Iterator result_pred = std::min_element(exec, begin, end, std::less()); - EXPECT_TRUE(expect == result, "wrong return result from min_element"); - EXPECT_TRUE(expect == result_pred, "wrong return result from min_element"); - } -}; - -struct check_maxelement -{ - template - void - operator()(Policy&& exec, Iterator begin, Iterator end) - { - typedef typename std::iterator_traits::value_type T; - const Iterator expect = std::max_element(begin, end); - const Iterator result = std::max_element(exec, begin, end); - const Iterator result_pred = std::max_element(exec, begin, end, std::less()); - EXPECT_TRUE(expect == result, "wrong return result from max_element"); - EXPECT_TRUE(expect == result_pred, "wrong return result from max_element"); - } -}; - -struct check_minmaxelement -{ - template - void - operator()(Policy&& exec, Iterator begin, Iterator end) - { - typedef typename std::iterator_traits::value_type T; - const std::pair expect = std::minmax_element(begin, end); - const std::pair got = std::minmax_element(exec, begin, end); - const std::pair got_pred = std::minmax_element(exec, begin, end, std::less()); - EXPECT_TRUE(expect.first == got.first, "wrong return result from minmax_element (min part)"); - EXPECT_TRUE(expect.second == got.second, "wrong return result from minmax_element (max part)"); - EXPECT_TRUE(expect == got_pred, "wrong return result from minmax_element"); - } -}; - -template -struct sequence_wrapper -{ - TestUtils::Sequence seq; - const T min_value; - const T max_value; - static const std::size_t bits = 30; // We assume that T can handle signed 2^bits+1 value - - // TestUtils::HashBits returns value between 0 and (1< T { return T(TestUtils::HashBits(i, bits)); }); - } - - // sets first one at position `at` and bunch of them farther - void - set_desired_value(std::size_t at, T value) - { - if (seq.size() == 0) - return; - seq[at] = value; - - //Producing serveral red herrings - for (std::size_t i = at + 1; i < seq.size(); i += 1 + TestUtils::HashBits(i, 5)) - seq[i] = value; - } -}; - -template -void -test_by_type(std::size_t n) -{ - sequence_wrapper wseq(n); - - // to avoid overtesing we use std::set to leave only unique indexes - std::set targets{0}; - if (n > 1) - { - targets.insert(1); - targets.insert(2.718282 * n / 3); - targets.insert(n / 2); - targets.insert(n / 7.389056); - targets.insert(n - 1); // last - } - - for (std::set::iterator it = targets.begin(); it != targets.end(); ++it) - { - wseq.pattern_fill(); - wseq.set_desired_value(*it, wseq.min_value); - TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.cbegin(), wseq.seq.cend()); - TestUtils::invoke_on_all_policies(check_minelement(), wseq.seq.begin(), wseq.seq.end()); - - wseq.set_desired_value(*it, wseq.max_value); - TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.cbegin(), wseq.seq.cend()); - TestUtils::invoke_on_all_policies(check_maxelement(), wseq.seq.begin(), wseq.seq.end()); - - if (targets.size() > 1) - { - for (std::set::reverse_iterator rit = targets.rbegin(); rit != targets.rend(); ++rit) - { - if (*rit == *it) // we requires at least 2 unique indexes in targets - break; - wseq.pattern_fill(); - wseq.set_desired_value(*it, wseq.min_value); // setting minimum element - wseq.set_desired_value(*rit, wseq.max_value); // setting maximum element - TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); - TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); - } - } - else - { // we must check this corner case; it can not be tested in loop above - TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.cbegin(), wseq.seq.cend()); - TestUtils::invoke_on_all_policies(check_minmaxelement(), wseq.seq.begin(), wseq.seq.end()); - } - } -} - -// should provide minimal requirements only -struct OnlyLessCompare -{ - int32_t val; - OnlyLessCompare() : val(0) {} - OnlyLessCompare(int32_t val_) : val(val_) {} - bool - operator<(const OnlyLessCompare& other) const - { - return val < other.val; - } -}; - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - max_element(exec, iter, iter, non_const(std::less())); - min_element(exec, iter, iter, non_const(std::less())); - minmax_element(exec, iter, iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - using TestUtils::float64_t; - const std::size_t N = 100000; - - for (std::size_t n = 0; n < N; n = n < 16 ? n + 1 : size_t(3.14159 * n)) - { - test_by_type(n); - test_by_type(n); - } - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << TestUtils::done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_mismatch.cpp =================================================================== --- pstl/trunk/test/test_mismatch.cpp +++ pstl/trunk/test/test_mismatch.cpp @@ -1,132 +0,0 @@ -// -*- C++ -*- -//===-- test_mismatch.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 the rest algorithms; temporary approach to check compiling - -#include "pstl/execution" -#include "pstl/algorithm" -#include "pstl/numeric" -#include "pstl/memory" - -#include "utils.h" - -using namespace TestUtils; - -struct test_mismatch -{ - template - void - operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2) - { - using namespace std; - typedef typename iterator_traits::value_type T; - { - const auto expected = std::mismatch(first1, last1, first2, std::equal_to()); - const auto res3 = mismatch(exec, first1, last1, first2, std::equal_to()); - EXPECT_TRUE(expected == res3, "wrong return result from mismatch"); - const auto res4 = mismatch(exec, first1, last1, first2); - EXPECT_TRUE(expected == res4, "wrong return result from mismatch"); - } - } - template - void - operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) - { - using namespace std; - typedef typename iterator_traits::value_type T; - { - const auto expected = mismatch(pstl::execution::seq, first1, last1, first2, last2, std::equal_to()); - const auto res1 = mismatch(exec, first1, last1, first2, last2, std::equal_to()); - EXPECT_TRUE(expected == res1, "wrong return result from mismatch"); - const auto res2 = mismatch(exec, first1, last1, first2, last2); - EXPECT_TRUE(expected == res2, "wrong return result from mismatch"); - } - } -}; - -template -void -test_mismatch_by_type() -{ - using namespace std; - for (size_t size = 0; size <= 100000; size = size <= 16 ? size + 1 : size_t(3.1415 * size)) - { - const T val = T(-1); - Sequence in(size, [](size_t v) -> T { return T(v % 100); }); - { - Sequence in2(in); - invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); - invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); - - const size_t min_size = 3; - if (size > min_size) - { - const size_t idx_for_1 = size / min_size; - in[idx_for_1] = val, in[idx_for_1 + 1] = val, in[idx_for_1 + 2] = val; - invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin(), in2.end()); - invoke_on_all_policies(test_mismatch(), in.begin(), in.end(), in2.begin()); - } - - const size_t idx_for_2 = 500; - if (size >= idx_for_2 - 1) - { - in2[size / idx_for_2] = val; - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); - } - } - { - Sequence in2(100, [](size_t v) -> T { return T(v); }); - invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); - // We can't call std::mismatch with semantic below when size of second sequence less than size of first sequence - if (in2.size() <= in.size()) - invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin()); - - const size_t idx = 97; - in2[idx] = val; - in2[idx + 1] = val; - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); - if (in.size() <= in2.size()) - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); - } - { - Sequence in2({}); - invoke_on_all_policies(test_mismatch(), in2.begin(), in2.end(), in.begin(), in.end()); - - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin(), in2.cend()); - if (in.size() == 0) - invoke_on_all_policies(test_mismatch(), in.cbegin(), in.cend(), in2.cbegin()); - } - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter) - { - mismatch(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - - test_mismatch_by_type(); - test_mismatch_by_type(); - test_mismatch_by_type>(); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_none_of.cpp =================================================================== --- pstl/trunk/test/test_none_of.cpp +++ pstl/trunk/test/test_none_of.cpp @@ -1,98 +0,0 @@ -// -*- C++ -*- -//===-- test_none_of.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -/* - TODO: consider implementing the following tests for a better code coverage - - correctness - - bad input argument (if applicable) - - data corruption around/of input and output - - correctly work with nested parallelism - - check that algorithm does not require anything more than is described in its requirements section -*/ - -using namespace TestUtils; - -struct test_none_of -{ - template - void - operator()(ExecutionPolicy&& exec, Iterator begin, Iterator end, Predicate pred, bool expected) - { - - auto actualr = std::none_of(exec, begin, end, pred); - EXPECT_EQ(expected, actualr, "result for none_of"); - } -}; - -template -void -test(size_t bits) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - - // Sequence of odd values - Sequence in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); }); - - // Even value, or false when T is bool. - T spike(2 * HashBits(n, bits - 1)); - - invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), true); - invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), true); - if (n > 0) - { - // Sprinkle in a hit - in[2 * n / 3] = spike; - invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); - invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); - - // Sprinkle in a few more hits - in[n / 3] = spike; - in[n / 2] = spike; - invoke_on_all_policies(test_none_of(), in.begin(), in.end(), is_equal_to(spike), false); - invoke_on_all_policies(test_none_of(), in.cbegin(), in.cend(), is_equal_to(spike), false); - } - } -} - -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - auto is_even = [&](float64_t v) { - uint32_t i = (uint32_t)v; - return i % 2 == 0; - }; - none_of(exec, iter, iter, non_const(is_even)); - } -}; - -int32_t -main() -{ - test(8 * sizeof(int32_t)); - test(8 * sizeof(uint16_t)); - test(53); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(1); -#endif - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_nth_element.cpp =================================================================== --- pstl/trunk/test/test_nth_element.cpp +++ pstl/trunk/test/test_nth_element.cpp @@ -1,175 +0,0 @@ -// -*- C++ -*- -//===-- test_nth_element.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 "pstl_test_config.h" - -#include -#include -#include "pstl/execution" -#include "pstl/algorithm" - -#include "utils.h" - -using namespace TestUtils; - -// User defined type with minimal requirements -template -struct DataType -{ - explicit DataType(int32_t k) : my_val(k) {} - DataType(DataType&& input) - { - my_val = std::move(input.my_val); - input.my_val = T(0); - } - DataType& - operator=(DataType&& input) - { - my_val = std::move(input.my_val); - input.my_val = T(0); - return *this; - } - T - get_val() const - { - return my_val; - } - - friend std::ostream& - operator<<(std::ostream& stream, const DataType& input) - { - return stream << input.my_val; - } - - private: - T my_val; -}; - -template -bool -is_equal(const DataType& x, const DataType& y) -{ - return x.get_val() == y.get_val(); -} - -template -bool -is_equal(const T& x, const T& y) -{ - return x == y; -} - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, - Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2, - Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp) - { - } -#endif - - // nth_element works only with random access iterators - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) - { - - using T = typename std::iterator_traits::value_type; - const Iterator1 mid1 = std::next(first1, m); - const Iterator1 mid2 = std::next(first2, m); - - fill_data(first1, mid1, generator1); - fill_data(mid1, last1, generator2); - fill_data(first2, mid2, generator1); - fill_data(mid2, last2, generator2); - std::nth_element(first1, mid1, last1, comp); - std::nth_element(exec, first2, mid2, last2, comp); - if (m > 0 && m < n) - { - EXPECT_TRUE(is_equal(*mid1, *mid2), "wrong result from nth_element with predicate"); - } - EXPECT_TRUE(std::find_first_of(first2, mid2, mid2, last2, [comp](T& x, T& y) { return comp(y, x); }) == mid2, - "wrong effect from nth_element with predicate"); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m, - Generator1 generator1, Generator2 generator2, Compare comp) - { - } -}; - -template -void -test_by_type(Generator1 generator1, Generator2 generator2, Compare comp) -{ - using namespace std; - size_t max_size = 10000; - Sequence in1(max_size, [](size_t v) { return T(v); }); - Sequence exp(max_size, [](size_t v) { return T(v); }); - size_t m; - - for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - m = 0; - invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, - generator1, generator2, comp); - m = n / 7; - invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, - generator1, generator2, comp); - m = 3 * n / 5; - invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + n, in1.begin(), in1.begin() + n, n, m, - generator1, generator2, comp); - } - invoke_on_all_policies(test_one_policy(), exp.begin(), exp.begin() + max_size, in1.begin(), in1.begin() + max_size, - max_size, max_size, generator1, generator2, comp); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { nth_element(exec, iter, iter, iter, non_const(std::less())); }); - } -}; - -int32_t -main() -{ - test_by_type([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less()); - test_by_type([](int32_t) { return 0; }, [](int32_t) { return 0; }, std::less()); - - test_by_type([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); }, - [](const float64_t x, const float64_t y) { return x > y; }); - - test_by_type>( - [](int32_t i) { return DataType(2 * i + 1); }, [](int32_t i) { return DataType(2 * i); }, - [](const DataType& x, const DataType& y) { return x.get_val() < y.get_val(); }); - - test_algo_basic_single(run_for_rnd>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_partial_sort.cpp =================================================================== --- pstl/trunk/test/test_partial_sort.cpp +++ pstl/trunk/test/test_partial_sort.cpp @@ -1,149 +0,0 @@ -// -*- C++ -*- -//===-- test_partial_sort.cpp ---------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for partial_sort - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -static std::atomic count_val; -static std::atomic count_comp; - -template -struct Num -{ - T val; - - Num() { ++count_val; } - Num(T v) : val(v) { ++count_val; } - Num(const Num& v) : val(v.val) { ++count_val; } - Num(Num&& v) : val(v.val) { ++count_val; } - ~Num() { --count_val; } - Num& - operator=(const Num& v) - { - val = v.val; - return *this; - } - operator T() const { return val; } - bool - operator<(const Num& v) const - { - ++count_comp; - return val < v.val; - } -}; - -struct test_brick_partial_sort -{ - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, - Compare compare) - { - - typedef typename std::iterator_traits::value_type T; - - // The rand()%(2*n+1) encourages generation of some duplicates. - std::srand(42); - const std::size_t n = last - first; - for (std::size_t k = 0; k < n; ++k) - { - first[k] = T(rand() % (2 * n + 1)); - } - std::copy(first, last, exp_first); - - for (std::size_t p = 0; p < n; p = p <= 16 ? p + 1 : std::size_t(31.415 * p)) - { - auto m1 = first + p; - auto m2 = exp_first + p; - - std::partial_sort(exp_first, m2, exp_last, compare); - count_comp = 0; - std::partial_sort(exec, first, m1, last, compare); - EXPECT_EQ_N(exp_first, first, p, "wrong effect from partial_sort"); - - //checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads; - if (m1 - first > 1) - { - auto complex = std::ceil(n * std::log(float32_t(m1 - first))); -#if defined(__PSTL_PAR_BACKEND_TBB) - auto p = tbb::this_task_arena::max_concurrency(); -#else - auto p = 1; -#endif - -#ifdef _DEBUG - if (count_comp > complex * p) - { - std::cout << "complexity exceeded" << std::endl; - } -#endif - } - } - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last, - Compare compare) - { - } -}; - -template -void -test_partial_sort(Compare compare) -{ - - const std::size_t n_max = 100000; - Sequence in(n_max); - Sequence exp(n_max); - for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - invoke_on_all_policies(test_brick_partial_sort(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, - compare); - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - partial_sort(exec, iter, iter, iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - count_val = 0; - - test_partial_sort>([](Num x, Num y) { return x < y; }); - - EXPECT_TRUE(count_val == 0, "cleanup error"); - - test_partial_sort( - [](int32_t x, int32_t y) { return x > y; }); // Reversed so accidental use of < will be detected. - - test_algo_basic_single(run_for_rnd>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_partial_sort_copy.cpp =================================================================== --- pstl/trunk/test/test_partial_sort_copy.cpp +++ pstl/trunk/test/test_partial_sort_copy.cpp @@ -1,189 +0,0 @@ -// -*- C++ -*- -//===-- test_partial_sort_copy.cpp ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for partial_sort_copy - -#include -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct Num -{ - T val; - - Num() : val(0) {} - Num(T v) : val(v) {} - Num(const Num& v) : val(v.val) {} - Num(Num&& v) : val(v.val) {} - Num& - operator=(const Num& v) - { - val = v.val; - return *this; - } - operator T() const { return val; } - bool - operator<(const Num& v) const - { - return val < v.val; - } -}; - -template -struct test_one_policy -{ - RandomAccessIterator d_first; - RandomAccessIterator d_last; - RandomAccessIterator exp_first; - RandomAccessIterator exp_last; - // This ctor is needed because output shouldn't be transformed to any iterator type (only random access iterators are allowed) - test_one_policy(RandomAccessIterator b1, RandomAccessIterator e1, RandomAccessIterator b2, RandomAccessIterator e2) - : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2) - { - } -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, - const T& trash, Compare compare) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, - const T& trash, Compare compare) - { - } - - template - void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, - const T& trash) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2, - const T& trash) - { - } -#endif - - template - void - operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash, - Compare compare) - { - prepare_data(first, last, n1, trash); - RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last, compare); - RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last, compare); - - EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy with predicate"); - EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy with predicate"); - } - - template - void - operator()(Policy&& exec, InputIterator first, InputIterator last, Size n1, Size n2, const T& trash) - { - prepare_data(first, last, n1, trash); - RandomAccessIterator exp = std::partial_sort_copy(first, last, exp_first, exp_last); - RandomAccessIterator res = std::partial_sort_copy(exec, first, last, d_first, d_last); - - EXPECT_TRUE((exp - exp_first) == (res - d_first), "wrong result from partial_sort_copy without predicate"); - EXPECT_EQ_N(exp_first, d_first, n2, "wrong effect from partial_sort_copy without predicate"); - } - - private: - template - void - prepare_data(InputIterator first, InputIterator last, Size n1, const T& trash) - { - // The rand()%(2*n+1) encourages generation of some duplicates. - std::srand(42); - std::generate(first, last, [n1]() { return T(rand() % (2 * n1 + 1)); }); - - std::fill(exp_first, exp_last, trash); - std::fill(d_first, d_last, trash); - } -}; - -template -void -test_partial_sort_copy(Compare compare) -{ - - typedef typename Sequence::iterator iterator_type; - const std::size_t n_max = 100000; - Sequence in(n_max); - Sequence out(2 * n_max); - Sequence exp(2 * n_max); - std::size_t n1 = 0; - std::size_t n2; - T trash = T(-666); - for (; n1 < n_max; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) - { - // If both sequences are equal - n2 = n1; - invoke_on_all_policies( - test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), - in.begin() + n1, n1, n2, trash, compare); - - // If first sequence is greater than second - n2 = n1 / 3; - invoke_on_all_policies( - test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), - in.begin() + n1, n1, n2, trash, compare); - - // If first sequence is less than second - n2 = 2 * n1; - invoke_on_all_policies( - test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), in.begin(), - in.begin() + n1, n1, n2, trash, compare); - } - // Test partial_sort_copy without predicate - n1 = n_max; - n2 = 2 * n1; - invoke_on_all_policies(test_one_policy(out.begin(), out.begin() + n2, exp.begin(), exp.begin() + n2), - in.begin(), in.begin() + n1, n1, n2, trash); -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) - { - invoke_if(exec, [&]() { - partial_sort_copy(exec, input_iter, input_iter, out_iter, out_iter, non_const(std::less())); - }); - } -}; - -int32_t -main() -{ - test_partial_sort_copy>([](Num x, Num y) { return x < y; }); - test_partial_sort_copy([](int32_t x, int32_t y) { return x > y; }); - - test_algo_basic_double(run_for_rnd>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_partition.cpp =================================================================== --- pstl/trunk/test/test_partition.cpp +++ pstl/trunk/test/test_partition.cpp @@ -1,177 +0,0 @@ -// -*- C++ -*- -//===-- test_partition.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -#include -#include - -using namespace TestUtils; - -template -struct DataType -{ - explicit DataType(int32_t k) : my_val(k) {} - DataType(DataType&& input) { my_val = std::move(input.my_val); } - DataType& - operator=(DataType&& input) - { - my_val = std::move(input.my_val); - return *this; - } - T - get_val() const - { - return my_val; - } - - friend std::ostream& - operator<<(std::ostream& stream, const DataType& input) - { - return stream << input.my_val; - } - - private: - T my_val; -}; - -template -typename std::enable_if::value_type>::value, bool>::type -is_equal(Iterator first, Iterator last, Iterator d_first) -{ - return std::equal(first, last, d_first); -} - -template -typename std::enable_if::value_type>::value, bool>::type -is_equal(Iterator first, Iterator last, Iterator d_first) -{ - return true; -} - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specializations to skip testing in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, - Size n, UnaryOp unary_op, Generator generator) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, - BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) - { - } -#elif __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specializations to skip testing in case of broken configuration - template - void - operator()(pstl::execution::parallel_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, - Size n, UnaryOp unary_op, Generator generator) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, - BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator) - { - } -#endif - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, - UnaryOp unary_op, Generator generator) - { - // partition - { - fill_data(first, last, generator); - BiDirIt actual_ret = std::partition(exec, first, last, unary_op); - EXPECT_TRUE(std::all_of(first, actual_ret, unary_op) && !std::any_of(actual_ret, last, unary_op), - "wrong effect from partition"); - } - // stable_partition - { - fill_data(exp_first, exp_last, generator); - BiDirIt exp_ret = std::stable_partition(exp_first, exp_last, unary_op); - fill_data(first, last, generator); - BiDirIt actual_ret = std::stable_partition(exec, first, last, unary_op); - - EXPECT_TRUE(std::distance(first, actual_ret) == std::distance(exp_first, exp_ret), - "wrong result from stable_partition"); - EXPECT_TRUE((is_equal(exp_first, exp_last, first)), "wrong effect from stable_partition"); - } - } - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n, - UnaryOp unary_op, Generator generator) - { - } -}; - -template -void -test_by_type(Generator generator, UnaryPred pred) -{ - - using namespace std; - size_t max_size = 100000; - Sequence in(max_size, [](size_t v) { return T(v); }); - Sequence exp(max_size, [](size_t v) { return T(v); }); - - for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n, exp.begin(), exp.begin() + n, n, pred, - generator); - } -} - -struct test_non_const -{ - template - 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 i) { return i; }, [](int32_t) { return true; }); -#endif - test_by_type([](int32_t i) { return -i; }, [](const float64_t x) { return x < 0; }); - test_by_type([](int32_t i) { return i + 1; }, [](int64_t x) { return x % 3 == 0; }); - test_by_type>([](int32_t i) { return DataType(2 * i + 1); }, - [](const DataType& x) { return x.get_val() < 0; }); - - test_algo_basic_single(run_for_rnd_bi()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_partition_copy.cpp =================================================================== --- pstl/trunk/test/test_partition_copy.cpp +++ pstl/trunk/test/test_partition_copy.cpp @@ -1,114 +0,0 @@ -// -*- C++ -*- -//===-- test_partition_copy.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -#include -#include - -using namespace TestUtils; - -struct test_partition_copy -{ - template - 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(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 - void - operator()(pstl::execution::unsequenced_policy, std::reverse_iterator first, - std::reverse_iterator last, std::reverse_iterator true_first, - std::reverse_iterator true_last, std::reverse_iterator false_first, - OutputIterator2 false_last, UnaryOp unary_op) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, std::reverse_iterator first, - std::reverse_iterator last, std::reverse_iterator true_first, - std::reverse_iterator true_last, std::reverse_iterator false_first, - OutputIterator2 false_last, UnaryOp unary_op) - { - } -#endif -}; - -template -void -test(UnaryPred pred) -{ - - const std::size_t max_size = 100000; - Sequence in(max_size, [](std::size_t v) -> T { return T(v); }); - Sequence actual_true(max_size); - Sequence 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 - 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([](const int32_t value) { return value % 2; }); - -#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test([](const int32_t value) { return true; }); -#endif - - test([](const float64_t value) { return value > 2 << 6; }); - test>([](const Wrapper& value) -> bool { return value.get_my_field() != nullptr; }); - - test_algo_basic_double(run_for_rnd_bi()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_reduce.cpp =================================================================== --- pstl/trunk/test/test_reduce.cpp +++ pstl/trunk/test/test_reduce.cpp @@ -1,111 +0,0 @@ -// -*- C++ -*- -//===-- test_reduce.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/numeric" -#include "utils.h" - -using namespace TestUtils; - -struct test_long_forms_for_one_policy -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, T init, BinaryOp binary, T expected) - { - T result_r = std::reduce(exec, first, last, init, binary); - EXPECT_EQ(expected, result_r, "bad result from reduce(exec, first, last, init, binary_op)"); - } -}; - -template -void -test_long_form(T init, BinaryOp binary_op, F f) -{ - // Try sequences of various lengths - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - T expected(init); - Sequence in(n, [n, f](size_t k) { return f((int32_t(k ^ n) % 1000 - 500)); }); - for (size_t k = 0; k < n; ++k) - expected = binary_op(expected, in[k]); - - using namespace std; - - T result = transform_reduce_serial(in.cfbegin(), in.cfend(), init, binary_op, [](const T& t) { return t; }); - EXPECT_EQ(expected, result, "bad result from reduce(first, last, init, binary_op_op)"); - - invoke_on_all_policies(test_long_forms_for_one_policy(), in.begin(), in.end(), init, binary_op, expected); - invoke_on_all_policies(test_long_forms_for_one_policy(), in.cbegin(), in.cend(), init, binary_op, expected); - } -} - -struct test_two_short_forms -{ - -#if __PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Sum init, Sum expected) - { - } -#endif - - template - void - operator()(Policy&& exec, Iterator first, Iterator last, Sum init, Sum expected) - { - using namespace std; - - Sum r0 = init + reduce(exec, first, last); - EXPECT_EQ(expected, r0, "bad result from reduce(exec, first, last)"); - - Sum r1 = reduce(exec, first, last, init); - EXPECT_EQ(expected, r1, "bad result from reduce(exec, first, last, init)"); - } -}; - -// Test forms of reduce(...) that omit the binary_op or init operands. -void -test_short_forms() -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sum init(42, OddTag()); - Sum expected(init); - Sequence in(n, [n](size_t k) { return Sum((int32_t(k ^ n) % 1000 - 500), OddTag()); }); - for (size_t k = 0; k < n; ++k) - expected = expected + in[k]; - invoke_on_all_policies(test_two_short_forms(), in.begin(), in.end(), init, expected); - invoke_on_all_policies(test_two_short_forms(), in.cbegin(), in.cend(), init, expected); - } -} - -int32_t -main() -{ - // Test for popular types - test_long_form(42, std::plus(), [](int32_t x) { return x; }); - test_long_form(42.0, std::plus(), [](float64_t x) { return x; }); - - // Test for strict types - test_long_form(Number(42, OddTag()), Add(OddTag()), [](int32_t x) { return Number(x, OddTag()); }); - - // Short forms are just facade for long forms, so just test with a single type. - test_short_forms(); - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_remove.cpp =================================================================== --- pstl/trunk/test/test_remove.cpp +++ pstl/trunk/test/test_remove.cpp @@ -1,151 +0,0 @@ -// -*- C++ -*- -//===-- test_remove.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - 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 - 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 - 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 - 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 - 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 - 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 -void -test(T trash, const T& value, Predicate pred, Convert convert) -{ - const std::size_t max_size = 100000; - Sequence out(max_size, [trash](size_t) { return trash; }); - Sequence 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 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 - 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(666, 42, [](int32_t val) { return true; }, [](size_t j) { return j; }); -#endif - - test(666, 2001, [](const int32_t& val) { return val != 2001; }, - [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 2001 : -1 - int32_t(j); }); - test(-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(-666, OddTag()), Number(42, OddTag()), IsMultiple(3, OddTag()), - [](int32_t j) { return Number(j, OddTag()); }); -#endif - - test_algo_basic_single(run_for_rnd_fw()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_remove_copy.cpp =================================================================== --- pstl/trunk/test/test_remove_copy.cpp +++ pstl/trunk/test/test_remove_copy.cpp @@ -1,87 +0,0 @@ -// -*- C++ -*- -//===-- test_remove_copy.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 remove_copy - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct run_remove_copy -{ - template - 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 -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 in(n, [&](size_t k) -> T { - T x = convert(n ^ k); - count += !(x == value) ? 1 : 0; - return x; - }); - using namespace std; - - Sequence out(count, [=](size_t) { return trash; }); - Sequence 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(-666.0, 8.5, [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); }); - - test(-666, 42, [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); }); - - test(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; -} Index: pstl/trunk/test/test_replace.cpp =================================================================== --- pstl/trunk/test/test_replace.cpp +++ pstl/trunk/test/test_replace.cpp @@ -1,157 +0,0 @@ -// -*- C++ -*- -//===-- test_replace.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 -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 - 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(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 - bool - check(Iterator1 b, Iterator1 e) - { - return true; - } - - template - typename std::enable_if::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 -void -test(Pred pred) -{ - typedef typename Sequence::iterator iterator_type; - - const std::size_t max_len = 100000; - - const T1 value = T1(0); - const T1 new_value = T1(666); - - Sequence expected(max_len); - Sequence actual(max_len); - - Sequence 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 temp(data.begin(), len); - - invoke_on_all_policies(temp, expected.begin(), expected.begin() + len, actual.begin(), actual.begin() + len, - pred, new_value, value); - } -} - -template -struct test_non_const -{ - template - 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(__pstl::internal::equal_value(666)); - test([](const uint16_t& elem) { return elem % 3 < 2; }); - test([](const float64_t& elem) { return elem * elem - 3.5 * elem > 10; }); - test([](const copy_int& val) { return val.value / 5 > 2; }); - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_replace_copy.cpp =================================================================== --- pstl/trunk/test/test_replace_copy.cpp +++ pstl/trunk/test/test_replace_copy.cpp @@ -1,102 +0,0 @@ -// -*- C++ -*- -//===-- test_replace_copy.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_replace_copy -{ - template - 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 -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 in(n, [&](size_t k) -> T { return convert(n ^ k); }); - Sequence out(n, [=](size_t) { return trash; }); - Sequence 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 -struct test_non_const -{ - template - 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(-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(-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(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(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_reverse.cpp =================================================================== --- pstl/trunk/test/test_reverse.cpp +++ pstl/trunk/test/test_reverse.cpp @@ -1,102 +0,0 @@ -// -*- C++ -*- -//===-- test_reverse.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ -#if __PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN || __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e) - { - } -#endif - - template - typename std::enable_if::value>::type - operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) - { - using namespace std; - - copy(data_b, data_e, actual_b); - - reverse(exec, actual_b, actual_e); - - bool check = equal(data_b, data_e, reverse_iterator(actual_e)); - - EXPECT_TRUE(check, "wrong result of reverse"); - } - - template - typename std::enable_if::value>::type - operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e) - { - } -}; - -template -void -test() -{ - const std::size_t max_len = 100000; - - Sequence actual(max_len); - - Sequence data(max_len, [](std::size_t i) { return T(i); }); - - for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) - { - invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), - actual.begin() + len); - } -} - -template -struct wrapper -{ - T t; - wrapper() {} - explicit wrapper(T t_) : t(t_) {} - bool - operator==(const wrapper& a) const - { - return t == a.t; - } -}; - -int32_t -main() -{ - test(); - test(); - test(); -#if !__PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN - test>(); -#endif - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_reverse_copy.cpp =================================================================== --- pstl/trunk/test/test_reverse_copy.cpp +++ pstl/trunk/test/test_reverse_copy.cpp @@ -1,131 +0,0 @@ -// -*- C++ -*- -//===-- test_reverse_copy.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -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 -bool -eq(const wrapper& a, const wrapper& b) -{ - return a.t == b.t; -} - -template -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 -struct test_one_policy -{ - Iterator data_b; - Iterator data_e; - test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {} - -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 actual_b, Iterator1 actual_e) - { - using namespace std; - using T = typename iterator_traits::value_type; - using DifferenceType = typename iterator_traits::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 res(n); - std::copy(std::reverse_iterator(data_e), std::reverse_iterator(data_b), res.begin()); - - EXPECT_EQ_N(res.begin(), actual_b, n, "wrong effect of reverse_copy"); - } -}; - -template -void -test() -{ - typedef typename Sequence::iterator iterator_type; - typedef typename Sequence::const_bidirectional_iterator cbi_iterator_type; - - const std::size_t max_len = 100000; - - Sequence actual(max_len); - - Sequence data(max_len, [](std::size_t i) { return T1(i); }); - - for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) - { - invoke_on_all_policies(test_one_policy(data.begin(), data.begin() + len), actual.begin(), - actual.begin() + len); - invoke_on_all_policies(test_one_policy(data.cbibegin(), std::next(data.cbibegin(), len)), - actual.begin(), actual.begin() + len); - } -} - -int32_t -main() -{ - // 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(); - test(); - test(); - test, wrapper>(); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_rotate.cpp =================================================================== --- pstl/trunk/test/test_rotate.cpp +++ pstl/trunk/test/test_rotate.cpp @@ -1,171 +0,0 @@ -// -*- C++ -*- -//===-- test_rotate.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -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& a) : move_count(0) { t = a.t; } - - wrapper& - operator=(wrapper& a) - { - t = a.t; - return *this; - } - - wrapper& - operator=(wrapper&& a) - { - t = a.t; - move_count += 1; - return *this; - } -}; - -template -struct compare -{ - bool - operator()(const T& a, const T& b) - { - return a == b; - } -}; - -template -struct compare> -{ - bool - operator()(const wrapper& a, const wrapper& b) - { - return a.t == b.t; - } -}; -#include - -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 - void - operator()(pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, - Iterator actual_e, Size shift) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b, - Iterator actual_e, Size shift) - { - } -#endif - - template - 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::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(); - 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 std::enable_if< - is_same_iterator_category::value && - !std::is_same::value && - std::is_same::value_type, wrapper>::value, - bool>::type - check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) - { - bool result = all_of(b, e, [](wrapper& a) { - bool temp = a.move_count > 0; - a.move_count = 0; - return temp; - }); - return shift == 0 || result; - } - - template - typename std::enable_if< - !(is_same_iterator_category::value && - !std::is_same::value && - std::is_same::value_type, wrapper>::value), - bool>::type - check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift) - { - return true; - } -}; - -template -void -test() -{ - const int32_t max_len = 100000; - - Sequence actual(max_len, [](std::size_t i) { return T(i); }); - Sequence 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(); - test>(); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_rotate_copy.cpp =================================================================== --- pstl/trunk/test/test_rotate_copy.cpp +++ pstl/trunk/test/test_rotate_copy.cpp @@ -1,144 +0,0 @@ -// -*- C++ -*- -//===-- test_rotate_copy.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct wrapper; - -template -bool -compare(const wrapper& a, const wrapper& b) -{ - return a.t == b.t; -} - -template -bool -compare(const T& a, const T& b) -{ - return a == b; -} - -template -struct wrapper -{ - explicit wrapper(T t_) : t(t_) {} - wrapper& - operator=(const T& t_) - { - t = t_; - return *this; - } - friend bool - compare(const wrapper& a, const wrapper& b); - - private: - T t; -}; - -template -struct comparator -{ - using T1 = typename std::iterator_traits::value_type; - using T2 = typename std::iterator_traits::value_type; - bool - operator()(T1 a, T2 b) - { - T temp = a; - return compare(temp, b); - } -}; - -struct test_one_policy -{ - -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e, std::size_t shift) - { - } - template - typename std::enable_if::value, void>::type - operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, - Iterator2 actual_e, std::size_t shift) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e, - std::size_t shift) - { - using namespace std; - using T = typename iterator_traits::value_type; - Iterator1 data_m = std::next(data_b, shift); - - fill(actual_b, actual_e, T(-123)); - Iterator2 actual_return = rotate_copy(exec, data_b, data_m, data_e, actual_b); - - EXPECT_TRUE(actual_return == actual_e, "wrong result of rotate_copy"); - auto comparer = comparator(); - bool check = std::equal(data_m, data_e, actual_b, comparer); - check = check && std::equal(data_b, data_m, std::next(actual_b, std::distance(data_m, data_e)), comparer); - - EXPECT_TRUE(check, "wrong effect of rotate_copy"); - } -}; - -template -void -test() -{ - - const std::size_t max_len = 100000; - - Sequence actual(max_len, [](std::size_t i) { return T1(i); }); - - Sequence data(max_len, [](std::size_t i) { return T1(i); }); - - for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len)) - { - std::size_t shifts[] = {0, 1, 2, len / 3, (2 * len) / 3, len - 1}; - for (std::size_t shift : shifts) - { - if (shift > 0 && shift < len) - { - invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(), - actual.begin() + len, shift); - invoke_on_all_policies(test_one_policy(), data.cbegin(), data.cbegin() + len, actual.begin(), - actual.begin() + len, shift); - } - } - } -} - -int32_t -main() -{ - test(); - test(); - test(); - test, wrapper>(); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_scan.cpp =================================================================== --- pstl/trunk/test/test_scan.cpp +++ pstl/trunk/test/test_scan.cpp @@ -1,196 +0,0 @@ -// -*- C++ -*- -//===-- test_scan.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 "pstl/execution" -#include "pstl/numeric" -#include "utils.h" -#include "pstl_test_config.h" - -using namespace TestUtils; - -// We provide the no execution policy versions of the exclusive_scan and inclusive_scan due checking correctness result of the versions with execution policies. -//TODO: to add a macro for availability of ver implementations -template -OutputIterator -exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init) -{ - for (; first != last; ++first, ++result) - { - *result = init; - init = init + *first; - } - return result; -} - -template -OutputIterator -exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op) -{ - for (; first != last; ++first, ++result) - { - *result = init; - init = binary_op(init, *first); - } - return result; -} - -// Note: N4582 is missing the ", class T". Issue was reported 2016-Apr-11 to cxxeditor@gmail.com -template -OutputIterator -inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, T init) -{ - for (; first != last; ++first, ++result) - { - init = binary_op(init, *first); - *result = init; - } - return result; -} - -template -OutputIterator -inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) -{ - if (first != last) - { - auto tmp = *first; - *result = tmp; - return inclusive_scan_serial(++first, last, ++result, binary_op, tmp); - } - else - { - return result; - } -} - -template -OutputIterator -inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result) -{ - typedef typename std::iterator_traits::value_type input_type; - return inclusive_scan_serial(first, last, result, std::plus()); -} - -// Most of the framework required for testing inclusive and exclusive scan is identical, -// so the tests for both are in this file. Which is being tested is controlled by the global -// flag inclusive, which is set to each alternative by main(). -static bool inclusive; - -template -void -check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) -{ - EXPECT_EQ_N(expected_first, out_first, n, - inclusive ? "wrong result from inclusive_scan" : "wrong result from exclusive_scan"); - std::fill_n(out_first, n, trash); -} - -struct test_scan_with_plus -{ - template - void - operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, T trash) - { - using namespace std; - - auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first) - : exclusive_scan_serial(in_first, in_last, expected_first, init); - auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first) - : exclusive_scan(exec, in_first, in_last, out_first, init); - EXPECT_TRUE(out_last == orr, - inclusive ? "inclusive_scan returned wrong iterator" : "exclusive_scan returned wrong iterator"); - - check_and_reset(expected_first, out_first, n, trash); - fill(out_first, out_last, trash); - } -}; - -template -void -test_with_plus(T init, T trash, Convert convert) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, convert); - Sequence expected(in); - Sequence out(n, [&](int32_t) { return trash; }); - - invoke_on_all_policies(test_scan_with_plus(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), init, trash); - invoke_on_all_policies(test_scan_with_plus(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), init, trash); - } -} -struct test_scan_with_binary_op -{ - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) - { - using namespace std; - - auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first, binary_op, init) - : exclusive_scan_serial(in_first, in_last, expected_first, init, binary_op); - auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first, binary_op, init) - : exclusive_scan(exec, in_first, in_last, out_first, init, binary_op); - - EXPECT_TRUE(out_last == orr, "scan returned wrong iterator"); - check_and_reset(expected_first, out_first, n, trash); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last, - Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash) - { - } -}; - -template -void -test_matrix(Out init, BinaryOp binary_op, Out trash) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [](size_t k) { return In(k, k + 1); }); - - Sequence out(n, [&](size_t) { return trash; }); - Sequence expected(n, [&](size_t) { return trash; }); - - invoke_on_all_policies(test_scan_with_binary_op(), in.begin(), in.end(), out.begin(), out.end(), - expected.begin(), expected.end(), in.size(), init, binary_op, trash); - invoke_on_all_policies(test_scan_with_binary_op(), in.cbegin(), in.cend(), out.begin(), out.end(), - expected.begin(), expected.end(), in.size(), init, binary_op, trash); - } -} - -int32_t -main() -{ - for (int32_t mode = 0; mode < 2; ++mode) - { - inclusive = mode != 0; -#if !__PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN - // Test with highly restricted type and associative but not commutative operation - test_matrix, Matrix2x2>(Matrix2x2(), multiply_matrix, - Matrix2x2(-666, 666)); -#endif - - // Since the implict "+" forms of the scan delegate to the generic forms, - // there's little point in using a highly restricted type, so just use double. - test_with_plus(inclusive ? 0.0 : -1.0, -666.0, - [](uint32_t k) { return float64_t((k % 991 + 1) ^ (k % 997 + 2)); }); - } - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_search_n.cpp =================================================================== --- pstl/trunk/test/test_search_n.cpp +++ pstl/trunk/test/test_search_n.cpp @@ -1,106 +0,0 @@ -// -*- C++ -*- -//===-- test_search_n.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_one_policy -{ -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ - __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration - template - void - operator()(pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, - Predicate pred) - { - } -#endif - - template - void - operator()(ExecutionPolicy&& exec, Iterator b, Iterator e, Size count, const T& value, Predicate pred) - { - using namespace std; - auto expected = search_n(b, e, count, value, pred); - auto actual = search_n(exec, b, e, count, value); - EXPECT_TRUE(actual == expected, "wrong return result from search_n"); - - actual = search_n(exec, b, e, count, value, pred); - EXPECT_TRUE(actual == expected, "wrong return result from search_n with a predicate"); - } -}; - -template -void -test() -{ - - const std::size_t max_n1 = 100000; - const T value = T(1); - for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1)) - { - std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8}; - std::size_t res[] = {0, 1, n1 / 2, n1}; - for (auto n2 : sub_n) - { - // Some of standard libraries return "first" in this case. We return "last" according to the standard - if (n2 == 0) - { - continue; - } - for (auto r : res) - { - Sequence in(n1, [n1](std::size_t k) { return T(0); }); - std::size_t i = r, isub = 0; - for (; i < n1 & isub < n2; ++i, ++isub) - in[i] = value; - - invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, n2, value, std::equal_to()); - invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, n2, value, std::equal_to()); - } - } - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { search_n(exec, iter, iter, 0, T(0), non_const(std::equal_to())); }); - } -}; - -int32_t -main() -{ - test(); - test(); - test(); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN - test(); -#endif - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_set.cpp =================================================================== --- pstl/trunk/test/test_set.cpp +++ pstl/trunk/test/test_set.cpp @@ -1,160 +0,0 @@ -// -*- C++ -*- -//===-- test_set.cpp ------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Tests for partial_sort - -#include -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct Num -{ - T val; - - Num() : val{} {} - Num(const T& v) : val(v) {} - - //for "includes" checks - template - bool - operator<(const Num& v1) const - { - return val < v1.val; - } - - //The types Type1 and Type2 must be such that an object of type InputIt can be dereferenced and then implicitly converted to both of them - template - operator Num() const - { - return Num((T1)val); - } - - friend bool - operator==(const Num& v1, const Num& v2) - { - return v1.val == v2.val; - } -}; - -struct test_one_policy -{ - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) - { - using T1 = typename std::iterator_traits::value_type; - - auto n1 = std::distance(first1, last1); - auto n2 = std::distance(first2, last2); - auto n = n1 + n2; - Sequence expect(n); - Sequence out(n); - - //1. set_union - auto expect_res = std::set_union(first1, last1, first2, last2, expect.begin(), comp); - auto res = std::set_union(exec, first1, last1, first2, last2, out.begin(), comp); - - EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_union"); - EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_union effect"); - - //2. set_intersection - expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp); - - EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_intersection"); - EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_intersection effect"); - - //3. set_difference - expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp); - - EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_difference"); - EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_difference effect"); - - //4. set_symmetric_difference - expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp); - res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp); - - EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_symmetric_difference"); - EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), - "wrong set_symmetric_difference effect"); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - Compare comp) - { - } -}; - -template -void -test_set(Compare compare) -{ - - const std::size_t n_max = 100000; - - // The rand()%(2*n+1) encourages generation of some duplicates. - std::srand(4200); - - for (std::size_t n = 0; n < n_max; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m)) - { - //prepare the input ranges - Sequence in1(n, [n](std::size_t k) { return rand() % (2 * k + 1); }); - Sequence in2(m, [m](std::size_t k) { return (m % 2) * rand() + rand() % (k + 1); }); - - std::sort(in1.begin(), in1.end(), compare); - std::sort(in2.begin(), in2.end(), compare); - - invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare); - } - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) - { - set_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); - - set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); - - set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, - non_const(std::less())); - - set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - - test_set(__pstl::internal::pstl_less()); - test_set, Num>([](const Num& x, const Num& y) { return x < y; }); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - - return 0; -} Index: pstl/trunk/test/test_sort.cpp =================================================================== --- pstl/trunk/test/test_sort.cpp +++ pstl/trunk/test/test_sort.cpp @@ -1,244 +0,0 @@ -// -*- C++ -*- -//===-- test_sort.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 sort and stable_sort - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; -#define _CRT_SECURE_NO_WARNINGS - -#include - -static bool Stable; - -//! Number of extant keys -static std::atomic KeyCount; - -//! One more than highest index in array to be sorted. -static uint32_t LastIndex; - -//! Keeping Equal() static and a friend of ParanoidKey class (C++, paragraphs 3.5/7.1.1) -class ParanoidKey; -static bool -Equal(const ParanoidKey& x, const ParanoidKey& y); - -//! A key to be sorted, with lots of checking. -class ParanoidKey -{ - //! Value used by comparator - int32_t value; - //! Original position or special value (Empty or Dead) - int32_t index; - //! Special value used to mark object without a comparable value, e.g. after being moved from. - static const int32_t Empty = -1; - //! Special value used to mark destroyed objects. - static const int32_t Dead = -2; - // True if key object has comparable value - bool - isLive() const - { - return (uint32_t)(index) < LastIndex; - } - // True if key object has been constructed. - bool - isConstructed() const - { - return isLive() || index == Empty; - } - - public: - ParanoidKey() - { - ++KeyCount; - index = Empty; - value = Empty; - } - ParanoidKey(const ParanoidKey& k) : value(k.value), index(k.index) - { - EXPECT_TRUE(k.isLive(), "source for copy-constructor is dead"); - ++KeyCount; - } - ~ParanoidKey() - { - EXPECT_TRUE(isConstructed(), "double destruction"); - index = Dead; - --KeyCount; - } - ParanoidKey& - operator=(const ParanoidKey& k) - { - EXPECT_TRUE(k.isLive(), "source for copy-assignment is dead"); - EXPECT_TRUE(isConstructed(), "destination for copy-assignment is dead"); - value = k.value; - index = k.index; - return *this; - } - ParanoidKey(int32_t index, int32_t value, OddTag) : index(index), value(value) {} - ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index) - { - EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead"); -// std::stable_sort() fails in move semantics on paranoid test before VS2015 -#if !defined(_MSC_VER) || _MSC_VER >= 1900 - k.index = Empty; -#endif - ++KeyCount; - } - ParanoidKey& - operator=(ParanoidKey&& k) - { - EXPECT_TRUE(k.isConstructed(), "source for move-assignment is dead"); - EXPECT_TRUE(isConstructed(), "destination for move-assignment is dead"); - value = k.value; - index = k.index; -// std::stable_sort() fails in move semantics on paranoid test before VS2015 -#if !defined(_MSC_VER) || _MSC_VER >= 1900 - k.index = Empty; -#endif - return *this; - } - friend class KeyCompare; - friend bool - Equal(const ParanoidKey& x, const ParanoidKey& y); -}; - -class KeyCompare -{ - enum statusType - { - //! Special value used to mark defined object. - Live = 0xabcd, - //! Special value used to mark destroyed objects. - Dead = -1 - } status; - - public: - KeyCompare(OddTag) : status(Live) {} - ~KeyCompare() { status = Dead; } - bool - operator()(const ParanoidKey& j, const ParanoidKey& k) const - { - EXPECT_TRUE(status == Live, "key comparison object not defined"); - EXPECT_TRUE(j.isLive(), "first key to operator() is not live"); - EXPECT_TRUE(k.isLive(), "second key to operator() is not live"); - return j.value < k.value; - } -}; - -// Equal is equality comparison used for checking result of sort against expected result. -static bool -Equal(const ParanoidKey& x, const ParanoidKey& y) -{ - return (x.value == y.value && !Stable) || (x.index == y.index); -} - -static bool -Equal(float32_t x, float32_t y) -{ - return x == y; -} - -static bool -Equal(int32_t x, int32_t y) -{ - return x == y; -} - -struct test_sort_with_compare -{ - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, - OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) - { - using namespace std; - copy_n(first, n, expected_first); - copy_n(first, n, tmp_first); - if (Stable) - std::stable_sort(expected_first + 1, expected_last - 1, compare); - else - std::sort(expected_first + 1, expected_last - 1, compare); - int32_t count0 = KeyCount; - if (Stable) - stable_sort(exec, tmp_first + 1, tmp_last - 1, compare); - else - sort(exec, tmp_first + 1, tmp_last - 1, compare); - - for (size_t i = 0; i < n; ++i, ++expected_first, ++tmp_first) - { - // Check that expected[i] is equal to tmp[i] - EXPECT_TRUE(Equal(*expected_first, *tmp_first), "bad sort"); - } - int32_t count1 = KeyCount; - EXPECT_EQ(count0, count1, "key cleanup error"); - } - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first, - OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare) - { - } -}; - -template -void -test_sort(Compare compare, Convert convert) -{ - for (size_t n = 0; n < 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - LastIndex = n + 2; - // The rand()%(2*n+1) encourages generation of some duplicates. - // Sequence is padded with an extra element at front and back, to detect overwrite bugs. - Sequence in(n + 2, [=](size_t k) { return convert(k, rand() % (2 * n + 1)); }); - Sequence expected(in); - Sequence tmp(in); - invoke_on_all_policies(test_sort_with_compare(), tmp.begin(), tmp.end(), expected.begin(), expected.end(), - in.begin(), in.end(), in.size(), compare); - } -} - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - sort(exec, iter, iter, non_const(std::less())); - stable_sort(exec, iter, iter, non_const(std::less())); - } -}; - -int32_t -main() -{ - std::srand(42); - for (int32_t kind = 0; kind < 2; ++kind) - { - Stable = kind != 0; - test_sort(KeyCompare(OddTag()), - [](size_t k, size_t val) { return ParanoidKey(k, val, OddTag()); }); - test_sort([](float32_t x, float32_t y) { return x < y; }, - [](size_t, size_t val) { return float32_t(val); }); - test_sort( - [](int32_t x, int32_t y) { return x > y; }, // Reversed so accidental use of < will be detected. - [](size_t, size_t val) { return int32_t(val); }); - } - - test_algo_basic_single(run_for_rnd>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_swap_ranges.cpp =================================================================== --- pstl/trunk/test/test_swap_ranges.cpp +++ pstl/trunk/test/test_swap_ranges.cpp @@ -1,131 +0,0 @@ -// -*- C++ -*- -//===-- test_swap_ranges.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 "pstl_test_config.h" - -#include - -#include "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -struct wrapper -{ - T t; - std::size_t number_of_swaps = 0; - wrapper() {} - explicit wrapper(T t_) : t(t_) {} - template - void - operator=(const U& b) - { - t = b; - } - bool - operator==(const wrapper& a) const - { - return t == a.t; - } -}; - -template -void -swap(wrapper& a, wrapper& b) -{ - std::swap(a.t, b.t); - a.number_of_swaps++; - b.number_of_swaps++; -} - -template -struct check_swap -{ - bool - operator()(T& a) - { - return true; - } -}; - -template -struct check_swap> -{ - bool - operator()(wrapper& a) - { - bool temp = (a.number_of_swaps == 1); - a.number_of_swaps = 0; - return temp; - } -}; - -struct test_one_policy -{ - template - 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::reference; - using T = typename iterator_traits::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()) && all_of(actual_b, actual_e, check_swap()); - EXPECT_TRUE(swap_check, "wrong effect of swap_ranges swap check"); - } - } - } -}; - -template -void -test() -{ - const std::size_t max_len = 100000; - - Sequence data(max_len); - Sequence 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>(); - test>(); - test(); - test(); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_transform_binary.cpp =================================================================== --- pstl/trunk/test/test_transform_binary.cpp +++ pstl/trunk/test/test_transform_binary.cpp @@ -1,116 +0,0 @@ -// -*- C++ -*- -//===-- test_transform_binary.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 "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -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 -void -check_and_reset(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator out_first) -{ - typedef typename std::iterator_traits::value_type Out; - typename std::iterator_traits::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::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 - 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 -void -test(Predicate pred) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in1(n, [](size_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); - Sequence in2(n, [](size_t k) { return k % 7 != 2 ? 5 * k - 5 : 0; }); - - Sequence 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 -struct test_non_const -{ - template - 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())); - }); - } -}; - -int32_t -main() -{ - //const operator() - test(TheOperation(1)); - test(TheOperation(1.5)); - //non-const operator() - test(non_const(TheOperation(1.5))); - test(non_const(TheOperation(1.5))); - //lambda - test([](const int8_t& x, const float64_t& y) { return int8_t(int8_t(1.5) + x - y); }); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_transform_reduce.cpp =================================================================== --- pstl/trunk/test/test_transform_reduce.cpp +++ pstl/trunk/test/test_transform_reduce.cpp @@ -1,133 +0,0 @@ -// -*- C++ -*- -//===-- test_transform_reduce.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 inner_product - -#include "pstl/execution" -#include "pstl/numeric" -#include "utils.h" - -using namespace TestUtils; - -// Equal for all types -template -static bool -Equal(T x, T y) -{ - return x == y; -} - -// Functor for xor-operation for modeling binary operations in inner_product -class XOR -{ - public: - template - T - operator()(const T& left, const T& right) const - { - return left ^ right; - } -}; - -// Model of User-defined class -class MyClass -{ - public: - int32_t my_field; - MyClass() { my_field = 0; } - MyClass(int32_t in) { my_field = in; } - MyClass(const MyClass& in) { my_field = in.my_field; } - - friend MyClass - operator+(const MyClass& x, const MyClass& y) - { - return MyClass(x.my_field + y.my_field); - } - friend MyClass - operator-(const MyClass& x) - { - return MyClass(-x.my_field); - } - friend MyClass operator*(const MyClass& x, const MyClass& y) { return MyClass(x.my_field * y.my_field); } - bool - operator==(const MyClass& in) - { - return my_field == in.my_field; - } -}; - -template -void -CheckResults(const T& expected, const T& in) -{ - EXPECT_TRUE(Equal(expected, in), "wrong result of transform_reduce"); -} - -// We need to check correctness only for "int" (for example) except cases -// if we have "floating-point type"-specialization -void -CheckResults(const float32_t& expected, const float32_t& in) -{ -} - -// Test for different types and operations with different iterators -struct test_transform_reduce -{ - template - void - operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, - T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU) - { - - auto expectedB = std::inner_product(first1, last1, first2, init, opB1, opB2); - auto expectedU = transform_reduce_serial(first1, last1, init, opB1, opU); - T resRA = std::transform_reduce(exec, first1, last1, first2, init, opB1, opB2); - CheckResults(expectedB, resRA); - resRA = std::transform_reduce(exec, first1, last1, init, opB1, opU); - CheckResults(expectedU, resRA); - } -}; - -template -void -test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU, Initializer initObj) -{ - - std::size_t maxSize = 100000; - Sequence in1(maxSize, initObj); - Sequence in2(maxSize, initObj); - - for (std::size_t n = 0; n < maxSize; n = n < 16 ? n + 1 : size_t(3.1415 * n)) - { - invoke_on_all_policies(test_transform_reduce(), in1.begin(), in1.begin() + n, in2.begin(), in2.begin() + n, - init, opB1, opB2, opU); - invoke_on_all_policies(test_transform_reduce(), in1.cbegin(), in1.cbegin() + n, in2.cbegin(), in2.cbegin() + n, - init, opB1, opB2, opU); - } -} - -int32_t -main() -{ - test_by_type(42, std::plus(), std::multiplies(), std::negate(), - [](std::size_t a) -> int32_t { return int32_t(rand() % 1000); }); - test_by_type(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(), - [](const int64_t& x) -> int64_t { return x * 2; }, - [](std::size_t a) -> int64_t { return int64_t(rand() % 1000); }); - test_by_type(1.0f, std::multiplies(), - [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; }, - [](const float32_t& x) -> float32_t { return x + 2; }, - [](std::size_t a) -> float32_t { return rand() % 1000; }); - test_by_type(MyClass(), std::plus(), std::multiplies(), std::negate(), - [](std::size_t a) -> MyClass { return MyClass(rand() % 1000); }); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_transform_scan.cpp =================================================================== --- pstl/trunk/test/test_transform_scan.cpp +++ pstl/trunk/test/test_transform_scan.cpp @@ -1,173 +0,0 @@ -// -*- C++ -*- -//===-- test_transform_scan.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 "pstl/execution" -#include "pstl/numeric" -#include "utils.h" -#include "pstl_test_config.h" - -using namespace TestUtils; - -// Most of the framework required for testing inclusive and exclusive transform-scans is identical, -// so the tests for both are in this file. Which is being tested is controlled by the global -// flag inclusive, which is set to each alternative by main(). -static bool inclusive; - -template -void -check_and_reset(Iterator expected_first, Iterator out_first, Size n, T trash) -{ - EXPECT_EQ_N(expected_first, out_first, n, - inclusive ? "wrong result from transform_inclusive_scan" - : "wrong result from transform_exclusive_scan"); - std::fill_n(out_first, n, trash); -} - -struct test_transform_scan -{ - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, - UnaryOp unary_op, T init, BinaryOp binary_op, T trash) - { - using namespace std; - - auto orr1 = inclusive ? transform_inclusive_scan(pstl::execution::seq, first, last, expected_first, binary_op, - unary_op, init) - : transform_exclusive_scan(pstl::execution::seq, first, last, expected_first, init, - binary_op, unary_op); - auto orr2 = inclusive ? transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op, init) - : transform_exclusive_scan(exec, first, last, out_first, init, binary_op, unary_op); - EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); - check_and_reset(expected_first, out_first, n, trash); - - // Checks inclusive scan if init is not provided - if (inclusive && n > 0) - { - orr1 = transform_inclusive_scan(pstl::execution::seq, first, last, expected_first, binary_op, unary_op); - orr2 = transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op); - EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator"); - check_and_reset(expected_first, out_first, n, trash); - } - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, - OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n, - UnaryOp unary_op, T init, BinaryOp binary_op, T trash) - { - } -}; - -const uint32_t encryption_mask = 0x314; - -template -std::pair -transform_inclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, - T init, BinaryOperation binary_op) noexcept -{ - for (; first != last; ++first, ++result) - { - init = binary_op(init, unary_op(*first)); - *result = init; - } - return std::make_pair(result, init); -} - -template -std::pair -transform_exclusive_scan_serial(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unary_op, - T init, BinaryOperation binary_op) noexcept -{ - for (; first != last; ++first, ++result) - { - *result = init; - init = binary_op(init, unary_op(*first)); - } - return std::make_pair(result, init); -} - -template -void -test(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [](size_t k) { return In(k ^ encryption_mask); }); - - Out tmp = init; - Sequence expected(n, [&](size_t k) -> Out { - if (inclusive) - { - tmp = binary_op(tmp, unary_op(in[k])); - return tmp; - } - else - { - Out val = tmp; - tmp = binary_op(tmp, unary_op(in[k])); - return val; - } - }); - - Sequence out(n, [&](size_t) { return trash; }); - - auto result = - inclusive - ? transform_inclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op) - : transform_exclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op); - check_and_reset(expected.begin(), out.begin(), out.size(), trash); - - invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), unary_op, init, binary_op, trash); - invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), unary_op, init, binary_op, trash); - } -} - -template -void -test_matrix(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash) -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [](size_t k) { return In(k, k + 1); }); - - Sequence out(n, [&](size_t) { return trash; }); - Sequence expected(n, [&](size_t) { return trash; }); - - invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), unary_op, init, binary_op, trash); - invoke_on_all_policies(test_transform_scan(), in.cbegin(), in.cend(), out.begin(), out.end(), expected.begin(), - expected.end(), in.size(), unary_op, init, binary_op, trash); - } -} - -int32_t -main() -{ - for (int32_t mode = 0; mode < 2; ++mode) - { - inclusive = mode != 0; -#if !__PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN - test_matrix, Matrix2x2>([](const Matrix2x2 x) { return x; }, - Matrix2x2(), multiply_matrix, - Matrix2x2(-666, 666)); -#endif - test([](int32_t x) { return x++; }, -123, [](int32_t x, int32_t y) { return x + y; }, 666); - } - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_transform_unary.cpp =================================================================== --- pstl/trunk/test/test_transform_unary.cpp +++ pstl/trunk/test/test_transform_unary.cpp @@ -1,86 +0,0 @@ -// -*- C++ -*- -//===-- test_transform_unary.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 "pstl/execution" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -template -void -check_and_reset(InputIterator first, InputIterator last, OutputIterator out_first) -{ - typedef typename std::iterator_traits::value_type Out; - typename std::iterator_traits::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 - 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 -void -test() -{ - for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [](int32_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; }); - - Sequence out(n); - - const auto flip = Complement(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 -struct test_non_const -{ - template - 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())); }); - } -}; - -int32_t -main() -{ - test(); - test(); - test(); - test(); - test(); - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_uninitialized_construct.cpp =================================================================== --- pstl/trunk/test/test_uninitialized_construct.cpp +++ pstl/trunk/test/test_uninitialized_construct.cpp @@ -1,120 +0,0 @@ -// -*- C++ -*- -//===-- test_uninitialized_construct.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 uninitialized_default_construct, uninitialized_default_construct_n, -// uninitialized_value_construct, uninitialized_value_construct_n - -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/memory" -#include "utils.h" - -using namespace TestUtils; - -// function of checking correctness for uninitialized.construct.value -template -bool -IsCheckValueCorrectness(Iterator begin, Iterator end) -{ - for (; begin != end; ++begin) - { - if (*begin != T()) - { - return false; - } - } - return true; -} - -struct test_uninit_construct -{ - template - void - operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::false_type) - { - typedef typename std::iterator_traits::value_type T; - // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) - // and for cleaning memory after last calling of uninitialized_value_construct_n. - // It is important for non-trivial types - std::destroy_n(exec, begin, n); - - // reset counter of constructors - T::SetCount(0); - // run algorithm - std::uninitialized_default_construct(exec, begin, end); - // compare counter of constructors to length of container - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct"); - // destroy objects for testing new algorithms on same memory - std::destroy(exec, begin, end); - - std::uninitialized_default_construct_n(exec, begin, n); - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_default_construct_n"); - std::destroy_n(exec, begin, n); - - std::uninitialized_value_construct(exec, begin, end); - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct"); - std::destroy(exec, begin, end); - - std::uninitialized_value_construct_n(exec, begin, n); - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_value_construct_n"); - } - - template - void - operator()(Policy&& exec, Iterator begin, Iterator end, size_t n, /*is_trivial=*/std::true_type) - { - typedef typename std::iterator_traits::value_type T; - - std::uninitialized_default_construct(exec, begin, end); - std::destroy(exec, begin, end); - - std::uninitialized_default_construct_n(exec, begin, n); - std::destroy_n(exec, begin, n); - - std::uninitialized_value_construct(exec, begin, end); - // check correctness for uninitialized.construct.value - EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct"); - std::destroy(exec, begin, end); - - std::uninitialized_value_construct_n(exec, begin, n); - EXPECT_TRUE(IsCheckValueCorrectness(begin, end), "wrong uninitialized_value_construct_n"); - std::destroy_n(exec, begin, n); - } -}; - -template -void -test_uninit_construct_by_type() -{ - std::size_t N = 100000; - for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - std::unique_ptr p(new T[n]); - invoke_on_all_policies(test_uninit_construct(), p.get(), std::next(p.get(), n), n, std::is_trivial()); - } -} - -int32_t -main() -{ - - // for user-defined types -#if !__PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN - test_uninit_construct_by_type>(); - test_uninit_construct_by_type>>(); -#endif - - // for trivial types - test_uninit_construct_by_type(); - test_uninit_construct_by_type(); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_uninitialized_copy_move.cpp =================================================================== --- pstl/trunk/test/test_uninitialized_copy_move.cpp +++ pstl/trunk/test/test_uninitialized_copy_move.cpp @@ -1,142 +0,0 @@ -// -*- C++ -*- -//===-- test_uninitialized_copy_move.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 uninitialized_copy, uninitialized_copy_n, uninitialized_move, uninitialized_move_n - -#include "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/memory" -#include "utils.h" - -using namespace TestUtils; - -// function of checking correctness for uninitialized.construct.value -template -bool -IsCheckValueCorrectness(InputIterator first1, OutputIterator first2, Size n) -{ - for (Size i = 0; i < n; ++i, ++first1, ++first2) - { - if (*first1 != *first2) - { - return false; - } - } - return true; -} - -struct test_uninitialized_copy_move -{ - template - void - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, - /*is_trivial=*/std::false_type) - { - typedef typename std::iterator_traits::value_type T; - // it needs for cleaning memory that was filled by default constructors in unique_ptr p(new T[n]) - // and for cleaning memory after last calling of uninitialized_value_construct_n. - // It is important for non-trivial types - std::destroy_n(exec, out_first, n); - - // reset counter of constructors - T::SetCount(0); - // run algorithm - std::uninitialized_copy(exec, first, last, out_first); - // compare counter of constructors to length of container - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy"); - // destroy objects for testing new algorithms on same memory - std::destroy_n(exec, out_first, n); - - std::uninitialized_copy_n(exec, first, n, out_first); - EXPECT_TRUE(T::Count() == n, "wrong uninitialized_copy_n"); - std::destroy_n(exec, out_first, n); - - // For move - std::uninitialized_move(exec, first, last, out_first); - // compare counter of constructors to length of container - EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move"); - // destroy objects for testing new algorithms on same memory - std::destroy_n(exec, out_first, n); - - std::uninitialized_move_n(exec, first, n, out_first); - EXPECT_TRUE(T::MoveCount() == n, "wrong uninitialized_move_n"); - std::destroy_n(exec, out_first, n); - } - -#if __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN - template - void - operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first, - size_t n, /*is_trivial=*/std::true_type) - { - } - template - void - operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, - OutputIterator out_first, size_t n, /*is_trivial=*/std::true_type) - { - } -#endif - - template - void - operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n, - /*is_trivial=*/std::true_type) - { - typedef typename std::iterator_traits::value_type T; - - std::uninitialized_copy(exec, first, last, out_first); - EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy"); - std::destroy_n(exec, out_first, n); - - std::uninitialized_copy_n(exec, first, n, out_first); - EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy_n"); - std::destroy_n(exec, out_first, n); - - std::uninitialized_move(exec, first, last, out_first); - EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move"); - std::destroy_n(exec, out_first, n); - - std::uninitialized_move_n(exec, first, n, out_first); - EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_move_n"); - std::destroy_n(exec, out_first, n); - } -}; - -template -void -test_uninitialized_copy_move_by_type() -{ - std::size_t N = 100000; - for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - Sequence in(n, [=](size_t k) -> T { return T(k); }); - std::unique_ptr p(new T[n]); - invoke_on_all_policies(test_uninitialized_copy_move(), in.begin(), in.end(), p.get(), n, std::is_trivial()); - } -} - -int32_t -main() -{ - - // for trivial types - test_uninitialized_copy_move_by_type(); - test_uninitialized_copy_move_by_type(); - - // for user-defined types -#if !__PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && !__PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && \ - !__PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN - test_uninitialized_copy_move_by_type>(); -#endif - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_uninitialized_fill_destroy.cpp =================================================================== --- pstl/trunk/test/test_uninitialized_fill_destroy.cpp +++ pstl/trunk/test/test_uninitialized_fill_destroy.cpp @@ -1,91 +0,0 @@ -// -*- C++ -*- -//===-- test_uninitialized_fill_destroy.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 the destroy, destroy_n, uninitialized_fill, uninitialized_fill_n algorithms - -#include "pstl/execution" -#include "pstl/memory" -#include "pstl/algorithm" -#include "utils.h" - -using namespace TestUtils; - -struct test_uninitialized_fill_destroy -{ - template - void - operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::false_type) - { - using namespace std; - { - T::SetCount(0); - uninitialized_fill(exec, first, last, in); - size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); - EXPECT_TRUE(n == count, "wrong work of uninitialized_fill"); - destroy(exec, first, last); - EXPECT_TRUE(T::Count() == 0, "wrong work of destroy"); - } - - { - auto res = uninitialized_fill_n(exec, first, n, in); - EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); - size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); - EXPECT_TRUE(n == count, "wrong work of uninitialized_fill_n"); - destroy_n(exec, first, n); - EXPECT_TRUE(T::Count() == 0, "wrong work of destroy_n"); - } - } - template - void - operator()(Policy&& exec, Iterator first, Iterator last, const T& in, std::size_t n, std::true_type) - { - using namespace std; - { - destroy(exec, first, last); - uninitialized_fill(exec, first, last, in); - size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); - EXPECT_EQ(n, count, "wrong work of uninitialized:_fill"); - } - { - destroy_n(exec, first, n); - auto res = uninitialized_fill_n(exec, first, n, in); - size_t count = count_if(first, last, [&in](T& x) -> bool { return x == in; }); - EXPECT_EQ(n, count, "wrong work of uninitialized_fill_n"); - EXPECT_TRUE(res == last, "wrong result of uninitialized_fill_n"); - } - } -}; - -template -void -test_uninitialized_fill_destroy_by_type() -{ - std::size_t N = 100000; - for (size_t n = 0; n <= N; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - std::unique_ptr p(new T[n]); - invoke_on_all_policies(test_uninitialized_fill_destroy(), p.get(), std::next(p.get(), n), T(), n, - std::is_trivial()); - } -} - -int32_t -main() -{ - // for trivial types - test_uninitialized_fill_destroy_by_type(); - test_uninitialized_fill_destroy_by_type(); - - // for user-defined types - test_uninitialized_fill_destroy_by_type>(); - test_uninitialized_fill_destroy_by_type>(); - std::cout << done() << std::endl; - - return 0; -} Index: pstl/trunk/test/test_unique.cpp =================================================================== --- pstl/trunk/test/test_unique.cpp +++ pstl/trunk/test/test_unique.cpp @@ -1,154 +0,0 @@ -// -*- C++ -*- -//===-- test_unique.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - void - operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, - ForwardIt last2, Generator generator) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, - ForwardIt last2, Generator generator) - { - } - - template - void - operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, - ForwardIt last2, BinaryPred pred, Generator generator) - { - } - - template - void - operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2, - ForwardIt last2, BinaryPred pred, Generator generator) - { - } -#endif - - template - 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 - 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 -void -test(Generator generator, Predicate pred) -{ - const std::size_t max_size = 1000000; - Sequence in(max_size, [](size_t v) { return T(v); }); - Sequence exp(max_size, [](size_t v) { return T(v); }); - - for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) - { - invoke_on_all_policies(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 -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& x, const LocalWrapper& y) - { - return x.my_val == y.my_val; - } -}; - -template -struct test_non_const -{ - template - void - operator()(Policy&& exec, Iterator iter) - { - invoke_if(exec, [&]() { unique(exec, iter, iter, non_const(std::equal_to())); }); - } -}; - -int32_t -main() -{ -#if !__PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN - test([](size_t j) { return j / 3; }, - [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; }); - test([](size_t) { return float64_t(1); }, - [](const float64_t& val1, const float64_t& val2) { return val1 != val2; }); -#endif - test>([](size_t j) { return LocalWrapper(j); }, - [](const LocalWrapper& val1, const LocalWrapper& val2) { - return val1.my_val != val2.my_val; - }); - - test_algo_basic_single(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/test_unique_copy_equal.cpp =================================================================== --- pstl/trunk/test/test_unique_copy_equal.cpp +++ pstl/trunk/test/test_unique_copy_equal.cpp @@ -1,132 +0,0 @@ -// -*- C++ -*- -//===-- test_unique_copy_equal.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 "pstl_test_config.h" - -#include "pstl/execution" -#include "pstl/algorithm" -#include "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 - 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 - 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 - 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 -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 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 out(count, [=](size_t) { return trash; }); - Sequence 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 -struct test_non_const -{ - template - void - operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter) - { - unique_copy(exec, input_iter, input_iter, out_iter, non_const(std::equal_to())); - } -}; - -int32_t -main(int32_t argc, char* argv[]) -{ - test(Number(42, OddTag()), std::equal_to(), - [](int32_t j) { return Number(3 * j / 13 ^ (j & 8), OddTag()); }); - - test(float32_t(42), std::equal_to(), - [](int32_t j) { return float32_t(5 * j / 23 ^ (j / 7)); }); -#if !__PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN - test(float32_t(42), [](float32_t x, float32_t y) { return false; }, - [](int32_t j) { return float32_t(j); }, false); -#endif - - test_algo_basic_double(run_for_rnd_fw>()); - - std::cout << done() << std::endl; - return 0; -} Index: pstl/trunk/test/utils.h =================================================================== --- pstl/trunk/test/utils.h +++ pstl/trunk/test/utils.h @@ -1,1247 +0,0 @@ -// -*- C++ -*- -//===-- utils.h -----------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// File contains common utilities that tests rely on - -// Do not #include , because if we do we will not detect accidental dependencies. -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pstl_test_config.h" - -namespace TestUtils -{ - -typedef double float64_t; -typedef float float32_t; - -template -constexpr size_t -const_size(const T (&array)[N]) noexcept -{ - return N; -} - -template -class Sequence; - -// Handy macros for error reporting -#define EXPECT_TRUE(condition, message) ::TestUtils::expect(true, condition, __FILE__, __LINE__, message) -#define EXPECT_FALSE(condition, message) ::TestUtils::expect(false, condition, __FILE__, __LINE__, message) - -// Check that expected and actual are equal and have the same type. -#define EXPECT_EQ(expected, actual, message) ::TestUtils::expect_equal(expected, actual, __FILE__, __LINE__, message) - -// Check that sequences started with expected and actual and have had size n are equal and have the same type. -#define EXPECT_EQ_N(expected, actual, n, message) \ - ::TestUtils::expect_equal(expected, actual, n, __FILE__, __LINE__, message) - -// Issue error message from outstr, adding a newline. -// Real purpose of this routine is to have a place to hang a breakpoint. -inline void -issue_error_message(std::stringstream& outstr) -{ - outstr << std::endl; - std::cerr << outstr.str(); - std::exit(EXIT_FAILURE); -} - -inline void -expect(bool expected, bool condition, const char* file, int32_t line, const char* message) -{ - if (condition != expected) - { - std::stringstream outstr; - outstr << "error at " << file << ":" << line << " - " << message; - issue_error_message(outstr); - } -} - -// Do not change signature to const T&. -// Function must be able to detect const differences between expected and actual. -template -void -expect_equal(T& expected, T& actual, const char* file, int32_t line, const char* message) -{ - if (!(expected == actual)) - { - std::stringstream outstr; - outstr << "error at " << file << ":" << line << " - " << message << ", expected " << expected << " got " - << actual; - issue_error_message(outstr); - } -} - -template -void -expect_equal(Sequence& expected, Sequence& actual, const char* file, int32_t line, const char* message) -{ - size_t n = expected.size(); - size_t m = actual.size(); - if (n != m) - { - std::stringstream outstr; - outstr << "error at " << file << ":" << line << " - " << message << ", expected sequence of size " << n - << " got sequence of size " << m; - issue_error_message(outstr); - return; - } - size_t error_count = 0; - for (size_t k = 0; k < n && error_count < 10; ++k) - { - if (!(expected[k] == actual[k])) - { - std::stringstream outstr; - outstr << "error at " << file << ":" << line << " - " << message << ", at index " << k << " expected " - << expected[k] << " got " << actual[k]; - issue_error_message(outstr); - ++error_count; - } - } -} - -template -void -expect_equal(Iterator1 expected_first, Iterator2 actual_first, Size n, const char* file, int32_t line, - const char* message) -{ - size_t error_count = 0; - for (size_t k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first) - { - if (!(*expected_first == *actual_first)) - { - std::stringstream outstr; - outstr << "error at " << file << ":" << line << " - " << message << ", at index " << k; - issue_error_message(outstr); - ++error_count; - } - } -} - -// ForwardIterator is like type Iterator, but restricted to be a forward iterator. -// Only the forward iterator signatures that are necessary for tests are present. -// Post-increment in particular is deliberatly omitted since our templates should avoid using it -// because of efficiency considerations. -template -class ForwardIterator -{ - public: - typedef IteratorTag iterator_category; - typedef typename std::iterator_traits::value_type value_type; - typedef typename std::iterator_traits::difference_type difference_type; - typedef typename std::iterator_traits::pointer pointer; - typedef typename std::iterator_traits::reference reference; - - protected: - Iterator my_iterator; - typedef value_type element_type; - - public: - ForwardIterator() = default; - explicit ForwardIterator(Iterator i) : my_iterator(i) {} - reference operator*() const { return *my_iterator; } - Iterator operator->() const { return my_iterator; } - ForwardIterator - operator++() - { - ++my_iterator; - return *this; - } - ForwardIterator operator++(int32_t) - { - auto retval = *this; - my_iterator++; - return retval; - } - friend bool - operator==(const ForwardIterator& i, const ForwardIterator& j) - { - return i.my_iterator == j.my_iterator; - } - friend bool - operator!=(const ForwardIterator& i, const ForwardIterator& j) - { - return i.my_iterator != j.my_iterator; - } - - Iterator - iterator() const - { - return my_iterator; - } -}; - -template -class BidirectionalIterator : public ForwardIterator -{ - typedef ForwardIterator base_type; - - public: - BidirectionalIterator() = default; - explicit BidirectionalIterator(Iterator i) : base_type(i) {} - BidirectionalIterator(const base_type& i) : base_type(i.iterator()) {} - - BidirectionalIterator - operator++() - { - ++base_type::my_iterator; - return *this; - } - BidirectionalIterator - operator--() - { - --base_type::my_iterator; - return *this; - } - BidirectionalIterator operator++(int32_t) - { - auto retval = *this; - base_type::my_iterator++; - return retval; - } - BidirectionalIterator operator--(int32_t) - { - auto retval = *this; - base_type::my_iterator--; - return retval; - } -}; - -template -void -fill_data(Iterator first, Iterator last, F f) -{ - typedef typename std::iterator_traits::value_type T; - for (std::size_t i = 0; first != last; ++first, ++i) - { - *first = T(f(i)); - } -} - -// Sequence is a container of a sequence of T with lots of kinds of iterators. -// Prefixes on begin/end mean: -// c = "const" -// f = "forward" -// No prefix indicates non-const random-access iterator. -template -class Sequence -{ - std::vector m_storage; - - public: - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; - typedef ForwardIterator forward_iterator; - typedef ForwardIterator const_forward_iterator; - - typedef BidirectionalIterator bidirectional_iterator; - typedef BidirectionalIterator const_bidirectional_iterator; - - typedef T value_type; - explicit Sequence(size_t size) : m_storage(size) {} - - // Construct sequence [f(0), f(1), ... f(size-1)] - // f can rely on its invocations being sequential from 0 to size-1. - template - Sequence(size_t size, Func f) - { - m_storage.reserve(size); - // Use push_back because T might not have a default constructor - for (size_t k = 0; k < size; ++k) - m_storage.push_back(T(f(k))); - } - Sequence(const std::initializer_list& data) : m_storage(data) {} - - const_iterator - begin() const - { - return m_storage.begin(); - } - const_iterator - end() const - { - return m_storage.end(); - } - iterator - begin() - { - return m_storage.begin(); - } - iterator - end() - { - return m_storage.end(); - } - const_iterator - cbegin() const - { - return m_storage.cbegin(); - } - const_iterator - cend() const - { - return m_storage.cend(); - } - forward_iterator - fbegin() - { - return forward_iterator(m_storage.begin()); - } - forward_iterator - fend() - { - return forward_iterator(m_storage.end()); - } - const_forward_iterator - cfbegin() const - { - return const_forward_iterator(m_storage.cbegin()); - } - const_forward_iterator - cfend() const - { - return const_forward_iterator(m_storage.cend()); - } - const_forward_iterator - fbegin() const - { - return const_forward_iterator(m_storage.cbegin()); - } - const_forward_iterator - fend() const - { - return const_forward_iterator(m_storage.cend()); - } - - const_bidirectional_iterator - cbibegin() const - { - return const_bidirectional_iterator(m_storage.cbegin()); - } - const_bidirectional_iterator - cbiend() const - { - return const_bidirectional_iterator(m_storage.cend()); - } - - bidirectional_iterator - bibegin() - { - return bidirectional_iterator(m_storage.begin()); - } - bidirectional_iterator - biend() - { - return bidirectional_iterator(m_storage.end()); - } - - std::size_t - size() const - { - return m_storage.size(); - } - const T* - data() const - { - return m_storage.data(); - } - typename std::vector::reference operator[](size_t j) { return m_storage[j]; } - const T& operator[](size_t j) const { return m_storage[j]; } - - // Fill with given value - void - fill(const T& value) - { - for (size_t i = 0; i < m_storage.size(); i++) - m_storage[i] = value; - } - - void - print() const; - - template - void - fill(Func f) - { - fill_data(m_storage.begin(), m_storage.end(), f); - } -}; - -template -void -Sequence::print() const -{ - std::cout << "size = " << size() << ": { "; - std::copy(begin(), end(), std::ostream_iterator(std::cout, " ")); - std::cout << " } " << std::endl; -} - -// Predicates for algorithms -template -struct is_equal_to -{ - is_equal_to(const DataType& expected) : m_expected(expected) {} - bool - operator()(const DataType& actual) const - { - return actual == m_expected; - } - - private: - DataType m_expected; -}; - -// Low-quality hash function, returns value between 0 and (1<= 8 * sizeof(size_t) ? ~size_t(0) : (size_t(1) << bits) - 1; - return (424157 * i ^ 0x24aFa) & mask; -} - -// Stateful unary op -template -class Complement -{ - int32_t val; - - public: - Complement(T v) : val(v) {} - U - operator()(const T& x) const - { - return U(val - x); - } -}; - -// Tag used to prevent accidental use of converting constructor, even if use is explicit. -struct OddTag -{ -}; - -class Sum; - -// Type with limited set of operations. Not default-constructible. -// Only available operator is "==". -// Typically used as value type in tests. -class Number -{ - int32_t value; - friend class Add; - friend class Sum; - friend class IsMultiple; - friend class Congruent; - friend Sum - operator+(const Sum& x, const Sum& y); - - public: - Number(int32_t val, OddTag) : value(val) {} - friend bool - operator==(const Number& x, const Number& y) - { - return x.value == y.value; - } - friend std::ostream& - operator<<(std::ostream& o, const Number& d) - { - return o << d.value; - } -}; - -// Stateful predicate for Number. Not default-constructible. -class IsMultiple -{ - long modulus; - - public: - // True if x is multiple of modulus - bool - operator()(Number x) const - { - return x.value % modulus == 0; - } - IsMultiple(long modulus_, OddTag) : modulus(modulus_) {} -}; - -// Stateful equivalence-class predicate for Number. Not default-constructible. -class Congruent -{ - long modulus; - - public: - // True if x and y have same remainder for the given modulus. - // Note: this is not quite the same as "equivalent modulo modulus" when x and y have different - // sign, but nonetheless AreCongruent is still an equivalence relationship, which is all - // we need for testing. - bool - operator()(Number x, Number y) const - { - return x.value % modulus == y.value % modulus; - } - Congruent(long modulus_, OddTag) : modulus(modulus_) {} -}; - -// Stateful reduction operation for Number -class Add -{ - long bias; - - public: - explicit Add(OddTag) : bias(1) {} - Number - operator()(Number x, const Number& y) - { - return Number(x.value + y.value + (bias - 1), OddTag()); - } -}; - -// Class similar to Number, but has default constructor and +. -class Sum : public Number -{ - public: - Sum() : Number(0, OddTag()) {} - Sum(long x, OddTag) : Number(x, OddTag()) {} - friend Sum - operator+(const Sum& x, const Sum& y) - { - return Sum(x.value + y.value, OddTag()); - } -}; - -// Type with limited set of operations, which includes an associative but not commutative operation. -// Not default-constructible. -// Typically used as value type in tests involving "GENERALIZED_NONCOMMUTATIVE_SUM". -class MonoidElement -{ - size_t a, b; - - public: - MonoidElement(size_t a_, size_t b_, OddTag) : a(a_), b(b_) {} - friend bool - operator==(const MonoidElement& x, const MonoidElement& y) - { - return x.a == y.a && x.b == y.b; - } - friend std::ostream& - operator<<(std::ostream& o, const MonoidElement& x) - { - return o << "[" << x.a << ".." << x.b << ")"; - } - friend class AssocOp; -}; - -// Stateful associative op for MonoidElement -// It's not really a monoid since the operation is not allowed for any two elements. -// But it's good enough for testing. -class AssocOp -{ - unsigned c; - - public: - explicit AssocOp(OddTag) : c(5) {} - MonoidElement - operator()(const MonoidElement& x, const MonoidElement& y) - { - unsigned d = 5; - EXPECT_EQ(d, c, "state lost"); - EXPECT_EQ(x.b, y.a, "commuted?"); - - return MonoidElement(x.a, y.b, OddTag()); - } -}; - -// Multiplication of matrix is an associative but not commutative operation -// Typically used as value type in tests involving "GENERALIZED_NONCOMMUTATIVE_SUM". -template -struct Matrix2x2 -{ - T a[2][2]; - Matrix2x2() : a{{1, 0}, {0, 1}} {} - Matrix2x2(T x, T y) : a{{0, x}, {x, y}} {} -#if !__PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN - Matrix2x2(const Matrix2x2& m) : a{{m.a[0][0], m.a[0][1]}, {m.a[1][0], m.a[1][1]}} {} - Matrix2x2& - operator=(const Matrix2x2& m) - { - a[0][0] = m.a[0][0], a[0][1] = m.a[0][1], a[1][0] = m.a[1][0], a[1][1] = m.a[1][1]; - return *this; - } -#endif -}; - -template -bool -operator==(const Matrix2x2& left, const Matrix2x2& right) -{ - return left.a[0][0] == right.a[0][0] && left.a[0][1] == right.a[0][1] && left.a[1][0] == right.a[1][0] && - left.a[1][1] == right.a[1][1]; -} - -template -Matrix2x2 -multiply_matrix(const Matrix2x2& left, const Matrix2x2& right) -{ - Matrix2x2 result; - for (int32_t i = 0; i < 2; ++i) - { - for (int32_t j = 0; j < 2; ++j) - { - result.a[i][j] = left.a[i][0] * right.a[0][j] + left.a[i][1] * right.a[1][j]; - } - } - return result; -} - -// Check that Intel(R) Threading Building Blocks header files are not used when parallel policies are off -#if !__PSTL_USE_PAR_POLICIES -#if defined(TBB_INTERFACE_VERSION) -#error The parallel backend is used while it should not (__PSTL_USE_PAR_POLICIES==0) -#endif -#endif - -//============================================================================ -// Adapters for creating different types of iterators. -// -// In this block we implemented some adapters for creating differnet types of iterators. -// It's needed for extending the unit testing of Parallel STL algorithms. -// We have adapters for iterators with different tags (forward_iterator_tag, bidirectional_iterator_tag), reverse iterators. -// The input iterator should be const or non-const, non-reverse random access iterator. -// Iterator creates in "MakeIterator": -// firstly, iterator is "packed" by "IteratorTypeAdapter" (creating forward or bidirectional iterator) -// then iterator is "packed" by "ReverseAdapter" (if it's possible) -// So, from input iterator we may create, for example, reverse bidirectional iterator. -// "Main" functor for testing iterators is named "invoke_on_all_iterator_types". - -// Base adapter -template -struct BaseAdapter -{ - typedef Iterator iterator_type; - iterator_type - operator()(Iterator it) - { - return it; - } -}; - -// Check if the iterator is reverse iterator -// Note: it works only for iterators that created by std::reverse_iterator -template -struct isReverse : std::false_type -{ -}; - -template -struct isReverse> : std::true_type -{ -}; - -// Reverse adapter -template -struct ReverseAdapter -{ - typedef std::reverse_iterator iterator_type; - iterator_type - operator()(Iterator it) - { -#if __PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT - return std::make_reverse_iterator(it); -#else - return iterator_type(it); -#endif - } -}; - -// Non-reverse adapter -template -struct ReverseAdapter : BaseAdapter -{ -}; - -// Iterator adapter by type (by default std::random_access_iterator_tag) -template -struct IteratorTypeAdapter : BaseAdapter -{ -}; - -// Iterator adapter for forward iterator -template -struct IteratorTypeAdapter -{ - typedef ForwardIterator iterator_type; - iterator_type - operator()(Iterator it) - { - return iterator_type(it); - } -}; - -// Iterator adapter for bidirectional iterator -template -struct IteratorTypeAdapter -{ - typedef BidirectionalIterator iterator_type; - iterator_type - operator()(Iterator it) - { - return iterator_type(it); - } -}; - -//For creating iterator with new type -template -struct MakeIterator -{ - typedef IteratorTypeAdapter IterByType; - typedef ReverseAdapter ReverseIter; - - typename ReverseIter::iterator_type - operator()(InputIterator it) - { - return ReverseIter()(IterByType()(it)); - } -}; - -// Useful constant variables -constexpr std::size_t GuardSize = 5; -constexpr std::ptrdiff_t sizeLimit = 1000; - -template // local iterator_traits for non-iterators -struct iterator_traits_ -{ -}; - -template // For iterators -struct iterator_traits_::value, void>::type> -{ - typedef typename Iter::iterator_category iterator_category; -}; - -template // For pointers -struct iterator_traits_ -{ - typedef std::random_access_iterator_tag iterator_category; -}; - -// is iterator Iter has tag Tag -template -using is_same_iterator_category = std::is_same::iterator_category, Tag>; - -// if we run with reverse or const iterators we shouldn't test the large range -template -struct invoke_if_ -{ - template - void - operator()(bool is_allow, Op op, Rest&&... rest) - { - if (is_allow) - op(std::forward(rest)...); - } -}; -template <> -struct invoke_if_ -{ - template - void - operator()(bool is_allow, Op op, Rest&&... rest) - { - op(std::forward(rest)...); - } -}; - -// Base non_const_wrapper struct. It is used to distinguish non_const testcases -// from a regular one. For non_const testcases only compilation is checked. -struct non_const_wrapper -{ -}; - -// Generic wrapper to specify iterator type to execute callable Op on. -// The condition can be either positive(Op is executed only with IteratorTag) -// or negative(Op is executed with every type of iterators except IteratorTag) -template -struct non_const_wrapper_tagged : non_const_wrapper -{ - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator iter) - { - Op()(exec, iter); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) - { - Op()(exec, input_iter, out_iter); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Iterator iter) - { - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, InputIterator input_iter, OutputIterator out_iter) - { - } -}; - -// These run_for_* structures specify with which types of iterators callable object Op -// should be executed. -template -struct run_for_rnd : non_const_wrapper_tagged -{ -}; - -template -struct run_for_rnd_bi : non_const_wrapper_tagged -{ -}; - -template -struct run_for_rnd_fw : non_const_wrapper_tagged -{ -}; - -// Invoker for different types of iterators. -template -struct iterator_invoker -{ - template - using make_iterator = MakeIterator; - template - using IsConst = typename std::is_const< - typename std::remove_pointer::pointer>::type>::type; - template - using invoke_if = invoke_if_>; - - // A single iterator version which is used for non_const testcases - template - typename std::enable_if::value && - std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, Iterator iter) - { - op(std::forward(exec), make_iterator()(iter)); - } - - // A version with 2 iterators which is used for non_const testcases - template - typename std::enable_if::value && - std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator input_iter, OutputIterator out_iter) - { - op(std::forward(exec), make_iterator()(input_iter), - make_iterator()(out_iter)); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Op op, Iterator begin, Size n, Rest&&... rest) - { - invoke_if()(n <= sizeLimit, op, exec, make_iterator()(begin), n, - std::forward(rest)...); - } - - template - typename std::enable_if::value && - !std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, Iterator inputBegin, Iterator inputEnd, Rest&&... rest) - { - invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, - make_iterator()(inputBegin), make_iterator()(inputEnd), - std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, - Rest&&... rest) - { - invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, - make_iterator()(inputBegin), make_iterator()(inputEnd), - make_iterator()(outputBegin), std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, - OutputIterator outputEnd, Rest&&... rest) - { - invoke_if()(std::distance(inputBegin, inputEnd) <= sizeLimit, op, exec, - make_iterator()(inputBegin), make_iterator()(inputEnd), - make_iterator()(outputBegin), - make_iterator()(outputEnd), std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator1 inputBegin1, InputIterator1 inputEnd1, InputIterator2 inputBegin2, - InputIterator2 inputEnd2, OutputIterator outputBegin, OutputIterator outputEnd, Rest&&... rest) - { - invoke_if()( - std::distance(inputBegin1, inputEnd1) <= sizeLimit, op, exec, make_iterator()(inputBegin1), - make_iterator()(inputEnd1), make_iterator()(inputBegin2), - make_iterator()(inputEnd2), make_iterator()(outputBegin), - make_iterator()(outputEnd), std::forward(rest)...); - } -}; - -// Invoker for reverse iterators only -// Note: if we run with reverse iterators we shouldn't test the large range -template -struct iterator_invoker -{ - - template - using make_iterator = MakeIterator; - - // A single iterator version which is used for non_const testcases - template - typename std::enable_if::value && - std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, Iterator iter) - { - op(std::forward(exec), make_iterator()(iter)); - } - - // A version with 2 iterators which is used for non_const testcases - template - typename std::enable_if::value && - std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator input_iter, OutputIterator out_iter) - { - op(std::forward(exec), make_iterator()(input_iter), - make_iterator()(out_iter)); - } - - template - typename std::enable_if::value, void>::type - operator()(Policy&& exec, Op op, Iterator begin, Size n, Rest&&... rest) - { - if (n <= sizeLimit) - op(exec, make_iterator()(begin + n), n, std::forward(rest)...); - } - - template - typename std::enable_if::value && - !std::is_base_of::value, - void>::type - operator()(Policy&& exec, Op op, Iterator inputBegin, Iterator inputEnd, Rest&&... rest) - { - if (std::distance(inputBegin, inputEnd) <= sizeLimit) - op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), - std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, - Rest&&... rest) - { - if (std::distance(inputBegin, inputEnd) <= sizeLimit) - op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), - make_iterator()(outputBegin + (inputEnd - inputBegin)), std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator inputBegin, InputIterator inputEnd, OutputIterator outputBegin, - OutputIterator outputEnd, Rest&&... rest) - { - if (std::distance(inputBegin, inputEnd) <= sizeLimit) - op(exec, make_iterator()(inputEnd), make_iterator()(inputBegin), - make_iterator()(outputEnd), make_iterator()(outputBegin), - std::forward(rest)...); - } - - template - typename std::enable_if::value, - void>::type - operator()(Policy&& exec, Op op, InputIterator1 inputBegin1, InputIterator1 inputEnd1, InputIterator2 inputBegin2, - InputIterator2 inputEnd2, OutputIterator outputBegin, OutputIterator outputEnd, Rest&&... rest) - { - if (std::distance(inputBegin1, inputEnd1) <= sizeLimit) - op(exec, make_iterator()(inputEnd1), make_iterator()(inputBegin1), - make_iterator()(inputEnd2), make_iterator()(inputBegin2), - make_iterator()(outputEnd), make_iterator()(outputBegin), - std::forward(rest)...); - } -}; - -// We can't create reverse iterator from forward iterator -template <> -struct iterator_invoker -{ - template - void - operator()(Rest&&... rest) - { - } -}; - -template -struct reverse_invoker -{ - template - void - operator()(Rest&&... rest) - { - // Random-access iterator - iterator_invoker()(std::forward(rest)...); - - // Forward iterator - iterator_invoker()(std::forward(rest)...); - - // Bidirectional iterator - iterator_invoker()(std::forward(rest)...); - } -}; - -struct invoke_on_all_iterator_types -{ - template - void - operator()(Rest&&... rest) - { - reverse_invoker()(std::forward(rest)...); - reverse_invoker()(std::forward(rest)...); - } -}; -//============================================================================ - -// Invoke op(policy,rest...) for each possible policy. -template -void -invoke_on_all_policies(Op op, T&&... rest) -{ - using namespace __pstl::execution; - - // Try static execution policies - invoke_on_all_iterator_types()(seq, op, std::forward(rest)...); - invoke_on_all_iterator_types()(unseq, op, std::forward(rest)...); -#if __PSTL_USE_PAR_POLICIES - invoke_on_all_iterator_types()(par, op, std::forward(rest)...); - invoke_on_all_iterator_types()(par_unseq, op, std::forward(rest)...); -#endif -} - -template -struct NonConstAdapter -{ - F my_f; - NonConstAdapter(const F& f) : my_f(f) {} - - template - auto - operator()(Types&&... args) -> decltype(std::declval(). - operator()(std::forward(args)...)) - { - return my_f(std::forward(args)...); - } -}; - -template -NonConstAdapter -non_const(const F& f) -{ - return NonConstAdapter(f); -} - -// Wrapper for types. It's need for counting of constructing and destructing objects -template -class Wrapper -{ - public: - Wrapper() - { - my_field = std::shared_ptr(new T()); - ++my_count; - } - Wrapper(const T& input) - { - my_field = std::shared_ptr(new T(input)); - ++my_count; - } - Wrapper(const Wrapper& input) - { - my_field = input.my_field; - ++my_count; - } - Wrapper(Wrapper&& input) - { - my_field = input.my_field; - input.my_field = nullptr; - ++move_count; - } - Wrapper& - operator=(const Wrapper& input) - { - my_field = input.my_field; - return *this; - } - Wrapper& - operator=(Wrapper&& input) - { - my_field = input.my_field; - input.my_field = nullptr; - ++move_count; - return *this; - } - bool - operator==(const Wrapper& input) const - { - return my_field == input.my_field; - } - bool - operator<(const Wrapper& input) const - { - return *my_field < *input.my_field; - } - bool - operator>(const Wrapper& input) const - { - return *my_field > *input.my_field; - } - friend std::ostream& - operator<<(std::ostream& stream, const Wrapper& input) - { - return stream << *(input.my_field); - } - ~Wrapper() - { - --my_count; - if (move_count > 0) - { - --move_count; - } - } - T* - get_my_field() const - { - return my_field.get(); - }; - static size_t - Count() - { - return my_count; - } - static size_t - MoveCount() - { - return move_count; - } - static void - SetCount(const size_t& n) - { - my_count = n; - } - static void - SetMoveCount(const size_t& n) - { - move_count = n; - } - - private: - static std::atomic my_count; - static std::atomic move_count; - std::shared_ptr my_field; -}; - -template -std::atomic Wrapper::my_count = {0}; - -template -std::atomic Wrapper::move_count = {0}; - -template -T -transform_reduce_serial(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, - UnaryOperation unary_op) noexcept -{ - for (; first != last; ++first) - { - init = binary_op(init, unary_op(*first)); - } - return init; -} - -static const char* -done() -{ -#if __PSTL_TEST_SUCCESSFUL_KEYWORD - return "done"; -#else - return "passed"; -#endif -} - -// test_algo_basic_* functions are used to execute -// f on a very basic sequence of elements of type T. - -// Should be used with unary predicate -template -static void -test_algo_basic_single(F&& f) -{ - size_t N = 10; - Sequence in(N, [](size_t v) -> T { return T(v); }); - - invoke_on_all_policies(f, in.begin()); -} - -// Should be used with binary predicate -template -static void -test_algo_basic_double(F&& f) -{ - size_t N = 10; - Sequence in(N, [](size_t v) -> T { return T(v); }); - Sequence out(N, [](size_t v) -> T { return T(v); }); - - invoke_on_all_policies(f, in.begin(), out.begin()); -} - -template -static void -invoke_if(Policy&& p, F f) -{ -#if __PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || __PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN - __pstl::internal::invoke_if_not(__pstl::internal::allow_unsequenced(), f); -#else - f(); -#endif -} - -} /* namespace TestUtils */