LCOV - code coverage report
Current view: top level - ext/amrex/3d-coverage-g++-24.08/include - AMReX_IntVect.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 58 70 82.9 %
Date: 2024-11-18 05:28:54 Functions: 3 4 75.0 %

          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     2982830 :     switch (ratio) {
      30           0 :     case  1: return i;
      31     2982830 :     case  2: return (i<0) ? -std::abs(i+1)/2    -1 : i/2;
      32           0 :     case  4: return (i<0) ? -std::abs(i+1)/4    -1 : i/4;
      33           0 :     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      807011 :     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   106621000 :     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      679869 :     explicit constexpr IntVectND (int s) noexcept {
     108     2719480 :         for (int i=0; i<dim; ++i) {
     109     2039610 :             vect[i] = s;
     110             :         }
     111      679869 :     }
     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             :             return Dim3{vect[0],vect[1],0};
     165             :         } else {
     166           0 :             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      511984 :         int retval = vect[0];
     202     1535952 :         for (int i=1; i<dim; ++i) {
     203     1023968 :             retval = retval > vect[i] ? retval : vect[i];
     204             :         }
     205      511984 :         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   641226387 :     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  1355655108 :     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   489611000 :     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      501908 :         bool retval = vect[0] != val;
     291     1505720 :         for (int i=1; i<dim; ++i) {
     292     1003816 :             retval = retval || vect[i] != val;
     293             :         }
     294      501908 :         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        6532 :         bool retval = vect[0] == rhs[0];
     302       19596 :         for (int i=1; i<dim; ++i) {
     303       13528 :             retval = retval && vect[i] == rhs[i];
     304             :         }
     305        6532 :         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         576 :         bool retval = vect[0] <= rhs[0];
     381        1728 :         for (int i=1; i<dim; ++i) {
     382        1950 :             retval = retval && vect[i] <= rhs[i];
     383             :         }
     384         576 :         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    75041316 :         bool retval = vect[0] >= rhs[0];
     431   225123648 :         for (int i=1; i<dim; ++i) {
     432   300164864 :             retval = retval && vect[i] >= rhs[i];
     433             :         }
     434    75041316 :         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     1516268 :         for (int i=0; i<dim; ++i) {
     474     1137201 :             vect[i] += p[i];
     475             :         }
     476      379067 :         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       38160 :         for (int i=0; i<dim; ++i) {
     492       28620 :             vect[i] *= p[i];
     493             :         }
     494        9540 :         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     1516268 :         for (int i=0; i<dim; ++i) {
     528     1137201 :             vect[i] -= p[i];
     529             :         }
     530      379067 :         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      369245 :         IntVectND<dim> retval = *this;
     551      369245 :         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     2265800 :         for (int i=0; i<dim; ++i) {
     593     1699350 :             vect[i] = (vect[i] < p.vect[i] ? vect[i] : p.vect[i]);
     594             :         }
     595      566450 :         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     2265800 :         for (int i=0; i<dim; ++i) {
     602     1699350 :             vect[i] = (vect[i] > p.vect[i] ? vect[i] : p.vect[i]);
     603             :         }
     604      566450 :         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     1958624 :         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     2899820 :         for (int i=0; i<dim; ++i) {
     639     2174870 :             vect[i] += s;
     640             :         }
     641      724956 :         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      281310 :         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           0 :         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      370507 :         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          33 :         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     3977100 :     for (int i=0; i<dim; ++i) {
     833     5965660 :         vect[i] = amrex::coarsen(vect[i], p.vect[i]);
     834             :     }
     835      994276 :     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           0 :     IntVectND<dim> retval = p;
     908           0 :     for (int i=0; i<dim; ++i) {
     909           0 :         retval[i] = s * retval[i];
     910             :     }
     911           0 :     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*/

Generated by: LCOV version 1.14