lemon/bits/array_map.h
author deba
Wed, 23 Nov 2005 15:42:36 +0000
changeset 1829 183b4cbf9733
parent 1810 474d093466a5
child 1875 98698b69a902
permissions -rw-r--r--
Correcting alteration notifing
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@906
    16
alpar@921
    17
#ifndef LEMON_ARRAY_MAP_H
alpar@921
    18
#define LEMON_ARRAY_MAP_H
deba@822
    19
deba@822
    20
#include <memory>
deba@1810
    21
#include <lemon/bits/map_extender.h>
deba@1813
    22
#include <lemon/bits/alteration_notifier.h>
deba@1669
    23
#include <lemon/concept_check.h>
deba@1669
    24
#include <lemon/concept/maps.h>
deba@822
    25
deba@1669
    26
/// \ingroup graphmapfactory
deba@1669
    27
/// \file
deba@1669
    28
/// \brief Graph maps that construct and destruct
deba@1669
    29
/// their elements dynamically.
deba@822
    30
alpar@921
    31
namespace lemon {
deba@822
    32
deba@1669
    33
  /// \ingroup graphmapfactory
deba@1669
    34
  ///
deba@1669
    35
  /// \brief Graph map based on the array storage.
deba@1669
    36
  ///
deba@1414
    37
  /// The ArrayMap template class is graph map structure what
deba@1414
    38
  /// automatically updates the map when a key is added to or erased from
deba@1669
    39
  /// the map. This map uses the allocators to implement 
deba@1414
    40
  /// the container functionality.
deba@1414
    41
  ///
deba@1414
    42
  /// The template parameter is the AlterationNotifier that the maps
deba@1414
    43
  /// will belong to and the Value.
deba@822
    44
klao@946
    45
  template <typename _Graph, 
klao@946
    46
	    typename _Item,
klao@946
    47
	    typename _Value>
deba@1039
    48
  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
deba@897
    49
deba@1267
    50
    typedef _Item Item;
deba@822
    51
  public:
deba@822
    52
    /// The graph type of the maps. 
klao@946
    53
    typedef _Graph Graph;
deba@1719
    54
    /// The reference map tag.
deba@1719
    55
    typedef True ReferenceMapTag;
deba@1719
    56
deba@822
    57
    /// The key type of the maps.
alpar@987
    58
    typedef _Item Key;
deba@1719
    59
    /// The value type of the map.
deba@1719
    60
    typedef _Value Value;
deba@1719
    61
    /// The const reference type of the map.
deba@1719
    62
    typedef const _Value& ConstReference;
deba@1719
    63
    /// The reference type of the map.
deba@1719
    64
    typedef _Value& Reference;
deba@1719
    65
deba@1719
    66
    typedef const Value ConstValue;
deba@1719
    67
    typedef Value* Pointer;
deba@1719
    68
    typedef const Value* ConstPointer;
klao@946
    69
deba@1039
    70
    typedef AlterationNotifier<_Item> Registry;
klao@946
    71
deba@822
    72
    /// The MapBase of the Map which imlements the core regisitry function.
klao@946
    73
    typedef typename Registry::ObserverBase Parent;
deba@822
    74
		
deba@822
    75
deba@822
    76
klao@946
    77
  private:
deba@822
    78
    typedef std::allocator<Value> Allocator;
deba@822
    79
klao@946
    80
klao@946
    81
  public:
klao@946
    82
deba@1719
    83
    /// \brief Graph initialized map constructor.
deba@1703
    84
    ///
deba@1719
    85
    /// Graph initialized map constructor.
deba@980
    86
    ArrayMap(const Graph& _g) : graph(&_g) {
deba@1267
    87
      Item it;
deba@1267
    88
      attach(_g.getNotifier(Item()));
deba@822
    89
      allocate_memory();
deba@1267
    90
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
    91
	int id = graph->id(it);;
deba@822
    92
	allocator.construct(&(values[id]), Value());
deba@822
    93
      }								
deba@822
    94
    }
deba@822
    95
deba@1703
    96
    /// \brief Constructor to use default value to initialize the map. 
deba@1703
    97
    ///
deba@1703
    98
    /// It constructs a map and initialize all of the the map. 
deba@980
    99
    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
deba@1267
   100
      Item it;
