Welcome to mirror list, hosted at ThFree Co, Russian Federation.

array_map.h « bits « lemon « lemon-1.3.1 « 3rd « quadriflow « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 355ee008246732565b190d8ab997f3d8026eb25b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/* -*- mode: C++; indent-tabs-mode: nil; -*-
 *
 * This file is a part of LEMON, a generic C++ optimization library.
 *
 * Copyright (C) 2003-2013
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
 *
 * Permission to use, modify and distribute this software is granted
 * provided that this copyright notice appears in all copies. For
 * precise terms see the accompanying LICENSE file.
 *
 * This software is provided "AS IS" with no warranty of any kind,
 * express or implied, and with no claim as to its suitability for any
 * purpose.
 *
 */

#ifndef LEMON_BITS_ARRAY_MAP_H
#define LEMON_BITS_ARRAY_MAP_H

#include <memory>

#include <lemon/bits/traits.h>
#include <lemon/bits/alteration_notifier.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>

// \ingroup graphbits
// \file
// \brief Graph map based on the array storage.

namespace lemon {

  // \ingroup graphbits
  //
  // \brief Graph map based on the array storage.
  //
  // The ArrayMap template class is graph map structure that automatically
  // updates the map when a key is added to or erased from the graph.
  // This map uses the allocators to implement the container functionality.
  //
  // The template parameters are the Graph, the current Item type and
  // the Value type of the map.
  template <typename _Graph, typename _Item, typename _Value>
  class ArrayMap
    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
  public:
    // The graph type.
    typedef _Graph GraphType;
    // The item type.
    typedef _Item Item;
    // The reference map tag.
    typedef True ReferenceMapTag;

    // The key type of the map.
    typedef _Item Key;
    // The value type of the map.
    typedef _Value Value;

    // The const reference type of the map.
    typedef const _Value& ConstReference;
    // The reference type of the map.
    typedef _Value& Reference;

    // The map type.
    typedef ArrayMap Map;

    // The notifier type.
    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;

  private:

    // The MapBase of the Map which imlements the core regisitry function.
    typedef typename Notifier::ObserverBase Parent;

    typedef std::allocator<Value> Allocator;

  public:

    // \brief Graph initialized map constructor.
    //
    // Graph initialized map constructor.
    explicit ArrayMap(const GraphType& graph) {
      Parent::attach(graph.notifier(Item()));
      allocate_memory();
      Notifier* nf = Parent::notifier();
      Item it;
      for (nf->first(it); it != INVALID; nf->next(it)) {
        int id = nf->id(it);;
        allocator.construct(&(values[id]), Value());
      }
    }

    // \brief Constructor to use default value to initialize the map.
    //
    // It constructs a map and initialize all of the the map.
    ArrayMap(const GraphType& graph, const Value& value) {
      Parent::attach(graph.notifier(Item()));
      allocate_memory();
      Notifier* nf = Parent::notifier();
      Item it;
      for (nf->first(it); it != INVALID; nf->next(it)) {
        int id = nf->id(it);;
        allocator.construct(&(values[id]), value);
      }
    }

  private:
    // \brief Constructor to copy a map of the same map type.
    //
    // Constructor to copy a map of the same map type.
    ArrayMap(const ArrayMap& copy) : Parent() {
      if (copy.attached()) {
        attach(*copy.notifier());
      }
      capacity = copy.capacity;
      if (capacity == 0) return;
      values = allocator.allocate(capacity);
      Notifier* nf = Parent::notifier();
      Item it;
      for (nf->first(it); it != INVALID; nf->next(it)) {
        int id = nf->id(it);;
        allocator.construct(&(values[id]), copy.values[id]);
      }
    }

    // \brief Assign operator.
    //
    // This operator assigns for each item in the map the
    // value mapped to the same item in the copied map.
    // The parameter map should be indiced with the same
    // itemset because this assign operator does not change
    // the container of the map.
    ArrayMap& operator=(const ArrayMap& cmap) {
      return operator=<ArrayMap>(cmap);
    }


    // \brief Template assign operator.
    //
    // The given parameter should conform to the ReadMap
    // concecpt and could be indiced by the current item set of
    // the NodeMap. In this case the value for each item
    // is assigned by the value of the given ReadMap.
    template <typename CMap>
    ArrayMap& operator=(const CMap& cmap) {
      checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
      const typename Parent::Notifier* nf = Parent::notifier();
      Item it;
      for (nf->first(it); it != INVALID; nf->next(it)) {
        set(it, cmap[it]);
      }
      return *this;
    }

  public:
    // \brief The destructor of the map.
    //
    // The destructor of the map.
    virtual ~ArrayMap() {
      if (attached()) {
        clear();
        detach();
      }
    }

  protected:

    using Parent::attach;
    using Parent::detach;
    using Parent::attached;

  public:

    // \brief The subscript operator.
    //
    // The subscript operator. The map can be subscripted by the
    // actual keys of the graph.
    Value& operator[](const Key& key) {
      int id = Parent::notifier()->id(key);
      return values[id];
    }

