Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

array_map.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Research Group on Combinatorial Optimization, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00017 #ifndef LEMON_ARRAY_MAP_H
00018 #define LEMON_ARRAY_MAP_H
00019 
00020 #include <memory>
00021 #include <lemon/bits/map_iterator.h>
00022 
00027 
00028 namespace lemon {
00029 
00030 
00033         
00041    
00042 
00043   template <typename _Graph, 
00044             typename _Item,
00045             typename _Value>
00046   class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
00047 
00048     typedef _Item Item;
00049   public:
00050                 
00052     typedef _Graph Graph;
00054     typedef _Item Key;
00055 
00056     typedef AlterationNotifier<_Item> Registry;
00057 
00059     typedef typename Registry::ObserverBase Parent;
00060                 
00062     typedef _Value Value;
00063 
00064 
00065   private:
00066     typedef std::allocator<Value> Allocator;
00067 
00068 
00069   public:
00070 
00072      
00073     ArrayMap(const Graph& _g) : graph(&_g) {
00074       Item it;
00075       attach(_g.getNotifier(Item()));
00076       allocate_memory();
00077       for (graph->first(it); it != INVALID; graph->next(it)) {
00078         int id = graph->id(it);;
00079         allocator.construct(&(values[id]), Value());
00080       }                                                         
00081     }
00082 
00084 
00086 
00087     ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
00088       Item it;
00089       attach(_g.getNotifier(_Item()));
00090       allocate_memory();
00091       for (graph->first(it); it != INVALID; graph->next(it)) {
00092         int id = graph->id(it);;
00093         allocator.construct(&(values[id]), _v);
00094       }                                                         
00095     }
00096 
00098      
00099     ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
00100       if (copy.attached()) {
00101         attach(*copy.getRegistry());
00102       }
00103       capacity = copy.capacity;
00104       if (capacity == 0) return;
00105       values = allocator.allocate(capacity);
00106       Item it;
00107       for (graph->first(it); it != INVALID; graph->next(it)) {
00108         int id = graph->id(it);;
00109         allocator.construct(&(values[id]), copy.values[id]);
00110       }
00111     }
00112 
00113     using Parent::attach;
00114     using Parent::detach;
00115     using Parent::attached;
00116 
00118      
00119     ArrayMap& operator=(const ArrayMap& copy) {
00120       if (&copy == this) return *this;
00121       
00122       if (graph != copy.graph) {
00123         if (attached()) {
00124           clear();
00125           detach();
00126         }
00127         if (copy.attached()) {
00128           attach(*copy.getRegistry());
00129         }
00130         capacity = copy.capacity;
00131         if (capacity == 0) return *this;
00132         values = allocator.allocate(capacity);      
00133       }
00134 
00135       Item it;
00136       for (graph->first(it); it != INVALID; graph->next(it)) {
00137         int id = graph->id(it);;
00138         allocator.construct(&(values[id]), copy.values[id]);
00139       }
00140 
00141       return *this;
00142     }
00143 
00145      
00146     virtual ~ArrayMap() {      
00147       if (attached()) {
00148         clear();
00149         detach();
00150       }
00151     }
00152         
00153         
00156      
00157     Value& operator[](const Key& key) {
00158       int id = graph->id(key);
00159       return values[id];
00160     } 
00161                 
00162 
00165      
00166     const Value& operator[](const Key& key) const {
00167       int id = graph->id(key);
00168       return values[id];
00169     }
00170         
00173      
00174     void set(const Key& key, const Value& val) {
00175       (*this)[key] = val;
00176     }
00177                 
00179      
00180     void add(const Key& key) {
00181       int id = graph->id(key);
00182       if (id >= capacity) {
00183         int new_capacity = (capacity == 0 ? 1 : capacity);
00184         while (new_capacity <= id) {
00185           new_capacity <<= 1;
00186         }
00187         Value* new_values = allocator.allocate(new_capacity);
00188         Item it;
00189         for (graph->first(it); it != INVALID; graph->next(it)) {
00190           int jd = graph->id(it);;
00191           if (id != jd) {
00192             allocator.construct(&(new_values[jd]), values[jd]);
00193             allocator.destroy(&(values[jd]));
00194           }
00195         }
00196         if (capacity != 0) allocator.deallocate(values, capacity);
00197         values = new_values;
00198         capacity = new_capacity;
00199       }
00200       allocator.construct(&(values[id]), Value());
00201     }
00202 
00203     void add(const std::vector<Key>& keys) {
00204       int max_id = -1;
00205       for (int i = 0; i < (int)keys.size(); ++i) {
00206         int id = graph->id(keys[i]);
00207         if (id > max_id) {
00208           max_id = id;
00209         }
00210       }
00211       if (max_id >= capacity) {
00212         int new_capacity = (capacity == 0 ? 1 : capacity);
00213         while (new_capacity <= max_id) {
00214           new_capacity <<= 1;
00215         }
00216         Value* new_values = allocator.allocate(new_capacity);
00217         Item it;
00218         for (graph->first(it); it != INVALID; graph->next(it)) {
00219           int id = graph->id(it);
00220           bool found = false;
00221           for (int i = 0; i < (int)keys.size(); ++i) {
00222             int jd = graph->id(keys[i]);
00223             if (id == jd) {
00224               found = true;
00225               break;
00226             }
00227           }
00228           if (found) continue;
00229           allocator.construct(&(new_values[id]), values[id]);
00230           allocator.destroy(&(values[id]));
00231         }
00232         if (capacity != 0) allocator.deallocate(values, capacity);
00233         values = new_values;
00234         capacity = new_capacity;
00235       }
00236       for (int i = 0; i < (int)keys.size(); ++i) {
00237         int id = graph->id(keys[i]);
00238         allocator.construct(&(values[id]), Value());
00239       }
00240     }
00241                 
00243      
00244     void erase(const Key& key) {
00245       int id = graph->id(key);
00246       allocator.destroy(&(values[id]));
00247     }
00248 
00249     void erase(const std::vector<Key>& keys) {
00250       for (int i = 0; i < (int)keys.size(); ++i) {
00251         int id = graph->id(keys[i]);
00252         allocator.destroy(&(values[id]));
00253       }
00254     }
00255 
00256     void build() {
00257       allocate_memory();
00258       Item it;
00259       for (graph->first(it); it != INVALID; graph->next(it)) {
00260         int id = graph->id(it);;
00261         allocator.construct(&(values[id]), Value());
00262       }                                                         
00263     }
00264 
00265     void clear() {      
00266       if (capacity != 0) {
00267         Item it;
00268         for (graph->first(it); it != INVALID; graph->next(it)) {
00269           int id = graph->id(it);
00270           allocator.destroy(&(values[id]));
00271         }                                                               
00272         allocator.deallocate(values, capacity);
00273         capacity = 0;
00274       }
00275     }
00276 
00277     const Graph* getGraph() {
00278       return graph;
00279     }
00280 
00281   private:
00282       
00283     void allocate_memory() {
00284       int max_id = graph->maxId(_Item());
00285       if (max_id == -1) {
00286         capacity = 0;
00287         values = 0;
00288         return;
00289       }
00290       capacity = 1;
00291       while (capacity <= max_id) {
00292         capacity <<= 1;
00293       }
00294       values = allocator.allocate(capacity);    
00295     }      
00296 
00297     const Graph* graph;
00298     int capacity;
00299     Value* values;
00300     Allocator allocator;
00301 
00302   };            
00303 
00304   template <typename _Base> 
00305   class ArrayMappableGraphExtender : public _Base {
00306   public:
00307 
00308     typedef ArrayMappableGraphExtender<_Base> Graph;
00309     typedef _Base Parent;
00310 
00311     typedef typename Parent::Node Node;
00312     typedef typename Parent::NodeIt NodeIt;
00313     typedef typename Parent::NodeNotifier NodeObserverRegistry;
00314 
00315     typedef typename Parent::Edge Edge;
00316     typedef typename Parent::EdgeIt EdgeIt;
00317     typedef typename Parent::EdgeNotifier EdgeObserverRegistry;
00318 
00319     
00320 
00321     template <typename _Value>
00322     class NodeMap 
00323       : public IterableMapExtender<ArrayMap<Graph, Node, _Value> > {
00324     public:
00325       typedef ArrayMappableGraphExtender<_Base> Graph;
00326 
00327       typedef typename Graph::Node Node;
00328       typedef typename Graph::NodeIt NodeIt;
00329 
00330       typedef IterableMapExtender<ArrayMap<Graph, Node, _Value> > Parent;
00331 
00332       //typedef typename Parent::Graph Graph;
00333       typedef typename Parent::Value Value;
00334 
00335       NodeMap(const Graph& g) 
00336         : Parent(g) {}
00337       NodeMap(const Graph& g, const Value& v) 
00338         : Parent(g, v) {}
00339 
00340     };
00341 
00342     template <typename _Value>
00343     class EdgeMap 
00344       : public IterableMapExtender<ArrayMap<Graph, Edge, _Value> > {
00345     public:
00346       typedef ArrayMappableGraphExtender<_Base> Graph;
00347 
00348       typedef typename Graph::Edge Edge;
00349       typedef typename Graph::EdgeIt EdgeIt;
00350 
00351       typedef IterableMapExtender<ArrayMap<Graph, Edge, _Value> > Parent;
00352 
00353       //typedef typename Parent::Graph Graph;
00354       typedef typename Parent::Value Value;
00355 
00356       EdgeMap(const Graph& g) 
00357         : Parent(g) {}
00358       EdgeMap(const Graph& g, const Value& v) 
00359         : Parent(g, v) {}
00360 
00361     };
00362     
00363   };
00364 
00366 
00367 }
00368 
00369 #endif //LEMON_ARRAY_MAP_H

Generated on Sat Aug 27 14:14:50 2005 for LEMON by  doxygen 1.4.4