Line data Source code
1 : //
2 : // Class Index
3 : // Define a slice in an array.
4 : //
5 : // This essentially defines a list of evenly spaced numbers.
6 : // Most commonly this list will be increasing (positive stride)
7 : // but it can also have negative stride and be decreasing.
8 : //
9 : // Index() --> A null interval with no elements.
10 : // Index(n) --> make an Index on [0..n-1]
11 : // Index(a,b) --> make an Index on [a..b]
12 : // Index(a,b,s) --> make an Index on [a..b] with stride s
13 : //
14 : // Example1:
15 : // --------
16 : // Index I(10); --> Index on [0..9]
17 : // Index Low(5); --> Index on [0..4]
18 : // Index High(5,9); --> Index on [5..9]
19 : // Index IOdd(1,9,2); --> Index on [1..9] stride 2
20 : // Index IEven(0,9,2); --> Index on [0..9] stride 2
21 : //
22 : // Given an Index I(a,n,s), and an integer j you can do the following:
23 : //
24 : // I+j : a+j+i*s for i in [0..n-1]
25 : // j-I : j-a-i*s
26 : // j*I : j*a + i*j*s
27 : // I/j : a/j + i*s/j
28 : //
29 : // j/I we don't do because it is not a uniform stride, and we don't
30 : // allow strides that are fractions.
31 : //
32 : #ifndef IPPL_INDEX_H
33 : #define IPPL_INDEX_H
34 :
35 : #include <Kokkos_Core.hpp>
36 :
37 : #include <iostream>
38 :
39 : namespace ippl {
40 : class Index {
41 : public:
42 : class iterator {
43 : public:
44 : iterator()
45 : : current_m(0)
46 : , stride_m(0) {}
47 :
48 : iterator(int current, int stride = 1)
49 : : current_m(current)
50 : , stride_m(stride) {}
51 :
52 : int operator*() { return current_m; }
53 :
54 : iterator operator--(int) {
55 : iterator tmp = *this;
56 : current_m -= stride_m; // Post decrement
57 : return tmp;
58 : }
59 :
60 : iterator& operator--() {
61 : current_m -= stride_m;
62 : return (*this);
63 : }
64 :
65 : iterator operator++(int) {
66 : iterator tmp = *this;
67 : current_m += stride_m; // Post increment
68 : return tmp;
69 : }
70 :
71 : iterator& operator++() {
72 : current_m += stride_m;
73 : return (*this);
74 : }
75 :
76 : iterator& operator+=(int i) {
77 : current_m += (stride_m * i);
78 : return *this;
79 : }
80 :
81 : iterator& operator-=(int i) {
82 : current_m -= (stride_m * i);
83 : return *this;
84 : }
85 :
86 : iterator operator+(int i) const { return iterator(current_m + i * stride_m, stride_m); }
87 :
88 : iterator operator-(int i) const { return iterator(current_m - i * stride_m, stride_m); }
89 :
90 : int operator[](int i) const { return current_m + i * stride_m; }
91 :
92 : bool operator==(const iterator& y) const {
93 : return (current_m == y.current_m) && (stride_m == y.stride_m);
94 : }
95 :
96 : bool operator<(const iterator& y) const {
97 : return (current_m < y.current_m)
98 : || ((current_m == y.current_m) && (stride_m < y.stride_m));
99 : }
100 :
101 : bool operator!=(const iterator& y) const { return !((*this) == y); }
102 :
103 : bool operator>(const iterator& y) const { return y < (*this); }
104 :
105 : bool operator<=(const iterator& y) const { return !(y < (*this)); }
106 :
107 : bool operator>=(const iterator& y) const { return !((*this) < y); }
108 :
109 : private:
110 : int current_m;
111 : int stride_m;
112 : };
113 :
114 : /*!
115 : * Instantiate Index without any range.
116 : */
117 : KOKKOS_INLINE_FUNCTION Index();
118 :
119 : /*!
120 : * Instantiate Index with range [0, ..., n-1]
121 : * @param n number of elements
122 : */
123 : KOKKOS_INLINE_FUNCTION Index(size_t n);
124 :
125 : /*!
126 : * Instantiate Index with user-defined lower and upper
127 : * bound [f, ..., l].
128 : * @param f first element
129 : * @param l last element
130 : */
131 : KOKKOS_INLINE_FUNCTION Index(int f, int l);
132 :
133 : /*!
134 : * First to Last using Step.
135 : * @param f first element
136 : * @param l last element
137 : * @param s step
138 : */
139 : KOKKOS_INLINE_FUNCTION Index(int f, int l, int s);
140 :
141 : KOKKOS_DEFAULTED_FUNCTION
142 : ~Index() = default;
143 :
144 : /*!
145 : * @returns the smallest element
146 : */
147 : KOKKOS_INLINE_FUNCTION int min() const noexcept;
148 :
149 : /*!
150 : * @returns the largest element
151 : */
152 : KOKKOS_INLINE_FUNCTION int max() const noexcept;
153 :
154 : /*!
155 : * @returns the number of elements
156 : */
157 : KOKKOS_INLINE_FUNCTION size_t length() const noexcept;
158 :
159 : /*!
160 : * @returns the stride
161 : */
162 : KOKKOS_INLINE_FUNCTION int stride() const noexcept;
163 :
164 : /*!
165 : * @returns the first element
166 : */
167 : KOKKOS_INLINE_FUNCTION int first() const noexcept;
168 :
169 : /*!
170 : * @returns the last element
171 : */
172 : KOKKOS_INLINE_FUNCTION int last() const noexcept;
173 :
174 : /*!
175 : * @returns true if empty, otherwise false
176 : */
177 : KOKKOS_INLINE_FUNCTION bool empty() const noexcept;
178 :
179 : KOKKOS_INLINE_FUNCTION Index& operator+=(int);
180 :
181 : KOKKOS_INLINE_FUNCTION Index& operator-=(int);
182 :
183 : // Additive operations.
184 : KOKKOS_INLINE_FUNCTION friend Index operator+(const Index&, int);
185 :
186 : KOKKOS_INLINE_FUNCTION friend Index operator+(int, const Index&);
187 :
188 : KOKKOS_INLINE_FUNCTION friend Index operator-(const Index&, int);
189 :
190 : KOKKOS_INLINE_FUNCTION friend Index operator-(int, const Index&);
191 :
192 : // Multipplicative operations.
193 : KOKKOS_INLINE_FUNCTION friend Index operator-(const Index&);
194 :
195 : KOKKOS_INLINE_FUNCTION friend Index operator*(const Index&, int);
196 :
197 : KOKKOS_INLINE_FUNCTION friend Index operator*(int, const Index&);
198 :
199 : KOKKOS_INLINE_FUNCTION friend Index operator/(const Index&, int);
200 :
201 : // Intersect with another Index.
202 : KOKKOS_INLINE_FUNCTION Index intersect(const Index&) const;
203 :
204 : // Intersect with another Index.
205 : KOKKOS_INLINE_FUNCTION Index grow(int ncells) const;
206 :
207 : // Test to see if there is any overlap between two Indexes.
208 : KOKKOS_INLINE_FUNCTION bool touches(const Index& a) const;
209 : // Test to see if one contains another (endpoints only)
210 : KOKKOS_INLINE_FUNCTION bool contains(const Index& a) const;
211 : // Split one into two.
212 : KOKKOS_INLINE_FUNCTION bool split(Index& l, Index& r) const;
213 : // Split one into two at index i.
214 : KOKKOS_INLINE_FUNCTION bool split(Index& l, Index& r, int i) const;
215 : // Split index into two with a ratio between 0 and 1.
216 : KOKKOS_INLINE_FUNCTION bool split(Index& l, Index& r, double a) const;
217 :
218 : // iterator begin
219 : iterator begin() { return iterator(first_m, stride_m); }
220 : // iterator end
221 : iterator end() { return iterator(first_m + stride_m * length_m, stride_m); }
222 :
223 : // An operator< so we can impose some sort of ordering.
224 : KOKKOS_INLINE_FUNCTION bool operator<(const Index& r) const {
225 : return (
226 : (length_m < r.length_m)
227 : || ((length_m == r.length_m)
228 : && ((first_m < r.first_m)
229 : || ((first_m == r.first_m) && (length_m > 0) && (stride_m < r.stride_m)))));
230 : }
231 : // Test for equality.
232 : KOKKOS_INLINE_FUNCTION bool operator==(const Index& r) const noexcept {
233 : return (length_m == r.length_m) && (first_m == r.first_m) && (stride_m == r.stride_m);
234 : }
235 :
236 : private:
237 : int first_m; /// First index element
238 : int stride_m;
239 : size_t length_m; /// The number of elements
240 :
241 : // Make an Index that interally counts the other direction.
242 : KOKKOS_INLINE_FUNCTION Index reverse() const;
243 :
244 : // Construct with a given base. This is private because
245 : // the interface shouldn't depend on how this is done.
246 :
247 : KOKKOS_INLINE_FUNCTION Index(int m, int a, const Index& b);
248 :
249 : KOKKOS_INLINE_FUNCTION Index(int f, int s, const Index* b);
250 :
251 : // Do a general intersect if the strides are not both 1.
252 : KOKKOS_INLINE_FUNCTION Index general_intersect(const Index&) const;
253 : };
254 :
255 42 : inline std::ostream& operator<<(std::ostream& out, const Index& I) {
256 42 : out << '[' << I.first() << ':' << I.last() << ':' << I.stride() << ']';
257 42 : return out;
258 : }
259 : } // namespace ippl
260 :
261 : #include "Index/Index.hpp"
262 :
263 : #endif
|