    // \brief The const subscript operator.
    //
    // The const subscript operator. The map can be subscripted by the
    // actual keys of the graph.
    const Value& operator[](const Key& key) const {
      int id = Parent::notifier()->id(key);
      return values[id];
    }

    // \brief Setter function of the map.
    //
    // Setter function of the map. Equivalent with map[key] = val.
    // This is a compatibility feature with the not dereferable maps.
    void set(const Key& key, const Value& val) {
      (*this)[key] = val;
    }

  protected:

    // \brief Adds a new key to the map.
    //
    // It adds a new key to the map. It is called by the observer notifier
    // and it overrides the add() member function of the observer base.
    virtual void add(const Key& key) {
      Notifier* nf = Parent::notifier();
      int id = nf->id(key);
      if (id >= capacity) {
        int new_capacity = (capacity == 0 ? 1 : capacity);
        while (new_capacity <= id) {
          new_capacity <<= 1;
        }
        Value* new_values = allocator.allocate(new_capacity);
        Item it;
        for (nf->first(it); it != INVALID; nf->next(it)) {
          int jd = nf->id(it);;
          if (id != jd) {
            allocator.construct(&(new_values[jd]), values[jd]);
            allocator.destroy(&(values[jd]));
          }
        }
        if (capacity != 0) allocator.deallocate(values, capacity);
        values = new_values;
        capacity = new_capacity;
      }
      allocator.construct(&(values[id]), Value());
    }

    // \brief Adds more new keys to the map.
    //
    // It adds more new keys to the map. It is called by the observer notifier
    // and it overrides the add() member function of the observer base.
    virtual void add(const std::vector<Key>& keys) {
      Notifier* nf = Parent::notifier();
      int max_id = -1;
      for (int i = 0; i < int(keys.size()); ++i) {
        int id = nf->id(keys[i]);
        if (id > max_id) {
          max_id = id;
        }
      }
      if (max_id >= capacity) {
        int new_capacity = (capacity == 0 ? 1 : capacity);
        while (new_capacity <= max_id) {
          new_capacity <<= 1;
        }
        Value* new_values = allocator.allocate(new_capacity);
        Item it;
        for (nf->first(it); it != INVALID; nf->next(it)) {
          int id = nf->id(it);
          bool found = false;
          for (int i = 0; i < int(keys.size()); ++i) {
            int jd = nf->id(keys[i]);
            if (id == jd) {
              found = true;
              break;
            }
          }
          if (found) continue;
          allocator.construct(&(new_values[id]), values[id]);
          allocator.destroy(&(values[id]));
        }
        if (capacity != 0) allocator.deallocate(values, capacity);
        values = new_values;
        capacity = new_capacity;
      }
      for (int i = 0; i < int(keys.size()); ++i) {
        int id = nf->id(keys[i]);
        allocator.construct(&(values[id]), Value());
      }
    }

    // \brief Erase a key from the map.
    //
    // Erase a key from the map. It is called by the observer notifier
    // and it overrides the erase() member function of the observer base.
    virtual void erase(const Key& key) {
      int id = Parent::notifier()->id(key);
      allocator.destroy(&(values[id]));
    }

    // \brief Erase more keys from the map.
    //
    // Erase more keys from the map. It is called by the observer notifier
    // and it overrides the erase() member function of the observer base.
    virtual void erase(const std::vector<Key>& keys) {
      for (int i = 0; i < int(keys.size()); ++i) {
        int id = Parent::notifier()->id(keys[i]);
        allocator.destroy(&(values[id]));
      }
    }

    // \brief Builds the map.
    //
    // It builds the map. It is called by the observer notifier
    // and it overrides the build() member function of the observer base.
    virtual void build() {
      Notifier* nf = Parent::notifier();
      allocate_memory();
      Item it;
      for (nf->first(it); it != INVALID; nf->next(it)) {
        int id = nf->id(it);;
        allocator.construct(&(values[id]), Value());
      }
    }

    // \brief Clear the map.
    //
    // It erase all items from the map. It is called by the observer notifier
    // and it overrides the clear() member function of the observer base.
    virtual void clear() {
      Notifier* nf = Parent::notifier();
      if (capacity != 0) {
        Item it;
        for (nf->first(it); it != INVALID; nf->next(it)) {
          int id = nf->id(it);
          allocator.destroy(&(values[id]));
        }
        allocator.deallocate(values, capacity);
        capacity = 0;
      }
    }

  private:

    void allocate_memory() {
      int max_id = Parent::notifier()->maxId();
      if (max_id == -1) {
        capacity = 0;
        values = 0;
        return;
      }
      capacity = 1;
      while (capacity <= max_id) {
        capacity <<= 1;
      }
      values = allocator.allocate(capacity);
    }

    int capacity;
    Value* values;
    Allocator allocator;

  };

}

#endif