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 472222164 : explicit iterator (T i) : _i(i) {} 65 : 66 1121266994 : T operator* () const { return _i; } 67 : 68 1112529148 : const iterator & operator++ () 69 : { 70 92397435498 : ++_i; 71 86277290189 : 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 0 : void operator+= (T2 n) 83 : { 84 0 : _i += cast_int<T>(n); 85 0 : } 86 : 87 : template <typename T2> 88 0 : iterator operator+ (T2 n) const 89 : { 90 0 : iterator returnval(_i); 91 0 : returnval += n; 92 0 : return returnval; 93 : } 94 : 95 1348640230 : bool operator== (const iterator & j) const 96 : { 97 1348640230 : return ( _i == j._i ); 98 : } 99 : 100 1348640230 : bool operator!= (const iterator & j) const 101 : { 102 1348640230 : 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 260733772 : IntRange(U begin, V end) : 113 60850560 : _begin(cast_int<T>(begin)), 114 260733772 : _end(cast_int<T>(end)) 115 260733772 : {} 116 : 117 : // Signature needed for use in threads_pthread.h 118 0 : IntRange(const IntRange &, 119 : const const_iterator & begin, 120 : const const_iterator & end) : 121 0 : _begin(begin), 122 0 : _end(end) 123 0 : {} 124 : 125 236112876 : iterator begin() const { return _begin; } 126 : 127 236112876 : iterator end () const { return _end; } 128 : 129 70 : std::size_t size () const 130 1934 : { return *_end - *_begin; } 131 : 132 : // For thread splitting control 133 1934 : std::size_t grainsize () const { return libMesh::default_grainsize(); } 134 : 135 : private: 136 : iterator _begin, _end; 137 : }; 138 : 139 : 140 : template <typename T, typename T2> 141 : typename IntRange<T>::iterator operator+ (T2 n, typename IntRange<T>::iterator i) 142 : { 143 : return i + n; 144 : } 145 : 146 : 147 : /** 148 : * Helper function that returns an IntRange<std::size_t> representing 149 : * all the indices of the passed-in vector-like object (i.e. any type that 150 : * has a size() member). 151 : */ 152 : template <typename T> 153 236151575 : auto index_range(const T & sizable) 154 : { 155 575711681 : return IntRange<decltype(sizable.size())>(0, sizable.size()); 156 : } 157 : 158 : 159 : /** 160 : * Same thing but for NumericVector. Returns a range (first_local_index, last_local_index). 161 : */ 162 : template <typename T> 163 0 : IntRange<numeric_index_type> index_range(const NumericVector<T> & vec) 164 : { 165 0 : return {vec.first_local_index(), vec.last_local_index()}; 166 : } 167 : 168 : 169 : 170 : /** 171 : * The 2-parameter make_range() helper function returns an IntRange<T> 172 : * when both input parameters are of type T. This saves a bit of 173 : * typing over calling the IntRange<T> constructor directly. 174 : */ 175 : template <typename T> 176 3804111 : IntRange<T> make_range(T beg, T end) 177 : { 178 3804111 : return {beg, end}; 179 : } 180 : 181 : 182 : 183 : /** 184 : * The 1-parameter version of make_range() saves even more typing in 185 : * the common case of a 0 starting point. Example usage: 186 : * 187 : * for (auto i : make_range(10)) 188 : * 189 : * will loop from 0 to 9. In more realistic cases such as: 190 : * 191 : * for (auto i : make_range(foo())) 192 : * 193 : * this construction guarantees that the function foo() is called 194 : * exactly once rather than once per loop iteration. 195 : */ 196 : template <typename T> 197 145298899 : IntRange<T> make_range(T end) 198 : { 199 145298899 : return {T(0), end}; 200 : } 201 : 202 : } // namespace libMesh 203 : 204 : #endif // LIBMESH_INT_RANGE_H