diff --git a/README.md b/README.md index c372ef2..3323942 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,13 @@ Tanya consists of the following packages and (top-level) modules: * `algorithm`: Collection of generic algorithms. * `async`: Event loop (epoll, kqueue and IOCP). * `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8 -string, Hash set. +string, Hash table. * `conv`: This module provides functions for converting between different types. * `encoding`: This package provides tools to work with text encodings. * `exception`: Common exceptions and errors. * `format`: Formatting and conversion functions. +* `hash`: Hash algorithms. * `math`: Arbitrary precision integer and a set of functions. * `memory`: Tools for manual memory management (allocators, smart pointers). * `meta`: Template metaprogramming. This package contains utilities to acquire diff --git a/source/tanya/hash/lookup.d b/source/tanya/hash/lookup.d new file mode 100644 index 0000000..a4f4a46 --- /dev/null +++ b/source/tanya/hash/lookup.d @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Non-cryptographic, lookup hash functions. + * + * Copyright: Eugene Wissner 2018. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/hash/lookup.d, + * tanya/hash/lookup.d) + */ +module tanya.hash.lookup; + +import tanya.meta.trait; + +/** + * FNV-1a (Fowler-Noll-Vo) hash function. + * + * See_Also: $(LINK http://www.isthe.com/chongo/tech/comp/fnv/). + */ +size_t fnv(const ubyte[] key) @nogc nothrow pure @safe +{ + static if (size_t.sizeof == 4) + { + enum uint offsetBasis = 2166136261; + enum uint fnvPrime = 16777619; + } + else static if (size_t.sizeof == 8) + { + enum ulong offsetBasis = 14695981039346656037UL; + enum ulong fnvPrime = 1099511628211UL; + } + else + { + static assert(false, "FNV requires at least 32-bit hash length"); + } + + size_t h = offsetBasis; + + foreach (c; key) + { + h = (h ^ c) * fnvPrime; + } + + return h; +} + +static if (size_t.sizeof == 4) @nogc nothrow pure @safe unittest +{ + assert(fnv(null) == 2166136261); + + ubyte[1] given = [0]; + assert(fnv(given) == 84696351); +} + +static if (size_t.sizeof == 8) @nogc nothrow pure @safe unittest +{ + assert(fnv(null) == 14695981039346656037UL); + + ubyte[1] given = [0]; + assert(fnv(given) == (14695981039346656037UL * 1099511628211UL)); +} + +size_t hash(T)(auto ref const T key) +{ + static if (isScalarType!T) + { + return (() @trusted => fnv(cast(const ubyte[]) (&key)[0 .. T.sizeof]))(); + } +} diff --git a/source/tanya/hash/package.d b/source/tanya/hash/package.d new file mode 100644 index 0000000..dab6f7f --- /dev/null +++ b/source/tanya/hash/package.d @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Copyright: Eugene Wissner 2018. + * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, + * Mozilla Public License, v. 2.0). + * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) + * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/hash/package.d, + * tanya/hash/package.d) + */ +module tanya.hash; + +public import tanya.hash.lookup;