| // -*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // UNSUPPORTED: c++03, c++11, c++14 |
| |
| // Tests for is_heap, is_heap_until |
| #include "support/pstl_test_config.h" |
| |
| #include <execution> |
| #include <algorithm> |
| |
| #include "support/utils.h" |
| #include <iostream> |
| |
| using namespace TestUtils; |
| |
| struct WithCmpOp |
| { |
| int32_t _first; |
| int32_t _second; |
| WithCmpOp() : _first(0), _second(0){}; |
| explicit WithCmpOp(int32_t x) : _first(x), _second(x){}; |
| bool |
| operator<(const WithCmpOp& rhs) const |
| { |
| return this->_first < rhs._first; |
| } |
| }; |
| |
| struct test_is_heap |
| { |
| #if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || \ |
| _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration |
| template <typename Iterator, typename Predicate> |
| typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type |
| operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred) |
| { |
| } |
| template <typename Iterator, typename Predicate> |
| typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type |
| operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred) |
| { |
| } |
| #endif |
| |
| template <typename Policy, typename Iterator, typename Predicate> |
| typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type |
| operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred) |
| { |
| using namespace std; |
| // is_heap |
| { |
| bool expected = is_heap(first, last); |
| bool actual = is_heap(exec, first, last); |
| EXPECT_TRUE(expected == actual, "wrong return value from is_heap"); |
| } |
| // is_heap with predicate |
| { |
| bool expected = is_heap(first, last, pred); |
| bool actual = is_heap(exec, first, last, pred); |
| EXPECT_TRUE(expected == actual, "wrong return value from is_heap with predicate"); |
| } |
| // is_heap_until |
| { |
| Iterator expected = is_heap_until(first, last); |
| Iterator actual = is_heap_until(exec, first, last); |
| EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until"); |
| } |
| // is_heap_until with predicate |
| { |
| const Iterator expected = is_heap_until(first, last, pred); |
| const auto y = std::distance(first, expected); |
| const Iterator actual = is_heap_until(exec, first, last, pred); |
| const auto x = std::distance(first, actual); |
| EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate"); |
| EXPECT_EQ(x, y, "both iterators should be the same distance away from 'first'"); |
| } |
| } |
| |
| // is_heap, is_heap_until works only with random access iterators |
| template <typename Policy, typename Iterator, typename Predicate> |
| typename std::enable_if<!is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type |
| operator()(Policy&&, Iterator, Iterator, Predicate) |
| { |
| } |
| }; |
| |
| template <typename T, typename Comp> |
| void |
| test_is_heap_by_type(Comp comp) |
| { |
| using namespace std; |
| |
| const size_t max_size = 100000; |
| for (size_t n = 0; n <= max_size; n = n <= 16 ? n + 1 : size_t(3.1415 * n)) |
| { |
| Sequence<T> in(n, [](size_t v) -> T { return T(v); }); |
| |
| invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); |
| |
| std::make_heap(in.begin(), in.begin() + n / 4, comp); |
| invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); |
| |
| std::make_heap(in.begin(), in.begin() + n / 3, comp); |
| invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); |
| |
| std::make_heap(in.begin(), in.end(), comp); |
| invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp); |
| } |
| |
| Sequence<T> in(max_size / 10, [](size_t) -> T { return T(1); }); |
| invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp); |
| } |
| |
| template <typename T> |
| struct test_non_const |
| { |
| template <typename Policy, typename Iterator> |
| void |
| operator()(Policy&& exec, Iterator iter) |
| { |
| invoke_if(exec, [&]() { |
| is_heap(exec, iter, iter, non_const(std::less<T>())); |
| is_heap_until(exec, iter, iter, non_const(std::less<T>())); |
| }); |
| } |
| }; |
| |
| int |
| main() |
| { |
| test_is_heap_by_type<float32_t>(std::greater<float32_t>()); |
| test_is_heap_by_type<WithCmpOp>(std::less<WithCmpOp>()); |
| test_is_heap_by_type<uint64_t>([](uint64_t x, uint64_t y) { return x % 100 < y % 100; }); |
| |
| test_algo_basic_single<int32_t>(run_for_rnd<test_non_const<int32_t>>()); |
| |
| std::cout << done() << std::endl; |
| return 0; |
| } |