Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 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 455029514 : iterator (T i) : _i(i) {} 65 : 66 1050058509 : T operator* () const { return _i; } 67 : 68 1041723276 : const iterator & operator++ () 69 : { 70 >15526*10^7 : ++_i; 71 >14328*10^7 : return *this; 72 : } 73 : 74 : iterator operator++ (int) 75 : { 76 : iterator returnval(*this); 77 : ++_i; 78 : return returnval; 79 : } 80 : 81 1269238033 : bool operator== (const iterator & j) const 82 : { 83 1269238033 : return ( _i == j._i ); 84 : } 85 : 86 1269238033 : bool operator!= (const iterator & j) const 87 : { 88 1269238033 : return !(*this == j); 89 : } 90 : 91 : private: 92 : T _i; 93 : }; 94 : 95 : template <typename U, typename V> 96 252265623 : IntRange(U begin, V end) : 97 62268264 : _begin(cast_int<T>(begin)), 98 252265623 : _end(cast_int<T>(end)) 99 252265623 : {} 100 : 101 227514757 : iterator begin() const { return _begin; } 102 : 103 227514757 : iterator end () const { return _end; } 104 : 105 : private: 106 : iterator _begin, _end; 107 : }; 108 : 109 : 110 : 111 : /** 112 : * Helper function that returns an IntRange<std::size_t> representing 113 : * all the indices of the passed-in vector-like object (i.e. any type that 114 : * has a size() member). 115 : */ 116 : template <typename T> 117 221361097 : auto index_range(const T & sizable) 118 : { 119 545246962 : return IntRange<decltype(sizable.size())>(0, sizable.size()); 120 : } 121 : 122 : 123 : /** 124 : * Same thing but for NumericVector. Returns a range (first_local_index, last_local_index). 125 : */ 126 : template <typename T> 127 0 : IntRange<numeric_index_type> index_range(const NumericVector<T> & vec) 128 : { 129 0 : return {vec.first_local_index(), vec.last_local_index()}; 130 : } 131 : 132 : 133 : 134 : /** 135 : * The 2-parameter make_range() helper function returns an IntRange<T> 136 : * when both input parameters are of type T. This saves a bit of 137 : * typing over calling the IntRange<T> constructor directly. 138 : */ 139 : template <typename T> 140 3976884 : IntRange<T> make_range(T beg, T end) 141 : { 142 3976884 : return {beg, end}; 143 : } 144 : 145 : 146 : 147 : /** 148 : * The 1-parameter version of make_range() saves even more typing in 149 : * the common case of a 0 starting point. Example usage: 150 : * 151 : * for (auto i : make_range(10)) 152 : * 153 : * will loop from 0 to 9. In more realistic cases such as: 154 : * 155 : * for (auto i : make_range(foo())) 156 : * 157 : * this construction guarantees that the function foo() is called 158 : * exactly once rather than once per loop iteration. 159 : */ 160 : template <typename T> 161 150787225 : IntRange<T> make_range(T end) 162 : { 163 150787225 : return {T(0), end}; 164 : } 165 : 166 : } // namespace libMesh 167 : 168 : #endif // LIBMESH_INT_RANGE_H