Line data Source code
1 : #ifndef AMREX_INTVECT_H_
2 : #define AMREX_INTVECT_H_
3 : #include <AMReX_Config.H>
4 :
5 : #include <AMReX_INT.H>
6 : #include <AMReX_SPACE.H>
7 : #include <AMReX_Array.H>
8 : #include <AMReX_Vector.H>
9 : #include <AMReX_Dim3.H>
10 : #include <AMReX_BLassert.H>
11 : #include <AMReX_Extension.H>
12 : #include <AMReX_GpuQualifiers.H>
13 : #include <AMReX_Math.H>
14 : #include <AMReX_Tuple.H>
15 : #include <AMReX_TypeTraits.H>
16 :
17 : #include <iosfwd>
18 : #include <cstdlib>
19 : #include <cmath>
20 : #include <limits>
21 : #include <climits>
22 : #include <algorithm>
23 :
24 : namespace amrex {
25 :
26 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
27 : int coarsen (int i, int ratio) noexcept
28 : {
29 3622572 : switch (ratio) {
30 0 : case 1: return i;
31 3277762 : case 2: return (i<0) ? -std::abs(i+1)/2 -1 : i/2;
32 150324 : case 4: return (i<0) ? -std::abs(i+1)/4 -1 : i/4;
33 194488 : default: return (i<0) ? -std::abs(i+1)/ratio-1 : i/ratio;
34 : }
35 : }
36 :
37 : /**
38 : * An Integer Vector in dim-Dimensional Space
39 : *
40 : * The class IntVectND is an implementation of an integer vector in a
41 : * dim-dimensional space. It represents a point in a discrete space.
42 : * IntVectND values are accessed using the operator[] function, as for a normal
43 : * C++ array. In addition, the basic arithmetic operators have been overloaded
44 : * to implement scaling and translation operations.
45 : */
46 : template<int dim>
47 : class IntVectND
48 : {
49 : public:
50 : static_assert(dim >= 1, "The number of dimensions of IntVectND must be positive");
51 :
52 : struct shift_hasher {
53 : std::size_t operator()(const IntVectND<dim>& vec) const noexcept
54 : {
55 : static constexpr unsigned shift1 = sizeof(size_t)>=8 ? 20 : 10;
56 : static constexpr unsigned shift2 = sizeof(size_t)>=8 ? 40 : 20;
57 : if constexpr (dim == 1) {
58 : return static_cast<std::size_t>(vec[0]);
59 : } else if constexpr (dim == 2) {
60 : return static_cast<std::size_t>(vec[0]) ^
61 : (static_cast<std::size_t>(vec[1]) << shift1);
62 : } else if constexpr (dim == 3) {
63 : return static_cast<std::size_t>(vec[0]) ^
64 : (static_cast<std::size_t>(vec[1]) << shift1) ^
65 : (static_cast<std::size_t>(vec[2]) << shift2);
66 : } else {
67 : std::size_t seed = dim;
68 : // hash function from
69 : // https://stackoverflow.com/questions/20511347/a-good-hash-function-for-a-vector
70 : for (int i=0; i<dim; ++i) {
71 : auto x = static_cast<unsigned int>(vec[i]);
72 : x = ((x >> 16) ^ x) * 0x45d9f3b;
73 : x = ((x >> 16) ^ x) * 0x45d9f3b;
74 : x = (x >> 16) ^ x;
75 : seed ^= x + 0x9e3779b9 + (seed << 6) + (seed >> 2);
76 : }
77 : return seed;
78 : }
79 : }
80 : };
81 :
82 : using hasher = shift_hasher;
83 :
84 : ///
85 : /**
86 : * \brief Construct an IntVectND whose components are all zero.
87 : */
88 1772380 : constexpr IntVectND () noexcept {} // cannot use = default due to Clang bug // NOLINT
89 :
90 : /**
91 : * \brief Construct an IntVectND given the specific values for its
92 : * coordinates. The inputs for this constructor are N integers,
93 : * where N is equal to the number of dimensions of the IntVectND.
94 : */
95 : template <class...Args,
96 : std::enable_if_t<
97 : (sizeof...(Args)+2 == dim) &&
98 : IsConvertible_v<int, Args...>,
99 : int> = 0>
100 : AMREX_GPU_HOST_DEVICE
101 43657300 : constexpr IntVectND (int i, int j, Args...ks) noexcept : vect{i, j, static_cast<int>(ks)...} {}
102 :
103 : /**
104 : * \brief Construct an IntVectND whose components are all the same.
105 : */
106 : AMREX_GPU_HOST_DEVICE
107 1780650 : explicit constexpr IntVectND (int s) noexcept {
108 5341960 : for (int i=0; i<dim; ++i) {
109 3561310 : vect[i] = s;
110 : }
111 1780650 : }
112 :
113 : /**
114 : * \brief Construct an IntVectND setting the coordinates to the
115 : * corresponding values in the integer array a.
116 : */
117 : AMREX_GPU_HOST_DEVICE
118 : explicit IntVectND (const int* a) noexcept {
119 : for (int i=0; i<dim; ++i) {
120 : vect[i] = a[i];
121 : }
122 : }
123 :
124 : /**
125 : * \brief Construct an IntVectND from an Vector<int>. It is an error if
126 : * the Vector<int> doesn't have the same dimension as this
127 : * IntVectND.
128 : */
129 : explicit IntVectND (const Vector<int>& a) noexcept {
130 : BL_ASSERT(a.size() == dim);
131 : for (int i=0; i<dim; ++i) {
132 : vect[i] = a[i];
133 : }
134 : }
135 :
136 : /**
137 : * \brief Construct an IntVectND from an Array<int,dim>.
138 : */
139 : explicit IntVectND (const Array<int,dim>& a) noexcept {
140 : for (int i=0; i<dim; ++i) {
141 : vect[i] = a[i];
142 : }
143 : }
144 :
145 : template <int N=dim, std::enable_if_t<( 1<=N && N<=3 ), int> = 0>
146 : explicit constexpr IntVectND (Dim3 const& a) noexcept {
147 : vect[0] = a.x;
148 : if constexpr (dim >= 2) {
149 : vect[1] = a.y;
150 : }
151 : if constexpr (dim == 3) {
152 : vect[2] = a.z;
153 : }
154 : }
155 :
156 : // dtor, copy-ctor, copy-op=, move-ctor, and move-op= are compiler generated.
157 :
158 : template <int N=dim, std::enable_if_t<( 1<=N && N<=3 ), int> = 0>
159 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
160 : Dim3 dim3 () const noexcept {
161 : if constexpr (dim == 1) {
162 : return Dim3{vect[0],0,0};
163 : } else if constexpr (dim == 2) {
164 0 : return Dim3{vect[0],vect[1],0};
165 : } else {
166 : return Dim3{vect[0],vect[1],vect[2]};
167 : }
168 : }
169 :
170 : #if __cplusplus >= 201402L
171 : template< typename T = int >
172 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
173 : Array<T, dim>
174 : toArray () const noexcept {
175 : Array<T, dim> ret {};
176 : for (int i=0; i<dim; ++i) {
177 : ret[i] = T(vect[i]);
178 : }
179 : return ret;
180 : }
181 : #endif
182 :
183 : ///
184 : /**
185 : Sum of all components of this IntVectND.
186 : */
187 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
188 : int sum () const noexcept
189 : {
190 : int retval = vect[0];
191 : for (int i=1; i<dim; ++i) {
192 : retval += vect[i];
193 : }
194 : return retval;
195 : }
196 :
197 : //! maximum (no absolute values) value
198 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
199 : int max () const noexcept
200 : {
201 1769411 : int retval = vect[0];
202 3538822 : for (int i=1; i<dim; ++i) {
203 1769411 : retval = retval > vect[i] ? retval : vect[i];
204 : }
205 1769411 : return retval;
206 : }
207 :
208 : //! minimum (no absolute values) value
209 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
210 : int min () const noexcept
211 : {
212 : int retval = vect[0];
213 : for (int i=1; i<dim; ++i) {
214 : retval = retval < vect[i] ? retval : vect[i];
215 : }
216 : return retval;
217 : }
218 :
219 : //return coordinate with largest value
220 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
221 : int maxDir(bool a_doAbsValue) const noexcept;
222 :
223 : //! Returns a reference to the i'th coordinate of the IntVectND.
224 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
225 5640893569 : int& operator[] (int i) noexcept { BL_ASSERT(i>=0 && i < dim); return vect[i]; }
226 :
227 : //! Returns the i'th coordinate of the IntVectND.
228 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
229 1268571928 : const int& operator[] (int i) const noexcept { BL_ASSERT(i>=0 && i < dim); return vect[i]; }
230 :
231 : //! Returns a reference to the i'th coordinate of the IntVectND. Used by structured bindings.
232 : template<std::size_t i>
233 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
234 : int& get () noexcept {static_assert(0<=i && i<dim); return vect[i];}
235 :
236 : //! Returns a reference to the i'th coordinate of the IntVectND. Used by structured bindings.
237 : template<std::size_t i>
238 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
239 : const int& get () const noexcept {static_assert(0<=i && i<dim); return vect[i];}
240 :
241 : //! Returns a pointer to the first element of the IntVectND.
242 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
243 : int* begin () noexcept { return &vect[0]; }
244 :
245 : //! Returns a pointer to the first element of the IntVectND.
246 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
247 : const int* begin () const noexcept { return &vect[0]; }
248 :
249 : //! Returns a pointer to the (last+1) element of the IntVectND.
250 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
251 : int* end () noexcept { return &vect[dim]; }
252 :
253 : //! Returns a pointer to the (last+1) element of the IntVectND.
254 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
255 : const int* end () const noexcept { return &vect[dim]; }
256 :
257 : //! Set i'th coordinate of IntVectND to val.
258 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
259 : IntVectND& setVal (int i, int val) noexcept
260 : {
261 0 : BL_ASSERT(i>=0 && i<dim); vect[i] = val; return *this;
262 : }
263 :
264 : /**
265 : * \brief Returns a const pointer to an array of coordinates of the
266 : * IntVectND. Useful for arguments to FORTRAN calls.
267 : */
268 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
269 204497000 : const int* getVect () const& noexcept { return vect; }
270 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
271 : int* getVect () & noexcept { return vect; }
272 : AMREX_GPU_HOST_DEVICE
273 : int* getVect () && = delete;
274 :
275 : //! Returns true if all components are equal to the argument val.
276 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
277 : bool operator== (int val) const noexcept
278 : {
279 : bool retval = vect[0] == val;
280 : for (int i=1; i<dim; ++i) {
281 : retval = retval && vect[i] == val;
282 : }
283 : return retval;
284 : }
285 :
286 : //! Returns true if any component is not equal to the argument val.
287 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
288 : bool operator!= (int val) const noexcept
289 : {
290 894084 : bool retval = vect[0] != val;
291 1788172 : for (int i=1; i<dim; ++i) {
292 894084 : retval = retval || vect[i] != val;
293 : }
294 894084 : return retval;
295 : }
296 :
297 : //! Returns true if this is equivalent to rhs.
298 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
299 : bool operator== (const IntVectND<dim>& rhs) const noexcept
300 : {
301 937467 : bool retval = vect[0] == rhs[0];
302 1874930 : for (int i=1; i<dim; ++i) {
303 1868190 : retval = retval && vect[i] == rhs[i];
304 : }
305 937467 : return retval;
306 : }
307 : //! Returns true if this is different from rhs.
308 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
309 : bool operator!= (const IntVectND<dim>& rhs) const noexcept
310 : {
311 : bool retval = vect[0] != rhs[0];
312 : for (int i=1; i<dim; ++i) {
313 : retval = retval || vect[i] != rhs[i];
314 : }
315 : return retval;
316 : }
317 : //! Return true if this is lexicographically less than rhs.
318 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
319 : bool operator< (const IntVectND<dim>& rhs) const noexcept
320 : {
321 : for (int i=dim-1; i>=0; --i) {
322 : if (vect[i] < rhs[i]) {
323 : return true;
324 : } else if (vect[i] > rhs[i]) {
325 : return false;
326 : }
327 : }
328 : return false;
329 : }
330 : //! Return true if this is lexicographically less than or equal to rhs.
331 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
332 : bool operator<= (const IntVectND<dim>& rhs) const noexcept
333 : {
334 : return !(rhs < *this);
335 : }
336 : //! Return true if this is lexicographically greater than rhs.
337 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
338 : bool operator> (const IntVectND<dim>& rhs) const noexcept
339 : {
340 : return rhs < *this;
341 : }
342 : //! Return true if this is lexicographically greater than or equal to rhs.
343 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
344 : bool operator>= (const IntVectND<dim>& rhs) const noexcept
345 : {
346 : return !(*this < rhs);
347 : }
348 : /**
349 : * \brief Returns true if this is less than argument for all components.
350 : * NOTE: This is NOT a strict weak ordering usable by STL sorting algorithms.
351 : */
352 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
353 : bool allLT (const IntVectND<dim>& rhs) const noexcept
354 : {
355 : bool retval = vect[0] < rhs[0];
356 : for (int i=1; i<dim; ++i) {
357 : retval = retval && vect[i] < rhs[i];
358 : }
359 : return retval;
360 : }
361 : /**
362 : * \brief Returns true if this is less than argument for all components.
363 : */
364 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
365 : bool allLT (int rhs) const noexcept
366 : {
367 : bool retval = vect[0] < rhs;
368 : for (int i=1; i<dim; ++i) {
369 : retval = retval && vect[i] < rhs;
370 : }
371 : return retval;
372 : }
373 : /**
374 : * \brief Returns true if this is less than or equal to argument for all components.
375 : * NOTE: This is NOT a strict weak ordering usable by STL sorting algorithms.
376 : */
377 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
378 : bool allLE (const IntVectND<dim>& rhs) const noexcept
379 : {
380 1091850 : bool retval = vect[0] <= rhs[0];
381 2183700 : for (int i=1; i<dim; ++i) {
382 2151570 : retval = retval && vect[i] <= rhs[i];
383 : }
384 1091850 : return retval;
385 : }
386 : /**
387 : * \brief Returns true if this is less than or equal to argument for all components.
388 : */
389 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
390 : bool allLE (int rhs) const noexcept
391 : {
392 : bool retval = vect[0] <= rhs;
393 : for (int i=1; i<dim; ++i) {
394 : retval = retval && vect[i] <= rhs;
395 : }
396 : return retval;
397 : }
398 : /**
399 : * \brief Returns true if this is greater than argument for all components.
400 : * NOTE: This is NOT a strict weak ordering usable by STL sorting algorithms.
401 : */
402 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
403 : bool allGT (const IntVectND<dim>& rhs) const noexcept
404 : {
405 : bool retval = vect[0] > rhs[0];
406 : for (int i=1; i<dim; ++i) {
407 : retval = retval && vect[i] > rhs[i];
408 : }
409 : return retval;
410 : }
411 : /**
412 : * \brief Returns true if this is greater than argument for all components.
413 : */
414 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
415 : bool allGT (int rhs) const noexcept
416 : {
417 : bool retval = vect[0] > rhs;
418 : for (int i=1; i<dim; ++i) {
419 : retval = retval && vect[i] > rhs;
420 : }
421 : return retval;
422 : }
423 : /**
424 : * \brief Returns true if this is greater than or equal to argument for all components.
425 : * NOTE: This is NOT a strict weak ordering usable by STL sorting algorithms.
426 : */
427 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
428 : bool allGE (const IntVectND<dim>& rhs) const noexcept
429 : {
430 95826300 : bool retval = vect[0] >= rhs[0];
431 191652200 : for (int i=1; i<dim; ++i) {
432 191390680 : retval = retval && vect[i] >= rhs[i];
433 : }
434 95826300 : return retval;
435 : }
436 : /**
437 : * \brief Returns true if this is greater than or equal to argument for all components.
438 : */
439 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
440 : bool allGE (int rhs) const noexcept
441 : {
442 : bool retval = vect[0] >= rhs;
443 : for (int i=1; i<dim; ++i) {
444 : retval = retval && vect[i] >= rhs;
445 : }
446 : return retval;
447 : }
448 : //! Unary plus -- for completeness.
449 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
450 : IntVectND<dim> operator+ () const noexcept { return *this; }
451 : //! Unary Minus -- negates all components.
452 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
453 : IntVectND<dim> operator- () const noexcept {
454 : IntVectND<dim> retval(0);
455 : for (int i=0; i<dim; ++i) {
456 : retval[i] = -vect[i];
457 : }
458 : return retval;
459 : }
460 : //! Modifies IntVectND by addition of a scalar to each component.
461 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
462 : IntVectND<dim>& operator+= (int s) noexcept
463 : {
464 : for (int i=0; i<dim; ++i) {
465 : vect[i] += s;
466 : }
467 : return *this;
468 : }
469 : //! Modifies IntVectND by component-wise addition with argument.
470 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
471 : IntVectND<dim>& operator+= (const IntVectND<dim>& p) noexcept
472 : {
473 5154345 : for (int i=0; i<dim; ++i) {
474 3436230 : vect[i] += p[i];
475 : }
476 1718115 : return *this;
477 : }
478 : //! Modifies IntVectND by multiplication of a scalar to each component.
479 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
480 : IntVectND<dim>& operator*= (int s) noexcept
481 : {
482 : for (int i=0; i<dim; ++i) {
483 : vect[i] *= s;
484 : }
485 : return *this;
486 : }
487 : //! Modifies IntVectND by component-wise multiplication with argument.
488 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
489 : IntVectND<dim>& operator*= (const IntVectND<dim>& p) noexcept
490 : {
491 26898 : for (int i=0; i<dim; ++i) {
492 17932 : vect[i] *= p[i];
493 : }
494 8966 : return *this;
495 : }
496 : //! Modifies IntVectND by division by a scalar to each component.
497 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
498 : IntVectND<dim>& operator/= (int s) noexcept
499 : {
500 : for (int i=0; i<dim; ++i) {
501 : vect[i] /= s;
502 : }
503 : return *this;
504 : }
505 : //! Modifies IntVectND by component-wise division with argument.
506 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
507 : IntVectND<dim>& operator/= (const IntVectND<dim>& p) noexcept
508 : {
509 : for (int i=0; i<dim; ++i) {
510 : vect[i] /= p[i];
511 : }
512 : return *this;
513 : }
514 : //! Modifies IntVectND by subtraction of a scalar to each component.
515 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
516 : IntVectND<dim>& operator-= (int s) noexcept
517 : {
518 : for (int i=0; i<dim; ++i) {
519 : vect[i] -= s;
520 : }
521 : return *this;
522 : }
523 : //! Modifies IntVectND by component-wise subtraction with argument.
524 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
525 : IntVectND<dim>& operator-= (const IntVectND<dim>& p) noexcept
526 : {
527 5155297 : for (int i=0; i<dim; ++i) {
528 3436868 : vect[i] -= p[i];
529 : }
530 1718429 : return *this;
531 : }
532 : //! Returns component-wise sum of IntVectND<and argument.
533 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
534 : IntVectND<dim> operator+ (const IntVectND<dim>& p) const noexcept
535 : {
536 : IntVectND<dim> retval = *this;
537 : return retval += p;
538 : }
539 : //! Return an IntVectND that is this IntVectND + s.
540 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
541 : IntVectND<dim> operator+ (int s) const noexcept
542 : {
543 : IntVectND<dim> retval = *this;
544 : return retval += s;
545 : }
546 : //! Returns component-wise difference of IntVectND and argument.
547 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
548 : IntVectND<dim> operator- (const IntVectND<dim>& p) const noexcept
549 : {
550 332207 : IntVectND<dim> retval = *this;
551 332207 : return retval -= p;
552 : }
553 : //! Return an IntVectND that is this IntVectND - s.
554 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
555 : IntVectND<dim> operator- (int s) const noexcept
556 : {
557 : IntVectND<dim> retval = *this;
558 : return retval -= s;
559 : }
560 : //! Returns component-wise product of IntVectND and argument.
561 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
562 : IntVectND<dim> operator* (const IntVectND<dim>& p) const noexcept
563 : {
564 : IntVectND<dim> retval = *this;
565 : return retval *= p;
566 : }
567 : //! Returns component-wise product of IntVectND and s.
568 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
569 : IntVectND<dim> operator* (int s) const noexcept
570 : {
571 : IntVectND<dim> retval = *this;
572 : return retval *= s;
573 : }
574 : //! Returns component-wise division of IntVectND by argument.
575 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
576 : IntVectND<dim> operator/ (const IntVectND<dim>& p) const noexcept
577 : {
578 : IntVectND<dim> retval = *this;
579 : return retval /= p;
580 : }
581 : //! Returns component-wise division of IntVectND by s.
582 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
583 : IntVectND<dim> operator/ (int s) const noexcept
584 : {
585 : IntVectND<dim> retval = *this;
586 : return retval /= s;
587 : }
588 : //! Modifies IntVectND by taking component-wise min with argument.
589 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
590 : IntVectND<dim>& min (const IntVectND<dim>& p) noexcept
591 : {
592 5117200 : for (int i=0; i<dim; ++i) {
593 3411470 : vect[i] = (vect[i] < p.vect[i] ? vect[i] : p.vect[i]);
594 : }
595 1705730 : return *this;
596 : }
597 : //! Modifies IntVectND by taking component-wise max with argument.
598 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
599 : IntVectND<dim>& max (const IntVectND<dim>& p) noexcept
600 : {
601 5117200 : for (int i=0; i<dim; ++i) {
602 3411470 : vect[i] = (vect[i] > p.vect[i] ? vect[i] : p.vect[i]);
603 : }
604 1705730 : return *this;
605 : }
606 : //! Modify IntVectND by multiplying each coordinate by s.
607 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
608 : IntVectND<dim>& scale (int s) noexcept {
609 : for (int i=0; i<dim; ++i) {
610 : vect[i] *= s;
611 : }
612 : return *this;
613 : }
614 : /**
615 : * \brief Modify IntVectND by reflecting it in the plane defined by
616 : * the index ref_ix and with normal in the direction of idir.
617 : */
618 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
619 : IntVectND<dim>& reflect (int ref_ix, int idir) noexcept
620 : {
621 : BL_ASSERT(idir >= 0 && idir < dim);
622 : vect[idir] = -vect[idir] + 2*ref_ix;
623 : return *this;
624 : }
625 : //! Modify IntVectND by adding s to given coordinate.
626 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
627 : IntVectND<dim>& shift (int coord, int s) noexcept
628 : {
629 6665026 : BL_ASSERT(coord >= 0 && coord < dim); vect[coord] += s; return *this;
630 : }
631 : //! Equivalent to shift(0,iv[0]).shift(1,iv[1]) ...
632 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
633 : IntVectND<dim>& shift (const IntVectND<dim>& iv) noexcept { *this += iv; return *this; }
634 : //! Modify IntVectND by adding s to each coordinate.
635 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
636 : IntVectND<dim>& diagShift (int s) noexcept
637 : {
638 11243900 : for (int i=0; i<dim; ++i) {
639 7495910 : vect[i] += s;
640 : }
641 3747960 : return *this;
642 : }
643 : //! Modify IntVectND<dim> by component-wise integer projection.
644 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
645 : IntVectND<dim>& coarsen (const IntVectND<dim>& p) noexcept;
646 : //! Modify IntVectND<dim> by component-wise integer projection.
647 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
648 : IntVectND<dim>& coarsen (int p) noexcept;
649 :
650 : /**
651 : * \brief This static member function returns a reference to a constant IntVectND
652 : * object, all of whose dim arguments are set to zero (0).
653 : * Figuratively, it is the zero vector in dim-dimensional space.
654 : * It is provided as a convenient way to specify the zero vector.
655 : */
656 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
657 : static constexpr IntVectND<dim> TheZeroVector () noexcept {
658 693718 : return IntVectND<dim>(0);
659 : }
660 : /**
661 : * \brief This static member function returns a reference to a constant IntVectND
662 : * object, all of whose dim arguments are set to one (1).
663 : * Figuratively, it is the unit vector in dim-dimensional space.
664 : * It is provided as a convenient way to specify the unit vector.
665 : */
666 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
667 : static constexpr IntVectND<dim> TheUnitVector () noexcept {
668 46 : return IntVectND<dim>(1);
669 : }
670 : /**
671 : * \brief This static member function returns a reference to a constant IntVectND
672 : * object, all of whose dim arguments are set to zero except that
673 : * the d-direction is set to one.
674 : */
675 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
676 : static constexpr IntVectND<dim> TheDimensionVector (int d) noexcept {
677 : IntVectND<dim> retval(0);
678 : retval[d] = 1;
679 : return retval;
680 : }
681 : /**
682 : * \brief This static member function returns a reference to a constant IntVectND
683 : * object, all of whose dim arguments are set to IndexType::NODE.
684 : * It is provided as a convenience to our users when defining Boxes.
685 : */
686 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
687 : static constexpr IntVectND<dim> TheNodeVector () noexcept {
688 332859 : return IntVectND<dim>(1);
689 : }
690 : /**
691 : * \brief This static member function returns a reference to a constant IntVectND
692 : * object, all of whose dim arguments are set to IndexType::CELL.
693 : * It is provided as a convenience to our users when defining Boxes.
694 : */
695 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
696 : static constexpr IntVectND<dim> TheCellVector () noexcept {
697 1440 : return IntVectND<dim>(0);
698 : }
699 :
700 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
701 : static constexpr IntVectND<dim> TheMaxVector () noexcept {
702 : return IntVectND<dim>(std::numeric_limits<int>::max());
703 : }
704 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
705 : static constexpr IntVectND<dim> TheMinVector () noexcept {
706 : return IntVectND<dim>(std::numeric_limits<int>::lowest());
707 : }
708 :
709 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
710 : static constexpr std::size_t size () noexcept {
711 : return static_cast<std::size_t>(dim);
712 : }
713 :
714 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
715 : static constexpr int isize () noexcept {
716 : return dim;
717 : }
718 :
719 : using value_type = int;
720 :
721 : /**
722 : * \brief Returns a new IntVectND of size new_dim and
723 : * assigns the first new_dim values of this IntVectND to it.
724 : */
725 : template<int new_dim>
726 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
727 : IntVectND<new_dim> shrink () const noexcept {
728 : static_assert(new_dim <= dim);
729 : return IntVectND<new_dim>(this->begin());
730 : }
731 :
732 : /**
733 : * \brief Returns a new IntVectND of size new_dim and
734 : * assigns all values of this IntVectND to it andĀ fill_extra to the remaining elements.
735 : */
736 : template<int new_dim>
737 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
738 : IntVectND<new_dim> expand (int fill_extra=0) const noexcept {
739 : static_assert(new_dim >= dim);
740 : IntVectND<new_dim> retval(fill_extra);
741 : for (int i=0; i<dim; ++i) {
742 : retval[i] = vect[i];
743 : }
744 : return retval;
745 : }
746 :
747 : /**
748 : * \brief Returns a new IntVectND of size new_dim
749 : * by either shrinking or expanding this IntVectND
750 : */
751 : template<int new_dim>
752 : [[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
753 : IntVectND<new_dim> resize (int fill_extra=0) const noexcept {
754 : if constexpr (new_dim > dim) {
755 : return expand<new_dim>(fill_extra);
756 : } else {
757 : return shrink<new_dim>();
758 : }
759 : }
760 :
761 : /**
762 : This is an IntVect all of whose components are equal to zero.
763 : */
764 : static const IntVectND<dim> Zero;
765 :
766 : /**
767 : This is an IntVect all of whose components are equal to one.
768 : */
769 : static const IntVectND<dim> Unit;
770 :
771 : private:
772 :
773 : int vect[dim] = {};
774 : };
775 :
776 : template <int dim>
777 : inline constexpr const IntVectND<dim> IntVectND<dim>::Zero{0};
778 :
779 : template <int dim>
780 : inline constexpr const IntVectND<dim> IntVectND<dim>::Unit{1};
781 :
782 : // Template deduction guide for IntVectND
783 : template<std::size_t dim>
784 : AMREX_GPU_HOST_DEVICE // __device__ for HIP
785 : IntVectND(const Array<int, dim>&) -> IntVectND<dim>;
786 :
787 : // Template deduction guide for IntVectND
788 : template <class...Args,
789 : std::enable_if_t<
790 : IsConvertible_v<int, Args...>,
791 : int> = 0>
792 : AMREX_GPU_HOST_DEVICE // __device__ for HIP
793 : IntVectND(int, int, Args...) -> IntVectND<sizeof...(Args)+2>;
794 :
795 : using IntVect = IntVectND<AMREX_SPACEDIM>;
796 :
797 : template<int dim>
798 : AMREX_GPU_HOST_DEVICE
799 : AMREX_FORCE_INLINE
800 : IntVectND<dim>&
801 : IntVectND<dim>::coarsen (int s) noexcept
802 : {
803 : BL_ASSERT(s > 0);
804 : switch (s) {
805 : case 1:
806 : break;
807 : case 2:
808 : for (int i=0; i<dim; ++i) {
809 : vect[i] = (vect[i]<0) ? -std::abs(vect[i]+1)/2-1 : vect[i]/2;
810 : }
811 : break;
812 : case 4:
813 : for (int i=0; i<dim; ++i) {
814 : vect[i] = (vect[i]<0) ? -std::abs(vect[i]+1)/4-1 : vect[i]/4;
815 : }
816 : break;
817 : default:
818 : for (int i=0; i<dim; ++i) {
819 : vect[i] = (vect[i]<0) ? -std::abs(vect[i]+1)/s-1 : vect[i]/s;
820 : }
821 : }
822 : return *this;
823 : }
824 :
825 : template<int dim>
826 : AMREX_GPU_HOST_DEVICE
827 : AMREX_FORCE_INLINE
828 : IntVectND<dim>&
829 : IntVectND<dim>::coarsen (const IntVectND<dim>& p) noexcept
830 : {
831 : BL_ASSERT(p.allGT(0));
832 5337608 : for (int i=0; i<dim; ++i) {
833 7116804 : vect[i] = amrex::coarsen(vect[i], p.vect[i]);
834 : }
835 1779206 : return *this;
836 : }
837 :
838 : template<int dim>
839 : AMREX_GPU_HOST_DEVICE
840 : AMREX_FORCE_INLINE
841 : int
842 : IntVectND<dim>::maxDir(bool a_doAbsValue) const noexcept
843 : {
844 : int retval = 0;
845 : if(a_doAbsValue)
846 : {
847 : int maxval = std::abs((*this)[0]);
848 : for(int idir = 1; idir < dim; idir++)
849 : {
850 : int curval = std::abs((*this)[idir]);
851 : if(curval > maxval)
852 : {
853 : maxval = curval;
854 : retval = idir;
855 : }
856 : }
857 : }
858 : else
859 : {
860 : int maxval = (*this)[0];
861 : for(int idir = 1; idir < dim; idir++)
862 : {
863 : int curval = (*this)[idir];
864 : if(curval > maxval)
865 : {
866 : maxval = curval;
867 : retval = idir;
868 : }
869 : }
870 : }
871 : return retval;
872 : }
873 :
874 : //! Returns p + s.
875 : template<int dim>
876 : AMREX_GPU_HOST_DEVICE
877 : AMREX_FORCE_INLINE
878 : IntVectND<dim> operator+ (int s, const IntVectND<dim>& p) noexcept
879 : {
880 : IntVectND<dim> retval = p;
881 : for (int i=0; i<dim; ++i) {
882 : retval[i] = s + retval[i];
883 : }
884 : return retval;
885 : }
886 :
887 : //! Returns -p + s.
888 : template<int dim>
889 : AMREX_GPU_HOST_DEVICE
890 : AMREX_FORCE_INLINE
891 : AMREX_GPU_HOST_DEVICE
892 : IntVectND<dim> operator- (int s, const IntVectND<dim>& p) noexcept
893 : {
894 : IntVectND<dim> retval = p;
895 : for (int i=0; i<dim; ++i) {
896 : retval[i] = s - retval[i];
897 : }
898 : return retval;
899 : }
900 :
901 : //! Returns p * s.
902 : template<int dim>
903 : AMREX_GPU_HOST_DEVICE
904 : AMREX_FORCE_INLINE
905 : IntVectND<dim> operator* (int s, const IntVectND<dim>& p) noexcept
906 : {
907 46 : IntVectND<dim> retval = p;
908 138 : for (int i=0; i<dim; ++i) {
909 184 : retval[i] = s * retval[i];
910 : }
911 46 : return retval;
912 : }
913 :
914 : /**
915 : * \brief Returns the IntVectND that is the component-wise minimum of two
916 : * argument IntVectNDs.
917 : */
918 : template<int dim>
919 : AMREX_GPU_HOST_DEVICE
920 : AMREX_FORCE_INLINE
921 : IntVectND<dim>
922 : min (const IntVectND<dim>& p1, const IntVectND<dim>& p2) noexcept
923 : {
924 : IntVectND<dim> p(p1);
925 : p.min(p2);
926 : return p;
927 : }
928 :
929 : template<int dim>
930 : AMREX_GPU_HOST_DEVICE
931 : AMREX_FORCE_INLINE
932 : IntVectND<dim>
933 : elemwiseMin (const IntVectND<dim>& p1, const IntVectND<dim>& p2) noexcept
934 : {
935 : IntVectND<dim> p(p1);
936 : p.min(p2);
937 : return p;
938 : }
939 :
940 : /**
941 : * \brief Returns the IntVectND that is the component-wise maximum of two
942 : * argument IntVectNDs.
943 : */
944 : template<int dim>
945 : AMREX_GPU_HOST_DEVICE
946 : AMREX_FORCE_INLINE
947 : IntVectND<dim>
948 : max (const IntVectND<dim>& p1, const IntVectND<dim>& p2) noexcept
949 : {
950 : IntVectND<dim> p(p1);
951 : p.max(p2);
952 : return p;
953 : }
954 :
955 : template<int dim>
956 : AMREX_GPU_HOST_DEVICE
957 : AMREX_FORCE_INLINE
958 : IntVectND<dim>
959 : elemwiseMax (const IntVectND<dim>& p1, const IntVectND<dim>& p2) noexcept
960 : {
961 : IntVectND<dim> p(p1);
962 : p.max(p2);
963 : return p;
964 : }
965 :
966 : /**
967 : * \brief Returns a basis vector in the given coordinate direction;
968 : * eg. IntVectND<3> BASISV<3>(1) == (0,1,0). Note that the coordinate
969 : * directions are zero based.
970 : */
971 : template<int dim = AMREX_SPACEDIM>
972 : AMREX_GPU_HOST_DEVICE
973 : AMREX_FORCE_INLINE
974 : IntVectND<dim>
975 : BASISV (int dir) noexcept
976 : {
977 : BL_ASSERT(dir >= 0 && dir < dim);
978 : IntVectND<dim> tmp(0);
979 : tmp[dir] = 1;
980 : return tmp;
981 : }
982 :
983 : /**
984 : * \brief Returns a IntVectND obtained by multiplying each of the
985 : * components of this IntVectND by s.
986 : */
987 : template<int dim>
988 : AMREX_GPU_HOST_DEVICE
989 : AMREX_FORCE_INLINE
990 : IntVectND<dim>
991 : scale (const IntVectND<dim>& p, int s) noexcept
992 : {
993 : return IntVectND<dim>(p).scale(s);
994 : }
995 :
996 : /**
997 : * \brief Returns an IntVectND that is the reflection of input in the
998 : * plane which passes through ref_ix and normal to the
999 : * coordinate direction idir.
1000 : */
1001 : template<int dim>
1002 : AMREX_GPU_HOST_DEVICE
1003 : AMREX_FORCE_INLINE
1004 : IntVectND<dim>
1005 : reflect (const IntVectND<dim>& a, int ref_ix, int idir) noexcept
1006 : {
1007 : return IntVectND<dim>(a).reflect(ref_ix, idir);
1008 : }
1009 :
1010 : /**
1011 : * \brief Returns IntVectND obtained by adding s to each of the
1012 : * components of this IntVectND.
1013 : */
1014 : template<int dim>
1015 : AMREX_GPU_HOST_DEVICE
1016 : AMREX_FORCE_INLINE
1017 : IntVectND<dim>
1018 : diagShift (const IntVectND<dim>& p, int s) noexcept
1019 : {
1020 : return p + s;
1021 : }
1022 :
1023 : /**
1024 : * \brief Returns an IntVectND that is the component-wise integer
1025 : * projection of p by s.
1026 : */
1027 : template<int dim>
1028 : AMREX_GPU_HOST_DEVICE
1029 : AMREX_FORCE_INLINE
1030 : IntVectND<dim>
1031 : coarsen (const IntVectND<dim>& p, int s) noexcept
1032 : {
1033 : BL_ASSERT(s > 0);
1034 : IntVectND<dim> v = p;
1035 : v.coarsen(s);
1036 : return v;
1037 : }
1038 :
1039 : /**
1040 : * \brief Returns an IntVectND which is the component-wise integer
1041 : * projection of IntVectND p1 by IntVectND p2.
1042 : */
1043 : template<int dim>
1044 : AMREX_GPU_HOST_DEVICE
1045 : AMREX_FORCE_INLINE
1046 : IntVectND<dim>
1047 : coarsen (const IntVectND<dim>& p1, const IntVectND<dim>& p2) noexcept
1048 : {
1049 0 : IntVectND<dim> v = p1;
1050 : v.coarsen(p2);
1051 0 : return v;
1052 : }
1053 :
1054 : template<int dim, std::enable_if_t<( 1<=dim && dim<=3 ), int> = 0>
1055 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
1056 : Dim3 refine (Dim3 const& coarse, IntVectND<dim> const& ratio) noexcept
1057 : {
1058 : if constexpr (dim == 1) {
1059 : return Dim3{coarse.x*ratio[0], coarse.y, coarse.z};
1060 : } else if constexpr (dim == 2) {
1061 : return Dim3{coarse.x*ratio[0], coarse.y*ratio[1], coarse.z};
1062 : } else {
1063 : return Dim3{coarse.x*ratio[0], coarse.y*ratio[1], coarse.z*ratio[2]};
1064 : }
1065 : }
1066 :
1067 : template<int dim, std::enable_if_t<( 1<=dim && dim<=3 ), int> = 0>
1068 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
1069 : Dim3 coarsen (Dim3 const& fine, IntVectND<dim> const& ratio) noexcept
1070 : {
1071 : if constexpr (dim == 1) {
1072 : return Dim3{amrex::coarsen(fine.x, ratio[0]),
1073 : fine.y,
1074 : fine.z};
1075 : } else if constexpr (dim == 2) {
1076 : return Dim3{amrex::coarsen(fine.x, ratio[0]),
1077 : amrex::coarsen(fine.y, ratio[1]),
1078 : fine.z};
1079 : } else {
1080 : return Dim3{amrex::coarsen(fine.x, ratio[0]),
1081 : amrex::coarsen(fine.y, ratio[1]),
1082 : amrex::coarsen(fine.z, ratio[2])};
1083 : }
1084 : }
1085 :
1086 : namespace detail {
1087 : std::ostream& int_vector_write (std::ostream& os, const int* iv, int dim);
1088 : std::istream& int_vector_read (std::istream& is, int* iv, int dim);
1089 :
1090 : template<int dim>
1091 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
1092 : void IntVectCat_imp (int*& dst, const IntVectND<dim>& src) noexcept {
1093 : for (int i=0; i<dim; ++i) {
1094 : dst[i] = src[i];
1095 : }
1096 : dst += dim;
1097 : }
1098 :
1099 : template<int dim>
1100 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
1101 : void IntVectSplit_imp2 (IntVectND<dim>& dst, const int*& src) noexcept {
1102 : for (int i=0; i<dim; ++i) {
1103 : dst[i] = src[i];
1104 : }
1105 : src += dim;
1106 : }
1107 :
1108 : template<class T, std::size_t...Ns>
1109 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
1110 : T IntVectSplit_imp (T& retval, std::index_sequence<Ns...>, const int * src) noexcept {
1111 : (IntVectSplit_imp2(amrex::get<Ns>(retval), src), ...);
1112 : return retval;
1113 : }
1114 :
1115 : template<int...dims>
1116 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr
1117 : int get_sum () {
1118 : return (0 + ... + dims);
1119 : }
1120 : }
1121 :
1122 : template<int dim>
1123 : std::ostream&
1124 : operator<< (std::ostream& os, const IntVectND<dim>& iv)
1125 : {
1126 : return detail::int_vector_write(os, iv.begin(), dim);
1127 : }
1128 :
1129 : template<int dim>
1130 : std::istream&
1131 : operator>> (std::istream& is, IntVectND<dim>& iv)
1132 : {
1133 : return detail::int_vector_read(is, iv.begin(), dim);
1134 : }
1135 :
1136 : /**
1137 : * \brief Returns a IntVectND obtained by concatenating the input IntVectNDs.
1138 : * The dimension of the return value equals the sum of the dimensions of the inputted IntVectNDs.
1139 : */
1140 : template<int d, int...dims>
1141 : AMREX_GPU_HOST_DEVICE
1142 : AMREX_FORCE_INLINE
1143 : constexpr IntVectND<detail::get_sum<d, dims...>()>
1144 : IntVectCat (const IntVectND<d>& v, const IntVectND<dims>&...vects) noexcept {
1145 : IntVectND<detail::get_sum<d, dims...>()> retval (0);
1146 : int* dst = retval.begin();
1147 : detail::IntVectCat_imp(dst, v);
1148 : (detail::IntVectCat_imp(dst, vects), ...);
1149 : return retval;
1150 : }
1151 :
1152 : /**
1153 : * \brief Returns a tuple of IntVectND obtained by splitting the input IntVectND
1154 : * according to the dimensions specified by the template arguments.
1155 : */
1156 : template<int d, int...dims>
1157 : AMREX_GPU_HOST_DEVICE
1158 : AMREX_FORCE_INLINE
1159 : constexpr GpuTuple<IntVectND<d>, IntVectND<dims>...>
1160 : IntVectSplit (const IntVectND<detail::get_sum<d, dims...>()>& v) noexcept {
1161 : GpuTuple<IntVectND<d>, IntVectND<dims>...> retval;
1162 : return detail::IntVectSplit_imp(retval,
1163 : std::make_index_sequence<1 + sizeof...(dims)>(),
1164 : v.begin());
1165 : }
1166 :
1167 : /**
1168 : * \brief Returns a new IntVectND of size new_dim and
1169 : * assigns the first new_dim values of iv to it.
1170 : */
1171 : template<int new_dim, int old_dim>
1172 : AMREX_GPU_HOST_DEVICE
1173 : AMREX_FORCE_INLINE
1174 : constexpr IntVectND<new_dim>
1175 : IntVectShrink (const IntVectND<old_dim>& iv) noexcept {
1176 : return iv.template shrink<new_dim>();
1177 : }
1178 :
1179 : /**
1180 : * \brief Returns a new IntVectND of size new_dim and
1181 : * assigns all values of iv to it andĀ fill_extra to the remaining elements.
1182 : */
1183 : template<int new_dim, int old_dim>
1184 : AMREX_GPU_HOST_DEVICE
1185 : AMREX_FORCE_INLINE
1186 : constexpr IntVectND<new_dim>
1187 : IntVectExpand (const IntVectND<old_dim>& iv, int fill_extra=0) noexcept {
1188 : return iv.template expand<new_dim>(fill_extra);
1189 : }
1190 :
1191 : /**
1192 : * \brief Returns a new IntVectND of size new_dim
1193 : * by either shrinking or expanding iv.
1194 : */
1195 : template<int new_dim, int old_dim>
1196 : AMREX_GPU_HOST_DEVICE
1197 : AMREX_FORCE_INLINE
1198 : constexpr IntVectND<new_dim>
1199 : IntVectResize (const IntVectND<old_dim>& iv, int fill_extra=0) noexcept {
1200 : return iv.template resize<new_dim>(fill_extra);
1201 : }
1202 :
1203 : } // namespace amrex
1204 :
1205 : // Spcialize std::tuple_size for IntVectND. Used by structured bindings.
1206 : template<int dim>
1207 : struct std::tuple_size<amrex::IntVectND<dim>> {
1208 : static constexpr std::size_t value = dim;
1209 : };
1210 :
1211 : // Spcialize std::tuple_element for IntVectND. Used by structured bindings.
1212 : template<std::size_t s, int dim>
1213 : struct std::tuple_element<s, amrex::IntVectND<dim>> {
1214 : using type = int;
1215 : };
1216 :
1217 : #endif /*AMREX_INTVECT_H*/
|