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