LCOV - code coverage report
Current view: top level - src/Index - Index.hpp (source / functions) Coverage Total Hit
Test: report.info Lines: 19.3 % 166 32
Test Date: 2025-05-21 12:05:18 Functions: 40.0 % 25 10
Branches: 3.0 % 134 4

             Branch data     Line data    Source code
       1                 :             : //
       2                 :             : // Class Index
       3                 :             : //   Define a slice in an array.
       4                 :             : //
       5                 :             : //   This essentially defines a list of evenly spaced numbers.
       6                 :             : //   Most commonly this list will be increasing (positive stride)
       7                 :             : //   but it can also have negative stride and be decreasing.
       8                 :             : //
       9                 :             : //   Index()      --> A null interval with no elements.
      10                 :             : //   Index(n)     --> make an Index on [0..n-1]
      11                 :             : //   Index(a,b)   --> make an Index on [a..b]
      12                 :             : //   Index(a,b,s) --> make an Index on [a..b] with stride s
      13                 :             : //
      14                 :             : //   Example1:
      15                 :             : //   --------
      16                 :             : //   Index I(10);           --> Index on [0..9]
      17                 :             : //   Index Low(5);          --> Index on [0..4]
      18                 :             : //   Index High(5,9);       --> Index on [5..9]
      19                 :             : //   Index IOdd(1,9,2);     --> Index on [1..9] stride 2
      20                 :             : //   Index IEven(0,9,2);    --> Index on [0..9] stride 2
      21                 :             : //
      22                 :             : //   Given an Index I(a,n,s), and an integer j you can do the following:
      23                 :             : //
      24                 :             : //   I+j  : a+j+i*s        for i in [0..n-1]
      25                 :             : //   j-I  : j-a-i*s
      26                 :             : //   j*I  : j*a + i*j*s
      27                 :             : //   I/j  : a/j + i*s/j
      28                 :             : //
      29                 :             : //   j/I we don't do because it is not a uniform stride, and we don't
      30                 :             : //   allow strides that are fractions.
      31                 :             : //
      32                 :             : #include "Utility/PAssert.h"
      33                 :             : 
      34                 :             : namespace ippl {
      35                 :             : 
      36                 :       14996 :     KOKKOS_INLINE_FUNCTION Index::Index()
      37                 :       14996 :         : first_m(0)
      38                 :       14996 :         , stride_m(0)
      39                 :       14996 :         , length_m(0) {}
      40                 :             : 
      41                 :        2478 :     KOKKOS_INLINE_FUNCTION Index::Index(size_t n)
      42                 :        2478 :         : first_m(0)
      43                 :        2478 :         , stride_m(1)
      44                 :        2478 :         , length_m(n) {}
      45                 :             : 
      46                 :        1252 :     KOKKOS_INLINE_FUNCTION Index::Index(int f, int l)
      47                 :        1252 :         : first_m(f)
      48                 :        1252 :         , stride_m(1)
      49                 :        1252 :         , length_m(l - f + 1) {
      50         [ -  + ]:        1252 :         PAssert_GE(l - f + 1, 0);
      51                 :        1252 :     }
      52                 :             : 
      53                 :           0 :     KOKKOS_INLINE_FUNCTION Index::Index(int f, int l, int s)
      54                 :           0 :         : first_m(f)
      55                 :           0 :         , stride_m(s) {
      56         [ #  # ]:           0 :         PAssert_NE(s, 0);
      57         [ #  # ]:           0 :         if (f == l) {
      58                 :           0 :             length_m = 1;
      59         [ #  # ]:           0 :         } else if ((l > f) ^ (s < 0)) {
      60                 :           0 :             length_m = (l - f) / s + 1;
      61                 :             :         } else {
      62                 :           0 :             length_m = 0;
      63                 :             :         }
      64                 :           0 :     }
      65                 :             : 
      66                 :           0 :     KOKKOS_INLINE_FUNCTION Index::Index(int m, int a, const Index& b)
      67                 :           0 :         : first_m(b.first_m * m + a)
      68                 :           0 :         , stride_m(b.stride_m * m)
      69                 :           0 :         , length_m(b.length_m) {}
      70                 :             : 
      71                 :             :     KOKKOS_INLINE_FUNCTION Index::Index(int f, int s, const Index* b)
      72                 :             :         : first_m(f)
      73                 :             :         , stride_m(s)
      74                 :             :         , length_m(b->length_m) {}
      75                 :             : 
      76                 :    28011048 :     KOKKOS_INLINE_FUNCTION int Index::first() const noexcept {
      77                 :    28011048 :         return first_m;
      78                 :             :     }
      79                 :             : 
      80                 :          42 :     KOKKOS_INLINE_FUNCTION int Index::stride() const noexcept {
      81                 :          42 :         return stride_m;
      82                 :             :     }
      83                 :             : 
      84                 :             :     KOKKOS_INLINE_FUNCTION bool Index::empty() const noexcept {
      85                 :             :         return length_m == 0;
      86                 :             :     }
      87                 :             : 
      88                 :    13926230 :     KOKKOS_INLINE_FUNCTION size_t Index::length() const noexcept {
      89                 :    13926230 :         return length_m;
      90                 :             :     }
      91                 :             : 
      92                 :        1044 :     KOKKOS_INLINE_FUNCTION int Index::last() const noexcept {
      93         [ -  + ]:        1044 :         return (length_m == 0) ? first_m : first_m + stride_m * (length_m - 1);
      94                 :             :     }
      95                 :             : 
      96                 :         840 :     KOKKOS_INLINE_FUNCTION int Index::min() const noexcept {
      97         [ +  - ]:         840 :         return (stride_m >= 0) ? first_m : first_m + stride_m * (length_m - 1);
      98                 :             :     }
      99                 :             : 
     100                 :         840 :     KOKKOS_INLINE_FUNCTION int Index::max() const noexcept {
     101         [ +  - ]:         840 :         return (stride_m >= 0) ? first_m + stride_m * (length_m - 1) : first_m;
     102                 :             :     }
     103                 :             : 
     104                 :           0 :     KOKKOS_INLINE_FUNCTION Index& Index::operator+=(int off) {
     105                 :           0 :         first_m += off;
     106                 :           0 :         return *this;
     107                 :             :     }
     108                 :             : 
     109                 :           0 :     KOKKOS_INLINE_FUNCTION Index& Index::operator-=(int off) {
     110                 :           0 :         first_m -= off;
     111                 :           0 :         return *this;
     112                 :             :     }
     113                 :             : 
     114                 :           0 :     KOKKOS_INLINE_FUNCTION Index operator+(const Index& i, int off) {
     115                 :           0 :         return Index(1, off, i);
     116                 :             :     }
     117                 :             : 
     118                 :             :     KOKKOS_INLINE_FUNCTION Index operator+(int off, const Index& i) {
     119                 :             :         return Index(1, off, i);
     120                 :             :     }
     121                 :             : 
     122                 :           0 :     KOKKOS_INLINE_FUNCTION Index operator-(const Index& i, int off) {
     123                 :           0 :         return Index(1, -off, i);
     124                 :             :     }
     125                 :             : 
     126                 :             :     KOKKOS_INLINE_FUNCTION Index operator-(int off, const Index& i) {
     127                 :             :         return Index(-1, off, i);
     128                 :             :     }
     129                 :             : 
     130                 :             :     KOKKOS_INLINE_FUNCTION Index operator-(const Index& i) {
     131                 :             :         return Index(-1, 0, i);
     132                 :             :     }
     133                 :             : 
     134                 :             :     KOKKOS_INLINE_FUNCTION Index operator*(const Index& i, int m) {
     135                 :             :         return Index(m, 0, i);
     136                 :             :     }
     137                 :             : 
     138                 :             :     KOKKOS_INLINE_FUNCTION Index operator*(int m, const Index& i) {
     139                 :             :         return Index(m, 0, i);
     140                 :             :     }
     141                 :             : 
     142                 :             :     KOKKOS_INLINE_FUNCTION Index operator/(const Index& i, int d) {
     143                 :             :         return Index(i.first_m / d, i.stride_m / d, &i);
     144                 :             :     }
     145                 :             : 
     146                 :           0 :     KOKKOS_INLINE_FUNCTION Index Index::reverse() const {
     147                 :           0 :         Index j;
     148                 :           0 :         j.first_m  = last();
     149                 :           0 :         j.length_m = length_m;
     150                 :           0 :         j.stride_m = -stride_m;
     151                 :           0 :         return j;
     152                 :             :     }
     153                 :             : 
     154                 :           0 :     KOKKOS_INLINE_FUNCTION bool Index::touches(const Index& a) const {
     155   [ #  #  #  # ]:           0 :         return (min() <= a.max()) && (max() >= a.min());
     156                 :             :     }
     157                 :             : 
     158                 :             :     KOKKOS_INLINE_FUNCTION bool Index::contains(const Index& a) const {
     159                 :             :         return (min() <= a.min()) && (max() >= a.max());
     160                 :             :     }
     161                 :             : 
     162                 :           0 :     KOKKOS_INLINE_FUNCTION bool Index::split(Index& l, Index& r) const {
     163         [ #  # ]:           0 :         PAssert_EQ(stride_m, 1);
     164         [ #  # ]:           0 :         PAssert_GT(length_m, 1);
     165                 :           0 :         auto mid = first_m + length_m / 2 - 1;
     166         [ #  # ]:           0 :         l        = Index(first_m, mid);
     167         [ #  # ]:           0 :         r        = Index(mid + 1, first_m + length_m - 1);
     168                 :           0 :         return true;
     169                 :             :     }
     170                 :             : 
     171                 :           0 :     KOKKOS_INLINE_FUNCTION bool Index::split(Index& l, Index& r, int i) const {
     172         [ #  # ]:           0 :         PAssert_EQ(stride_m, 1);
     173         [ #  # ]:           0 :         PAssert_GT(length_m, 1);
     174         [ #  # ]:           0 :         if (i >= first_m + static_cast<int>(length_m)) {
     175                 :           0 :             return false;
     176                 :             :         }
     177         [ #  # ]:           0 :         l = Index(first_m, i);
     178         [ #  # ]:           0 :         r = Index(i + 1, first_m + length_m - 1);
     179                 :           0 :         return true;
     180                 :             :     }
     181                 :             : 
     182                 :           0 :     KOKKOS_INLINE_FUNCTION bool Index::split(Index& l, Index& r, double a) const {
     183         [ #  # ]:           0 :         PAssert_EQ(stride_m, 1);
     184         [ #  # ]:           0 :         PAssert_GT(length_m, 1);
     185         [ #  # ]:           0 :         PAssert_LT(a, 1.0);
     186         [ #  # ]:           0 :         PAssert_GT(a, 0.0);
     187                 :           0 :         int mid = first_m + static_cast<int>(length_m * a + 0.5) - 1;
     188         [ #  # ]:           0 :         l       = Index(first_m, mid);
     189         [ #  # ]:           0 :         r       = Index(mid + 1, first_m + length_m - 1);
     190                 :           0 :         return true;
     191                 :             :     }
     192                 :             : 
     193                 :             :     //////////////////////////////////////////////////////////////////////
     194                 :             :     // Calculate the lowest common multiple of s1 and s2.
     195                 :             :     // put the result in s.
     196                 :             :     // Also calculate m1 = s/s1 and m2 = s/s2.
     197                 :             :     // This version is optimized for small s1 and s2 and
     198                 :             :     // just uses an exhaustive search.
     199                 :             :     //////////////////////////////////////////////////////////////////////
     200                 :           0 :     KOKKOS_INLINE_FUNCTION void lcm(int s1, int s2, int& s, int& m1, int& m2) {
     201         [ #  # ]:           0 :         PAssert_GT(s1, 0);  // For simplicity, make some assumptions.
     202         [ #  # ]:           0 :         PAssert_GT(s2, 0);
     203                 :           0 :         int i1  = s1;
     204                 :           0 :         int i2  = s2;
     205                 :           0 :         int _m1 = 1;
     206                 :           0 :         int _m2 = 1;
     207         [ #  # ]:           0 :         if (i2 < i1) {
     208                 :             :             while (true) {
     209         [ #  # ]:           0 :                 while (i2 < i1) {
     210                 :           0 :                     i2 += s2;
     211                 :           0 :                     ++_m2;
     212                 :             :                 }
     213         [ #  # ]:           0 :                 if (i1 == i2) {
     214                 :           0 :                     m1 = _m1;
     215                 :           0 :                     m2 = _m2;
     216                 :           0 :                     s  = i1;
     217                 :           0 :                     return;
     218                 :             :                 }
     219                 :           0 :                 i1 += s1;
     220                 :           0 :                 ++_m1;
     221                 :             :             }
     222                 :             :         } else {
     223                 :             :             while (true) {
     224         [ #  # ]:           0 :                 while (i1 < i2) {
     225                 :           0 :                     i1 += s1;
     226                 :           0 :                     ++_m1;
     227                 :             :                 }
     228         [ #  # ]:           0 :                 if (i1 == i2) {
     229                 :           0 :                     m1 = _m1;
     230                 :           0 :                     m2 = _m2;
     231                 :           0 :                     s  = i1;
     232                 :           0 :                     return;
     233                 :             :                 }
     234                 :           0 :                 i2 += s2;
     235                 :           0 :                 ++_m2;
     236                 :             :             }
     237                 :             :         }
     238                 :             :     }
     239                 :             : 
     240                 :             :     //
     241                 :             :     // Intersect, with the code for the common case of
     242                 :             :     // both strides equal to one.
     243                 :             :     //
     244                 :           0 :     KOKKOS_INLINE_FUNCTION Index Index::intersect(const Index& rhs) const {
     245                 :           0 :         Index ret;
     246   [ #  #  #  #  :           0 :         if ((stride() == 1) && (rhs.stride() == 1)) {
                   #  # ]
     247                 :           0 :             int lf       = first();
     248                 :           0 :             int rf       = rhs.first();
     249                 :           0 :             int ll       = last();
     250                 :           0 :             int rl       = rhs.last();
     251         [ #  # ]:           0 :             int f        = lf > rf ? lf : rf;
     252         [ #  # ]:           0 :             int l        = ll < rl ? ll : rl;
     253                 :           0 :             ret.first_m  = f;
     254         [ #  # ]:           0 :             ret.length_m = ((l >= f) ? l - f + 1 : 0);
     255                 :           0 :             ret.stride_m = 1;
     256                 :             :         } else
     257         [ #  # ]:           0 :             ret = general_intersect(rhs);
     258                 :           0 :         return ret;
     259                 :             :     }
     260                 :             : 
     261                 :          84 :     KOKKOS_INLINE_FUNCTION Index Index::grow(int ncells) const {
     262                 :          84 :         Index index;
     263                 :             : 
     264                 :          84 :         index.first_m  = this->first_m - ncells;
     265                 :          84 :         index.length_m = this->length_m + 2 * ncells;
     266                 :          84 :         index.stride_m = this->stride_m;
     267                 :             : 
     268                 :          84 :         return index;
     269                 :             :     }
     270                 :             : 
     271                 :           0 :     KOKKOS_INLINE_FUNCTION static Index do_intersect(const Index& a, const Index& b) {
     272   [ #  #  #  # ]:           0 :         PAssert_GT(a.stride(), 0);  // This should be assured by the
     273   [ #  #  #  # ]:           0 :         PAssert_GT(b.stride(), 0);  // caller of this function.
     274                 :             : 
     275                 :             :         int newStride;                 // The stride for the new index is
     276                 :             :         int a_mul, b_mul;              // a_mul=newStride/a.stride() ...
     277         [ #  # ]:           0 :         lcm(a.stride(), b.stride(),    // The input strides...
     278                 :             :             newStride, a_mul, b_mul);  // the lcm of the strides of a and b.
     279                 :             : 
     280                 :             :         // Find the offset from a.first() in units of newStride
     281                 :             :         // that puts the ranges close together.
     282                 :           0 :         int a_i   = (b.first() - a.first()) / a.stride();
     283                 :           0 :         int a_off = a.first() + a_i * a.stride();
     284         [ #  # ]:           0 :         if (a_off < b.first()) {
     285                 :           0 :             a_i++;
     286                 :           0 :             a_off += a.stride();
     287                 :             :         }
     288                 :             : 
     289   [ #  #  #  # ]:           0 :         PAssert_GE(a_off, b.first());  // make sure I'm understanding this right...
     290                 :             : 
     291                 :             :         // Now do an exhaustive search for the first point in common.
     292                 :             :         // Count over all possible offsets for a.
     293   [ #  #  #  #  :           0 :         for (int a_m = 0; (a_m < a_mul) && (a_i < (int)a.length());
                   #  # ]
     294                 :           0 :              a_m++, a_i++, a_off += a.stride()) {
     295                 :           0 :             int b_off = b.first();
     296                 :             :             // Count over all possible offsets for b.
     297   [ #  #  #  #  :           0 :             for (int b_m = 0; (b_m < b_mul) && (b_m < (int)b.length()); b_m++, b_off += b.stride())
                   #  # ]
     298         [ #  # ]:           0 :                 if (a_off == b_off) {  // If the offsets are the same, we found it!
     299                 :           0 :                     int am = a.max();  // Find the minimum maximum of a and b...
     300                 :           0 :                     int bm = b.max();
     301         [ #  # ]:           0 :                     int m  = am < bm ? am : bm;
     302         [ #  # ]:           0 :                     return Index(a_off, m, newStride);
     303                 :             :                 }
     304                 :             :         }
     305                 :           0 :         return Index(0);  // If we get to here there is no intersection.
     306                 :             :     }
     307                 :             : 
     308                 :           0 :     KOKKOS_INLINE_FUNCTION Index Index::general_intersect(const Index& that) const {
     309                 :             :         // If they just don't overlap, return null indexes.
     310   [ #  #  #  #  :           0 :         if ((min() > that.max()) || (that.min() > max()))
                   #  # ]
     311                 :           0 :             return Index(0);
     312   [ #  #  #  # ]:           0 :         if ((stride_m == 0) || (that.stride_m == 0))
     313                 :           0 :             return Index(0);
     314                 :             : 
     315                 :             :         // If one or the other counts -ve, reverse it and intersect result.
     316         [ #  # ]:           0 :         if (that.stride_m < 0)
     317         [ #  # ]:           0 :             return intersect(that.reverse());
     318         [ #  # ]:           0 :         if (stride_m < 0) {
     319                 :           0 :             Index r;
     320         [ #  # ]:           0 :             r = reverse().intersect(that).reverse();
     321                 :           0 :             return r;
     322                 :             :         }
     323                 :             : 
     324                 :             :         // Getting closer to the real thing: intersect them.
     325                 :             :         // Pass the one that starts lower as the first argument.
     326                 :           0 :         Index r;
     327         [ #  # ]:           0 :         if (first_m < that.first_m)
     328         [ #  # ]:           0 :             r = do_intersect(*this, that);
     329                 :             :         else
     330         [ #  # ]:           0 :             r = do_intersect(that, *this);
     331                 :             : 
     332                 :           0 :         return r;
     333                 :             :     }
     334                 :             : }  // namespace ippl
        

Generated by: LCOV version 2.0-1