00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef OR_TOOLS_BASE_HASH_H_
00015 #define OR_TOOLS_BASE_HASH_H_
00016
00017
00018 #ifdef __GNUC__
00019 #include <ext/hash_map>
00020 #include <ext/hash_set>
00021 namespace operations_research {
00022 using namespace __gnu_cxx;
00023 }
00024 #else
00025 #include <hash_map>
00026 #include <hash_set>
00027 #endif
00028 #include <string>
00029 #include <utility>
00030
00031 #include "base/basictypes.h"
00032
00033 namespace operations_research {
00034 static inline void mix(uint32& a, uint32& b, uint32& c) {
00035 a -= b; a -= c; a ^= (c>>13);
00036 b -= c; b -= a; b ^= (a<<8);
00037 c -= a; c -= b; c ^= (b>>13);
00038 a -= b; a -= c; a ^= (c>>12);
00039 b -= c; b -= a; b ^= (a<<16);
00040 c -= a; c -= b; c ^= (b>>5);
00041 a -= b; a -= c; a ^= (c>>3);
00042 b -= c; b -= a; b ^= (a<<10);
00043 c -= a; c -= b; c ^= (b>>15);
00044 }
00045
00046 static inline void mix(uint64& a, uint64& b, uint64& c) {
00047 a -= b; a -= c; a ^= (c>>43);
00048 b -= c; b -= a; b ^= (a<<9);
00049 c -= a; c -= b; c ^= (b>>8);
00050 a -= b; a -= c; a ^= (c>>38);
00051 b -= c; b -= a; b ^= (a<<23);
00052 c -= a; c -= b; c ^= (b>>5);
00053 a -= b; a -= c; a ^= (c>>35);
00054 b -= c; b -= a; b ^= (a<<49);
00055 c -= a; c -= b; c ^= (b>>11);
00056 a -= b; a -= c; a ^= (c>>12);
00057 b -= c; b -= a; b ^= (a<<18);
00058 c -= a; c -= b; c ^= (b>>22);
00059 }
00060 }
00061 #if !defined(SWIG)
00062 #if !defined(_MSC_VER)
00063 namespace __gnu_cxx {
00064 template<class T> struct hash<T*> {
00065 size_t operator()(T *x) const { return reinterpret_cast<size_t>(x); }
00066 };
00067
00068 template<> struct hash<int64> {
00069 size_t operator()(int64 x) const { return static_cast<size_t>(x); }
00070 };
00071
00072 template<> struct hash<std::string> {
00073 size_t operator()(const std::string& x) const {
00074 size_t hash = 0;
00075 int c;
00076 const char* s = x.c_str();
00077 while (c = *s++) {
00078 hash = ((hash << 5) + hash) ^ c;
00079 }
00080 return hash;
00081 }
00082 };
00083
00084 inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) {
00085 uint32 b = 0x9e3779b9UL;
00086 operations_research::mix(num, b, c);
00087 return c;
00088 }
00089
00090 inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) {
00091 uint64 b = GG_ULONGLONG(0xe08c1d668b756f82);
00092 operations_research::mix(num, b, c);
00093 return c;
00094 }
00095
00096 template<class First, class Second>
00097 struct hash<std::pair<First, Second> > {
00098 size_t operator()(const std::pair<First, Second>& p) const {
00099 size_t h1 = hash<First>()(p.first);
00100 size_t h2 = hash<Second>()(p.second);
00101
00102 return (sizeof(h1) <= sizeof(uint32)) ?
00103 Hash32NumWithSeed(h1, h2)
00104 : Hash64NumWithSeed(h1, h2);
00105 }
00106 };
00107 }
00108 #else // !defined(_MSC_VER)
00109
00110 class PairInt64Hasher : public stdext::hash_compare <std::pair<int64, int64> > {
00111 public:
00112 size_t operator() (const std::pair<int64, int64>& a) const {
00113 uint64 x = a.first;
00114 uint64 y = GG_ULONGLONG(0xe08c1d668b756f82);
00115 uint64 z = a.second;
00116 operations_research::mix(x, y, z);
00117 return z;
00118 }
00119 bool operator() (const std::pair<int64, int64>& a1,
00120 const std::pair<int64, int64>& a2) const {
00121 return a1.first < a2.first ||
00122 (a1.first == a2.first && a1.second < a2.second);
00123 }
00124 };
00125
00126 class PairIntHasher : public stdext::hash_compare <std::pair<int, int> > {
00127 public:
00128 size_t operator() (const std::pair<int, int>& a) const {
00129 uint32 x = a.first;
00130 uint32 y = 0x9e3779b9UL;
00131 uint32 z = a.second;
00132 operations_research::mix(x, y, z);
00133 return z;
00134 }
00135 bool operator() (const std::pair<int, int>& a1,
00136 const std::pair<int, int>& a2) const {
00137 return a1.first < a2.first ||
00138 (a1.first == a2.first && a1.second < a2.second);
00139 }
00140 };
00141 #endif // defined(_MSC_VER)
00142 #endif // defined(SWIG)
00143
00144 #if !defined(SWIG)
00145 # if defined(__GNUC__)
00146 using __gnu_cxx::hash;
00147 using __gnu_cxx::hash_set;
00148 # elif defined(_MSC_VER)
00149 using std::hash;
00150 using stdext::hash_map;
00151 using stdext::hash_set;
00152 # else
00153 using std::hash;
00154 using std::hash_map;
00155 using std::hash_set;
00156 # endif
00157 #endif
00158
00159 #endif // OR_TOOLS_BASE_HASH_H_