deba@1039
   101
      attach(_g.getNotifier(_Item()));
deba@822
   102
      allocate_memory();
deba@1267
   103
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   104
	int id = graph->id(it);;
klao@946
   105
	allocator.construct(&(values[id]), _v);
deba@822
   106
      }								
deba@822
   107
    }
deba@822
   108
deba@1703
   109
    /// \brief Constructor to copy a map of the same map type.
deba@1703
   110
    ///
deba@1703
   111
    /// Constructor to copy a map of the same map type.     
alpar@1613
   112
    ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
klao@946
   113
      if (copy.attached()) {
klao@946
   114
	attach(*copy.getRegistry());
klao@946
   115
      }
deba@822
   116
      capacity = copy.capacity;
deba@822
   117
      if (capacity == 0) return;
deba@822
   118
      values = allocator.allocate(capacity);
deba@1267
   119
      Item it;
deba@1267
   120
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   121
	int id = graph->id(it);;
deba@891
   122
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   123
      }
deba@822
   124
    }
deba@822
   125
deba@1669
   126
    /// \brief The destructor of the map.
deba@1669
   127
    ///     
deba@1414
   128
    /// The destructor of the map.
klao@946
   129
    virtual ~ArrayMap() {      
klao@946
   130
      if (attached()) {
klao@946
   131
	clear();
klao@946
   132
	detach();
deba@822
   133
      }
deba@822
   134
    }
deba@1669
   135
		
deba@1669
   136
  private:
deba@1669
   137
deba@1669
   138
    ArrayMap& operator=(const ArrayMap&);
deba@1669
   139
deba@1669
   140
  protected:
deba@1669
   141
deba@1669
   142
    using Parent::attach;
deba@1669
   143
    using Parent::detach;
deba@1669
   144
    using Parent::attached;
deba@1669
   145
deba@1669
   146
    const Graph* getGraph() {
deba@1669
   147
      return graph;
deba@1669
   148
    }
deba@1669
   149
deba@1669
   150
deba@1669
   151
  public:
deba@1669
   152
deba@1703
   153
    /// \brief The subscript operator. 
deba@1703
   154
    ///
deba@1703
   155
    /// The subscript operator. The map can be subscripted by the
deba@1703
   156
    /// actual keys of the graph. 
deba@1267
   157
    Value& operator[](const Key& key) {
deba@980
   158
      int id = graph->id(key);
deba@822
   159
      return values[id];
deba@822
   160
    } 
deba@822
   161
		
deba@1703
   162
    /// \brief The const subscript operator.
deba@1703
   163
    ///
deba@1703
   164
    /// The const subscript operator. The map can be subscripted by the
deba@1703
   165
    /// actual keys of the graph. 
deba@1267
   166
    const Value& operator[](const Key& key) const {
deba@980
   167
      int id = graph->id(key);
deba@822
   168
      return values[id];
deba@822
   169
    }
deba@1703
   170
deba@1703
   171
    /// \brief Setter function of the map.
deba@1703
   172
    ///	
deba@1414
   173
    /// Setter function of the map. Equivalent with map[key] = val.
deba@1414
   174
    /// This is a compatibility feature with the not dereferable maps.
alpar@987
   175
    void set(const Key& key, const Value& val) {
klao@946
   176
      (*this)[key] = val;
deba@822
   177
    }
deba@1669
   178
deba@1669
   179
  protected:
deba@1703
   180
deba@1414
   181
    /// Add a new key to the map. It called by the map registry.
deba@1703
   182
         
deba@1703
   183
    virtual void add(const Key& key) {
deba@980
   184
      int id = graph->id(key);
deba@822
   185
      if (id >= capacity) {
deba@822
   186
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   187
	while (new_capacity <= id) {
deba@822
   188
	  new_capacity <<= 1;
deba@822
   189
	}
klao@946
   190
	Value* new_values = allocator.allocate(new_capacity);
deba@1267
   191
	Item it;
deba@1267
   192
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   193
	  int jd = graph->id(it);;
deba@822
   194
	  if (id != jd) {
deba@822
   195
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   196
	    allocator.destroy(&(values[jd]));
deba@822
   197
	  }
deba@822
   198
	}
deba@822
   199
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   200
	values = new_values;
deba@822
   201
	capacity = new_capacity;
deba@822
   202
      }
