1 // Copyright (C) 2020-2023 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 #ifndef VC_TESTS_SIMD_VIEW_H_
19 #define VC_TESTS_SIMD_VIEW_H_
20
21 #include <experimental/simd>
22
23 _GLIBCXX_SIMD_BEGIN_NAMESPACE
24
25 namespace experimental
26 {
27 namespace imported_begin_end
28 {
29 using std::begin;
30 using std::end;
31
32 template <class T>
33 using begin_type = decltype(begin(std::declval<T>()));
34
35 template <class T>
36 using end_type = decltype(end(std::declval<T>()));
37 } // namespace imported_begin_end
38
39 template <class V, class It, class End>
40 class viewer
41 {
42 It it;
43 const End end;
44
45 template <class F>
46 void
47 for_each_impl(F &&fun, std::index_sequence<0, 1, 2>)
48 {
49 for (; it + V::size() <= end; it += V::size())
50 {
51 fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
52 V([&](auto i) { return std::get<1>(it[i].as_tuple()); }),
53 V([&](auto i) { return std::get<2>(it[i].as_tuple()); }));
54 }
55 if (it != end)
56 {
57 fun(V([&](auto i)
58 {
59 auto ii = it + i < end ? i + 0 : 0;
60 return std::get<0>(it[ii].as_tuple());
61 }),
62 V([&](auto i) {
63 auto ii = it + i < end ? i + 0 : 0;
64 return std::get<1>(it[ii].as_tuple());
65 }),
66 V([&](auto i) {
67 auto ii = it + i < end ? i + 0 : 0;
68 return std::get<2>(it[ii].as_tuple());
69 }));
70 }
71 }
72
73 template <class F>
74 void
75 for_each_impl(F &&fun, std::index_sequence<0, 1>)
76 {
77 for (; it + V::size() <= end; it += V::size())
78 {
79 fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
80 V([&](auto i) { return std::get<1>(it[i].as_tuple()); }));
81 }
82 if (it != end)
83 {
84 fun(V([&](auto i) {
85 auto ii = it + i < end ? i + 0 : 0;
86 return std::get<0>(it[ii].as_tuple());
87 }),
88 V([&](auto i) {
89 auto ii = it + i < end ? i + 0 : 0;
90 return std::get<1>(it[ii].as_tuple());
91 }));
92 }
93 }
94
95 public:
96 viewer(It _it, End _end)
97 : it(_it), end(_end) {}
98
99 template <class F>
100 void
101 for_each(F &&fun)
102 {
103 constexpr size_t N
104 = std::tuple_size<std::decay_t<decltype(it->as_tuple())>>::value;
105 for_each_impl(std::forward<F>(fun), std::make_index_sequence<N>());
106 }
107 };
108
109 template <class V, class Cont>
110 viewer<V, imported_begin_end::begin_type<const Cont &>,
111 imported_begin_end::end_type<const Cont &>>
112 simd_view(const Cont &data)
113 {
114 using std::begin;
115 using std::end;
116 return {begin(data), end(data)};
117 }
118 } // namespace experimental
119 _GLIBCXX_SIMD_END_NAMESPACE
120
121 #endif // VC_TESTS_SIMD_VIEW_H_