diff --git a/spot/misc/bitvect.cc b/spot/misc/bitvect.cc index 3dfd80288..c39ff2ed1 100644 --- a/spot/misc/bitvect.cc +++ b/spot/misc/bitvect.cc @@ -43,48 +43,6 @@ namespace spot return n; } - // Fowler-Noll-Vo hash parameters. - // Add specializations as needed. - template - struct fnv - { - }; - - // Do not define the following if ULONG_MAX cannot - // hold a 64-bit value, otherwise the parser will - // choke when parsing the constants. -#if ULONG_MAX >> 31 >> 31 >> 1 > 0 - // Fowler-Noll-Vo hash parameters for 64bits - template<> - struct fnv<8> - { - static unsigned long init() - { - return 14695981039346656037UL; - } - - static unsigned long prime() - { - return 1099511628211UL; - } - }; -#endif - - // Fowler-Noll-Vo hash parameters for 32bits - template<> - struct fnv<4> - { - static unsigned long init() - { - return 2166136261UL; - } - - static unsigned long prime() - { - return 16777619UL; - } - }; - } bitvect::bitvect(size_t size, size_t block_count): @@ -117,23 +75,17 @@ namespace spot size_t bitvect::hash() const noexcept { - - block_t res = fnv::init(); - size_t i; - size_t m = used_blocks(); + const size_t m = used_blocks(); if (m == 0) - return res; - for (i = 0; i < m - 1; ++i) - { - res ^= storage_[i]; - res *= fnv::prime(); - } + return fnv_hash(storage_, storage_ + m); + + size_t res = fnv_hash(storage_, storage_ + m - 1); // Deal with the last block, that might not be fully used. // Compute the number n of bits used in the last block. const size_t bpb = 8 * sizeof(bitvect::block_t); size_t n = size() % bpb; // Use only the least n bits from storage_[i]. - res ^= storage_[i] & ((1UL << n) - 1); + res ^= storage_[m-1] & ((1UL << n) - 1); return res; } diff --git a/spot/misc/hashfunc.hh b/spot/misc/hashfunc.hh index bf52451e9..60d7e2a09 100644 --- a/spot/misc/hashfunc.hh +++ b/spot/misc/hashfunc.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2015 Laboratoire de Recherche et Développement +// Copyright (C) 2015, 2018 Laboratoire de Recherche et Développement // de l'Epita (LRDE) // Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre @@ -23,6 +23,7 @@ #pragma once #include +#include namespace spot { @@ -62,5 +63,44 @@ namespace spot // bits assumes that all objects are aligned on a 8 byte boundary. return (key >> 3) * 2654435761U; } + + /// Struct for Fowler-Noll-Vo parameters + template + struct fnv + {}; + + /// Fowler-Noll-Vo hash parameters for 32 bits + template<> + struct fnv + { + static constexpr uint32_t init = 2166136261UL; + static constexpr uint32_t prime = 16777619UL; + }; + + /// Fowler-Noll-Vo hash parameters for 64 bits + template<> + struct fnv + { + static constexpr uint64_t init = 14695981039346656037UL; + static constexpr uint64_t prime = 1099511628211UL; + }; + + /// \brief Fowler-Noll-Vo hash function + /// + /// This function is a non-cryptographic fast hash function. + /// The magic constants depend on the size of a size_t. + template + size_t + fnv_hash(It begin, It end) + { + size_t res = fnv::init; + for (; begin != end; ++begin) + { + res ^= *begin; + res *= fnv::prime; + } + return res; + } + /// @} }