rewrite hash part

This commit is contained in:
lperron@google.com
2014-04-04 09:11:49 +00:00
parent aeb1a56ade
commit 3c15315a8b
3 changed files with 130 additions and 85 deletions

View 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_

View File

@@ -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_

View File

@@ -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