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--present, The Simons Foundation
2// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
3// SPDX-License-Identifier: Apache-2.0
4// See LICENSE in the root of this distribution for details.
5
10
11#pragma once
12
13#include "./stdutil/array.hpp"
14
15#include <array>
16#include <cstddef>
17#include <iterator>
18
19namespace nda {
20
25
26 namespace detail {
27
28 // N-dimensional rectangular grid iterator in C traversal order.
29 template <int Rank>
30 class grid_iterator {
31 // Stride or number of elements to skip when increasing the iterator in the current dimension.
32 long stri = 0;
33
34 // Position of the iterator in the current dimension.
35 long pos = 0;
36
37 // Position times the stride in the current dimension.
38 long offset = 0;
39
40 // Iterator to the beginning of the Rank - 1 dimensional grid (excluding the current dimension).
41 grid_iterator<Rank - 1> it_begin;
42
43 // Iterator to the end of the Rank - 1 dimensional grid (excluding the current dimension).
44 grid_iterator<Rank - 1> it_end;
45
46 // Iterator to the Rank - 1 dimensional grid (excluding the current dimension).
47 grid_iterator<Rank - 1> it;
48
49 public:
50 using iterator_category = std::forward_iterator_tag;
51 using value_type = long;
52 using difference_type = std::ptrdiff_t;
53 using pointer = long *;
54 using reference = long &;
55
56 // Default constructor.
57 grid_iterator() = default;
58
59 // Construct an iterator from the shape of the grid, the stride of the grid and a flag indicating if the iterator
60 // is at the end.
61 grid_iterator(long const *lengths, long const *strides, bool at_end)
62 : stri(strides[0]),
63 pos(at_end ? lengths[0] : 0),
64 offset(pos * stri),
65 it_begin(lengths + 1, strides + 1, false),
66 it_end(lengths + 1, strides + 1, true),
67 it(it_begin) {}
68
69 // Get the position/multi-dimensional index of the iterator.
70 [[nodiscard]] std::array<long, Rank> indices() { return stdutil::front_append(it.indices(), pos); }
71
72 // Dereference operator returns the sum of the offsets of every dimension = its linear index.
73 [[nodiscard]] long operator*() const { return offset + *it; }
74
75 // Member access operator returns the sum of the offsets of every dimension = its linear index.
76 [[nodiscard]] long operator->() const { return operator*(); }
77
78 // True if the positions of the iterators are equal in every dimension, false otherwise.
79 [[nodiscard]] bool operator==(grid_iterator const &rhs) const { return ((rhs.pos == pos) and (rhs.it == it)); }
80
81 // True if the positions of the iterators are not equal in every dimension, false otherwise.
82 [[nodiscard]] bool operator!=(grid_iterator const &rhs) const { return not operator==(rhs); }
83
84 // Prefix increment operator.
85 grid_iterator &operator++() {
86 // increment the iterator of the subgrid
87 ++it;
88
89 // if the iterator of the subgrid is at the end, reset it and increment the current position and offset
90 if (it == it_end) { //FIXME [[unlikely]]
91 ++pos;
92 offset += stri;
93 it = it_begin;
94 }
95 return *this;
96 }
97
98 // Postfix increment operator.
99 grid_iterator operator++(int) {
100 auto c = *this;
101 ++(*this);
102 return c;
103 }
104 };
105
106 // Specialization of nda::grid_iterator for 1-dimensional grids.
107 template <>
108 class grid_iterator<1> {
109 // Stride or number of elements to skip when increasing the iterator.
110 long stri = 0;
111
112 // Position of the iterator.
113 long pos = 0;
114
115 // Position times the stride.
116 long offset = 0;
117
118 public:
119 using iterator_category = std::forward_iterator_tag;
120 using value_type = long;
121 using difference_type = std::ptrdiff_t;
122 using pointer = long *;
123 using reference = long &;
124
125 // Default constructor.
126 grid_iterator() = default;
127
128 // Construct an iterator from the shape of the grid, the stride of the grid and a flag indicating if the iterator
129 // is at the end.
130 grid_iterator(long const *lengths, long const *strides, bool at_end) : stri(strides[0]), pos(at_end ? lengths[0] : 0), offset(pos * stri) {}
131
132 // Get the position/index of the iterator.
133 [[nodiscard]] std::array<long, 1> indices() { return {pos}; }
134
135 // Dereference operator returns the offset = its linear index.
136 [[nodiscard]] long operator*() const { return offset; }
137
138 // Member access operator returns the offset = its linear index.
139 [[nodiscard]] long operator->() const { return operator*(); }
140
141 // True if the positions of the iterators are equal, false otherwise.
142 [[nodiscard]] bool operator==(grid_iterator const &rhs) const { return (rhs.pos == pos); }
143
144 // True if the positions of the iterators are not equal, false otherwise.
145 [[nodiscard]] bool operator!=(grid_iterator const &rhs) const { return (rhs.pos != pos); }
146
147 // Prefix increment operator increments the offset by the stride and the position by one.
148 grid_iterator &operator++() {
149 offset += stri;
150 ++pos;
151 return *this;
152 }
153
154 // Prefix decrement operator decrements the offset by the stride and the position by one.
155 grid_iterator &operator--() {
156 offset -= stri;
157 --pos;
158 return *this;
159 }
160
161 // Compound assignment addition operator increments the offset by n times the stride and the position by n.
162 grid_iterator &operator+=(std::ptrdiff_t n) {
163 offset += n * stri;
164 pos += n;
165 return *this;
166 }
167
168 // Binary addition of a grid iterator and an integer.
169 [[nodiscard]] friend grid_iterator operator+(grid_iterator it, std::ptrdiff_t n) { return it += n; }
170
171 // Binary subtraction of two grid iterators.
172 [[nodiscard]] friend std::ptrdiff_t operator-(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos - rhs.pos; }
173
174 // True if the position of the left hand side iterator is less than the position of the right hand side iterator,
175 // false otherwise.
176 [[nodiscard]] friend bool operator<(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos < rhs.pos; }
177
178 // True if the position of the left hand side iterator is greater than the position of the right hand side
179 // iterator, false otherwise.
180 [[nodiscard]] friend bool operator>(grid_iterator const &lhs, grid_iterator const &rhs) { return lhs.pos > rhs.pos; }
181 };
182
183 } // namespace detail
184
203 template <int Rank, typename T, typename Pointer>
205 // Pointer to the data (to the first element).
206 T *data = nullptr;
207
208 // Shape of the array.
209 std::array<long, Rank> len;
210
211 // Strides of the array.
212 std::array<long, Rank> stri;
213
214 // Grid iterator.
215 detail::grid_iterator<Rank> iter;
216
217 public:
219 using iterator_category = std::forward_iterator_tag;
220
222 using value_type = T;
223
225 using difference_type = std::ptrdiff_t;
226
228 using pointer = T *;
229
231 using reference = T &;
232
234 array_iterator() = default;
235
245 array_iterator(std::array<long, Rank> const &lengths, std::array<long, Rank> const &strides, T *start, bool at_end)
246 : data(start), len(lengths), stri(strides), iter(len.data(), stri.data(), at_end) {}
247
252 [[nodiscard]] auto indices() { return iter.indices(); }
253
258 [[nodiscard]] value_type &operator*() const { return ((Pointer)data)[*iter]; }
259
264 [[nodiscard]] value_type &operator->() const { return operator*(); }
265
271 ++iter;
272 return *this;
273 }
274
280 auto c = *this;
281 ++iter;
282 return c;
283 }
284
290 [[nodiscard]] bool operator==(array_iterator const &rhs) const { return (rhs.iter == iter); }
291
297 [[nodiscard]] bool operator!=(array_iterator const &rhs) const { return (!operator==(rhs)); }
298 };
299
309 template <typename T, typename Pointer>
310 class array_iterator<1, T, Pointer> {
311 // Pointer to the data.
312 T *data = nullptr;
313
314 // Shape of the array.
315 std::array<long, 1> len{};
316
317 // Strides of the array.
318 std::array<long, 1> stri{};
319
320 // Grid iterator.
321 detail::grid_iterator<1> iter;
322
323 public:
325 using iterator_category = std::random_access_iterator_tag;
326
328 using value_type = T;
329
331 using difference_type = std::ptrdiff_t;
332
334 using pointer = T *;
335
337 using reference = T &;
338
340 array_iterator() = default;
341
351 array_iterator(std::array<long, 1> const &lengths, std::array<long, 1> const &strides, T *start, bool at_end)
352 : data(start), len(lengths), stri(strides), iter(len.data(), stri.data(), at_end) {}
353
358 [[nodiscard]] auto indices() { return iter.indices(); }
359
364 [[nodiscard]] T &operator*() const { return ((Pointer)data)[*iter]; }
365
370 T &operator->() const { return operator*(); }
371
377 ++iter;
378 return *this;
379 }
380
386 auto c = *this;
387 ++iter;
388 return c;
389 }
390
396 --iter;
397 return *this;
398 }
399
405 auto c = *this;
406 --iter;
407 return c;
408 }
409
415 [[nodiscard]] bool operator==(array_iterator const &rhs) const { return (rhs.iter == iter); }
416
422 [[nodiscard]] bool operator!=(array_iterator const &rhs) const { return (!operator==(rhs)); }
423
430 array_iterator &operator+=(std::ptrdiff_t n) {
431 iter += n;
432 return *this;
433 }
434
441 array_iterator &operator-=(std::ptrdiff_t n) {
442 iter += (-n);
443 return *this;
444 }
445
453 [[nodiscard]] friend array_iterator operator+(std::ptrdiff_t n, array_iterator it) { return it += n; }
454
462 [[nodiscard]] friend array_iterator operator+(array_iterator it, std::ptrdiff_t n) { return it += n; }
463
471 [[nodiscard]] friend array_iterator operator-(array_iterator it, std::ptrdiff_t n) { return it -= n; }
472
480 [[nodiscard]] friend std::ptrdiff_t operator-(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter - rhs.iter; }
481
488 [[nodiscard]] T &operator[](std::ptrdiff_t n) { return ((Pointer)data)[*(iter + n)]; }
489
490 // FIXME C++20 ? with <=> operator
499 [[nodiscard]] friend bool operator<(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter < rhs.iter; }
500
509 [[nodiscard]] friend bool operator>(array_iterator const &lhs, array_iterator const &rhs) { return lhs.iter > rhs.iter; }
510
519 [[nodiscard]] friend bool operator<=(array_iterator const &lhs, array_iterator const &rhs) { return not(lhs.iter > rhs.iter); }
520
529 [[nodiscard]] friend bool operator>=(array_iterator const &lhs, array_iterator const &rhs) { return not(lhs.iter < rhs.iter); }
530 };
531
533
534} // 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.
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...
array_iterator operator++(int)
Postfix increment operator.
array_iterator()=default
Default constructor leaves the iterator in an uninitialized state.
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.
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:222