Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
VMap.h
1/*
2 * Copyright 2020 IFPEN-CEA
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * SPDX-License-Identifier: Apache-2.0
17 */
18
19#pragma once
20
21#include <alien/utils/ArrayUtils.h>
22#include <alien/utils/Precomp.h>
23#include <arccore/base/ArccoreGlobal.h>
24
25#define VMAP_USE_REALLOC
26
27/*------------------------------------------------------------------------------------------*/
28
29namespace Alien
30{
31
32/*------------------------------------------------------------------------------------------*/
33
34template <typename IndexT, typename DataT>
35DataT*
36intrusive_vmap_insert(IndexT new_index, Integer& hint_pos, Integer& size,
37 Integer capacity, IndexT* indexes, DataT* data)
38{
39 hint_pos =
40 ArrayScan::dichotomicPositionScan(new_index, ConstArrayView<IndexT>(size, indexes));
41 if (hint_pos < size and indexes[hint_pos] == new_index) {
42 return &data[hint_pos];
43 }
44 else if (size < capacity) {
45 for (Integer i = size; i > hint_pos; --i) {
46 data[i] = data[i - 1];
47 indexes[i] = indexes[i - 1];
48 }
49 indexes[hint_pos] = new_index;
50 data[hint_pos] = DataT();
51 ++size;
52 return &data[hint_pos];
53 }
54 else {
55 return NULL;
56 }
57}
58
59/*------------------------------------------------------------------------------------------*/
60
65template <typename IndexT, typename DataT>
66class VMap
67{
68 public:
69 class const_iterator;
70
71 class iterator
72 {
73 public:
74 iterator(VMap& vmap, Integer index)
75 : m_vmap(vmap)
76 , m_index(index)
77 {}
78
79 DataT& value() { return m_vmap.m_data[m_index]; }
80
81 const IndexT& key() const { return m_vmap.m_indexes[m_index]; }
82
83 iterator& operator++()
84 {
85 ++m_index;
86 return *this;
87 }
88
89 bool operator==(const iterator& i) const { return (m_index == i.m_index); }
90
91 bool operator!=(const iterator& i) const { return (m_index != i.m_index); }
92
93 private:
94 VMap& m_vmap;
95 Integer m_index;
96
97 private:
98 friend class const_iterator;
99 };
100
101 class const_iterator
102 {
103 public:
104 const_iterator(const VMap& vmap, Integer index)
105 : m_vmap(vmap)
106 , m_index(index)
107 {}
108
109 explicit const_iterator(const iterator& itr)
110 : m_vmap(itr.m_vmap)
111 , m_index(itr.m_index)
112 {}
113
114 const DataT& value() const { return m_vmap.m_data[m_index]; }
115
116 const IndexT& key() const { return m_vmap.m_indexes[m_index]; }
117
118 const_iterator& operator++()
119 {
120 ++m_index;
121 return *this;
122 }
123
124 bool operator==(const const_iterator& i) const { return (m_index == i.m_index); }
125
126 bool operator!=(const const_iterator& i) const { return (m_index != i.m_index); }
127
128 private:
129 const VMap& m_vmap;
130 Integer m_index;
131 };
132
133 public:
134 explicit VMap(Integer first_capacity = 4);
135
136 virtual ~VMap();
137
138 VMap(const VMap& vmap);
139
140 VMap& operator=(const VMap& vmap);
141
142 public:
143 DataT& operator[](IndexT index);
144
145 iterator find(IndexT index);
146
147 const_iterator find(IndexT index) const;
148
149 std::pair<iterator, bool> insert(IndexT index);
150
151 const_iterator begin() const { return const_iterator(*this, 0); }
152
153 const_iterator end() const { return const_iterator(*this, m_size); }
154
155 iterator begin() { return iterator(*this, 0); }
156
157 iterator end() { return iterator(*this, m_size); }
158
159 [[nodiscard]] Integer size() const { return m_size; }
160
161 private:
162 Integer m_size, m_capacity;
163 IndexT* m_indexes;
164 DataT* m_data;
165 void* m_memory_pool;
166
167 private:
168 static Integer new_capacity(Integer capacity);
169};
170
171/*------------------------------------------------------------------------------------------*/
172
173template <typename IndexT, typename DataT>
174VMap<IndexT, DataT>::VMap(const Integer first_capacity)
175: m_size(0)
176, m_capacity(first_capacity)
177{
178 m_memory_pool = malloc(m_capacity * (sizeof(IndexT) + sizeof(DataT)));
179 m_data = (DataT*)m_memory_pool;
180 m_indexes = (IndexT*)(m_data + m_capacity);
181}
182
183/*------------------------------------------------------------------------------------------*/
184
185template <typename IndexT, typename DataT>
186VMap<IndexT, DataT>::VMap(const VMap& vmap)
187: m_size(vmap.m_size)
188, m_capacity(vmap.m_capacity)
189{
190 m_memory_pool = malloc(m_capacity * (sizeof(IndexT) + sizeof(DataT)));
191 m_data = (DataT*)m_memory_pool;
192 m_indexes = (IndexT*)(m_data + m_capacity);
193 memcpy(
194 m_memory_pool, vmap.m_memory_pool, m_capacity * (sizeof(IndexT) + sizeof(DataT)));
195}
196
197/*------------------------------------------------------------------------------------------*/
198
199template <typename IndexT, typename DataT>
200VMap<IndexT, DataT>&
201VMap<IndexT, DataT>::operator=(const VMap& vmap)
202{
203 m_size = vmap.m_size;
204 m_capacity = vmap.m_capacity;
205 free(m_memory_pool);
206 m_memory_pool = malloc(m_capacity * (sizeof(IndexT) + sizeof(DataT)));
207 memcpy(
208 m_memory_pool, vmap.m_memory_pool, m_capacity * (sizeof(IndexT) + sizeof(DataT)));
209 m_data = (DataT*)m_memory_pool;
210 m_indexes = (IndexT*)(m_data + m_capacity);
211 return *this;
212}
213
214/*------------------------------------------------------------------------------------------*/
215
216template <typename IndexT, typename DataT>
217VMap<IndexT, DataT>::~VMap()
218{
219 free(m_memory_pool);
220}
221
222/*------------------------------------------------------------------------------------------*/
223
224template <typename IndexT, typename DataT>
225DataT&
226VMap<IndexT, DataT>::operator[](const IndexT index)
227{
228 return insert(index).first.value();
229}
230
231/*------------------------------------------------------------------------------------------*/
232
233template <typename IndexT, typename DataT>
234typename VMap<IndexT, DataT>::iterator
235VMap<IndexT, DataT>::find(const IndexT index)
236{
237 const Integer col =
238 ArrayScan::dichotomicScan(index, ConstArrayView<IndexT>(m_size, m_indexes));
239 if (col == -1)
240 return end();
241 else
242 return iterator(*this, col);
243}
244
245/*------------------------------------------------------------------------------------------*/
246
247template <typename IndexT, typename DataT>
248typename VMap<IndexT, DataT>::const_iterator
249VMap<IndexT, DataT>::find(const IndexT index) const
250{
251 const Integer col =
252 ArrayScan::dichotomicScan(index, ConstArrayView<IndexT>(m_size, m_indexes));
253 if (col == -1)
254 return end();
255 else
256 return const_iterator(*this, col);
257}
258
259/*------------------------------------------------------------------------------------------*/
260
261template <typename IndexT, typename DataT>
262std::pair<typename VMap<IndexT, DataT>::iterator, bool>
263VMap<IndexT, DataT>::insert(const IndexT index)
264{
265 Integer old_size = m_size;
266
267 Integer hint_pos = 0;
268 DataT* data =
269 intrusive_vmap_insert(index, hint_pos, m_size, m_capacity, m_indexes, m_data);
270 if (data == NULL) { // Too small: needs resize
271 Integer old_capacity = m_capacity;
272 m_capacity = new_capacity(m_capacity);
273 // std::cout << "Extending from " << old_capacity << " to " << m_capacity << "\n";
274
275#ifdef VMAP_USE_REALLOC
276 m_memory_pool = realloc(m_memory_pool, m_capacity * (sizeof(IndexT) + sizeof(DataT)));
277 m_data = (DataT*)m_memory_pool;
278 m_indexes = (IndexT*)(m_data + m_capacity);
279
280 auto* old_data = (DataT*)m_memory_pool;
281 auto* old_indexes = (IndexT*)(old_data + old_capacity);
282
283 for (Integer i = old_capacity; i > hint_pos; --i)
284 m_indexes[i] = old_indexes[i - 1];
285 m_indexes[hint_pos] = index;
286 for (Integer i = hint_pos; --i >= 0;)
287 m_indexes[i] = old_indexes[i];
288 for (Integer i = old_capacity; i > hint_pos; --i)
289 m_data[i] = old_data[i - 1];
290
291// Pas de copie des premières valeurs de data qui sont déjà bien placées
292#else /* VMAP_USE_REALLOC */
293 void* old_memory_pool = m_memory_pool;
294 DataT* old_data = (DataT*)old_memory_pool;
295 IndexT* old_indexes = (IndexT*)(old_data + old_capacity);
296
297 m_memory_pool = malloc(m_capacity * (sizeof(IndexT) + sizeof(DataT)));
298 // memset(m_memory_pool, -1, m_capacity*(sizeof(IndexT)+sizeof(DataT))); // raw debug
299
300 m_data = (DataT*)m_memory_pool;
301 m_indexes = (IndexT*)(m_data + m_capacity);
302
303 for (Integer i = old_capacity; i > hint_pos; --i)
304 m_indexes[i] = old_indexes[i - 1];
305 m_indexes[hint_pos] = index;
306 for (Integer i = hint_pos; --i >= 0;)
307 m_indexes[i] = old_indexes[i];
308 for (Integer i = old_capacity; i > hint_pos; --i)
309 m_data[i] = old_data[i - 1];
310 for (Integer i = 0; i < hint_pos; ++i)
311 m_data[i] = old_data[i];
312
313 free(old_memory_pool);
314#endif /* VMAP_USE_RealLOC */
315
316 ++m_size;
317 m_data[hint_pos] = DataT();
318 }
319
320 return std::pair<iterator, bool>(iterator(*this, hint_pos), m_size != old_size);
321}
322
323/*------------------------------------------------------------------------------------------*/
324
325template <typename IndexT, typename DataT>
326Integer
327VMap<IndexT, DataT>::new_capacity(const Integer capacity)
328{
329 if (capacity < 20)
330 return capacity + 4;
331 else if (capacity < 4096)
332 return 2 * capacity + 12;
333 else
334 return capacity + 4096;
335}
336
337/*------------------------------------------------------------------------------------------*/
338
339} // namespace Alien
Integer dichotomicScan(const T &x, ConstArrayView< T > v)
Definition ArrayUtils.h:133
Integer dichotomicPositionScan(const T &x, ConstArrayView< T > v)
Definition ArrayUtils.h:183
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17