src/lemon/array_map.h
author klao
Wed, 10 Nov 2004 21:59:59 +0000
changeset 979 b5fb023cdb7b
parent 978 175cf8c3a994
child 980 0f1044b7a3af
permissions -rw-r--r--
"make check" pass under icc v8.0

* There are _many_ remarks which are worth examinating! Non-inline (and even
not template) functions in header files for example.
alpar@906
     1
/* -*- C++ -*-
alpar@921
     2
 * src/lemon/array_map.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@906
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, 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@822
    21
alpar@921
    22
#include <lemon/map_iterator.h>
deba@822
    23
deba@822
    24
///\ingroup graphmaps
deba@822
    25
///\file
deba@822
    26
///\brief Graph maps that construates and destruates
deba@822
    27
///their elements dynamically.
deba@822
    28
alpar@921
    29
namespace lemon {
deba@822
    30
deba@822
    31
deba@822
    32
  /// \addtogroup graphmaps
deba@822
    33
  /// @{
deba@822
    34
	
deba@822
    35
  /** The ArrayMap template class is graph map structure what
deba@822
    36
   *  automatically updates the map when a key is added to or erased from
deba@822
    37
   *  the map. This map factory uses the allocators to implement 
deba@822
    38
   *  the container functionality.
deba@822
    39
   *
deba@822
    40
   *  The template parameter is the MapRegistry that the maps
deba@822
    41
   *  will belong to and the ValueType.
deba@822
    42
   */
deba@822
    43
klao@946
    44
  template <typename _Graph, 
klao@946
    45
	    typename _Item,
klao@946
    46
	    typename _ItemIt,
klao@946
    47
	    typename _IdMap,
klao@946
    48
	    typename _Value>
klao@946
    49
  class ArrayMap : public AlterationObserverRegistry<_Item>::ObserverBase {
deba@897
    50
deba@822
    51
  public:
deba@822
    52
		
deba@822
    53
    /// The graph type of the maps. 
klao@946
    54
    typedef _Graph Graph;
deba@822
    55
    /// The key type of the maps.
klao@946
    56
    typedef _Item KeyType;
klao@946
    57
klao@946
    58
    typedef AlterationObserverRegistry<_Item> Registry;
klao@946
    59
klao@946
    60
  private:
deba@822
    61
    /// The iterator to iterate on the keys.
klao@946
    62
    typedef _ItemIt KeyIt;
klao@946
    63
klao@946
    64
    typedef _IdMap IdMap;
klao@946
    65
klao@946
    66
    typedef _Value Value;
deba@822
    67
deba@822
    68
    /// The MapBase of the Map which imlements the core regisitry function.
klao@946
    69
    typedef typename Registry::ObserverBase Parent;
deba@822
    70
		
deba@822
    71
    
deba@822
    72
  public:
deba@822
    73
deba@822
    74
    /// The value type of the map.
deba@822
    75
    typedef Value ValueType;
deba@822
    76
    /// The reference type of the map;
deba@822
    77
    typedef Value& ReferenceType;
deba@822
    78
    /// The pointer type of the map;
deba@822
    79
    typedef Value* PointerType;
deba@822
    80
deba@822
    81
    /// The const value type of the map.
deba@822
    82
    typedef const Value ConstValueType;
deba@822
    83
    /// The const reference type of the map;
deba@822
    84
    typedef const Value& ConstReferenceType;
deba@822
    85
    /// The pointer type of the map;
deba@822
    86
    typedef const Value* ConstPointerType;
deba@822
    87
deba@822
    88
klao@946
    89
  private:
deba@822
    90
    typedef std::allocator<Value> Allocator;
deba@822
    91
klao@946
    92
klao@946
    93
  public:
klao@946
    94
deba@822
    95
    /** Graph and Registry initialized map constructor.
deba@822
    96
     */
klao@946
    97
    ArrayMap(const Graph& _g, Registry& _r) : graph(&_g) {
klao@946
    98
      attach(_r);
deba@822
    99
      allocate_memory();
klao@946
   100
      for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   101
	int id = IdMap(*graph)[it];
deba@822
   102
	allocator.construct(&(values[id]), Value());
deba@822
   103
      }								
deba@822
   104
    }
deba@822
   105
klao@946
   106
    /// Constructor to use default value to initialize the map. 
klao@946
   107
klao@946
   108
    /// It constrates a map and initialize all of the the map. 
klao@946
   109
klao@946
   110
    ArrayMap(const Graph& _g, Registry& _r, const Value& _v) : graph(&_g) {
klao@946
   111
      attach(_r);
deba@822
   112
      allocate_memory();
klao@946
   113
      for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   114
	int id = IdMap(*graph)[it];
klao@946
   115
	allocator.construct(&(values[id]), _v);
deba@822
   116
      }								
