LCOV - code coverage report
Current view: top level - include/utils - int_range.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 34 36 94.4 %
Date: 2026-06-03 14:29:06 Functions: 93 126 73.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #ifndef LIBMESH_INT_RANGE_H
      21             : #define LIBMESH_INT_RANGE_H
      22             : 
      23             : #include "libmesh/libmesh_common.h" // cast_int
      24             : 
      25             : // C++ includes
      26             : #include <vector>
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : // Forward declarations
      32             : template <typename T> class DenseSubVector;
      33             : template <typename T> class DenseVector;
      34             : template <typename T> class NumericVector;
      35             : 
      36             : /**
      37             :  * The \p IntRange templated class is intended to make it easy to
      38             :  * loop over integers which are indices of a container.
      39             :  *
      40             :  * In cases where such a range is defined by the result of a virtual
      41             :  * function call, this allows range-based for loops to be easily
      42             :  * written which make only a single such call, rather than a new call
      43             :  * for each iteration.
      44             :  *
      45             :  * We perform a cast_int operation (no-op in opt mode, test+assert in
      46             :  * debug) at construction time to make sure that the given range
      47             :  * bounds are representable by the given range type.
      48             :  *
      49             :  * \author  Roy H. Stogner
      50             :  */
      51             : 
      52             : template <typename T>
      53             : class IntRange
      54             : {
      55             : public:
      56             :   class iterator {
      57             :   public:
      58             :     using iterator_category = std::input_iterator_tag;
      59             :     using value_type = T;
      60             :     using difference_type = T;
      61             :     using pointer = T;
      62             :     using reference = T&;
      63             : 
      64   473012446 :     explicit iterator (T i) : _i(i) {}
      65             : 
      66  1122484949 :     T operator* () const { return _i; }
      67             : 
      68  1113738932 :     const iterator & operator++ ()
      69             :     {
      70 93303898336 :       ++_i;
      71 87169245858 :       return *this;
      72             :     }
      73             : 
      74             :     iterator operator++ (int)
      75             :     {
      76             :       iterator returnval(*this);
      77             :       ++_i;
      78             :       return returnval;
      79             :     }
      80             : 
      81             :     template <typename T2>
      82         256 :     void operator+= (T2 n)
      83             :     {
      84         480 :       _i += cast_int<T>(n);
      85         256 :     }
      86             : 
      87             :     template <typename T2>
      88         256 :     iterator operator+ (T2 n) const
      89             :     {
      90         256 :       iterator returnval(_i);
      91         256 :       returnval += n;
      92         256 :       return returnval;
      93             :     }
      94             : 
      95  1350245155 :     bool operator== (const iterator & j) const
      96             :     {
      97  1350245155 :       return ( _i == j._i );
      98             :     }
      99             : 
     100  1350245155 :     bool operator!= (const iterator & j) const
     101             :     {
     102  1350245155 :       return !(*this == j);
     103             :     }
     104             : 
     105             :   private:
     106             :     T _i;
     107             :   };
     108             : 
     109             :   typedef typename IntRange<T>::iterator const_iterator;
     110             : 
     111             :   template <typename U, typename V>
     112   261237555 :   IntRange(U begin, V end) :
     113    60896326 :     _begin(cast_int<T>(begin)),
     114   261237555 :     _end(cast_int<T>(end))
     115   261237555 :   {}
     116             : 
     117             :   // Signature needed for use in threads_pthread.h
     118         352 :   IntRange(const IntRange &,
     119             :            const const_iterator & begin,
     120             :            const const_iterator & end) :
     121          96 :     _begin(begin),
     122         352 :     _end(end)
     123         128 :   {}
     124             : 
     125   236508065 :   iterator begin() const { return _begin; }
     126             : 
     127   236508065 :   iterator end () const { return _end; }
     128             : 
     129         198 :   std::size_t size () const
     130        2286 :   { return *_end - *_begin; }
     131             : 
     132             : private:
     133             :   iterator _begin, _end;
     134             : };
     135             : 
     136             : 
     137             : template <typename T, typename T2>
     138             : typename IntRange<T>::iterator operator+ (T2 n, typename IntRange<T>::iterator i)
     139             : {
     140             :   return i + n;
     141             : }
     142             : 
     143             : 
     144             : /**
     145             :  * Helper function that returns an IntRange<std::size_t> representing
     146             :  * all the indices of the passed-in vector-like object (i.e. any type that
     147             :  * has a size() member).
     148             :  */
     149             : template <typename T>
     150   236616377 : auto index_range(const T & sizable)
     151             : {
     152   576625807 :   return IntRange<decltype(sizable.size())>(0, sizable.size());
     153             : }
     154             : 
     155             : 
     156             : /**
     157             :  * Same thing but for NumericVector. Returns a range (first_local_index, last_local_index).
     158             :  */
     159             : template <typename T>
     160           0 : IntRange<numeric_index_type> index_range(const NumericVector<T> & vec)
     161             : {
     162           0 :   return {vec.first_local_index(), vec.last_local_index()};
     163             : }
     164             : 
     165             : 
     166             : 
     167             : /**
     168             :  * The 2-parameter make_range() helper function returns an IntRange<T>
     169             :  * when both input parameters are of type T. This saves a bit of
     170             :  * typing over calling the IntRange<T> constructor directly.
     171             :  */
     172             : template <typename T>
     173     3974863 : IntRange<T> make_range(T beg, T end)
     174             : {
     175     3974863 :   return {beg, end};
     176             : }
     177             : 
     178             : 
     179             : 
     180             : /**
     181             :  * The 1-parameter version of make_range() saves even more typing in
     182             :  * the common case of a 0 starting point. Example usage:
     183             :  *
     184             :  * for (auto i : make_range(10))
     185             :  *
     186             :  * will loop from 0 to 9. In more realistic cases such as:
     187             :  *
     188             :  * for (auto i : make_range(foo()))
     189             :  *
     190             :  * this construction guarantees that the function foo() is called
     191             :  * exactly once rather than once per loop iteration.
     192             :  */
     193             : template <typename T>
     194   145487523 : IntRange<T> make_range(T end)
     195             : {
     196   145487523 :   return {T(0), end};
     197             : }
     198             : 
     199             : } // namespace libMesh
     200             : 
     201             : #endif // LIBMESH_INT_RANGE_H

Generated by: LCOV version 1.14