2 //===-- inplace_merge.pass.cpp --------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++03, c++11, c++14
12 #include "support/pstl_test_config.h"
17 #include "support/utils.h"
19 using namespace TestUtils
;
21 struct test_one_policy
23 #if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || \
24 defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
25 template <typename BiDirIt1
, typename Size
, typename Generator1
, typename Generator2
, typename Compare
>
27 operator()(pstl::execution::unsequenced_policy
, BiDirIt1 first1
, BiDirIt1 last1
, BiDirIt1 first2
, BiDirIt1 last2
,
28 Size n
, Size m
, Generator1 generator1
, Generator2 generator2
, Compare comp
)
32 template <typename BiDirIt1
, typename Size
, typename Generator1
, typename Generator2
, typename Compare
>
34 operator()(pstl::execution::parallel_unsequenced_policy
, BiDirIt1 first1
, BiDirIt1 last1
, BiDirIt1 first2
,
35 BiDirIt1 last2
, Size n
, Size m
, Generator1 generator1
, Generator2 generator2
, Compare comp
)
40 // inplace_merge works with bidirectional iterators at least
41 template <typename Policy
, typename BiDirIt1
, typename Size
, typename Generator1
, typename Generator2
,
43 typename
std::enable_if
<!is_same_iterator_category
<BiDirIt1
, std::forward_iterator_tag
>::value
, void>::type
44 operator()(Policy
&& exec
, BiDirIt1 first1
, BiDirIt1 last1
, BiDirIt1 first2
, BiDirIt1 last2
, Size n
, Size m
,
45 Generator1 generator1
, Generator2 generator2
, Compare comp
)
47 const BiDirIt1 mid1
= std::next(first1
, m
);
48 fill_data(first1
, mid1
, generator1
);
49 fill_data(mid1
, last1
, generator2
);
51 const BiDirIt1 mid2
= std::next(first2
, m
);
52 fill_data(first2
, mid2
, generator1
);
53 fill_data(mid2
, last2
, generator2
);
55 std::inplace_merge(first1
, mid1
, last1
, comp
);
56 std::inplace_merge(exec
, first2
, mid2
, last2
, comp
);
57 EXPECT_EQ_N(first1
, first2
, n
, "wrong effect from inplace_merge with predicate");
60 template <typename Policy
, typename BiDirIt1
, typename Size
, typename Generator1
, typename Generator2
,
62 typename
std::enable_if
<is_same_iterator_category
<BiDirIt1
, std::forward_iterator_tag
>::value
, void>::type
63 operator()(Policy
&&, BiDirIt1
, BiDirIt1
, BiDirIt1
, BiDirIt1
, Size
, Size
, Generator1
, Generator2
, Compare
)
68 template <typename T
, typename Generator1
, typename Generator2
, typename Compare
>
70 test_by_type(Generator1 generator1
, Generator2 generator2
, Compare comp
)
73 size_t max_size
= 100000;
74 Sequence
<T
> in1(max_size
, [](size_t v
) { return T(v
); });
75 Sequence
<T
> exp(max_size
, [](size_t v
) { return T(v
); });
78 for (size_t n
= 0; n
<= max_size
; n
= n
<= 16 ? n
+ 1 : size_t(3.1415 * n
))
81 invoke_on_all_policies(test_one_policy(), in1
.begin(), in1
.begin() + n
, exp
.begin(), exp
.begin() + n
, n
, m
,
82 generator1
, generator2
, comp
);
85 invoke_on_all_policies(test_one_policy(), in1
.begin(), in1
.begin() + n
, exp
.begin(), exp
.begin() + n
, n
, m
,
86 generator1
, generator2
, comp
);
89 invoke_on_all_policies(test_one_policy(), in1
.begin(), in1
.begin() + n
, exp
.begin(), exp
.begin() + n
, n
, m
,
90 generator1
, generator2
, comp
);
97 explicit LocalWrapper(int32_t k
) : my_val(k
) {}
98 LocalWrapper(LocalWrapper
&& input
) { my_val
= std::move(input
.my_val
); }
100 operator=(LocalWrapper
&& input
)
102 my_val
= std::move(input
.my_val
);
106 operator<(const LocalWrapper
<T
>& w
) const
108 return my_val
< w
.my_val
;
111 operator==(const LocalWrapper
<T
>& x
, const LocalWrapper
<T
>& y
)
113 return x
.my_val
== y
.my_val
;
116 operator<<(std::ostream
& stream
, const LocalWrapper
<T
>& input
)
118 return stream
<< input
.my_val
;
125 template <typename T
>
126 struct test_non_const
128 template <typename Policy
, typename Iterator
>
130 operator()(Policy
&& exec
, Iterator iter
)
132 invoke_if(exec
, [&]() { inplace_merge(exec
, iter
, iter
, iter
, non_const(std::less
<T
>())); });
139 test_by_type
<float64_t
>([](int32_t i
) { return -2 * i
; }, [](int32_t i
) { return -(2 * i
+ 1); },
140 [](const float64_t x
, const float64_t y
) { return x
> y
; });
142 test_by_type
<int32_t>([](int32_t i
) { return 10 * i
; }, [](int32_t i
) { return i
+ 1; }, std::less
<int32_t>());
144 test_by_type
<LocalWrapper
<float32_t
>>([](int32_t i
) { return LocalWrapper
<float32_t
>(2 * i
+ 1); },
145 [](int32_t i
) { return LocalWrapper
<float32_t
>(2 * i
); },
146 std::less
<LocalWrapper
<float32_t
>>());
148 test_algo_basic_single
<int32_t>(run_for_rnd_bi
<test_non_const
<int32_t>>());
150 test_by_type
<MemoryChecker
>(
151 [](std::size_t idx
){ return MemoryChecker
{std::int32_t(idx
* 2)}; },
152 [](std::size_t idx
){ return MemoryChecker
{std::int32_t(idx
* 2 + 1)}; },
153 [](const MemoryChecker
& val1
, const MemoryChecker
& val2
){ return val1
.value() == val2
.value(); });
154 EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from inplace_merge: number of ctors calls < num of dtors calls");
155 EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from inplace_merge: number of ctors calls > num of dtors calls");
157 std::cout
<< done() << std::endl
;