deba@822
   117
    }
deba@822
   118
deba@822
   119
    /** Constructor to copy a map of the same map type.
deba@822
   120
     */
klao@946
   121
    ArrayMap(const ArrayMap& copy) {
klao@946
   122
      if (copy.attached()) {
klao@946
   123
	attach(*copy.getRegistry());
klao@946
   124
      }
deba@822
   125
      capacity = copy.capacity;
deba@822
   126
      if (capacity == 0) return;
deba@822
   127
      values = allocator.allocate(capacity);
klao@946
   128
      for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   129
	int id = IdMap(*graph)[it];
deba@891
   130
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   131
      }
deba@822
   132
    }
deba@822
   133
klao@978
   134
    using Parent::attach;
klao@978
   135
    using Parent::detach;
klao@978
   136
    using Parent::attached;
klao@978
   137
deba@822
   138
    /** Assign operator to copy a map of the same map type.
deba@822
   139
     */
deba@822
   140
    ArrayMap& operator=(const ArrayMap& copy) {
deba@822
   141
      if (&copy == this) return *this;
deba@897
   142
      
klao@946
   143
      if (graph != copy.graph) {
klao@946
   144
	if (attached()) {
klao@946
   145
	  clear();
klao@946
   146
	  detach();
deba@897
   147
	}
klao@946
   148
	if (copy.attached()) {
klao@946
   149
	  attach(*copy.getRegistry());
klao@946
   150
	}
deba@897
   151
	capacity = copy.capacity;
deba@897
   152
	if (capacity == 0) return *this;
deba@897
   153
	values = allocator.allocate(capacity);      
deba@822
   154
      }
deba@891
   155
klao@946
   156
      for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   157
	int id = IdMap(*graph)[it];
deba@822
   158
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   159
      }
deba@891
   160
deba@822
   161
      return *this;
deba@822
   162
    }
deba@822
   163
deba@822
   164
    /** The destructor of the map.
deba@822
   165
     */
klao@946
   166
    virtual ~ArrayMap() {      
klao@946
   167
      if (attached()) {
klao@946
   168
	clear();
klao@946
   169
	detach();
deba@822
   170
      }
deba@822
   171
    }
deba@822
   172
	
deba@822
   173
	
deba@822
   174
    /**
deba@822
   175
     * The subscript operator. The map can be subscripted by the
deba@822
   176
     * actual keys of the graph. 
deba@822
   177
     */
deba@822
   178
    ReferenceType operator[](const KeyType& key) {
klao@946
   179
      int id = IdMap(*graph)[key];
deba@822
   180
      return values[id];
deba@822
   181
    } 
deba@822
   182
		
deba@822
   183
    /**
deba@822
   184
     * The const subscript operator. The map can be subscripted by the
deba@822
   185
     * actual keys of the graph. 
deba@822
   186
     */
deba@822
   187
    ConstReferenceType operator[](const KeyType& key) const {
klao@946
   188
      int id = IdMap(*graph)[key];
deba@822
   189
      return values[id];
deba@822
   190
    }
deba@822
   191
	
deba@822
   192
    /** Setter function of the map. Equivalent with map[key] = val.
deba@822
   193
     *  This is a compatibility feature with the not dereferable maps.
deba@822
   194
     */
deba@822
   195
    void set(const KeyType& key, const ValueType& val) {
klao@946
   196
      (*this)[key] = val;
deba@822
   197
    }
deba@822
   198
		
deba@822
   199
    /** Add a new key to the map. It called by the map registry.
deba@822
   200
     */
deba@822
   201
    void add(const KeyType& key) {
klao@946
   202
      int id = IdMap(*graph)[key];
deba@822
   203
      if (id >= capacity) {
deba@822
   204
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   205
	while (new_capacity <= id) {
deba@822
   206
	  new_capacity <<= 1;
deba@822
   207
	}
klao@946
   208
	Value* new_values = allocator.allocate(new_capacity);
klao@946
   209
	for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   210
	  int jd = IdMap(*graph)[it];
deba@822
   211
	  if (id != jd) {
deba@822
   212
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   213
	    allocator.destroy(&(values[jd]));
deba@822
   214
	  }
deba@822
   215
	}
deba@822
   216
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   217
	values = new_values;
deba@822
   218
	capacity = new_capacity;
deba@822
   219
      }
deba@822
   220
      allocator.construct(&(values[id]), Value());
deba@822
   221
    }
