1 // -*- C++ -*-
2 // { dg-options "-std=gnu++17 -ltbb" }
3 // { dg-do run { target c++17 } }
4 // { dg-timeout-factor 3 }
5 // { dg-require-effective-target tbb-backend }
6 
7 //===-- swap_ranges.pass.cpp ----------------------------------------------===//
8 //
9 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10 // See https://llvm.org/LICENSE.txt for license information.
11 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "pstl/pstl_test_config.h"
16 
17 #ifdef PSTL_STANDALONE_TESTS
18 #include <iterator>
19 
20 #include "pstl/execution"
21 #include "pstl/algorithm"
22 #else
23 #include <execution>
24 #include <algorithm>
25 #endif // PSTL_STANDALONE_TESTS
26 
27 #include "pstl/test_utils.h"
28 
29 using namespace TestUtils;
30 
31 template <typename T>
32 struct wrapper
33 {
34     T t;
35     std::size_t number_of_swaps = 0;
wrapperwrapper36     wrapper() {}
wrapperwrapper37     explicit wrapper(T t_) : t(t_) {}
38     template <typename U>
39     void
operator =wrapper40     operator=(const U& b)
41     {
42         t = b;
43     }
44     bool
operator ==wrapper45     operator==(const wrapper<T>& a) const
46     {
47         return t == a.t;
48     }
49 };
50 
51 template <typename T>
52 void
swap(wrapper<T> & a,wrapper<T> & b)53 swap(wrapper<T>& a, wrapper<T>& b)
54 {
55     std::swap(a.t, b.t);
56     a.number_of_swaps++;
57     b.number_of_swaps++;
58 }
59 
60 template <typename T>
61 struct check_swap
62 {
63     bool
operator ()check_swap64     operator()(T& a)
65     {
66         return true;
67     }
68 };
69 
70 template <typename T>
71 struct check_swap<wrapper<T>>
72 {
73     bool
operator ()check_swap74     operator()(wrapper<T>& a)
75     {
76         bool temp = (a.number_of_swaps == 1);
77         a.number_of_swaps = 0;
78         return temp;
79     }
80 };
81 
82 struct test_one_policy
83 {
84     template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
85     void
operator ()test_one_policy86     operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e)
87     {
88         using namespace std;
89         using T_ref = typename iterator_traits<Iterator1>::reference;
90         using T = typename iterator_traits<Iterator1>::value_type;
91 
92         iota(data_b, data_e, 0);
93         iota(actual_b, actual_e, std::distance(data_b, data_e));
94 
95         Iterator2 actual_return = swap_ranges(exec, data_b, data_e, actual_b);
96         bool check_return = (actual_return == actual_e);
97         EXPECT_TRUE(check_return, "wrong result of swap_ranges");
98         if (check_return)
99         {
100             std::size_t i = 0;
101             bool check = all_of(actual_b, actual_e, [&i](T_ref a) { return a == T(i++); }) &&
102                          all_of(data_b, data_e, [&i](T_ref a) { return a == T(i++); });
103 
104             EXPECT_TRUE(check, "wrong effect of swap_ranges");
105 
106             if (check)
107             {
108                 bool swap_check =
109                     all_of(data_b, data_e, check_swap<T>()) && all_of(actual_b, actual_e, check_swap<T>());
110                 EXPECT_TRUE(swap_check, "wrong effect of swap_ranges swap check");
111             }
112         }
113     }
114 };
115 
116 template <typename T>
117 void
test()118 test()
119 {
120     const std::size_t max_len = 100000;
121 
122     Sequence<T> data(max_len);
123     Sequence<T> actual(max_len);
124 
125     for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
126     {
127         invoke_on_all_policies(test_one_policy(), data.begin(), data.begin() + len, actual.begin(),
128                                actual.begin() + len);
129     }
130 }
131 
132 int32_t
main()133 main()
134 {
135     test<wrapper<uint16_t>>();
136     test<wrapper<float64_t>>();
137     test<int32_t>();
138     test<float32_t>();
139 
140     std::cout << done() << std::endl;
141     return 0;
142 }
143