summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sashihara <21227491+n8sh@users.noreply.github.com>2018-08-02 12:08:32 -0400
committerNathan Sashihara <21227491+n8sh@users.noreply.github.com>2018-08-02 12:37:02 -0400
commitceb8e6a113809110526844d18a367d501b09ed4c (patch)
tree92a91678bdf0486d44edbac4f870b465016613d5
parent900a7172bf10fb1caa0e3228b31bd390a24da1f7 (diff)
downloadtanya-ceb8e6a113809110526844d18a367d501b09ed4c.tar.gz
Use identity hash for integers and pointers
This is appropriate because HashArray in tanya.container.entry uses prime numbers instead of powers of 2 for its number of buckets so there is no pitfall if the hashes are all multiples of some power of 2.
-rw-r--r--source/tanya/hash/lookup.d27
1 files changed, 21 insertions, 6 deletions
diff --git a/source/tanya/hash/lookup.d b/source/tanya/hash/lookup.d
index f564b53..9b0d883 100644
--- a/source/tanya/hash/lookup.d
+++ b/source/tanya/hash/lookup.d
@@ -89,7 +89,10 @@ private struct FNV
* }
* ---
*
- * For scalar types FNV-1a (Fowler-Noll-Vo) hash function is used internally.
+ * For pointers and for scalar types implicitly convertible to `size_t` this
+ * is an identity operation (i.e. the value is cast to `size_t` and returned
+ * unaltered). Integer types wider than `size_t` are XOR folded down to
+ * `size_t`. Other scalar types use the FNV-1a (Fowler-Noll-Vo) hash function.
* If the type provides a `toHash`-function, only `toHash()` is called and its
* result is returned.
*
@@ -110,6 +113,19 @@ size_t hash(T)(auto ref T key)
{
return key.toHash();
}
+ else static if ((isIntegral!T || isSomeChar!T || isBoolean!T)
+ && T.sizeof <= size_t.sizeof)
+ {
+ return cast(size_t) key;
+ }
+ else static if (isIntegral!T && T.sizeof > size_t.sizeof)
+ {
+ return cast(size_t) (key ^ (key >>> (size_t.sizeof * 8)));
+ }
+ else static if (isPointer!T || is(T : typeof(null)))
+ {
+ return (() @trusted => cast(size_t) key)();
+ }
else
{
FNV fnv;
@@ -177,30 +193,29 @@ version (unittest)
// Tests that work for any hash size
@nogc nothrow pure @safe unittest
{
- assert(hash(null) == FNV.offsetBasis);
+ assert(hash(null) == 0);
assert(hash(ToHash()) == 0U);
+ assert(hash('a') == 'a');
}
static if (size_t.sizeof == 4) @nogc nothrow pure @safe unittest
{
- assert(hash('a') == 0xe40c292cU);
assert(hash(HashRange()) == 0x6222e842U);
assert(hash(ToHashRange()) == 1268118805U);
}
static if (size_t.sizeof == 8) @nogc nothrow pure @safe unittest
{
- assert(hash('a') == 0xaf63dc4c8601ec8cUL);
assert(hash(HashRange()) == 0x08985907b541d342UL);
assert(hash(ToHashRange()) == 12161962213042174405UL);
}
static if (size_t.sizeof == 4) @nogc nothrow pure @system unittest
{
- assert(hash(cast(void*) 0x6e6f6863) == 0xac297727U);
+ assert(hash(cast(void*) 0x6e6f6863) == 0x6e6f6863);
}
static if (size_t.sizeof == 8) @nogc nothrow pure @system unittest
{
- assert(hash(cast(void*) 0x77206f676e6f6863) == 0xd1edd10b507344d0UL);
+ assert(hash(cast(void*) 0x77206f676e6f6863) == 0x77206f676e6f6863);
}
/*