FlexELA
Loading...
Searching...
No Matches
fields.h
1#ifndef ARRAY_HELPER_H
2#define ARRAY_HELPER_H
3
4#include <cstddef>
5#include <iterator>
6#include <type_traits>
7
19namespace fields {
20
26template <class T>
27class Helper {
28 public:
40 Helper(T* array, const int n[3], const int pad[6]);
41
53 T& at(int i, int j, int k) const;
54
60 std::size_t size() const;
61
78 Helper<T> slice(int is, int ie, int js, int je, int ks, int ke) const;
79
88 struct Iterator {
90 using iterator_category = std::forward_iterator_tag;
91 using value_type = T;
92 using difference_type = long;
93 using pointer = T*;
94 using reference = T&;
97 Iterator() = default;
98
103 Iterator(Helper<T> array, int i, int j, int k);
104
106 T& operator*() const
107 {
108 return *ptr;
109 }
110
113 {
114 return ptr;
115 }
116
118 const T* operator->() const
119 {
120 return ptr;
121 }
122
124 bool operator==(const Iterator& other) const
125 {
126 return ptr == other.ptr;
127 }
128
129 bool operator!=(const Iterator& other) const
130 {
131 return ptr != other.ptr;
132 }
133
134 protected:
135 T* ptr;
136 int index[2];
137 int n[2];
138 int jump[2];
139 };
140
141 struct forward_Iterator : public Iterator {
142 forward_Iterator(Helper<T> array, int i, int j, int k) : Iterator(array, i, j, k){};
143
146
149 {
150 forward_Iterator tmp = *this;
151 ++(*this);
152 return tmp;
153 }
154 };
155
156 struct reverse_Iterator : public Iterator {
157 reverse_Iterator(Helper<T> array, int i, int j, int k) : Iterator(array, i, j, k){};
158
161
164 {
165 reverse_Iterator tmp = *this;
166 ++(*this);
167 return tmp;
168 }
169 };
170
177 {
178 return _begin;
179 }
180
187 {
188 return _end;
189 }
190
197 {
198 return _rbegin;
199 }
200
207 {
208 return _rend;
209 }
210
211 protected:
216 T* const basePtr;
220 int const n[3];
221
226 int const pad[6];
227
228 private:
229 constexpr std::ptrdiff_t getIndex(int i, int j, int k) const;
230
231 const forward_Iterator _begin = forward_Iterator(*this, 0, 0, 0);
232 const forward_Iterator _end = ++forward_Iterator(*this, n[0] - 1, n[1] - 1, n[2] - 1);
233
234 const reverse_Iterator _rend = ++reverse_Iterator(*this, 0, 0, 0);
235 const reverse_Iterator _rbegin = reverse_Iterator(*this, n[0] - 1, n[1] - 1, n[2] - 1);
236};
237
243template <class T>
244class Owner : public Helper<T> {
245 public:
256 Owner(const int n[3], const int pad[6]);
257
258 Owner(T* array, const int n[3], const int pad[6]) = delete;
259
264 Owner(const Owner<T>& rhs);
265
266 ~Owner();
267};
268
277constexpr std::size_t getLength(const int n[3], const int pad[6])
278{
279 return (n[0] + pad[0] + pad[1]) * (n[1] + pad[2] + pad[3]) * (n[2] + pad[4] + pad[5]);
280}
281
282template <class T>
283inline Helper<T>::Helper(T* array, const int n[3], const int pad[6])
284 : basePtr{array}, n{n[0], n[1], n[2]}, pad{pad[0], pad[1], pad[2], pad[3], pad[4], pad[5]}
285{
286}
287
288template <class T>
289inline T& Helper<T>::at(int i, int j, int k) const
290{
291 return *(basePtr + getIndex(i, j, k));
292}
293
294template <class T>
295inline std::size_t Helper<T>::size() const
296{
297 return n[0] * n[1] * n[2];
298}
299
300template <class T>
301inline Helper<T> Helper<T>::slice(int is, int ie, int js, int je, int ks, int ke) const
302{
303 int n_new[3] = {ie - is, je - js, ke - ks};
304 int pad_new[6] = {
305 pad[0] + is, pad[1] + (n[0] - ie), pad[2] + js,
306 pad[3] + (n[1] - je), pad[4] + ks, pad[5] + (n[2] - ke),
307 };
308
309 return Helper<T>(basePtr, n_new, pad_new);
310}
311
312template <typename T>
313constexpr std::ptrdiff_t Helper<T>::getIndex(int i, int j, int k) const
314{
315 std::ptrdiff_t bounds[3] = {
316 n[0] + pad[0] + pad[1], n[1] + pad[2] + pad[3], n[2] + pad[4] + pad[5]};
317
318#ifdef F_STYLE
319 return ((k + pad[4]) * bounds[1] + (j + pad[2])) * bounds[0] + i + pad[0];
320#else
321 return ((i + pad[0]) * bounds[1] + (j + pad[2])) * bounds[2] + k + pad[4];
322#endif
323}
324
325template <class T>
327 :
328// clang-format off
330 index{i,j},
331 n{array.n[0], array.n[1]},
332 jump{
333 (array.pad[0]+array.pad[1]),
334 (array.pad[2]+array.pad[3]) * (array.n[0]+array.pad[0]+array.pad[1])
335 }
336{
337#else
338 index{k,j},
339 n{array.n[2], array.n[1]},
340 jump{
341 (array.pad[4]+array.pad[5]),
342 (array.pad[2]+array.pad[3]) * (array.n[2]+array.pad[4]+array.pad[5])
343 }
344{
345#endif
346 ptr=array.basePtr+array.getIndex(i,j,k);
347}
348// clang-format on
349
350template <class T>
352{
353 ++Iterator::ptr;
354 ++Iterator::index[0];
355
356 if (Iterator::index[0] == Iterator::n[0]) {
357 Iterator::index[0] = 0;
358
359 Iterator::ptr += Iterator::jump[0];
360 ++Iterator::index[1];
361
362 if (Iterator::index[1] == Iterator::n[1]) {
363 Iterator::index[1] = 0;
364
365 Iterator::ptr += Iterator::jump[1];
366 }
367 }
368
369 return *this;
370}
371
372template <class T>
374{
375 if (Iterator::index[0] == 0) {
376 Iterator::index[0] = Iterator::n[0];
377
378 if (Iterator::index[1] == 0) {
379 Iterator::index[1] = Iterator::n[1];
380
381 Iterator::ptr -= Iterator::jump[1];
382 }
383 Iterator::ptr -= Iterator::jump[0];
384 --Iterator::index[1];
385 }
386
387 --Iterator::ptr;
388 --Iterator::index[0];
389
390 return *this;
391}
392
393template <class T>
394inline Owner<T>::Owner(const int n[3], const int pad[6])
395 : Helper<T>(new T[getLength(n, pad)], n, pad)
396{
397}
398
399template <class T>
401 : Helper<T>(new T[getLength(other.n, other.pad)], other.n, other.pad)
402{
404}
405
406template <class T>
407inline Owner<T>::~Owner()
408{
409 delete[] this->basePtr;
410}
411
412} // namespace fields
413
414#endif
A helper class to wrap pointers to padded 3D cartesian data.
Definition fields.h:27
reverse_Iterator rend() const
Reverse Iterator end.
Definition fields.h:206
std::size_t size() const
Return the number of (not pad) cells.
Definition fields.h:295
forward_Iterator end() const
Iterator to the end of the data.
Definition fields.h:186
int const pad[6]
Definition fields.h:226
forward_Iterator begin() const
Iterator to the start (0,0,0) of the data.
Definition fields.h:176
Helper< T > slice(int is, int ie, int js, int je, int ks, int ke) const
Create a slice of the array.
Definition fields.h:301
int const n[3]
Definition fields.h:220
T & at(int i, int j, int k) const
Get the element at (i,j,k)
Definition fields.h:289
reverse_Iterator rbegin() const
Reverse Iterator to the end (ni-1,nj-1,nk-1) of the data.
Definition fields.h:196
Helper(T *array, const int n[3], const int pad[6])
Construct a new Array Helper object pointing to array.
Definition fields.h:283
T *const basePtr
Pointer to start of underlying data.
Definition fields.h:216
An extension of Helper<T> which owns the array.
Definition fields.h:244
Owner(const int n[3], const int pad[6])
Definition fields.h:394
Template to wrap pointer to padded 3D cartesian data.
Definition fields.h:19
constexpr std::size_t getLength(const int n[3], const int pad[6])
Get the total number of elements (including padding)
Definition fields.h:277
An iterator for all data (excluding padding) in Helper<T>.
Definition fields.h:88
T * operator->()
Get pointer.
Definition fields.h:112
T & operator*() const
Get reference.
Definition fields.h:106
const T * operator->() const
Get pointer to const.
Definition fields.h:118
bool operator==(const Iterator &other) const
Comparison.
Definition fields.h:124
Definition fields.h:141
forward_Iterator operator++(int)
Postfix forward increment.
Definition fields.h:148
forward_Iterator & operator++()
Prefix forward increment.
Definition fields.h:351
Definition fields.h:156
reverse_Iterator operator++(int)
Postfix forward increment.
Definition fields.h:163
reverse_Iterator & operator++()
Prefix forward increment.
Definition fields.h:373