hm_hash.hpp

Go to the documentation of this file.
00001 #ifndef wali_HM_HASH_GUARD
00002 #define wali_HM_HASH_GUARD 1
00003 
00004 /*!
00005  * @author Nicholas Kidd
00006  */
00007 
00008 #include <cstring> // for hm_equal< char * >
00009 
00010 
00011 /* These were taken from Thomas Wang
00012  * http://www.concentric.net/~Ttwang/tech/inthash.htm
00013  *
00014  * On machines where long is 64 bits, the below should
00015  * probably be used.
00016  *
00017  */
00018 
00019 #undef longhash1
00020 #define longhash1(key)  \
00021 {                       \
00022   key += ~(key << 32);  \
00023   key ^= (key >> 22);  \
00024   key += ~(key << 13);  \
00025   key ^= (key >> 8);   \
00026   key += (key << 3);    \
00027   key ^= (key >> 15);  \
00028   key += ~(key << 27);  \
00029   key ^= (key >> 31);  \
00030 }
00031 
00032 
00033 #undef jenkins_mix
00034 #define jenkins_mix(a,b,c) \
00035 { \
00036   a=a-b;  a=a-c;  a=a^(c>>13); \
00037   b=b-c;  b=b-a;  b=b^(a<<8);  \
00038   c=c-a;  c=c-b;  c=c^(b>>13); \
00039   a=a-b;  a=a-c;  a=a^(c>>12); \
00040   b=b-c;  b=b-a;  b=b^(a<<16); \
00041   c=c-a;  c=c-b;  c=c^(b>>5);  \
00042   a=a-b;  a=a-c;  a=a^(c>>3);  \
00043   b=b-c;  b=b-a;  b=b^(a<<10); \
00044   c=c-a;  c=c-b;  c=c^(b>>15); \
00045 }
00046 
00047 #undef jenkins_wrapper
00048 #define jenkins_wrapper( c )            \
00049 {                                       \
00050   size_t a = 0x9e3779b9;     \
00051   size_t b = 0x9e3779b9;     \
00052   jenkins_mix(a,b,c);             \
00053 }
00054 
00055 #undef primitive_type_hash
00056 #define primitive_type_hash( key ) \
00057 {                                       \
00058   key += (key << 12);                 \
00059   key ^= (key >> 22);                 \
00060   key += (key << 4);                  \
00061   key ^= (key >> 9);                  \
00062   key += (key << 10);                 \
00063   key ^= (key >> 2);                  \
00064   key += (key << 7);                  \
00065   key ^= (key >> 12);                 \
00066 }
00067 
00068 namespace wali 
00069 {
00070 
00071   /*
00072    * hm_hash is a templated functor to provide defaults
00073    * for hashing the c++ primitive types.  It is defined
00074    * because std::hash<> is currently an SGI extension
00075    * to the STL.
00076    */
00077 
00078   template< typename T > struct hm_hash { };
00079   template< typename T > struct hm_equal {};
00080 
00081   /*
00082    * Primitives hm_hash is defined for (includes const prim):
00083    *      int
00084    *      unsigned int
00085    *      char
00086    *      unsigned char
00087    *      char *
00088    */
00089 
00090 
00091   /********************/
00092   /* char             */
00093   /********************/
00094   template<> struct hm_hash< char >
00095   {
00096     size_t operator()( char key ) const
00097     {
00098       size_t sz = key;
00099       primitive_type_hash( sz );
00100       return sz;
00101     }
00102   };
00103 
00104   template<> struct hm_hash< const char >
00105   {
00106     size_t operator()( const char key ) const
00107     {
00108       size_t sz = key;
00109       primitive_type_hash( sz );
00110       return sz;
00111     }
00112   };
00113 
00114   template<> struct hm_equal< char >
00115   {
00116     bool operator()( char lhs,char rhs ) const
00117     {
00118       return lhs == rhs;
00119     }
00120   };
00121   template<> struct hm_equal< const char >
00122   {
00123     bool operator()( const char lhs,const char rhs ) const
00124     {
00125       return lhs == rhs;
00126     }
00127   };
00128 
00129   /********************/
00130   /* unsigned char    */
00131   /********************/
00132   template<> struct hm_hash< unsigned char >
00133   {
00134     size_t operator()( unsigned char key ) const
00135     {
00136       size_t sz = key;
00137       primitive_type_hash( sz );
00138       return sz;
00139     }
00140   };
00141 
00142   template<> struct hm_hash< const unsigned char >
00143   {
00144     size_t operator()( const unsigned char key ) const
00145     {
00146       size_t sz = key;
00147       primitive_type_hash( sz );
00148       return sz;
00149     }
00150   };
00151 
00152   template<> struct hm_equal< unsigned char >
00153   {
00154     bool operator()( unsigned char lhs,unsigned char rhs ) const
00155     {
00156       return lhs == rhs;
00157     }
00158   };
00159 
00160   template<> struct hm_equal< const unsigned char >
00161   {
00162     bool operator()( const unsigned char lhs,const unsigned char rhs ) const
00163     {
00164       return lhs == rhs;
00165     }
00166   };
00167 
00168   /********************/
00169   /* int              */
00170   /********************/
00171   template<> struct hm_hash< int >
00172   {
00173     size_t operator()( int key ) const
00174     {
00175       size_t sz = key;
00176       primitive_type_hash( sz );
00177       return sz;
00178     }
00179   };
00180 
00181   template<> struct hm_hash< const int >
00182   {
00183     size_t operator()( const int key ) const
00184     {
00185       size_t sz = key;
00186       primitive_type_hash( sz );
00187       return sz;
00188     }
00189   };
00190 
00191   template<> struct hm_equal< int >
00192   {
00193     bool operator()( int lhs,int rhs ) const
00194     {
00195       return lhs == rhs;
00196     }
00197   };
00198 
00199   template<> struct hm_equal< const int >
00200   {
00201     bool operator()( const int lhs,const int rhs ) const
00202     {
00203       return lhs == rhs;
00204     }
00205   };
00206 
00207   /********************/
00208   /* unsigned int */
00209   /********************/
00210   template<> struct hm_hash< unsigned int >
00211   {
00212     size_t operator()( int key ) const
00213     {
00214       size_t sz = key;
00215       primitive_type_hash( sz );
00216       return sz;
00217     }
00218   };
00219 
00220   template<> struct hm_hash< const unsigned int >
00221   {
00222     size_t operator()( const unsigned int key ) const
00223     {
00224       size_t sz = key;
00225       primitive_type_hash( sz );
00226       return sz;
00227     }
00228   };
00229 
00230   template<> struct hm_equal< unsigned int >
00231   {
00232     bool operator()( unsigned int lhs,unsigned int rhs ) const
00233     {
00234       return lhs == rhs;
00235     }
00236   };
00237 
00238   template<> struct hm_equal< const unsigned int >
00239   {
00240     bool operator()( const unsigned int lhs,const unsigned int rhs ) const
00241     {
00242       return lhs == rhs;
00243     }
00244   };
00245 
00246   /********************/
00247   /* long              */
00248   /********************/
00249   template<> struct hm_hash< long >
00250   {
00251     size_t operator()( long key ) const
00252     {
00253       size_t sz = key;
00254       primitive_type_hash( sz );
00255       return sz;
00256     }
00257   };
00258 
00259   template<> struct hm_hash< const long >
00260   {
00261     size_t operator()( const long key ) const
00262     {
00263       size_t sz = key;
00264       primitive_type_hash( sz );
00265       return sz;
00266     }
00267   };
00268 
00269   template<> struct hm_equal< long >
00270   {
00271     bool operator()( long lhs,long rhs ) const
00272     {
00273       return lhs == rhs;
00274     }
00275   };
00276 
00277   template<> struct hm_equal< const long >
00278   {
00279     bool operator()( const long lhs,const long rhs ) const
00280     {
00281       return lhs == rhs;
00282     }
00283   };
00284 
00285   /********************/
00286   /* unsigned long    */
00287   /********************/
00288   template<> struct hm_hash< unsigned long >
00289   {
00290     size_t operator()( unsigned long key ) const
00291     {
00292       size_t sz = key;
00293       primitive_type_hash( sz );
00294       return sz;
00295     }
00296   };
00297 
00298   template<> struct hm_hash< const unsigned long >
00299   {
00300     size_t operator()( const unsigned long key ) const
00301     {
00302       size_t sz = key;
00303       primitive_type_hash( sz );
00304       return sz;
00305     }
00306   };
00307 
00308   template<> struct hm_equal< unsigned long >
00309   {
00310     bool operator()( unsigned long lhs,unsigned long rhs ) const
00311     {
00312       return lhs == rhs;
00313     }
00314   };
00315 
00316   template<> struct hm_equal< const unsigned long >
00317   {
00318     bool operator()( const unsigned long lhs,const unsigned long rhs ) const
00319     {
00320       return lhs == rhs;
00321     }
00322   };
00323 
00324   /********************/
00325   /* char*            */
00326   /********************/
00327   /* The hash function used was found at:
00328    *      http://www.cs.yorku.ca/~oz/hash.html
00329    *
00330    * The algorithm (djb2) is attributed to Dan Bernstein
00331    * on the web page.  It claims to have been posted on the
00332    * newsgroup comp.lang.c so I am assuming it is in the public
00333    * domain.
00334    */
00335   static unsigned long strhashfn( const char* str )
00336   {
00337     unsigned long hash = 5381;
00338     int c;
00339 
00340     while (0 != (c = *str++))
00341       hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
00342 
00343     return hash;
00344   }
00345 
00346   template<> struct hm_hash< char * >
00347   {
00348     size_t operator()( char * str ) const
00349     {
00350       return strhashfn( str );
00351     }
00352   };
00353 
00354   template<> struct hm_hash< const char * >
00355   {
00356     size_t operator()( const char * str ) const
00357     {
00358       return strhashfn( str );
00359     }
00360   };
00361 
00362   template<> struct hm_equal< char * >
00363   {
00364     bool operator()( char * lhs,char * rhs ) const
00365     {
00366       return (0 == strcmp(lhs,rhs));
00367     }
00368   };
00369 
00370   template<> struct hm_equal< const char * >
00371   {
00372     bool operator()( const char * lhs,const char * rhs ) const
00373     {
00374       return (0 == strcmp(lhs,rhs));
00375     }
00376   };
00377 
00378   /********************/
00379   /* long long        */
00380   /********************/
00381   template<> struct hm_hash< long long >
00382   {
00383     size_t operator()( long long key ) const
00384     {
00385       longhash1( key );
00386       return (size_t)key;
00387     }
00388   };
00389 
00390   template<> struct hm_hash< const long long >
00391   {
00392     size_t operator()( const long long key ) const
00393     {
00394       long long sz = key;
00395       longhash1( sz );
00396       return (size_t)sz;
00397     }
00398   };
00399 
00400   template<> struct hm_equal< long long >
00401   {
00402     bool operator()( long long lhs , long long rhs ) const
00403     {
00404       return lhs == rhs;
00405     }
00406   };
00407 
00408   template<> struct hm_equal< const long long >
00409   {
00410     bool operator()( const long long lhs , const long long rhs ) const
00411     {
00412       return lhs == rhs;
00413     }
00414   };
00415 
00416   /**********************/
00417   /* unsigned long long */
00418   /**********************/
00419   template<> struct hm_hash< unsigned long long >
00420   {
00421     size_t operator()( unsigned long long key ) const
00422     {
00423       longhash1( key );
00424       return (size_t)key;
00425     }
00426   };
00427 
00428   template<> struct hm_hash< const unsigned long long >
00429   {
00430     size_t operator()( const unsigned long long key ) const
00431     {
00432       unsigned long long sz = key;
00433       longhash1( sz );
00434       return (size_t)sz;
00435     }
00436   };
00437 
00438   template<> struct hm_equal< unsigned long long >
00439   {
00440     bool operator()( unsigned long long lhs , unsigned long long rhs ) const
00441     {
00442       return lhs == rhs;
00443     }
00444   };
00445 
00446   template<> struct hm_equal< const unsigned long long >
00447   {
00448     bool operator()( const unsigned long long lhs , const unsigned long long rhs ) const
00449     {
00450       return lhs == rhs;
00451     }
00452   };
00453 
00454 } // namespace wali
00455 
00456 #endif  // wali_HM_HASH_GUARD
00457