deba@822
   203
      allocator.construct(&(values[id]), Value());
deba@822
   204
    }
deba@1414
   205
deba@1703
   206
    virtual void add(const std::vector<Key>& keys) {
deba@1414
   207
      int max_id = -1;
deba@1414
   208
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   209
	int id = graph->id(keys[i]);
deba@1414
   210
	if (id > max_id) {
deba@1414
   211
	  max_id = id;
deba@1414
   212
	}
deba@1414
   213
      }
deba@1414
   214
      if (max_id >= capacity) {
deba@1414
   215
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@1414
   216
	while (new_capacity <= max_id) {
deba@1414
   217
	  new_capacity <<= 1;
deba@1414
   218
	}
deba@1414
   219
	Value* new_values = allocator.allocate(new_capacity);
deba@1414
   220
	Item it;
deba@1414
   221
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   222
	  int id = graph->id(it);
deba@1414
   223
	  bool found = false;
deba@1414
   224
	  for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   225
	    int jd = graph->id(keys[i]);
deba@1414
   226
	    if (id == jd) {
deba@1414
   227
	      found = true;
deba@1414
   228
	      break;
deba@1414
   229
	    }
deba@1414
   230
	  }
deba@1414
   231
	  if (found) continue;
deba@1414
   232
	  allocator.construct(&(new_values[id]), values[id]);
deba@1414
   233
	  allocator.destroy(&(values[id]));
deba@1414
   234
	}
deba@1414
   235
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@1414
   236
	values = new_values;
deba@1414
   237
	capacity = new_capacity;
deba@1414
   238
      }
deba@1414
   239
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   240
	int id = graph->id(keys[i]);
deba@1414
   241
	allocator.construct(&(values[id]), Value());
deba@1414
   242
      }
deba@1414
   243
    }
deba@822
   244
		
deba@1414
   245
    /// Erase a key from the map. It called by the map registry.
deba@1414
   246
     
deba@1703
   247
    virtual void erase(const Key& key) {
deba@980
   248
      int id = graph->id(key);
deba@822
   249
      allocator.destroy(&(values[id]));
deba@822
   250
    }
deba@822
   251
deba@1703
   252
    virtual void erase(const std::vector<Key>& keys) {
deba@1414
   253
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   254
	int id = graph->id(keys[i]);
deba@1414
   255
	allocator.destroy(&(values[id]));
deba@1414
   256
      }
deba@1414
   257
    }
deba@1414
   258
deba@1703
   259
    virtual void build() {
klao@946
   260
      allocate_memory();
deba@1267
   261
      Item it;
deba@1267
   262
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   263
	int id = graph->id(it);;
klao@946
   264
	allocator.construct(&(values[id]), Value());
klao@946
   265
      }								
klao@946
   266
    }
klao@946
   267
deba@1703
   268
    virtual void clear() {	
deba@822
   269
      if (capacity != 0) {
deba@1267
   270
	Item it;
deba@1267
   271
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   272
	  int id = graph->id(it);
klao@946
   273
	  allocator.destroy(&(values[id]));
klao@946
   274
	}								
deba@822
   275
	allocator.deallocate(values, capacity);
deba@822
   276
	capacity = 0;
deba@822
   277
      }
deba@822
   278
    }
deba@822
   279
deba@822
   280
  private:
deba@822
   281
      
deba@822
   282
    void allocate_memory() {
deba@980
   283
      int max_id = graph->maxId(_Item());
deba@822
   284
      if (max_id == -1) {
deba@822
   285
	capacity = 0;
deba@822
   286
	values = 0;
deba@822
   287
	return;
deba@822
   288
      }
deba@822
   289
      capacity = 1;
deba@822
   290
      while (capacity <= max_id) {
deba@822
   291
	capacity <<= 1;
deba@822
   292
      }
deba@822
   293
      values = allocator.allocate(capacity);	
deba@822
   294
    }      
deba@822
   295
klao@946
   296
    const Graph* graph;
deba@822
   297
    int capacity;
deba@822
   298
    Value* values;
deba@822
   299
    Allocator allocator;
deba@844
   300
deba@822
   301
  };		
deba@822
   302
deba@822
   303
}
deba@822
   304
alpar@921
   305
#endif //LEMON_ARRAY_MAP_H