summaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/experimental/simd/tests/bits/simd_view.h
blob: 24fd999cdddb4eebdde7c7b147f5ca3ba341a57a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (C) 2020-2023 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#ifndef VC_TESTS_SIMD_VIEW_H_
#define VC_TESTS_SIMD_VIEW_H_

#include <experimental/simd>

_GLIBCXX_SIMD_BEGIN_NAMESPACE

namespace experimental
{
  namespace imported_begin_end
  {
    using std::begin;
    using std::end;

    template <class T>
      using begin_type = decltype(begin(std::declval<T>()));

    template <class T>
      using end_type = decltype(end(std::declval<T>()));
  }  // namespace imported_begin_end

  template <class V, class It, class End>
    class viewer
    {
      It it;
      const End end;

      template <class F>
	void
	for_each_impl(F &&fun, std::index_sequence<0, 1, 2>)
	{
	  for (; it + V::size() <= end; it += V::size())
	    {
	      fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
		  V([&](auto i) { return std::get<1>(it[i].as_tuple()); }),
		  V([&](auto i) { return std::get<2>(it[i].as_tuple()); }));
	    }
	  if (it != end)
	    {
	      fun(V([&](auto i)
	      {
		auto ii = it + i < end ? i + 0 : 0;
		return std::get<0>(it[ii].as_tuple());
	      }),
		  V([&](auto i) {
		    auto ii = it + i < end ? i + 0 : 0;
		    return std::get<1>(it[ii].as_tuple());
		  }),
		  V([&](auto i) {
		    auto ii = it + i < end ? i + 0 : 0;
		    return std::get<2>(it[ii].as_tuple());
		  }));
	    }
	}

      template <class F>
	void
	for_each_impl(F &&fun, std::index_sequence<0, 1>)
	{
	  for (; it + V::size() <= end; it += V::size())
	    {
	      fun(V([&](auto i) { return std::get<0>(it[i].as_tuple()); }),
		  V([&](auto i) { return std::get<1>(it[i].as_tuple()); }));
	    }
	  if (it != end)
	    {
	      fun(V([&](auto i) {
		auto ii = it + i < end ? i + 0 : 0;
		return std::get<0>(it[ii].as_tuple());
	      }),
		  V([&](auto i) {
		    auto ii = it + i < end ? i + 0 : 0;
		    return std::get<1>(it[ii].as_tuple());
		  }));
	    }
	}

    public:
      viewer(It _it, End _end)
      : it(_it), end(_end) {}

      template <class F>
	void
	for_each(F &&fun)
	{
	  constexpr size_t N
	    = std::tuple_size<std::decay_t<decltype(it->as_tuple())>>::value;
	  for_each_impl(std::forward<F>(fun), std::make_index_sequence<N>());
	}
    };

  template <class V, class Cont>
    viewer<V, imported_begin_end::begin_type<const Cont &>,
	   imported_begin_end::end_type<const Cont &>>
    simd_view(const Cont &data)
    {
      using std::begin;
      using std::end;
      return {begin(data), end(data)};
    }
}  // namespace experimental
_GLIBCXX_SIMD_END_NAMESPACE

#endif  // VC_TESTS_SIMD_VIEW_H_