TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
iterators.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Olivier Parcollet, Nils Wentzell
16
22#pragma once
23
24#include "./stdutil/array.hpp"
25
26#include <array>
27#include <cstddef>
28#include <iterator>
29
30namespace nda {
31
37 namespace detail {
38
39 // N-dimensional rectangular grid iterator in C traversal order.
40 template <int Rank>
41 class grid_iterator {
42 // Stride or number of elements to skip when increasing the iterator in the current dimension.
43 long stri = 0;
44
45 // Position of the iterator in the current dimension.
46 long pos = 0;
47
48 // Position times the stride in the current dimension.
49 long offset = 0;
50
51 // Iterator to the beginning of the Rank - 1 dimensional grid (excluding the current dimension).
52 grid_iterator<Rank - 1> it_begin;
53
54 // Iterator to the end of the Rank - 1 dimensional grid (excluding the current dimension).
55 grid_iterator<Rank - 1> it_end;
56
57 // Iterator to the Rank - 1 dimensional grid (excluding the current dimension).
58 grid_iterator<Rank - 1> it;
59
60 public:
61 using iterator_category = std::forward_iterator_tag;
62 using value_type = long;
63 using difference_type = std::ptrdiff_t;
64 using pointer = long *;
65 using reference = long &;
66
67 // Default constructor.
68 grid_iterator() = default;
69
70 // Construct an iterator from the shape of the grid, the stride of the grid and a flag indicating if the iterator
71 // is at the end.
72 grid_iterator(long const *lengths, long const *strides, bool at_end)
73 : stri(strides[0]),
74 pos(at_end ? lengths[0] : 0),
75 offset(pos * stri),
76 it_begin(lengths + 1, strides + 1, false),
77 it_end(lengths + 1, strides + 1, true),
78 it(it_begin) {}
79
80 // Get the position/multi-dimensional index of the iterator.
81 [[nodiscard]] std::array<long, Rank> indices() { return stdutil::front_append(it.indices(), pos); }
82
83 // Dereference operator returns the sum of the offsets of every dimension = its linear index.
84 [[nodiscard]] long operator*() const { return offset + *it; }
85
86 // Member access operator returns the sum of the offsets of every dimension = its linear index.
87 [[nodiscard]] long operator->() const { return operator*(); }
88
89 // True if the positions of the iterators are equal in every dimension, false otherwise.
90 [[nodiscard]] bool operator==(grid_iterator const &rhs) const { return ((rhs.pos == pos) and (rhs.it == it)); }
91
92 // True if the positions of the iterators are not equal in every dimension, false otherwise.
93 [[nodiscard]] bool operator!=(grid_iterator const &rhs) const { return not operator==(rhs); }
94
95 // Prefix increment operator.
96 grid_iterator &operator++() {
97 // increment the iterator of the subgrid
98 ++it;
99
100 // if the iterator of the subgrid is at the end, reset it and increment the current position and offset
101 if (it == it_end) { //FIXME [[unlikely]]
102 ++pos;
103 offset += stri;
104 it = it_begin;
105 }
106 return *this;
107 }
108
109 // Postfix increment operator.
110 grid_iterator operator++(int) {
111 auto c = *this;
112 ++(*this);
113 return c;
114 }
115 };
116
117 // Specialization of nda::grid_iterator for 1-dimensional grids.
118 template <>
119 class grid_iterator<1> {
120 // Stride or number of elements to skip when increasing the iterator.
121 long stri = 0;
122
123 // Position of the iterator.
124 long pos = 0;
125
126 // Position times the stride.
127 long offset = 0;
128
129 public:
130 using iterator_category = std::forward_iterator_tag;
131 using value_type = long;
132 using difference_type = std::ptrdiff_t;
133 using pointer = long *;
134 using reference = long &;
135
136 // Default constructor.
137 grid_iterator() = default;
138
139 // Construct an iterator from the shape of the grid, the stride of the grid and a flag indicating if the iterator
140 // is at the end.
141 grid_iterator(long const *lengths, long const *strides, bool at_end) : stri(strides[0]), pos(at_end ? lengths[0] : 0), offset(pos * stri) {}
142
143 // Get the position/index of the iterator.
144 [[nodiscard]] std::array<long, 1> indices() { return {pos}; }
145
146 // Dereference operator returns the offset = its linear index.
147 [[nodiscard]] long operator*() const { return offset; }
148
149 // Member access operator returns the offset = its linear index.
150 [[nodiscard]] long operator->() const { return operator*(); }
151
152 // True if the positions of the iterators are equal, false otherwise.
153 [[nodiscard]] bool operator==(grid_iterator const &rhs) const { return (rhs.pos == pos); }
154
155 // True if the positions of the iterators are not equal, false otherwise.
156 [[nodiscard]] bool operator!=(grid_iterator const &rhs) const { return (rhs.pos != pos); }
157
158 // Prefix increment operator increments the offset by the stride and the position by one.
159 grid_iterator &operator++() {
160 offset += stri;
161 ++pos;
162 return *this;
163 }
164
165 // Prefix decrement operator decrements the offset by the stride and the position by one.
166 grid_iterator &operator--() {
167 offset -= stri;
168 --pos;
169 return *this;
170 }
171
172 // Compound assignment addition operator increments the offset by n times the stride and the position by n.
173 grid_iterator &operator+=(std::ptrdiff_t n) {
174 offset += n * stri;
175 pos += n;
176 return *this;
177 }
178
179 // Binary addition of a grid iterator and an integer.
180 [[nodiscard]] friend grid_iterator operator+(grid_iterator it, std::ptrdiff_t n) { return it += n; }
181
182 // Binary subtraction of two grid iterators.
183 [[nodiscard]] friend std::ptrdiff_t operator-(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos - rhs.pos; }
184
185 // True if the position of the left hand side iterator is less than the position of the right hand side iterator,
186 // false otherwise.
187 [[nodiscard]] friend bool operator<(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos < rhs.pos; }
188
189 // True if the position of the left hand side iterator is greater than the position of the right hand side
190 // iterator, false otherwise.
191 [[nodiscard]] friend bool operator>(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos > rhs.pos; }
192 };
193
194 } // namespace detail
195
214 template <int Rank, typename T, typename Pointer>
216 // Pointer to the data (to the first element).
217 T *data = nullptr;
218
219 // Shape of the array.
220 std::array<long, Rank> len;
221
222 // Strides of the array.
223 std::array<long, Rank> stri;
224
225 // Grid iterator.
226 detail::grid_iterator<Rank> iter;
227
228 public:
230 using iterator_category = std::forward_iterator_tag;
231
233 using value_type = T;
234
236 using difference_type = std::ptrdiff_t;
237
239 using pointer = T *;
240
242 using reference = T &;
243
245 array_iterator() = default;
246
256 array_iterator(std::array<long, Rank> const &lengths, std::array<long, Rank> const &strides, T *start, bool at_end)
257 : data(start), len(lengths), stri(strides), iter(len.data(), stri.data(), at_end) {}
258
263 [[nodiscard]] auto indices() { return iter.indices(); }
264
269 [[nodiscard]] value_type &operator*() const { return ((Pointer)data)[*iter]; }
270
275 [[nodiscard]] value_type &operator->() const { return operator*(); }
276
282 ++iter;
283 return *this;
284 }
285
291 auto c = *this;
292 ++iter;
293 return c;
294 }
295
301 [[nodiscard]] bool operator==(array_iterator const &rhs) const { return (rhs.iter == iter); }
302
308 [[nodiscard]] bool operator!=(array_iterator const &rhs) const { return (!operator==(rhs)); }
309 };
310
320 template <typename T, typename Pointer>
321 class array_iterator<1, T, Pointer> {
322 // Pointer to the data.
323 T *data = nullptr;
324
325 // Shape of the array.
326 std::array<long, 1> len{};
327
328 // Strides of the array.
329 std::array<long, 1> stri{};
330
331 // Grid iterator.
332 detail::grid_iterator<1> iter;
333
334 public:
336 using iterator_category = std::random_access_iterator_tag;
337
339 using value_type = T;
340
342 using difference_type = std::ptrdiff_t;
343
345 using pointer = T *;
346
348 using reference = T &;
349
351 array_iterator() = default;
352
362 array_iterator(std::array<long, 1> const &lengths, std::array<long, 1> const &strides, T *start, bool at_end)
363 : data(start), len(lengths), stri(strides), iter(len.data(), stri.data(), at_end) {}
364
369 [[nodiscard]] auto indices() { return iter.indices(); }
370
375 [[nodiscard]] T &operator*() const { return ((Pointer)data)[*iter]; }
376
381 T &operator->() const { return operator*(); }
382
388 ++iter;
389 return *this;
390 }
391
397 auto c = *this;
398 ++iter;
399 return c;
400 }
401
407 --iter;
408 return *this;
409 }
410
416 auto c = *this;
417 --iter;
418 return c;
419 }
420
426 [[nodiscard]] bool operator==(array_iterator const &rhs) const { return (rhs.iter == iter); }
427
433 [[nodiscard]] bool operator!=(array_iterator const &rhs) const { return (!operator==(rhs)); }
434
441 array_iterator &operator+=(std::ptrdiff_t n) {
442 iter += n;
443 return *this;
444 }
445
452 array_iterator &operator-=(std::ptrdiff_t n) {
453 iter += (-n);
454 return *this;
455 }
456
464 [[nodiscard]] friend array_iterator operator+(std::ptrdiff_t n, array_iterator it) { return it += n; }
465
473 [[nodiscard]] friend array_iterator operator+(array_iterator it, std::ptrdiff_t n) { return it += n; }
474
482 [[nodiscard]] friend array_iterator operator-(array_iterator it, std::ptrdiff_t n) { return it -= n; }
483
491 [[nodiscard]] friend std::ptrdiff_t operator-(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter - rhs.iter; }
492
499 [[nodiscard]] T &operator[](std::ptrdiff_t n) { return ((Pointer)data)[*(iter + n)]; }
500
501 // FIXME C++20 ? with <=> operator
510 [[nodiscard]] friend bool operator<(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter < rhs.iter; }
511
520 [[nodiscard]] friend bool operator>(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter > rhs.iter; }
521
530 [[nodiscard]] friend bool operator<=(array_iterator const &lhs, array_iterator const &rhs) { return not(lhs.iter > rhs.iter); }
531
540 [[nodiscard]] friend bool operator>=(array_iterator const &lhs, array_iterator const &rhs) { return not(lhs.iter < rhs.iter); }
541 };
542
545} // namespace nda
Provides utility functions for std::array.
friend std::ptrdiff_t operator-(array_iterator const &lhs, array_iterator const &rhs)
Binary subtraction of two 1-dimensional array iterators.
friend bool operator>=(array_iterator const &lhs, array_iterator const &rhs)
Greater-than or equal-to comparison operator for two 1-dimensional array iterators.
friend bool operator<=(array_iterator const &lhs, array_iterator const &rhs)
Less-than or equal-to comparison operator for two 1-dimensional array iterators.
array_iterator & operator--()
Prefix decrement operator.
friend array_iterator operator+(std::ptrdiff_t n, array_iterator it)
Binary addition of an integer with an 1-dimensional array iterator.
array_iterator()=default
Default constructor leaves the iterator in an uninitialized state.
friend bool operator>(array_iterator const &lhs, array_iterator const &rhs)
Greater-than comparison operator for two 1-dimensional array iterators.
T & operator[](std::ptrdiff_t n)
Subscript operator.
bool operator!=(array_iterator const &rhs) const
Not-equal-to operator.
array_iterator & operator++()
Prefix increment operator.
array_iterator & operator+=(std::ptrdiff_t n)
Compound assignment addition operator increments the iterator a given number of times.
array_iterator operator--(int)
Postfix decrement operator.
T & operator*() const
Dereference operator.
array_iterator operator++(int)
Postfix increment operator.
friend array_iterator operator-(array_iterator it, std::ptrdiff_t n)
Binary subtraction of an 1-dimensional array iterator with an integer.
array_iterator & operator-=(std::ptrdiff_t n)
Compound assignment subtraction operator decrements the iterator a given number of times.
array_iterator(std::array< long, 1 > const &lengths, std::array< long, 1 > const &strides, T *start, bool at_end)
Construct an iterator from the shape and the strides of an array/view, a pointer to its data and a fl...
bool operator==(array_iterator const &rhs) const
Equal-to operator.
friend array_iterator operator+(array_iterator it, std::ptrdiff_t n)
Binary addition of an 1-dimensional array iterator with an integer.
friend bool operator<(array_iterator const &lhs, array_iterator const &rhs)
Less-than comparison operator for two 1-dimensional array iterators.
T & operator->() const
Member access operator.
std::ptrdiff_t difference_type
Difference type.
std::random_access_iterator_tag iterator_category
Iterator category.
auto indices()
Get the current position/index of the iterator.
Iterator for nda::basic_array and nda::basic_array_view types.
value_type & operator->() const
Member access operator.
array_iterator(std::array< long, Rank > const &lengths, std::array< long, Rank > const &strides, T *start, bool at_end)
Construct an iterator from the shape and the strides of an array/view, a pointer to its data and a fl...
std::ptrdiff_t difference_type
Difference type.
array_iterator operator++(int)
Postfix increment operator.
array_iterator()=default
Default constructor leaves the iterator in an uninitialized state.
std::forward_iterator_tag iterator_category
Iterator category.
T value_type
Value type.
T & reference
Reference type.
bool operator==(array_iterator const &rhs) const
Equal-to operator.
bool operator!=(array_iterator const &rhs) const
Not-equal-to operator.
value_type & operator*() const
Dereference operator.
auto indices()
Get the current position/multi-dimensional index of the iterator.
array_iterator & operator++()
Prefix increment operator.
T * pointer
Pointer type.
Array auto operator+(L &&l, R &&r)
Addition operator for two nda::Array types.
expr_unary<'-', A > operator-(A &&a)
Unary minus operator for nda::Array types.
__inline__ auto operator<(L &&l, R &&r)
Implementation of the lazy binary < operation.
__inline__ auto operator>(L &&l, R &&r)
Implementation of the lazy binary > operation.
constexpr std::array< T, R+1 > front_append(std::array< T, R > const &a, U const &x)
Make a new std::array by prepending one element at the front to an existing std::array.
Definition array.hpp:235