libMesh
chunked_mapvector.h
Go to the documentation of this file.
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_CHUNKED_MAPVECTOR_H
21 #define LIBMESH_CHUNKED_MAPVECTOR_H
22 
23 // C++ Includes -----------------------------------
24 #include <map>
25 
26 namespace libMesh
27 {
28 
42 template <typename Val, typename index_t=unsigned int, unsigned int N=16>
43 class chunked_mapvector : public std::map<index_t, std::array<Val,N>>
44 {
45 public:
46  typedef std::map<index_t, std::array<Val,N>> maptype;
47 
48  typedef unsigned int iter_t; // Only has to hold 0 through N
49 
50  template <typename MapIter>
52  {
53  public:
54  veclike_iterator_base(const MapIter & i,
55  const iter_t idx)
56  : it(i), array_index(idx) {}
57 
58  veclike_iterator_base(const veclike_iterator_base & i) = default;
59 
60  template <typename T>
62  : it(i.it), array_index(i.idx) {}
63 
65  {
66  ++array_index;
67  if (array_index >= N)
68  {
69  array_index = 0;
70  ++it;
71  }
72  return *this;
73  }
74 
76  {
77  veclike_iterator i = *this;
78  ++(*this);
79  return i;
80  }
81 
82  bool operator==(const veclike_iterator_base & other) const
83  {
84  return (it == other.it && array_index == other.array_index);
85  }
86 
87  bool operator!=(const veclike_iterator_base & other) const
88  {
89  return (it != other.it || array_index != other.array_index);
90  }
91 
92  index_t index() const { return this->it->first * N + this->array_index; }
93 
94  private:
95  friend class chunked_mapvector;
96 
97  MapIter it;
98 
100  };
101 
103  public veclike_iterator_base<typename maptype::iterator>
104  {
105  public:
106  veclike_iterator(const typename maptype::iterator & i,
107  const iter_t idx)
108  : veclike_iterator_base<typename maptype::iterator>(i,idx) {}
109 
110  Val & operator*() const { return (this->it->second)[this->array_index]; }
111 
112  Val * operator->() const { return &((this->it->second)[this->array_index]); }
113  };
114 
115 
117  public veclike_iterator_base<typename maptype::const_iterator>
118  {
119  public:
120  const_veclike_iterator(const typename maptype::const_iterator & i,
121  const iter_t idx)
122  : veclike_iterator_base<typename maptype::const_iterator>(i,idx) {}
123 
124  const Val & operator*() const { return (this->it->second)[this->array_index]; }
125 
126  const Val * operator->() const { return &((this->it->second)[this->array_index]); }
127  };
128 
130  {
131  public:
132  const_reverse_veclike_iterator(const typename maptype::const_reverse_iterator & i,
133  const iter_t idx)
134  : it(i), array_index(idx) {}
135 
137 
139  {
140  if (array_index == 0)
141  {
142  array_index = N-1;
143  ++it;
144  }
145  else
146  --array_index;
147  return *this;
148  }
149 
151  {
152  veclike_iterator i = *this;
153  ++(*this);
154  return i;
155  }
156 
157  const Val & operator*() const { return (this->it->second)[this->array_index]; }
158 
159  const Val * operator->() const { return &((this->it->second)[this->array_index]); }
160 
161  index_t index() const { return this->it->first * N + this->array_index; }
162 
163  bool operator==(const const_reverse_veclike_iterator & other) const
164  {
165  return (it == other.it && array_index == other.array_index);
166  }
167 
168  bool operator!=(const const_reverse_veclike_iterator & other) const
169  {
170  return (it != other.it || array_index != other.array_index);
171  }
172 
173  private:
174  typename maptype::const_reverse_iterator it;
175 
177  };
178 
179  veclike_iterator find (const index_t & k)
180  {
181  auto sub_it = maptype::find(k/N);
182  if (sub_it == maptype::end())
183  return veclike_iterator(sub_it, 0);
184 
185  veclike_iterator it {sub_it, iter_t(k%N)};
186  if (*it)
187  return it;
188  return this->end();
189  }
190 
191  const_veclike_iterator find (const index_t & k) const
192  {
193  auto sub_it = maptype::find(k/N);
194  if (sub_it == maptype::end())
195  return const_veclike_iterator(sub_it, 0);
196 
197  const_veclike_iterator it {sub_it, iter_t(k%N)};
198  if (*it)
199  return it;
200  return this->end();
201  }
202 
203  Val & operator[] (const index_t & k)
204  {
205  return maptype::operator[](k/N)[k%N];
206  }
207 
208  Val operator[] (const index_t & k) const
209  {
210  typename maptype::const_iterator it = maptype::find(k/N);
211  return it == this->end().it? Val() : (it->second)[k%N];
212  }
213 
214  void erase(index_t i)
215  {
216  typename maptype::iterator it = maptype::find(i/N);
217  if (it == maptype::end())
218  return;
219 
220  (it->second)[i%N] = Val();
221  for (auto v : it->second)
222  if (v != Val())
223  return;
224 
225  maptype::erase(it);
226  }
227 
229  {
230  if (pos.it == maptype::end())
231  return pos;
232  *pos = Val();
233 
234  veclike_iterator newpos = pos;
235  do {
236  ++newpos;
237  } while (newpos.it == pos.it &&
238  *newpos == Val());
239 
240  for (auto v : pos.it->second)
241  if (v != Val())
242  return newpos;
243 
244  maptype::erase(pos.it);
245 
246  return newpos;
247  }
248 
250  {
251  return veclike_iterator(maptype::begin(), 0);
252  }
253 
255  {
256  return const_veclike_iterator(maptype::begin(), 0);
257  }
258 
260  {
261  return veclike_iterator(maptype::end(), 0);
262  }
263 
265  {
266  return const_veclike_iterator(maptype::end(), 0);
267  }
268 
270  {
271  return const_reverse_veclike_iterator(maptype::rbegin(), N-1);
272  }
273 
275  {
276  return const_reverse_veclike_iterator(maptype::rend(), N-1);
277  }
278 };
279 
280 } // namespace libMesh
281 
282 #endif // LIBMESH_CHUNKED_MAPVECTOR_H
veclike_iterator erase(const veclike_iterator &pos)
bool operator==(const veclike_iterator_base &other) const
veclike_iterator_base(const veclike_iterator_base< T > &i)
bool operator!=(const const_reverse_veclike_iterator &other) const
Val & operator[](const index_t &k)
veclike_iterator(const typename maptype::iterator &i, const iter_t idx)
const_veclike_iterator find(const index_t &k) const
const_veclike_iterator begin() const
The libMesh namespace provides an interface to certain functionality in the library.
veclike_iterator_base(const MapIter &i, const iter_t idx)
const_veclike_iterator end() const
const_veclike_iterator(const typename maptype::const_iterator &i, const iter_t idx)
const_reverse_veclike_iterator rend() const
const_reverse_veclike_iterator rbegin() const
std::map< index_t, std::array< Val, N > > maptype
bool operator!=(const veclike_iterator_base &other) const
bool operator==(const const_reverse_veclike_iterator &other) const
This chunked_mapvector templated class is intended to provide the asymptotic performance characterist...
veclike_iterator find(const index_t &k)
const_reverse_veclike_iterator(const typename maptype::const_reverse_iterator &i, const iter_t idx)
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
A useful inline function which replaces the macros used previously.