aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/include/G3D/HashTrait.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/include/G3D/HashTrait.h')
-rw-r--r--dep/g3dlite/include/G3D/HashTrait.h135
1 files changed, 114 insertions, 21 deletions
diff --git a/dep/g3dlite/include/G3D/HashTrait.h b/dep/g3dlite/include/G3D/HashTrait.h
index 72de3da52fd..1de3777baec 100644
--- a/dep/g3dlite/include/G3D/HashTrait.h
+++ b/dep/g3dlite/include/G3D/HashTrait.h
@@ -1,11 +1,11 @@
/**
- @file HashTrait.h
+ \file G3D/HashTrait.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-10-01
- @edited 2009-11-01
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2008-10-01
+ \edited 2011-06-09
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -16,6 +16,88 @@
#include "G3D/Crypto.h"
#include "G3D/g3dmath.h"
#include "G3D/uint128.h"
+#include <typeinfo>
+
+#include <stdint.h>
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+namespace G3D {
+/** \brief A hash function that is faster than CRC32 for arbitrary long strings
+ \cite From http://www.azillionmonkeys.com/qed/hash.html by Paul Hsieh*/
+inline uint32_t superFastHash (const void* _data, size_t numBytes) {
+ const char* data = (const char*)_data;
+ uint32_t hash = (uint32_t)numBytes;
+ uint32_t tmp;
+ int rem;
+
+ if ((numBytes <= 0) || (data == NULL)) {
+ return 0;
+ }
+
+ rem = numBytes & 3;
+ numBytes >>= 2;
+
+ /* Main loop */
+ for (;numBytes > 0; --numBytes) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (uint16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem) {
+ case 3: hash += get16bits (data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof (uint16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
+
+/**
+ Thomas Wang's 64-to-32-bit mix hash based on Robert Jenkin's hash http://www.concentric.net/~ttwang/tech/inthash.htm
+
+ Found by Morgan to produce the best net performance for building tables from Vector4int16
+*/
+inline uint32_t wangHash6432Shift(int64 key) {
+ key = (~key) + (key << 18); // key = (key << 18) - key - 1;
+ key = key ^ (key >> 31);
+ key = key * 21; // key = (key + (key << 2)) + (key << 4);
+ key = key ^ (key >> 11);
+ key = key + (key << 6);
+ return uint32_t(key) ^ uint32_t(key >> 22);
+}
+
+}
+#undef get16bits
/** Must be specialized for custom types.
@see G3D::Table for specialization requirements.
@@ -23,14 +105,19 @@
template <typename T> struct HashTrait{};
template <typename T> struct HashTrait<T*> {
- static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k); }
+ static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k) >> 1; }
};
-#if 0
-template <> struct HashTrait <int> {
- static size_t hashCode(int k) { return static_cast<size_t>(k); }
+/** For use with \code Table<std::type_info* const, ValueType> \endcode. */
+template <> struct HashTrait <std::type_info* const> {
+ static size_t hashCode(const std::type_info* const t) {
+# ifdef _MSC_VER
+ return t->hash_code();
+# else
+ return reinterpret_cast<size_t>(t) >> 1;
+# endif
+ }
};
-#endif
template <> struct HashTrait <G3D::int16> {
static size_t hashCode(G3D::int16 k) { return static_cast<size_t>(k); }
@@ -40,10 +127,6 @@ template <> struct HashTrait <G3D::uint16> {
static size_t hashCode(G3D::uint16 k) { return static_cast<size_t>(k); }
};
-//template <> struct HashTrait <int> {
-// static size_t hashCode(int k) { return static_cast<size_t>(k); }
-//};
-
template <> struct HashTrait <G3D::int32> {
static size_t hashCode(G3D::int32 k) { return static_cast<size_t>(k); }
};
@@ -58,21 +141,30 @@ template <> struct HashTrait <long unsigned int> {
};
#endif
-template <> struct HashTrait <G3D::int64> {
- static size_t hashCode(G3D::int64 k) { return static_cast<size_t>(k); }
-};
template <> struct HashTrait <G3D::uint64> {
- static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k); }
+ static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k) ^ static_cast<size_t>(k >> 32); }
};
+template <> struct HashTrait <G3D::int64> {
+ static size_t hashCode(G3D::int64 k) { return HashTrait<G3D::uint64>::hashCode(G3D::uint64(k)); }
+};
+
+
template <> struct HashTrait <std::string> {
- static size_t hashCode(const std::string& k) { return static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size())); }
+ static size_t hashCode(const std::string& k) {
+ return G3D::superFastHash(k.c_str(), k.size());
+ //return static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size()));
+ }
};
template <> struct HashTrait<G3D::uint128> {
- // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
static size_t hashCode(G3D::uint128 key) {
+ return G3D::superFastHash(&key, sizeof(key));
+ //return HashTrait<G3D::uint64>::hashCode(key.hi) ^ HashTrait<G3D::uint64>::hashCode(key.lo);
+
+#if 0 // Really slow under gcc
+ // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159);
static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2ULL, 0xF52F88BF32307F8FULL);
@@ -83,9 +175,10 @@ template <> struct HashTrait<G3D::uint128> {
hash ^= (mask & key);
key >>= 8;
}
-
+
G3D::uint64 foldedHash = hash.hi ^ hash.lo;
return static_cast<size_t>((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF));
+#endif
}
};