Low-Level Abstraction of Memory Access
Array.hpp
Go to the documentation of this file.
1 // Copyright 2022 Alexander Matthes, Bernhard Manfred Gruber
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #pragma once
5 
6 #include "macros.hpp"
7 
8 #include <ostream>
9 #include <stdexcept>
10 #include <tuple>
11 
12 namespace llama
13 {
18  template<typename T, std::size_t N>
19  // NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
20  struct Array
21  {
22  using value_type = T;
23  T element[N];
24 
25  LLAMA_FN_HOST_ACC_INLINE constexpr auto size() const
26  {
27  return N;
28  }
29 
30  LLAMA_FN_HOST_ACC_INLINE constexpr auto empty() const -> bool
31  {
32  return N == 0;
33  }
34 
35  LLAMA_FN_HOST_ACC_INLINE constexpr auto begin() -> T*
36  {
37  return &element[0];
38  }
39 
40  LLAMA_FN_HOST_ACC_INLINE constexpr auto begin() const -> const T*
41  {
42  return &element[0];
43  }
44 
45  LLAMA_FN_HOST_ACC_INLINE constexpr auto end() -> T*
46  {
47  return &element[0] + N;
48  }
49 
50  LLAMA_FN_HOST_ACC_INLINE constexpr auto end() const -> const T*
51  {
52  return &element[0] + N;
53  }
54 
55  LLAMA_FN_HOST_ACC_INLINE constexpr auto front() -> T&
56  {
57  return element[0];
58  }
59 
60  LLAMA_FN_HOST_ACC_INLINE constexpr auto front() const -> const T&
61  {
62  return element[0];
63  }
64 
65  LLAMA_FN_HOST_ACC_INLINE constexpr auto back() -> T&
66  {
67  return element[N - 1];
68  }
69 
70  LLAMA_FN_HOST_ACC_INLINE constexpr auto back() const -> const T&
71  {
72  return element[N - 1];
73  }
74 
75  template<typename IndexType>
76  LLAMA_FN_HOST_ACC_INLINE constexpr auto operator[](IndexType&& idx) -> T&
77  {
78  return element[idx];
79  }
80 
81  template<typename IndexType>
82  LLAMA_FN_HOST_ACC_INLINE constexpr auto operator[](IndexType&& idx) const -> const T&
83  {
84  return element[idx];
85  }
86 
87  LLAMA_FN_HOST_ACC_INLINE constexpr auto data() -> T*
88  {
89  return &element[0];
90  }
91 
92  LLAMA_FN_HOST_ACC_INLINE constexpr auto data() const -> const T*
93  {
94  return &element[0];
95  }
96 
97  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator==(const Array& a, const Array& b) -> bool
98  {
99  for(std::size_t i = 0; i < N; ++i)
100  if(a.element[i] != b.element[i])
101  return false;
102  return true;
103  }
104 
105  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator!=(const Array& a, const Array& b) -> bool
106  {
107  return !(a == b);
108  }
109 
110  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator+(const Array& a, const Array& b) -> Array
111  {
112  Array temp{};
113  for(std::size_t i = 0; i < N; ++i)
114  temp[i] = a[i] + b[i];
115  return temp;
116  }
117 
118  template<std::size_t I>
119  LLAMA_FN_HOST_ACC_INLINE constexpr auto get() -> T&
120  {
121  return element[I];
122  }
123 
124  template<std::size_t I>
125  LLAMA_FN_HOST_ACC_INLINE constexpr auto get() const -> const T&
126  {
127  return element[I];
128  }
129  };
130 
132  template<typename T>
133  struct Array<T, 0>
134  {
135  using value_type = T;
136 
137  LLAMA_FN_HOST_ACC_INLINE constexpr auto size() const
138  {
139  return 0;
140  }
141 
142  LLAMA_FN_HOST_ACC_INLINE constexpr auto empty() const -> bool
143  {
144  return true;
145  }
146 
147  LLAMA_FN_HOST_ACC_INLINE constexpr auto begin() -> T*
148  {
149  return nullptr;
150  }
151 
152  LLAMA_FN_HOST_ACC_INLINE constexpr auto begin() const -> const T*
153  {
154  return nullptr;
155  }
156 
157  LLAMA_FN_HOST_ACC_INLINE constexpr auto end() -> T*
158  {
159  return nullptr;
160  }
161 
162  LLAMA_FN_HOST_ACC_INLINE constexpr auto end() const -> const T*
163  {
164  return nullptr;
165  }
166 
167  LLAMA_FN_HOST_ACC_INLINE constexpr auto front() -> T&
168  {
169  outOfRange();
170  }
171 
172  LLAMA_FN_HOST_ACC_INLINE constexpr auto front() const -> const T&
173  {
174  outOfRange();
175  }
176 
177  LLAMA_FN_HOST_ACC_INLINE constexpr auto back() -> T&
178  {
179  outOfRange();
180  }
181 
182  LLAMA_FN_HOST_ACC_INLINE constexpr auto back() const -> const T&
183  {
184  outOfRange();
185  }
186 
187  template<typename IndexType>
188  LLAMA_FN_HOST_ACC_INLINE constexpr auto operator[](IndexType&&) -> T&
189  {
190  outOfRange();
191  }
192 
193  template<typename IndexType>
194  LLAMA_FN_HOST_ACC_INLINE constexpr auto operator[](IndexType&&) const -> const T&
195  {
196  outOfRange();
197  }
198 
199  LLAMA_FN_HOST_ACC_INLINE constexpr auto data() -> T*
200  {
201  return nullptr;
202  }
203 
204  LLAMA_FN_HOST_ACC_INLINE constexpr auto data() const -> const T*
205  {
206  return nullptr;
207  }
208 
209  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator==(const Array&, const Array&) -> bool
210  {
211  return true;
212  }
213 
214  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator!=(const Array&, const Array&) -> bool
215  {
216  return false;
217  }
218 
219  LLAMA_FN_HOST_ACC_INLINE constexpr friend auto operator+(const Array&, const Array&) -> Array
220  {
221  return {};
222  }
223 
224  template<std::size_t I>
225  LLAMA_FN_HOST_ACC_INLINE constexpr auto get() -> T&
226  {
227  outOfRange();
228  }
229 
230  template<std::size_t I>
231  LLAMA_FN_HOST_ACC_INLINE constexpr auto get() const -> const T&
232  {
233  outOfRange();
234  }
235 
236  private:
237  [[noreturn]] void outOfRange() const
238  {
239  throw std::out_of_range{"Array has zero length"};
240  }
241  };
242 
244  template<typename First, typename... Args>
245  Array(First, Args... args) -> Array<First, sizeof...(Args) + 1>;
246 
248  template<typename T, std::size_t N>
249  auto operator<<(std::ostream& os, const Array<T, N>& a) -> std::ostream&
250  {
251  os << "Array{";
252  bool first = true;
253  for(auto e : a)
254  {
255  if(first)
256  first = false;
257  else
258  os << ", ";
259  os << e;
260  }
261  os << "}";
262  return os;
263  }
264 
266  template<typename T, std::size_t N>
267  LLAMA_FN_HOST_ACC_INLINE constexpr auto pushFront([[maybe_unused]] Array<T, N> a, T v) -> Array<T, N + 1>
268  {
269  Array<T, N + 1> r{};
270  r[0] = v;
271  if constexpr(N > 0)
272  for(std::size_t i = 0; i < N; i++)
273  r[i + 1] = a[i];
274  return r;
275  }
276 
278  template<typename T, std::size_t N>
279  LLAMA_FN_HOST_ACC_INLINE constexpr auto pushBack([[maybe_unused]] Array<T, N> a, T v) -> Array<T, N + 1>
280  {
281  Array<T, N + 1> r{};
282  if constexpr(N > 0)
283  for(std::size_t i = 0; i < N; i++)
284  r[i] = a[i];
285  r[N] = v;
286  return r;
287  }
288 
290  template<typename T, std::size_t N>
291  LLAMA_FN_HOST_ACC_INLINE constexpr auto popBack([[maybe_unused]] Array<T, N> a)
292  {
293  static_assert(N > 0);
294  Array<T, N - 1> r{};
295  if constexpr(N > 1)
296  for(std::size_t i = 0; i < N - 1; i++)
297  r[i] = a[i];
298  return r;
299  }
300 
302  template<typename T, std::size_t N>
303  LLAMA_FN_HOST_ACC_INLINE constexpr auto popFront([[maybe_unused]] Array<T, N> a)
304  {
305  static_assert(N > 0);
306  Array<T, N - 1> r{};
307  if constexpr(N > 1)
308  for(std::size_t i = 0; i < N - 1; i++)
309  r[i] = a[i + 1];
310  return r;
311  }
312 
314  template<typename T, std::size_t N>
316  {
317  T prod = 1;
318  for(auto s : a)
319  prod *= s;
320  return prod;
321  }
322 
324  template<typename T, std::size_t N>
325  LLAMA_FN_HOST_ACC_INLINE constexpr auto dot([[maybe_unused]] Array<T, N> a, [[maybe_unused]] Array<T, N> b) -> T
326  {
327  T r = 0;
328  if constexpr(N > 0)
329  for(std::size_t i = 0; i < N; i++)
330  r += a[i] * b[i];
331  return r;
332  }
333 } // namespace llama
334 
336 template<typename T, size_t N>
337 struct std::tuple_size<llama::Array<T, N>> : std::integral_constant<size_t, N> // NOLINT(cert-dcl58-cpp)
338 {
339 };
340 
342 template<size_t I, typename T, size_t N>
343 struct std::tuple_element<I, llama::Array<T, N>> // NOLINT(cert-dcl58-cpp)
344 {
345  using type = T;
346 };
#define LLAMA_EXPORT
Definition: macros.hpp:192
#define LLAMA_FN_HOST_ACC_INLINE
Definition: macros.hpp:96
constexpr auto pushBack([[maybe_unused]] Array< T, N > a, T v) -> Array< T, N+1 >
Definition: Array.hpp:279
constexpr auto dot([[maybe_unused]] Array< T, N > a, [[maybe_unused]] Array< T, N > b) -> T
Definition: Array.hpp:325
Array(First, Args... args) -> Array< First, sizeof...(Args)+1 >
auto operator<<(std::ostream &os, const Array< T, N > &a) -> std::ostream &
Definition: Array.hpp:249
constexpr auto popBack([[maybe_unused]] Array< T, N > a)
Definition: Array.hpp:291
constexpr auto product(Array< T, N > a) -> T
Definition: Array.hpp:315
constexpr auto popFront([[maybe_unused]] Array< T, N > a)
Definition: Array.hpp:303
constexpr auto pushFront([[maybe_unused]] Array< T, N > a, T v) -> Array< T, N+1 >
Definition: Array.hpp:267
constexpr auto size() const
Definition: Array.hpp:137
constexpr auto back() const -> const T &
Definition: Array.hpp:182
constexpr auto data() const -> const T *
Definition: Array.hpp:204
constexpr friend auto operator+(const Array &, const Array &) -> Array
Definition: Array.hpp:219
constexpr auto get() -> T &
Definition: Array.hpp:225
constexpr auto data() -> T *
Definition: Array.hpp:199
constexpr friend auto operator!=(const Array &, const Array &) -> bool
Definition: Array.hpp:214
constexpr auto end() const -> const T *
Definition: Array.hpp:162
constexpr auto get() const -> const T &
Definition: Array.hpp:231
constexpr auto end() -> T *
Definition: Array.hpp:157
constexpr auto begin() const -> const T *
Definition: Array.hpp:152
constexpr auto empty() const -> bool
Definition: Array.hpp:142
constexpr auto front() -> T &
Definition: Array.hpp:167
constexpr auto front() const -> const T &
Definition: Array.hpp:172
constexpr friend auto operator==(const Array &, const Array &) -> bool
Definition: Array.hpp:209
constexpr auto back() -> T &
Definition: Array.hpp:177
constexpr auto operator[](IndexType &&) -> T &
Definition: Array.hpp:188
constexpr auto begin() -> T *
Definition: Array.hpp:147
constexpr auto operator[](IndexType &&) const -> const T &
Definition: Array.hpp:194
constexpr auto back() -> T &
Definition: Array.hpp:65
T value_type
Definition: Array.hpp:22
constexpr friend auto operator+(const Array &a, const Array &b) -> Array
Definition: Array.hpp:110
constexpr auto operator[](IndexType &&idx) -> T &
Definition: Array.hpp:76
constexpr auto begin() -> T *
Definition: Array.hpp:35
constexpr auto front() const -> const T &
Definition: Array.hpp:60
constexpr auto get() const -> const T &
Definition: Array.hpp:125
T element[N]
Definition: Array.hpp:23
constexpr auto end() const -> const T *
Definition: Array.hpp:50
constexpr friend auto operator!=(const Array &a, const Array &b) -> bool
Definition: Array.hpp:105
constexpr friend auto operator==(const Array &a, const Array &b) -> bool
Definition: Array.hpp:97
constexpr auto end() -> T *
Definition: Array.hpp:45
constexpr auto empty() const -> bool
Definition: Array.hpp:30
constexpr auto size() const
Definition: Array.hpp:25
constexpr auto data() -> T *
Definition: Array.hpp:87
constexpr auto begin() const -> const T *
Definition: Array.hpp:40
constexpr auto data() const -> const T *
Definition: Array.hpp:92
constexpr auto operator[](IndexType &&idx) const -> const T &
Definition: Array.hpp:82
constexpr auto front() -> T &
Definition: Array.hpp:55
constexpr auto get() -> T &
Definition: Array.hpp:119
constexpr auto back() const -> const T &
Definition: Array.hpp:70