Generated on Mon Aug 25 11:35:44 2008 for Gecode by doxygen 1.5.6

map.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Guido Tack, 2007
00008  *
00009  *  Last modified:
00010  *     $Date: 2007-12-10 11:40:09 +0100 (Mon, 10 Dec 2007) $ by $Author: schulte $
00011  *     $Revision: 5654 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 namespace Gecode { namespace Support {
00039   
00045   template <class Key, class Value>
00046   class Map {
00047   private:
00049     class Pair {
00050     public:
00051       Key k; Value v;
00052       Pair(const Key& k0, const Value& v0) : k(k0), v(v0) {}
00053     };
00054     
00056     Pair** a;
00058     int n;
00060     int usage;
00062     int modulo(void) const;
00064     void rehash(void);
00065   public:
00067     Map(void);
00069     void put(const Key& k, Value v);
00071     bool get(const Key& k, Value& v) const;
00073     GECODE_MSC_VIRTUAL ~Map(void);
00074   };
00075   
00077   template <class Value>
00078   class SymbolMap : public Map<Symbol,Value> {
00079   };
00080 
00082   template <class P>
00083   class Pointer {
00084   protected:
00086     P* p;
00087   public:
00089     Pointer(P* p0) : p(p0) {}
00091     P* operator()(void) { return p; }
00093     bool operator==(const Pointer<P>& p0) const { 
00094       return p == p0.p; 
00095     }
00097     int hash(int m) const {
00098       return static_cast<unsigned int>(reinterpret_cast<ptrdiff_t>(p)) % m;
00099     }
00100   };
00101   
00103   template <class P, class Value>
00104   class PtrMap : public Map<Pointer<P>,Value> {
00105   };
00106   
00107   /*
00108    * Implementation
00109    *
00110    */
00111   
00112   template <class Key, class Value>
00113   forceinline int
00114   Map<Key,Value>::modulo(void) const {
00115     const int primes[] = { 17, 47, 1021, 2039, 4093, 8191,
00116                            16381, 32749, 65521, 131071,
00117                            262139, 524287, 1048573, 2097143,
00118                            4194301, 8388593 };
00119     return primes[n];
00120   }
00121   
00122   template <class Key, class Value>
00123   Map<Key,Value>::Map(void) : n(0), usage(0) {
00124     a = static_cast<Pair**>(Memory::malloc(sizeof(Pair*)*modulo()));
00125     for (int i=modulo(); i--; )
00126       a[i] = NULL;
00127   }
00128   
00129   template <class Key, class Value>
00130   void
00131   Map<Key,Value>::rehash(void) {
00132     int oldM = modulo();
00133     n++;
00134     Pair** olda = a;
00135     a = static_cast<Pair**>(Memory::malloc(sizeof(Pair*)*modulo()));
00136     for (int i=modulo(); i--; )
00137       a[i] = NULL;
00138     for (int i=oldM; i--;) {
00139       if (olda[i] != NULL) {
00140         int j = olda[i]->k.hash(modulo());
00141         for (; j < modulo() && a[j] != NULL; j++) {}
00142         if (j >= modulo()) {
00143           for (j=0; a[j] != NULL; j++) {}
00144           assert(j<olda[i]->k.hash(modulo()));
00145         }
00146         assert(j < modulo());
00147         assert(a[j] == NULL);
00148         a[j] = olda[i];
00149       }
00150     }
00151 #ifndef NDEBUG
00152     int actualUsage = 0;
00153     for (int i=modulo(); i--;)
00154       if (a[i]) actualUsage++;
00155     assert(actualUsage == usage);
00156 #endif
00157     Memory::free(olda);
00158   }
00159   
00160   template <class Key, class Value>
00161   void
00162   Map<Key,Value>::put(const Key& k, Value v) {
00163     // If more than 75% are used, make some room
00164     if (usage * 3 >= modulo() * 2)
00165       rehash();
00166       
00167     int i = k.hash(modulo());
00168     for (; i < modulo() && a[i] != NULL; i++) {}
00169     if (i >= modulo()) {
00170       for (i=0; a[i] != NULL; i++) {}
00171       assert(i<k.hash(modulo()));
00172     }
00173     assert(i < modulo());
00174     assert(a[i] == NULL);
00175     a[i] = new Pair(k,v);
00176     usage++;
00177   }
00178   
00179   template <class Key, class Value>
00180   inline bool
00181   Map<Key,Value>::get(const Key& k, Value& v) const {
00182     int i=k.hash(modulo());
00183     for (; i<modulo() && a[i] != NULL; i++) {
00184       if (a[i]->k == k) {
00185         v = a[i]->v; return true;
00186       }
00187     }
00188     if (i >= modulo()) {
00189       for (i=0; a[i] != NULL; i++) {
00190         if (a[i]->k == k) {
00191           v = a[i]->v; return true;
00192         }        
00193       }
00194     }
00195     return false;
00196   }
00197   
00198   template <class Key, class Value>
00199   Map<Key,Value>::~Map(void) {
00200     for (int i=modulo(); i--; )
00201       delete a[i];
00202     Memory::free(a);
00203   }
00204 
00205 }}
00206 
00207 // STATISTICS: support-any