]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/experimental/simd/tests/reductions.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / experimental / simd / tests / reductions.cc
1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
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
18 // expensive: * [1-9] * *
19 #include "bits/main.h"
20 #include <random>
21
22 template <typename V>
23 void
24 test()
25 {
26 using T = typename V::value_type;
27 COMPARE(reduce(V(1)), T(V::size()));
28 {
29 V x = 1;
30 COMPARE(reduce(x, std::multiplies<>()), T(1));
31 x[0] = 2;
32 COMPARE(reduce(x, std::multiplies<>()), T(2));
33 if constexpr (V::size() > 1)
34 {
35 x[V::size() - 1] = 3;
36 COMPARE(reduce(x, std::multiplies<>()), T(6));
37 }
38 }
39 COMPARE(reduce(V([](int i) { return i & 1; })), T(V::size() / 2));
40 COMPARE(reduce(V([](int i) { return i % 3; })),
41 T(3 * (V::size() / 3) // 0+1+2 for every complete 3 elements in V
42 + (V::size() % 3) / 2 // 0->0, 1->0, 2->1 adjustment
43 ));
44 if ((1 + V::size()) * V::size() / 2 <= std::__finite_max_v<T>)
45 {
46 COMPARE(reduce(V([](int i) { return i + 1; })),
47 T((1 + V::size()) * V::size() / 2));
48 }
49
50 {
51 const V y = 2;
52 COMPARE(reduce(y), T(2 * V::size()));
53 COMPARE(reduce(where(y > 2, y)), T(0));
54 COMPARE(reduce(where(y == 2, y)), T(2 * V::size()));
55 }
56
57 {
58 COMPARE(hmin(V(1)), T(1));
59 COMPARE(hmax(V(1)), T(1));
60 const V z([](T i) { return i + 1; });
61 COMPARE(std::experimental::reduce(z,
62 [](auto a, auto b) {
63 using std::min;
64 return min(a, b);
65 }),
66 T(1))
67 << "z: " << z;
68 COMPARE(std::experimental::reduce(z,
69 [](auto a, auto b) {
70 using std::max;
71 return max(a, b);
72 }),
73 T(V::size()))
74 << "z: " << z;
75 COMPARE(std::experimental::reduce(where(z > 1, z), 117,
76 [](auto a, auto b) {
77 using std::min;
78 return min(a, b);
79 }),
80 T(V::size() == 1 ? 117 : 2))
81 << "z: " << z;
82 COMPARE(hmin(z), T(1));
83 COMPARE(hmax(z), T(V::size()));
84 if (V::size() > 1)
85 {
86 COMPARE(hmin(where(z > 1, z)), T(2));
87 COMPARE(hmax(where(z > 1, z)), T(V::size()));
88 }
89 COMPARE(hmin(where(z < 4, z)), T(1));
90 COMPARE(hmax(where(z < 4, z)), std::min(T(V::size()), T(3)));
91 const V zz = make_value_unknown(z);
92 COMPARE(hmin(zz), T(1));
93 COMPARE(hmax(zz), T(V::size()));
94 if (V::size() > 1)
95 {
96 COMPARE(hmin(where(zz > 1, zz)), T(2));
97 COMPARE(hmax(where(zz > 1, zz)), T(V::size()));
98 }
99 COMPARE(hmin(where(zz < 4, zz)), T(1));
100 COMPARE(hmax(where(zz < 4, zz)), std::min(T(V::size()), T(3)));
101 }
102
103 test_values<V>({}, {1000}, [](V x) {
104 // avoid over-/underflow on signed integers:
105 if constexpr (std::is_signed_v<T> && std::is_integral_v<T>)
106 x /= int(V::size());
107 // The error in the following could be huge if catastrophic
108 // cancellation occurs. (e.g. `a-a+b+b` vs. `a+b+b-a`).
109 // Avoid catastrophic cancellation for floating point:
110 if constexpr (std::is_floating_point_v<T>)
111 x = abs(x);
112 T acc = x[0];
113 for (size_t i = 1; i < V::size(); ++i)
114 acc += x[i];
115 const T max_distance = std::is_integral_v<T> ? 0 : V::size() / 2;
116 ULP_COMPARE(reduce(x), acc, max_distance).on_failure("x = ", x);
117 });
118 }