]>
Commit | Line | Data |
---|---|---|
a945c346 | 1 | // Copyright (C) 2020-2024 Free Software Foundation, Inc. |
02e32295 MK |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | // | |
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
aa89c53c | 18 | // expensive: * [1-9] * * |
073df3e7 | 19 | #include "bits/main.h" |
02e32295 MK |
20 | |
21 | using std::experimental::simd_cast; | |
22 | ||
23 | template <typename V, bool ConstProp, typename F> | |
24 | auto | |
25 | gen(const F& fun) | |
26 | { | |
27 | if constexpr (ConstProp) | |
28 | return V(fun); | |
29 | else | |
30 | return make_value_unknown(V(fun)); | |
31 | } | |
32 | ||
33 | template <typename V, bool ConstProp> | |
34 | void | |
35 | split_concat() | |
36 | { | |
37 | using T = typename V::value_type; | |
38 | if constexpr (V::size() * 3 | |
39 | <= std::experimental::simd_abi::max_fixed_size<T>) | |
40 | { | |
41 | V a(0), b(1), c(2); | |
42 | auto x = concat(a, b, c); | |
43 | COMPARE(x.size(), a.size() * 3); | |
44 | std::size_t i = 0; | |
45 | for (; i < a.size(); ++i) | |
46 | { | |
47 | COMPARE(x[i], T(0)); | |
48 | } | |
49 | for (; i < 2 * a.size(); ++i) | |
50 | { | |
51 | COMPARE(x[i], T(1)); | |
52 | } | |
53 | for (; i < 3 * a.size(); ++i) | |
54 | { | |
55 | COMPARE(x[i], T(2)); | |
56 | } | |
57 | } | |
58 | ||
59 | if constexpr (V::size() >= 4) | |
60 | { | |
61 | const V a = gen<V, ConstProp>([](auto i) -> T { return i; }); | |
62 | constexpr auto N0 = V::size() / 4u; | |
63 | constexpr auto N1 = V::size() - 2 * N0; | |
64 | using V0 = std::experimental::simd< | |
65 | T, std::experimental::simd_abi::deduce_t<T, N0>>; | |
66 | using V1 = std::experimental::simd< | |
67 | T, std::experimental::simd_abi::deduce_t<T, N1>>; | |
68 | { | |
69 | auto x = std::experimental::split<N0, N0, N1>(a); | |
70 | COMPARE(std::tuple_size<decltype(x)>::value, 3u); | |
71 | COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; })); | |
72 | COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N0; })); | |
73 | COMPARE(std::get<2>(x), V1([](auto i) -> T { return i + 2 * N0; })); | |
74 | auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); | |
75 | // a and b may have different types if a was fixed_size<N> such that | |
76 | // another ABI tag exists with equal N, then b will have the | |
77 | // non-fixed-size ABI tag. | |
78 | COMPARE(a.size(), b.size()); | |
79 | COMPARE( | |
80 | b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); })); | |
81 | } | |
82 | { | |
83 | auto x = std::experimental::split<N0, N1, N0>(a); | |
84 | COMPARE(std::tuple_size<decltype(x)>::value, 3u); | |
85 | COMPARE(std::get<0>(x), V0([](auto i) -> T { return i; })); | |
86 | COMPARE(std::get<1>(x), V1([](auto i) -> T { return i + N0; })); | |
87 | COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; })); | |
88 | auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); | |
89 | // a and b may have different types if a was fixed_size<N> such that | |
90 | // another ABI tag exists with equal N, then b will have the | |
91 | // non-fixed-size ABI tag. | |
92 | COMPARE(a.size(), b.size()); | |
93 | COMPARE( | |
94 | b, decltype(b)([](auto i) -> T { return (N0 + i) % V::size(); })); | |
95 | } | |
96 | { | |
97 | auto x = std::experimental::split<N1, N0, N0>(a); | |
98 | COMPARE(std::tuple_size<decltype(x)>::value, 3u); | |
99 | COMPARE(std::get<0>(x), V1([](auto i) -> T { return i; })); | |
100 | COMPARE(std::get<1>(x), V0([](auto i) -> T { return i + N1; })); | |
101 | COMPARE(std::get<2>(x), V0([](auto i) -> T { return i + N0 + N1; })); | |
102 | auto b = concat(std::get<1>(x), std::get<2>(x), std::get<0>(x)); | |
103 | // a and b may have different types if a was fixed_size<N> such that | |
104 | // another ABI tag exists with equal N, then b will have the | |
105 | // non-fixed-size ABI tag. | |
106 | COMPARE(a.size(), b.size()); | |
107 | COMPARE( | |
108 | b, decltype(b)([](auto i) -> T { return (N1 + i) % V::size(); })); | |
109 | } | |
110 | } | |
111 | ||
112 | if constexpr (V::size() % 3 == 0) | |
113 | { | |
114 | const V a = gen<V, ConstProp>([](auto i) -> T { return i; }); | |
115 | constexpr auto N0 = V::size() / 3; | |
116 | using V0 = std::experimental::simd< | |
117 | T, std::experimental::simd_abi::deduce_t<T, N0>>; | |
118 | using V1 = std::experimental::simd< | |
119 | T, std::experimental::simd_abi::deduce_t<T, 2 * N0>>; | |
120 | { | |
121 | auto [x, y, z] = std::experimental::split<N0, N0, N0>(a); | |
122 | COMPARE(x, V0([](auto i) -> T { return i; })); | |
123 | COMPARE(y, V0([](auto i) -> T { return i + N0; })); | |
124 | COMPARE(z, V0([](auto i) -> T { return i + N0 * 2; })); | |
125 | auto b = concat(x, y, z); | |
126 | COMPARE(a.size(), b.size()); | |
127 | COMPARE(b, simd_cast<decltype(b)>(a)); | |
128 | COMPARE(simd_cast<V>(b), a); | |
129 | } | |
130 | { | |
131 | auto [x, y] = std::experimental::split<N0, 2 * N0>(a); | |
132 | COMPARE(x, V0([](auto i) -> T { return i; })); | |
133 | COMPARE(y, V1([](auto i) -> T { return i + N0; })); | |
134 | auto b = concat(x, y); | |
135 | COMPARE(a.size(), b.size()); | |
136 | COMPARE(b, simd_cast<decltype(b)>(a)); | |
137 | COMPARE(simd_cast<V>(b), a); | |
138 | } | |
139 | { | |
140 | auto [x, y] = std::experimental::split<2 * N0, N0>(a); | |
141 | COMPARE(x, V1([](auto i) -> T { return i; })); | |
142 | COMPARE(y, V0([](auto i) -> T { return i + 2 * N0; })); | |
143 | auto b = concat(x, y); | |
144 | COMPARE(a.size(), b.size()); | |
145 | COMPARE(b, simd_cast<decltype(b)>(a)); | |
146 | COMPARE(simd_cast<V>(b), a); | |
147 | } | |
148 | } | |
149 | ||
150 | if constexpr ((V::size() & 1) == 0) | |
151 | { | |
152 | using std::experimental::simd; | |
153 | using std::experimental::simd_abi::deduce_t; | |
154 | using V0 = simd<T, deduce_t<T, V::size()>>; | |
155 | using V2 = simd<T, deduce_t<T, 2>>; | |
156 | using V3 = simd<T, deduce_t<T, V::size() / 2>>; | |
157 | ||
158 | const V a = gen<V, ConstProp>([](auto i) -> T { return i; }); | |
159 | ||
160 | std::array<V2, V::size() / 2> v2s = std::experimental::split<V2>(a); | |
161 | int offset = 0; | |
162 | for (V2 test : v2s) | |
163 | { | |
164 | COMPARE(test, V2([&](auto i) -> T { return i + offset; })); | |
165 | offset += 2; | |
166 | } | |
167 | COMPARE(concat(v2s), simd_cast<V0>(a)); | |
168 | ||
169 | std::array<V3, 2> v3s = std::experimental::split<V3>(a); | |
170 | COMPARE(v3s[0], V3([](auto i) -> T { return i; })); | |
171 | COMPARE(v3s[1], V3([](auto i) -> T { return i + V3::size(); })); | |
172 | COMPARE(concat(v3s), simd_cast<V0>(a)); | |
173 | } | |
174 | } | |
175 | ||
176 | template <typename V> | |
177 | void | |
178 | test() | |
179 | { | |
180 | split_concat<V, true>(); | |
181 | split_concat<V, false>(); | |
182 | } |