deba@822
   222
		
deba@822
   223
    /** Erase a key from the map. It called by the map registry.
deba@822
   224
     */
deba@822
   225
    void erase(const KeyType& key) {
klao@946
   226
      int id = IdMap(*graph)[key];
deba@822
   227
      allocator.destroy(&(values[id]));
deba@822
   228
    }
deba@822
   229
klao@946
   230
    void build() {
klao@946
   231
      allocate_memory();
klao@946
   232
      for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   233
	int id = IdMap(*graph)[it];
klao@946
   234
	allocator.construct(&(values[id]), Value());
klao@946
   235
      }								
klao@946
   236
    }
klao@946
   237
deba@822
   238
    void clear() {	
deba@822
   239
      if (capacity != 0) {
klao@946
   240
	for (KeyIt it(*graph); it != INVALID; ++it) {
klao@946
   241
	  int id = IdMap(*graph)[it];
klao@946
   242
	  allocator.destroy(&(values[id]));
klao@946
   243
	}								
deba@822
   244
	allocator.deallocate(values, capacity);
deba@822
   245
	capacity = 0;
deba@822
   246
      }
deba@822
   247
    }
deba@822
   248
klao@946
   249
//     /// The stl compatible pair iterator of the map.
klao@946
   250
//     typedef MapIterator<ArrayMap> Iterator;
klao@946
   251
//     /// The stl compatible const pair iterator of the map.
klao@946
   252
//     typedef MapConstIterator<ArrayMap> ConstIterator;
deba@822
   253
klao@946
   254
//     /** Returns the begin iterator of the map.
klao@946
   255
//      */
klao@946
   256
//     Iterator begin() {
klao@946
   257
//       return Iterator(*this, KeyIt(*MapBase::getGraph()));
klao@946
   258
//     }
deba@822
   259
klao@946
   260
//     /** Returns the end iterator of the map.
klao@946
   261
//      */
klao@946
   262
//     Iterator end() {
klao@946
   263
//       return Iterator(*this, INVALID);
klao@946
   264
//     }
deba@822
   265
klao@946
   266
//     /** Returns the begin ConstIterator of the map.
klao@946
   267
//      */
klao@946
   268
//     ConstIterator begin() const {
klao@946
   269
//       return ConstIterator(*this, KeyIt(*MapBase::getGraph()));
klao@946
   270
//     }
deba@822
   271
klao@946
   272
//     /** Returns the end const_iterator of the map.
klao@946
   273
//      */
klao@946
   274
//     ConstIterator end() const {
klao@946
   275
//       return ConstIterator(*this, INVALID);
klao@946
   276
//     }
deba@822
   277
klao@946
   278
//     /// The KeySet of the Map.
klao@946
   279
//     typedef MapConstKeySet<ArrayMap> ConstKeySet;
deba@830
   280
klao@946
   281
//     /// KeySet getter function.
klao@946
   282
//     ConstKeySet keySet() const {
klao@946
   283
//       return ConstKeySet(*this); 
klao@946
   284
//     }
deba@830
   285
klao@946
   286
//     /// The ConstValueSet of the Map.
klao@946
   287
//     typedef MapConstValueSet<ArrayMap> ConstValueSet;
deba@830
   288
klao@946
   289
//     /// ConstValueSet getter function.
klao@946
   290
//     ConstValueSet valueSet() const {
klao@946
   291
//       return ConstValueSet(*this);
klao@946
   292
//     }
deba@830
   293
klao@946
   294
//     /// The ValueSet of the Map.
klao@946
   295
//     typedef MapValueSet<ArrayMap> ValueSet;
deba@830
   296
klao@946
   297
//     /// ValueSet getter function.
klao@946
   298
//     ValueSet valueSet() {
klao@946
   299
//       return ValueSet(*this);
klao@946
   300
//     }
deba@830
   301
deba@822
   302
  private:
deba@822
   303
      
deba@822
   304
    void allocate_memory() {
klao@946
   305
      int max_id = IdMap(*graph).maxId();
deba@822
   306
      if (max_id == -1) {
deba@822
   307
	capacity = 0;
deba@822
   308
	values = 0;
deba@822
   309
	return;
deba@822
   310
      }
deba@822
   311
      capacity = 1;
deba@822
   312
      while (capacity <= max_id) {
deba@822
   313
	capacity <<= 1;
deba@822
   314
      }
deba@822
   315
      values = allocator.allocate(capacity);	
deba@822
   316
    }      
deba@822
   317
klao@946
   318
    const Graph* graph;
deba@822
   319
    int capacity;
deba@822
   320
    Value* values;
