Skip to content

Commit

Permalink
Update string hash algorithm (#93)
Browse files Browse the repository at this point in the history
As described in https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
FNV-1 hash lower bits don't have a good entrpy. Use FNV-1a instead, with the
lower bits pruned.
  • Loading branch information
serge-sans-paille committed Sep 16, 2020
1 parent ea201bf commit 30b4752
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
8 changes: 5 additions & 3 deletions include/frozen/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ template <typename _CharT> struct elsa<basic_string<_CharT>> {
d = d * 33 + value[i];
return d;
}
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
// With the lowest bits removed, based on experimental setup.
constexpr std::size_t operator()(basic_string<_CharT> value, std::size_t seed) const {
std::size_t d = seed;
std::size_t d = (0x811c9dc5 ^ seed) * 0x01000193;
for (std::size_t i = 0; i < value.size(); ++i)
d = (d * 0x01000193) ^ value[i];
return d;
d = (d ^ value[i]) * 0x01000193;
return d >> 8 ;
}
};

Expand Down
21 changes: 21 additions & 0 deletions tests/test_unordered_map.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <frozen/unordered_map.h>
#include <frozen/string.h>
#include <iostream>
#include <unordered_map>

Expand Down Expand Up @@ -147,6 +148,26 @@ TEST_CASE("frozen::unordered_map <> frozen::make_unordered_map", "[unordered_map
}
}

TEST_CASE("frozen::unordered_map <> std::unordered_map /small", "[unordered_map]") {
#define INIT_SEQ_SMALL \
{"0", 0},{"1", 1},{"2", 2},{"3", 3},{"5", 4},{"8", 5},{"9", 6},{"A", 7},{"W", 8},{"X", 9},{"r", 10},{"y", 11},{"BF", 12},{"AP", 13}

const std::unordered_map<frozen::string, int> std_map = { INIT_SEQ_SMALL };
constexpr frozen::unordered_map<frozen::string, int, 14> frozen_map = { INIT_SEQ_SMALL };
SECTION("checking size and content") {
REQUIRE(std_map.size() == frozen_map.size());
for (auto v : std_map)
REQUIRE(frozen_map.count(std::get<0>(v)));
for (auto v : frozen_map)
REQUIRE(std_map.count(std::get<0>(v)));
}

static_assert(std::is_same<typename decltype(std_map)::key_type,
typename decltype(frozen_map)::key_type>::value, "");
static_assert(std::is_same<typename decltype(std_map)::mapped_type,
typename decltype(frozen_map)::mapped_type>::value, "");
}

TEST_CASE("frozen::unordered_map constexpr", "[unordered_map]") {
constexpr frozen::unordered_map<unsigned, unsigned, 2> ce = {{3,4}, {11,12}};
static_assert(ce.begin() +2 == ce.end(), "");
Expand Down

0 comments on commit 30b4752

Please sign in to comment.