hash: add halfsipmix
This commit is contained in:
parent
4b57e373f9
commit
8f5604dde6
@ -383,6 +383,8 @@ list (
|
||||
hash/fletcher.hpp
|
||||
hash/fnv1a.cpp
|
||||
hash/fnv1a.hpp
|
||||
hash/halfsipmix.cpp
|
||||
hash/halfsipmix.hpp
|
||||
hash/murmur/common.cpp
|
||||
hash/murmur/common.hpp
|
||||
hash/murmur.hpp
|
||||
@ -698,6 +700,7 @@ if (TESTS)
|
||||
hash/crc
|
||||
hash/fasthash
|
||||
hash/fnv1a
|
||||
hash/halfsipmix
|
||||
hash/murmur
|
||||
hash/siphash
|
||||
hash/table
|
||||
|
1
hash/halfsipmix.cpp
Normal file
1
hash/halfsipmix.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "./halfsipmix.hpp"
|
147
hash/halfsipmix.hpp
Normal file
147
hash/halfsipmix.hpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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 2020, Danny Robson <danny@nerdcruft.net>
|
||||
*
|
||||
* Derived from the CC0 reference implementation by:
|
||||
* Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../std.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <span>
|
||||
|
||||
|
||||
namespace cruft::hash {
|
||||
template <
|
||||
typename ResultT,
|
||||
int CRoundsV,
|
||||
int DRoundsV,
|
||||
typename = std::enable_if_t<std::is_same_v<ResultT, u32> || std::is_same_v<ResultT, u64>>
|
||||
>
|
||||
struct halfsiphash {
|
||||
u32 rotl (u32 x, u32 b)
|
||||
{
|
||||
return ((x) << (b)) | ((x) >> (32 - (b)));
|
||||
}
|
||||
|
||||
u32 v0, v1, v2, v3;
|
||||
|
||||
constexpr halfsiphash (u32 k0, u32 k1)
|
||||
{
|
||||
v0 = 0 ^ k0;
|
||||
v1 = 0 ^ k1;
|
||||
v2 = 0x6c796765 ^ k0;
|
||||
v3 = 0x74656462 ^ k1;
|
||||
|
||||
if constexpr (std::is_same_v<ResultT, u64>)
|
||||
v1 ^= 0xee;
|
||||
}
|
||||
|
||||
constexpr void round (void)
|
||||
{
|
||||
v0 += v1;
|
||||
v1 = rotl (v1, 5);
|
||||
v1 ^= v0;
|
||||
v0 = rotl (v0, 16);
|
||||
v2 += v3;
|
||||
v3 = rotl (v3, 8);
|
||||
v3 ^= v2;
|
||||
v0 += v3;
|
||||
v3 = rotl (v3, 7);
|
||||
v3 ^= v0;
|
||||
v2 += v1;
|
||||
v1 = rotl (v1, 13);
|
||||
v1 ^= v2;
|
||||
v2 = rotl (v2, 16);
|
||||
}
|
||||
|
||||
constexpr void put (u32 word)
|
||||
{
|
||||
v3 ^= word;
|
||||
for (int i = 0; i < CRoundsV; ++i)
|
||||
round ();
|
||||
v0 ^= word;
|
||||
}
|
||||
|
||||
constexpr ResultT
|
||||
operator() (
|
||||
std::span<u32 const> in
|
||||
) {
|
||||
for (auto const &m: in)
|
||||
put (m);
|
||||
|
||||
return finish (u32 (in.size ()));
|
||||
}
|
||||
|
||||
template <typename ...ArgsT>
|
||||
requires (std::is_same_v<std::remove_cvref_t<ArgsT>, u32> && ...)
|
||||
constexpr ResultT
|
||||
operator() (ArgsT &&...vals)
|
||||
{
|
||||
(put (vals), ...);
|
||||
return finish (sizeof ...(vals));
|
||||
}
|
||||
|
||||
constexpr ResultT
|
||||
finish (u32 count)
|
||||
{
|
||||
u32 const b = u32(count * sizeof (u32)) << 24;
|
||||
|
||||
v3 ^= b;
|
||||
|
||||
for (int i = 0; i < CRoundsV; ++i)
|
||||
round ();
|
||||
|
||||
v0 ^= b;
|
||||
|
||||
if (std::is_same_v<ResultT,u64>)
|
||||
v2 ^= 0xee;
|
||||
else
|
||||
v2 ^= 0xff;
|
||||
|
||||
for (int i = 0; i < DRoundsV; ++i)
|
||||
round ();
|
||||
|
||||
ResultT res = v1 ^ v3;
|
||||
|
||||
if constexpr (std::is_same_v<ResultT, u32>)
|
||||
return res;
|
||||
|
||||
v1 ^= 0xdd;
|
||||
|
||||
for (int i = 0; i < DRoundsV; ++i)
|
||||
round ();
|
||||
|
||||
res |= u64(v1 ^ v3) << 32;
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <
|
||||
int CRoundsV,
|
||||
int DRoundsV,
|
||||
typename ...ValuesT
|
||||
>
|
||||
requires (std::is_same_v<std::remove_cvref_t<ValuesT>, u32> && ...)
|
||||
inline constexpr
|
||||
u32 halfsipmix (u32 key0, u32 key1, ValuesT &&...vals)
|
||||
{
|
||||
return halfsiphash<u32, 2,4> (key0, key1) (vals...);
|
||||
}
|
||||
|
||||
|
||||
template <typename ...ValueT>
|
||||
decltype(auto)
|
||||
halfsipmix24 (ValueT &&...vals)
|
||||
{
|
||||
return halfsipmix<2, 4> (vals...);
|
||||
}
|
||||
};
|
98
test/hash/halfsipmix.cpp
Normal file
98
test/hash/halfsipmix.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "hash/halfsipmix.hpp"
|
||||
#include "tap.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
static constexpr u32
|
||||
vectors_hsip32[64] = {
|
||||
0x5b9f35a9,
|
||||
0x89466e2a,
|
||||
0x8f84b8d0,
|
||||
0x2f87f057,
|
||||
0x84acb5d9,
|
||||
0x45104de3,
|
||||
0x630c4027,
|
||||
0x004064b0,
|
||||
0x1221e7fe,
|
||||
0xecc65ce7,
|
||||
0x4018bcb6,
|
||||
0x48d50577,
|
||||
0xe32ce169,
|
||||
0xd4f3853b,
|
||||
0x40b9c5a5,
|
||||
0x736ce7d4,
|
||||
};
|
||||
|
||||
|
||||
static constexpr u64
|
||||
vectors_hsip64[64] = {
|
||||
0xc83cb8b9591f8d21,
|
||||
0xa12ee55b178ae7d5,
|
||||
0x8c85e4bc20e8feed,
|
||||
0x99c7f5ae9f1fc77b,
|
||||
0xb5f37b5fd2aa3673,
|
||||
0xdba7ee6f0a2bf51b,
|
||||
0xf1a63fae45107470,
|
||||
0xb516001efb5f922d,
|
||||
0x6c6211d8469d7028,
|
||||
0xdc7642ec407ad686,
|
||||
0x4caec8671cc8385b,
|
||||
0x5ab1dc27adf3301e,
|
||||
0x3e3ea94bc0a8eaa9,
|
||||
0xe150f598795a4402,
|
||||
0x1d5ff142f992a4a1,
|
||||
0x60e426bf902876d6,
|
||||
};
|
||||
|
||||
|
||||
static constexpr
|
||||
u32 SRC[64] {
|
||||
0x03020100,
|
||||
0x07060504,
|
||||
0x0b0a0908,
|
||||
0x0f0e0d0c,
|
||||
0x13121110,
|
||||
0x17161514,
|
||||
0x1b1a1918,
|
||||
0x1f1e1d1c,
|
||||
0x23222120,
|
||||
0x27262524,
|
||||
0x2b2a2928,
|
||||
0x2f2e2d2c,
|
||||
0x33323130,
|
||||
0x37363534,
|
||||
0x3b3a3938,
|
||||
0x3f3e3d3c,
|
||||
};
|
||||
|
||||
|
||||
template <typename ValueT>
|
||||
int siphash_test (ValueT const *v) {
|
||||
bool any_failed = false;
|
||||
int fails = 0;
|
||||
|
||||
u32 const k0 = 0x03020100;
|
||||
u32 const k1 = 0x07060504;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
ValueT res = cruft::hash::halfsiphash<ValueT, 2, 4>{k0, k1} (std::span (SRC, SRC + i));
|
||||
|
||||
if (v[i] != res) {
|
||||
fails++;
|
||||
any_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return any_failed;
|
||||
}
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
cruft::TAP::logger tap;
|
||||
tap.expect_eq (siphash_test<u32> (vectors_hsip32), 0, "siphash-2-4: u32");
|
||||
tap.expect_eq (siphash_test<u64> (vectors_hsip64), 0, "siphash-2-4: u64");
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user