deba@822
   321
    Allocator allocator;
deba@844
   322
deba@844
   323
  public:
klao@946
   324
//     // STL  compatibility typedefs.
klao@946
   325
//     typedef Iterator iterator;
klao@946
   326
//     typedef ConstIterator const_iterator;
klao@946
   327
//     typedef typename Iterator::PairValueType value_type;
klao@946
   328
//     typedef typename Iterator::KeyType key_type;
klao@946
   329
//     typedef typename Iterator::ValueType data_type;
klao@946
   330
//     typedef typename Iterator::PairReferenceType reference;
klao@946
   331
//     typedef typename Iterator::PairPointerType pointer;
klao@946
   332
//     typedef typename ConstIterator::PairReferenceType const_reference;
klao@946
   333
//     typedef typename ConstIterator::PairPointerType const_pointer;
klao@946
   334
//     typedef int difference_type;		
deba@822
   335
  };		
deba@822
   336
klao@946
   337
  template <typename _Base> 
klao@946
   338
  class ArrayMappableGraphExtender : public _Base {
klao@946
   339
  public:
klao@946
   340
klao@946
   341
    typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   342
    typedef _Base Parent;
klao@946
   343
klao@946
   344
    typedef typename Parent::Node Node;
klao@946
   345
    typedef typename Parent::NodeIt NodeIt;
klao@946
   346
    typedef typename Parent::NodeIdMap NodeIdMap;
klao@946
   347
    typedef typename Parent::NodeObserverRegistry NodeObserverRegistry;
klao@946
   348
klao@946
   349
    typedef typename Parent::Edge Edge;
klao@946
   350
    typedef typename Parent::EdgeIt EdgeIt;
klao@946
   351
    typedef typename Parent::EdgeIdMap EdgeIdMap;
klao@946
   352
    typedef typename Parent::EdgeObserverRegistry EdgeObserverRegistry;
klao@946
   353
klao@946
   354
    
klao@946
   355
klao@946
   356
    template <typename _Value>
klao@946
   357
    class NodeMap : public ArrayMap<Graph, Node, NodeIt, NodeIdMap, _Value> {
klao@946
   358
    public:
klao@946
   359
      typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   360
klao@946
   361
      typedef typename Graph::Node Node;
klao@946
   362
      typedef typename Graph::NodeIt NodeIt;
klao@946
   363
      typedef typename Graph::NodeIdMap NodeIdMap;
klao@946
   364
klao@946
   365
      typedef ArrayMap<Graph, Node, NodeIt, NodeIdMap, _Value> Parent;
klao@946
   366
klao@979
   367
      //typedef typename Parent::Graph Graph;
klao@946
   368
      typedef typename Parent::Value Value;
klao@946
   369
klao@946
   370
      NodeMap(const Graph& g) 
klao@946
   371
	: Parent(g, g.getNodeObserverRegistry()) {}
klao@946
   372
      NodeMap(const Graph& g, const Value& v) 
klao@946
   373
	: Parent(g, g.getNodeObserverRegistry(), v) {}
klao@946
   374
klao@946
   375
    };
klao@946
   376
klao@946
   377
    template <typename _Value>
klao@946
   378
    class EdgeMap : public ArrayMap<Graph, Edge, EdgeIt, EdgeIdMap, _Value> {
klao@946
   379
    public:
klao@946
   380
      typedef ArrayMappableGraphExtender<_Base> Graph;
klao@946
   381
klao@946
   382
      typedef typename Graph::Edge Edge;
klao@946
   383
      typedef typename Graph::EdgeIt EdgeIt;
klao@946
   384
      typedef typename Graph::EdgeIdMap EdgeIdMap;
klao@946
   385
klao@946
   386
      typedef ArrayMap<Graph, Edge, EdgeIt, EdgeIdMap, _Value> Parent;
klao@946
   387
klao@979
   388
      //typedef typename Parent::Graph Graph;
klao@946
   389
      typedef typename Parent::Value Value;
klao@946
   390
klao@946
   391
      EdgeMap(const Graph& g) 
klao@946
   392
	: Parent(g, g.getEdgeObserverRegistry()) {}
klao@946
   393
      EdgeMap(const Graph& g, const Value& v) 
klao@946
   394
	: Parent(g, g.getEdgeObserverRegistry(), v) {}
klao@946
   395
klao@946
   396
    };
klao@946
   397
    
klao@946
   398
  };
klao@946
   399
deba@822
   400
/// @}
deba@822
   401
deba@822
   402
}
deba@822
   403
alpar@921
   404
#endif //LEMON_ARRAY_MAP_H