rewrite hash part
This commit is contained in:
38
src/base/fingerprint2011.h
Normal file
38
src/base/fingerprint2011.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef OR_TOOLS_BASE_FINGERPRINT2011_H_
|
||||
#define OR_TOOLS_BASE_FINGERPRINT2011_H_
|
||||
|
||||
#include "base/integral_types.h"
|
||||
|
||||
uint64 FingerprintCat2011(uint64 fp1, uint64 fp2) {
|
||||
// Two big prime numbers.
|
||||
const uint64 kMul1 = 0xc6a4a7935bd1e995ULL;
|
||||
const uint64 kMul2 = 0x228876a7198b743ULL;
|
||||
uint64 a = fp1 * kMul1 + fp2 * kMul2;
|
||||
// Note: The following line also makes sure we never return 0 or 1, because we
|
||||
// will only add something to 'a' if there are any MSBs (the remaining bits
|
||||
// after the shift) being 0, in which case wrapping around would not happen.
|
||||
return a + (~a >> 47);
|
||||
}
|
||||
|
||||
// This should be better (collision-wise) than the default hash<std::string>, without
|
||||
// being much slower. It never returns 0 or 1.
|
||||
uint64 Fingerprint2011(const char* bytes, size_t len) {
|
||||
// Some big prime numer.
|
||||
uint64 fp = 0xa5b85c5e198ed849ULL;
|
||||
const char* end = bytes + len;
|
||||
while (bytes + 8 <= end) {
|
||||
fp = FingerprintCat2011(fp, *(reinterpret_cast<const uint64*>(bytes)));
|
||||
bytes += 8;
|
||||
}
|
||||
// Note: we don't care about "consistency" (little or big endian) between
|
||||
// the bulk and the suffix of the message.
|
||||
uint64 last_bytes = 0;
|
||||
while (bytes < end) {
|
||||
last_bytes += *bytes;
|
||||
last_bytes <<= 8;
|
||||
bytes++;
|
||||
}
|
||||
return FingerprintCat2011(fp, last_bytes);
|
||||
}
|
||||
|
||||
#endif // OR_TOOLS_BASE_FINGERPRINT2011_H_
|
||||
176
src/base/hash.h
176
src/base/hash.h
@@ -32,7 +32,7 @@ using namespace __gnu_cxx; // NOLINT
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// In SWIG mode, we don't want anything besides these top-level includes.
|
||||
#ifndef SWIG
|
||||
#if !defined(SWIG)
|
||||
|
||||
namespace operations_research {
|
||||
// 32 bit version.
|
||||
@@ -107,10 +107,100 @@ static inline void mix(uint64& a, uint64& b, uint64& c) { // NOLINT
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// GNU C++ port, with or without STLport.
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUC__
|
||||
// hash namespace
|
||||
#if defined(__GNUC__) && defined(STLPORT)
|
||||
#define HASH_NAMESPACE std
|
||||
#elif defined(__GNUC__) && !defined(STLPORT)
|
||||
#define HASH_NAMESPACE __gnu_cxx
|
||||
#endif
|
||||
|
||||
// Support a few hash<> operators, in the hash namespace.
|
||||
inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) {
|
||||
uint32 b = 0x9e3779b9UL; // The golden ratio; an arbitrary value.
|
||||
operations_research::mix(num, b, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) {
|
||||
uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); // More of the golden ratio.
|
||||
operations_research::mix(num, b, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
namespace HASH_NAMESPACE {
|
||||
template <class First, class Second>
|
||||
struct hash<std::pair<First, Second> > {
|
||||
size_t operator()(const std::pair<First, Second>& p) const {
|
||||
size_t h1 = hash<First>()(p.first);
|
||||
size_t h2 = hash<Second>()(p.second);
|
||||
// The decision below is at compile time
|
||||
return (sizeof(h1) <= sizeof(uint32)) ? // NOLINT
|
||||
Hash32NumWithSeed(h1, h2)
|
||||
: Hash64NumWithSeed(h1, h2);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct hash<T*> {
|
||||
size_t operator()(T* x) const { return reinterpret_cast<size_t>(x); }
|
||||
};
|
||||
|
||||
// hash<int64> and hash<std::string> are already defined with STLport.
|
||||
#ifndef STLPORT
|
||||
template <>
|
||||
struct hash<int64> {
|
||||
size_t operator()(int64 x) const { return static_cast<size_t>(x); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<uint64> {
|
||||
size_t operator()(uint64 x) const { return static_cast<size_t>(x); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<const std::string> {
|
||||
size_t operator()(const std::string& x) const {
|
||||
size_t hash = 0;
|
||||
int c;
|
||||
const char* s = x.c_str();
|
||||
while ((c = *s++)) { // Extra () to remove a warning on Windows.
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<std::string> {
|
||||
size_t operator()(const std::string& x) const {
|
||||
size_t hash = 0;
|
||||
int c;
|
||||
const char* s = x.c_str();
|
||||
while ((c = *s++)) { // Extra () to remove a warning on Windows.
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
#endif // STLPORT
|
||||
} // namespace HASH_NAMESPACE
|
||||
|
||||
using HASH_NAMESPACE::hash;
|
||||
using HASH_NAMESPACE::hash_map;
|
||||
using HASH_NAMESPACE::hash_set;
|
||||
#endif // __GNUC__
|
||||
|
||||
#undef HASH_NAMESPACE
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Microsoft Visual C++ port
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef _MSC_VER
|
||||
// TODO(user): Nuke this section and merge with gcc version.
|
||||
// The following class defines a hash function for std::pair<int64, int64>.
|
||||
class PairInt64Hasher : public stdext::hash_compare<std::pair<int64, int64> > {
|
||||
public:
|
||||
@@ -238,90 +328,6 @@ using stdext::hash_map;
|
||||
using stdext::hash_set;
|
||||
#endif // _MSC_VER
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// GNU C++ port, with or without STLport.
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUC__
|
||||
// hash namespace
|
||||
#if defined(__GNUC__) && defined(STLPORT)
|
||||
#define HASH_NAMESPACE std
|
||||
#elif defined(__GNUC__) && !defined(STLPORT)
|
||||
#define HASH_NAMESPACE __gnu_cxx
|
||||
#endif
|
||||
|
||||
// Support a few hash<> operators, in the hash namespace.
|
||||
inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) {
|
||||
uint32 b = 0x9e3779b9UL; // The golden ratio; an arbitrary value.
|
||||
operations_research::mix(num, b, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) {
|
||||
uint64 b = GG_ULONGLONG(0xe08c1d668b756f82); // More of the golden ratio.
|
||||
operations_research::mix(num, b, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
namespace HASH_NAMESPACE {
|
||||
template <class First, class Second>
|
||||
struct hash<std::pair<First, Second> > {
|
||||
size_t operator()(const std::pair<First, Second>& p) const {
|
||||
size_t h1 = hash<First>()(p.first);
|
||||
size_t h2 = hash<Second>()(p.second);
|
||||
// The decision below is at compile time
|
||||
return (sizeof(h1) <= sizeof(uint32)) ? // NOLINT
|
||||
Hash32NumWithSeed(h1, h2)
|
||||
: Hash64NumWithSeed(h1, h2);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct hash<T*> {
|
||||
size_t operator()(T* x) const { return reinterpret_cast<size_t>(x); }
|
||||
};
|
||||
|
||||
// hash<int64> and hash<std::string> are already defined with STLport.
|
||||
#ifndef STLPORT
|
||||
template <>
|
||||
struct hash<int64> {
|
||||
size_t operator()(int64 x) const { return static_cast<size_t>(x); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<const std::string> {
|
||||
size_t operator()(const std::string& x) const {
|
||||
size_t hash = 0;
|
||||
int c;
|
||||
const char* s = x.c_str();
|
||||
while ((c = *s++)) { // Extra () to remove a warning on Windows.
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<std::string> {
|
||||
size_t operator()(const std::string& x) const {
|
||||
size_t hash = 0;
|
||||
int c;
|
||||
const char* s = x.c_str();
|
||||
while ((c = *s++)) { // Extra () to remove a warning on Windows.
|
||||
hash = ((hash << 5) + hash) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
#endif // STLPORT
|
||||
} // namespace HASH_NAMESPACE
|
||||
|
||||
using HASH_NAMESPACE::hash;
|
||||
using HASH_NAMESPACE::hash_map;
|
||||
using HASH_NAMESPACE::hash_set;
|
||||
#endif // __GNUC__
|
||||
|
||||
#undef HASH_NAMESPACE
|
||||
|
||||
#endif // SWIG
|
||||
|
||||
#endif // OR_TOOLS_BASE_HASH_H_
|
||||
|
||||
@@ -185,6 +185,7 @@ class ITIVector : protected std::vector<T, Alloc> {
|
||||
return x.get() op y.get(); \
|
||||
}
|
||||
ITIVECTOR_COMPARISON_OP(== ); // NOLINT
|
||||
ITIVECTOR_COMPARISON_OP(!= ); // NOLINT
|
||||
ITIVECTOR_COMPARISON_OP(< ); // NOLINT
|
||||
ITIVECTOR_COMPARISON_OP(<= ); // NOLINT
|
||||
ITIVECTOR_COMPARISON_OP(> ); // NOLINT
|
||||
|
||||
Reference in New Issue
Block a user