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