]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/experimental/simd/tests/operators.cc
1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
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)
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.
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/>.
18 // expensive: * [1-9] * *
19 #include "bits/verify.h"
20 #include "bits/make_vec.h"
21 #include "bits/test_values.h"
27 if constexpr (std::is_floating_point_v
<T
>)
30 return std::__finite_max_v
<T
> >> (std::__digits_v
<T
> / 2);
37 using M
= typename
V::mask_type
;
38 using T
= typename
V::value_type
;
39 constexpr auto min
= std::__finite_min_v
<T
>;
40 constexpr auto norm_min
= std::__norm_min_v
<T
>;
41 constexpr auto max
= std::__finite_max_v
<T
>;
43 COMPARE(V(0) == make_vec
<V
>({0, 1}, 0), make_mask
<M
>({1, 0}));
44 COMPARE(V(0) == make_vec
<V
>({0, 1, 2}, 0), make_mask
<M
>({1, 0, 0}));
45 COMPARE(V(1) == make_vec
<V
>({0, 1, 2}, 0), make_mask
<M
>({0, 1, 0}));
46 COMPARE(V(2) == make_vec
<V
>({0, 1, 2}, 0), make_mask
<M
>({0, 0, 1}));
47 COMPARE(V(0) < make_vec
<V
>({0, 1, 2}, 0), make_mask
<M
>({0, 1, 1}));
49 constexpr T half
= genHalfBits
<T
>();
50 for (T lo_
: {min
, T(min
+ 1), T(-1), T(0), norm_min
, T(1), T(half
- 1),
51 half
, T(half
+ 1), T(max
- 1)})
53 for (T hi_
: {T(min
+ 1), T(-1), T(0), norm_min
, T(1), T(half
- 1),
54 half
, T(half
+ 1), T(max
- 1), max
})
59 for (std::size_t pos
= 0; pos
< V::size(); ++pos
)
63 lo
[pos
] = 0; // have a different value in the vector in case
64 hi
[pos
] = 1; // this affects neighbors
66 VERIFY(all_of(hi
!= lo
)) << "hi: " << hi
<< ", lo: " << lo
;
67 VERIFY(all_of(lo
!= hi
)) << "hi: " << hi
<< ", lo: " << lo
;
68 VERIFY(none_of(hi
!= hi
)) << "hi: " << hi
<< ", lo: " << lo
;
69 VERIFY(none_of(hi
== lo
)) << "hi: " << hi
<< ", lo: " << lo
;
70 VERIFY(none_of(lo
== hi
)) << "hi: " << hi
<< ", lo: " << lo
;
71 VERIFY(all_of(lo
< hi
)) << "hi: " << hi
<< ", lo: " << lo
72 << ", lo < hi: " << (lo
< hi
);
73 VERIFY(none_of(hi
< lo
)) << "hi: " << hi
<< ", lo: " << lo
;
74 VERIFY(none_of(hi
<= lo
)) << "hi: " << hi
<< ", lo: " << lo
;
75 VERIFY(all_of(hi
<= hi
)) << "hi: " << hi
<< ", lo: " << lo
;
76 VERIFY(all_of(hi
> lo
)) << "hi: " << hi
<< ", lo: " << lo
;
77 VERIFY(none_of(lo
> hi
)) << "hi: " << hi
<< ", lo: " << lo
;
78 VERIFY(all_of(hi
>= lo
)) << "hi: " << hi
<< ", lo: " << lo
;
79 VERIFY(all_of(hi
>= hi
)) << "hi: " << hi
<< ", lo: " << lo
;
86 for (std::size_t i
= 0; i
< V::size(); ++i
)
92 for (std::size_t i
= 0; i
< V::size(); ++i
)
98 COMPARE(typeid(x
[0] * x
[0]), typeid(T() * T()));
99 COMPARE(typeid(x
[0] * T()), typeid(T() * T()));
100 COMPARE(typeid(T() * x
[0]), typeid(T() * T()));
101 COMPARE(typeid(x
* x
[0]), typeid(x
));
102 COMPARE(typeid(x
[0] * x
), typeid(x
));
104 x
= V([](auto i
) -> T
{ return i
; });
105 for (std::size_t i
= 0; i
< V::size(); ++i
)
109 for (std::size_t i
= 0; i
+ 1 < V::size(); i
+= 2)
112 swap(x
[i
], x
[i
+ 1]);
114 for (std::size_t i
= 0; i
+ 1 < V::size(); i
+= 2)
116 COMPARE(x
[i
], T(i
+ 1)) << x
;
117 COMPARE(x
[i
+ 1], T(i
)) << x
;
122 x
[0] = y
[0]; // make sure non-const smart_reference assignment works
125 x
[0] = x
[0]; // self-assignment on smart_reference
128 std::experimental::simd
<typename
V::value_type
,
129 std::experimental::simd_abi::scalar
>
137 // TODO: check that only value-preserving conversions happen on subscript
142 COMPARE(!x
, M
{true});
144 COMPARE(!y
, M
{false});
149 COMPARE(-x
, V(T(-T(0))));
151 COMPARE(-y
, V(T(-T(1))));
158 COMPARE(x
= x
+ T(1), V(1));
159 COMPARE(x
+ x
, V(2));
160 y
= make_vec
<V
>({1, 2, 3, 4, 5, 6, 7});
161 COMPARE(x
= x
+ y
, make_vec
<V
>({2, 3, 4, 5, 6, 7, 8}));
162 COMPARE(x
= x
+ -y
, V(1));
163 COMPARE(x
+= y
, make_vec
<V
>({2, 3, 4, 5, 6, 7, 8}));
164 COMPARE(x
, make_vec
<V
>({2, 3, 4, 5, 6, 7, 8}));
165 COMPARE(x
+= -y
, V(1));
173 COMPARE(x
- T(1), y
);
174 COMPARE(y
, x
- T(1));
176 y
= make_vec
<V
>({1, 2, 3, 4, 5, 6, 7});
177 COMPARE(x
= y
- x
, make_vec
<V
>({0, 1, 2, 3, 4, 5, 6}));
178 COMPARE(x
= y
- x
, V(1));
179 COMPARE(y
-= x
, make_vec
<V
>({0, 1, 2, 3, 4, 5, 6}));
180 COMPARE(y
, make_vec
<V
>({0, 1, 2, 3, 4, 5, 6}));
181 COMPARE(y
-= y
, V(0));
189 COMPARE(x
= x
* T(2), V(2));
190 COMPARE(x
* x
, V(4));
191 y
= make_vec
<V
>({1, 2, 3, 4, 5, 6, 7});
192 COMPARE(x
= x
* y
, make_vec
<V
>({2, 4, 6, 8, 10, 12, 14}));
194 // don't test norm_min/2*2 in the following. There's no guarantee, in
195 // general, that the result isn't flushed to zero (e.g. NEON without
198 {T(max
- 1), std::is_floating_point_v
<T
> ? T(norm_min
* 3) : min
})
201 COMPARE(x
* y
, V(n
));
203 if (std::is_integral
<T
>::value
&& std::is_unsigned
<T
>::value
)
205 // test modulo arithmetics
208 for (T m
: {T(2), T(7), T(max
/ 127), max
})
211 // if T is of lower rank than int, `n * m` will promote to int
212 // before executing the multiplication. In this case an overflow
213 // will be UB (and ubsan will warn about it). The solution is to
214 // cast to uint in that case.
216 = std::conditional_t
<(sizeof(T
) < sizeof(int)), unsigned, T
>;
217 COMPARE(x
* y
, V(T(U(n
) * U(m
))));
221 COMPARE(x
*= make_vec
<V
>({1, 2, 3}), make_vec
<V
>({2, 4, 6}));
222 COMPARE(x
, make_vec
<V
>({2, 4, 6}));
226 constexpr bool is_iec559
= __GCC_IEC_559
>= 2;
227 if constexpr (std::is_floating_point_v
<T
> && !is_iec559
)
228 { // avoid testing subnormals and expect minor deltas for non-IEC559 float
230 ULP_COMPARE(x
/ x
, V(1), 1);
231 ULP_COMPARE(T(3) / x
, V(T(3) / T(2)), 1);
232 ULP_COMPARE(x
/ T(3), V(T(2) / T(3)), 1);
233 V y
= make_vec
<V
>({1, 2, 3, 4, 5, 6, 7});
236 {T(.5), T(1), T(1.5), T(2), T(2.5), T(3), T(3.5)}),
239 test_values
<V
>({norm_min
* 1024, T(1), T(), T(-1), max
/ 1024,
240 max
/ 4.1, max
, min
},
243 V
ref([&](auto i
) { return a
[i
] / 2; });
244 ULP_COMPARE(a
/ b
, ref
, 1);
245 where(a
== 0, a
) = 1;
246 // -freciprocal-math together with flush-to-zero makes
247 // the following range restriction necessary (i.e.
248 // 1/|a| must be >= min). Intel vrcpps and vrcp14ps
249 // need some extra slack (use 1.1 instead of 1).
250 where(abs(a
) >= T(1.1) / norm_min
, a
) = 1;
251 ULP_COMPARE(a
/ a
, V(1), 1) << "\na = " << a
;
252 ref
= V([&](auto i
) { return 2 / a
[i
]; });
253 ULP_COMPARE(b
/ a
, ref
, 1) << "\na = " << a
;
254 ULP_COMPARE(b
/= a
, ref
, 1);
255 ULP_COMPARE(b
, ref
, 1);
261 COMPARE(x
/ x
, V(1));
262 COMPARE(T(3) / x
, V(T(3) / T(2)));
263 COMPARE(x
/ T(3), V(T(2) / T(3)));
264 V y
= make_vec
<V
>({1, 2, 3, 4, 5, 6, 7});
266 make_vec
<V
>({T(.5), T(1), T(1.5), T(2), T(2.5), T(3), T(3.5)}));
268 y
= make_vec
<V
>({max
, norm_min
});
269 V ref
= make_vec
<V
>({T(max
/ 2), T(norm_min
/ 2)});
272 y
= make_vec
<V
>({norm_min
, max
});
273 ref
= make_vec
<V
>({T(norm_min
/ 2), T(max
/ 2)});
276 y
= make_vec
<V
>({max
, T(norm_min
+ 1)});
277 COMPARE(y
/ y
, V(1));
279 ref
= make_vec
<V
>({T(2 / max
), T(2 / (norm_min
+ 1))});
281 COMPARE(x
/= y
, ref
);
285 { // increment & decrement
286 const V from0
= make_vec
<V
>({0, 1, 2, 3}, 4);
289 COMPARE(x
, from0
+ 1);
290 COMPARE(++x
, from0
+ 2);
291 COMPARE(x
, from0
+ 2);
293 COMPARE(x
--, from0
+ 2);
294 COMPARE(x
, from0
+ 1);