Move the Fowler-Noll-Vo hash function to a header
* spot/misc/bitvect.cc, spot/misc/hashfunc.hh: move FNV hash function, use the new interface
This commit is contained in:
parent
5b2ce2736b
commit
85bc05e737
2 changed files with 46 additions and 54 deletions
|
|
@ -43,48 +43,6 @@ namespace spot
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fowler-Noll-Vo hash parameters.
|
|
||||||
// Add specializations as needed.
|
|
||||||
template<int numbytes>
|
|
||||||
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):
|
bitvect::bitvect(size_t size, size_t block_count):
|
||||||
|
|
@ -117,23 +75,17 @@ namespace spot
|
||||||
|
|
||||||
size_t bitvect::hash() const noexcept
|
size_t bitvect::hash() const noexcept
|
||||||
{
|
{
|
||||||
|
const size_t m = used_blocks();
|
||||||
block_t res = fnv<sizeof(block_t)>::init();
|
|
||||||
size_t i;
|
|
||||||
size_t m = used_blocks();
|
|
||||||
if (m == 0)
|
if (m == 0)
|
||||||
return res;
|
return fnv_hash(storage_, storage_ + m);
|
||||||
for (i = 0; i < m - 1; ++i)
|
|
||||||
{
|
size_t res = fnv_hash(storage_, storage_ + m - 1);
|
||||||
res ^= storage_[i];
|
|
||||||
res *= fnv<sizeof(block_t)>::prime();
|
|
||||||
}
|
|
||||||
// Deal with the last block, that might not be fully used.
|
// Deal with the last block, that might not be fully used.
|
||||||
// Compute the number n of bits used in the last block.
|
// Compute the number n of bits used in the last block.
|
||||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||||
size_t n = size() % bpb;
|
size_t n = size() % bpb;
|
||||||
// Use only the least n bits from storage_[i].
|
// Use only the least n bits from storage_[i].
|
||||||
res ^= storage_[i] & ((1UL << n) - 1);
|
res ^= storage_[m-1] & ((1UL << n) - 1);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- 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)
|
// de l'Epita (LRDE)
|
||||||
// Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6),
|
// Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -62,5 +63,44 @@ namespace spot
|
||||||
// bits assumes that all objects are aligned on a 8 byte boundary.
|
// bits assumes that all objects are aligned on a 8 byte boundary.
|
||||||
return (key >> 3) * 2654435761U;
|
return (key >> 3) * 2654435761U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Struct for Fowler-Noll-Vo parameters
|
||||||
|
template<class T>
|
||||||
|
struct fnv
|
||||||
|
{};
|
||||||
|
|
||||||
|
/// Fowler-Noll-Vo hash parameters for 32 bits
|
||||||
|
template<>
|
||||||
|
struct fnv<uint32_t>
|
||||||
|
{
|
||||||
|
static constexpr uint32_t init = 2166136261UL;
|
||||||
|
static constexpr uint32_t prime = 16777619UL;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Fowler-Noll-Vo hash parameters for 64 bits
|
||||||
|
template<>
|
||||||
|
struct fnv<uint64_t>
|
||||||
|
{
|
||||||
|
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<class It>
|
||||||
|
size_t
|
||||||
|
fnv_hash(It begin, It end)
|
||||||
|
{
|
||||||
|
size_t res = fnv<size_t>::init;
|
||||||
|
for (; begin != end; ++begin)
|
||||||
|
{
|
||||||
|
res ^= *begin;
|
||||||
|
res *= fnv<size_t>::prime;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue