4 Commits

Author SHA1 Message Date
abdelrahman 900c16415b Add implementation for siphash
Release / release (push) Successful in 4s
2026-08-31 02:15:01 +01:00
abdelrahman bca2e720ad Add Murmur3 validation
Release / release (push) Successful in 3s
2026-08-30 23:56:50 +01:00
abdelrahman 850f709a10 Update Murmur3 hasher IO
Release / release (push) Successful in 3s
2026-08-30 23:50:22 +01:00
abdelrahman 55ff77c4ea Add implementation for the murmur3 x64_128 hash
Release / release (push) Successful in 3s
2026-08-30 22:03:28 +01:00
20 changed files with 1832 additions and 0 deletions
+8
View File
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- `wpMiscUtilsRotl64` utility
- `wpMur3HasherIO` to setup the MurmurHash3 IO struct
- `wpX64Mur3Hasher128` implementation for the x64 128-bit variant of the MurmurHash3 algorithm
- `wpSip24Hasher128IO`, `wpSip48Hasher128IO`, `wpSip24Hasher64IO` and `wpSip48Hasher64IO` to setup the siphash IO structs for the different variants
- `wpSipHasher128` and `wpSipHasher64` implementation for the 128 and 64 variants of siphash
## [2.4.0] - 2026-08-30
### Added
+18
View File
@@ -0,0 +1,18 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef HASHER_H
#define HASHER_H
#include "../../stream/stream.h"
#ifdef WP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP
typedef void (*WpHasher)(WpU8Stream *stream, void *hasher_io);
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WP_PLATFORM_CPP
#endif // !HASHER_H
+112
View File
@@ -0,0 +1,112 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "murmur3.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/misc/misc_utils.h"
#define _bigConstant(x) (x##LLU)
wp_intern inline void _validateIO(const WpMur3HasherIO *io);
wp_intern inline u64 _fmix64(u64 k);
void wpX64Mur3Hasher128(WpU8Stream *bytes, void *hasher_io) {
WpMur3HasherIO *io = (WpMur3HasherIO *)hasher_io;
_validateIO(io);
const i32 nblocks = (bytes->count * bytes->item_size) / 16;
u64 h1 = io->seed;
u64 h2 = io->seed;
const u64 c1 = _bigConstant(0x87c37b91114253d5);
const u64 c2 = _bigConstant(0x4cf5ad432745937f);
//----------
// body
for(int i = 0; i < nblocks; ++i) {
u64 k1 = *((u64 *)wpStreamConsumeCount(u8, bytes, sizeof(u64)));
u64 k2 = *((u64 *)wpStreamConsumeCount(u8, bytes, sizeof(u64)));
k1 *= c1;
k1 = wpMiscUtilsRotl64(k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = wpMiscUtilsRotl64(h1, 27);
h1 += h2;
h1 = h1 * 5 +0x52dce729;
k2 *= c2;
k2 = wpMiscUtilsRotl64(k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = wpMiscUtilsRotl64(h2, 31);
h2 += h1;
h2 = h2*5+0x38495ab5;
}
//----------
// tail
const u8 *tail = wpStreamConsumeCount(u8, bytes, bytes->count - bytes->position);
u64 k1 = 0;
u64 k2 = 0;
u64 len = bytes->count * bytes->item_size;
switch(len & 15) {
case 15: k2 ^= ((u64)tail[14]) << 48;
case 14: k2 ^= ((u64)tail[13]) << 40;
case 13: k2 ^= ((u64)tail[12]) << 32;
case 12: k2 ^= ((u64)tail[11]) << 24;
case 11: k2 ^= ((u64)tail[10]) << 16;
case 10: k2 ^= ((u64)tail[ 9]) << 8;
case 9: k2 ^= ((u64)tail[ 8]) << 0;
k2 *= c2; k2 = wpMiscUtilsRotl64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((u64)tail[ 7]) << 56;
case 7: k1 ^= ((u64)tail[ 6]) << 48;
case 6: k1 ^= ((u64)tail[ 5]) << 40;
case 5: k1 ^= ((u64)tail[ 4]) << 32;
case 4: k1 ^= ((u64)tail[ 3]) << 24;
case 3: k1 ^= ((u64)tail[ 2]) << 16;
case 2: k1 ^= ((u64)tail[ 1]) << 8;
case 1: k1 ^= ((u64)tail[ 0]) << 0;
k1 *= c1; k1 = wpMiscUtilsRotl64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = _fmix64(h1);
h2 = _fmix64(h2);
h1 += h2;
h2 += h1;
io->hash[0] = h1;
io->hash[1] = h2;
}
wp_intern inline void _validateIO(const WpMur3HasherIO *io) {
wpRuntimeAssert(io->magic == WP_MUR3_HASHER_MAGIC, "Invalid Murmur3 hash IO");
}
wp_intern inline u64 _fmix64(u64 k) {
k ^= k >> 33;
k *= _bigConstant(0xff51afd7ed558ccd);
k ^= k >> 33;
k *= _bigConstant(0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
+39
View File
@@ -0,0 +1,39 @@
// vim:fileencoding=utf-8:foldmethod=marker
/**
* An implementation of the x64 128-bit variant of the MurmurHash3 algorithm
* based on https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
*/
#ifndef MURMUR3_H
#define MURMUR3_H
#include "../../stream/stream.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#ifdef WP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP
#define WP_MUR3_HASHER_MAGIC ((u64)0x57504d4841534833)
typedef struct {
u64 hash[2];
u64 magic;
u32 seed;
} WpMur3HasherIO;
#ifdef WP_PLATFORM_CPP
#define wpMur3HasherIO(SEED) (WpMur3HasherIO{{}, WP_MUR3_HASHER_MAGIC, SEED})
#else
#define wpMur3HasherIO(SEED) ((WpMur3HasherIO){ .magic = WP_MUR3_HASHER_MAGIC, .seed = SEED })
#endif
void wpX64Mur3Hasher128(WpU8Stream *bytes, void *hasher_io);
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WP_PLATFORM_CPP
#endif // !MURMUR3_H
+177
View File
@@ -0,0 +1,177 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "siphash.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/misc/misc_utils.h"
#include <stdint.h>
wp_intern inline void _siphash(WpStream *bytes, const WpSipHasherParams *params, u8 *out, u64 outlen);
wp_intern inline void _validate128IO(const WpSipHasher128IO *io);
wp_intern inline void _validate64IO(const WpSipHasher64IO *io);
wp_intern inline b8 _checkRounds(const WpSipHasherParams *params);
#define _u32To8LE(p, v) \
(p)[0] = (u8)((v)); \
(p)[1] = (u8)((v) >> 8); \
(p)[2] = (u8)((v) >> 16); \
(p)[3] = (u8)((v) >> 24);
#define _u64To8LE(p, v) \
_u32To8LE((p), (u32)((v))); \
_u32To8LE((p) + 4, (u32)((v) >> 32));
#define _u8To64LE(p) \
(((u64)((p)[0])) | ((u64)((p)[1]) << 8) | \
((u64)((p)[2]) << 16) | ((u64)((p)[3]) << 24) | \
((u64)((p)[4]) << 32) | ((u64)((p)[5]) << 40) | \
((u64)((p)[6]) << 48) | ((u64)((p)[7]) << 56))
#define _sipRound \
do { \
v0 += v1; \
v1 = wpMiscUtilsRotl64(v1, 13); \
v1 ^= v0; \
v0 = wpMiscUtilsRotl64(v0, 32); \
v2 += v3; \
v3 = wpMiscUtilsRotl64(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = wpMiscUtilsRotl64(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = wpMiscUtilsRotl64(v1, 17); \
v1 ^= v2; \
v2 = wpMiscUtilsRotl64(v2, 32); \
} while (0)
void wpSipHasher128(WpStream *bytes, void *hasher_io) {
WpSipHasher128IO *io = (WpSipHasher128IO *)hasher_io;
_validate128IO(io);
_siphash(bytes, &io->params, (u8 *)&io->hash, sizeof(u64) * 2);
}
void wpSipHasher64(WpStream *bytes, void *hasher_io) {
WpSipHasher64IO *io = (WpSipHasher64IO *)hasher_io;
_validate64IO(io);
_siphash(bytes, &io->params, (u8 *)&io->hash, sizeof(u64));
}
wp_intern inline void _siphash(WpStream *bytes, const WpSipHasherParams *params, u8 *out,
u64 outlen) {
const u8 *kk = (const u8 *)&params->key;
u64 inlen = bytes->count * bytes->item_size;
wpRuntimeAssert((outlen == 8) || (outlen == 16), "outlen should be 8 or 16");
u64 v0 = UINT64_C(0x736f6d6570736575);
u64 v1 = UINT64_C(0x646f72616e646f6d);
u64 v2 = UINT64_C(0x6c7967656e657261);
u64 v3 = UINT64_C(0x7465646279746573);
u64 k0 = _u8To64LE(kk);
u64 k1 = _u8To64LE(kk + 8);
u64 m;
u64 i;
const i32 left = inlen & 7;
u64 b = ((u64)inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16) {
v1 ^= 0xee;
}
u8 *data;
while (wpStreamHasCount(bytes, sizeof(u64))) {
data = wpStreamConsumeCount(u8, bytes, sizeof(u64));
m = _u8To64LE(data);
v3 ^= m;
for (i = 0; i < params->compression; ++i) {
_sipRound;
}
v0 ^= m;
}
data = wpStreamConsume(u8, bytes);
switch (left) {
case 7:
b |= ((u64)data[6]) << 48;
/* FALLTHRU */
case 6:
b |= ((u64)data[5]) << 40;
/* FALLTHRU */
case 5:
b |= ((u64)data[4]) << 32;
/* FALLTHRU */
case 4:
b |= ((u64)data[3]) << 24;
/* FALLTHRU */
case 3:
b |= ((u64)data[2]) << 16;
/* FALLTHRU */
case 2:
b |= ((u64)data[1]) << 8;
/* FALLTHRU */
case 1:
b |= ((u64)data[0]);
break;
case 0:
break;
}
v3 ^= b;
for (i = 0; i < params->compression; ++i) {
_sipRound;
}
v0 ^= b;
if (outlen == 16) {
v2 ^= 0xee;
} else {
v2 ^= 0xff;
}
for (i = 0; i < params->finalisation; ++i) {
_sipRound;
}
b = v0 ^ v1 ^ v2 ^ v3;
_u64To8LE(out, b);
if (outlen == 8) {
return;
}
v1 ^= 0xdd;
for (i = 0; i < params->finalisation; ++i) {
_sipRound;
}
b = v0 ^ v1 ^ v2 ^ v3;
_u64To8LE(out + 8, b);
}
wp_intern inline void _validate128IO(const WpSipHasher128IO *io) {
b8 magic_match = io->params.magic == WP_SIP_HASHER_128_MAGIC;
b8 rounds = _checkRounds(&io->params);
wpRuntimeAssert(magic_match && rounds, "Invalid Siphash 128 IO");
}
wp_intern inline void _validate64IO(const WpSipHasher64IO *io) {
b8 magic_match = io->params.magic == WP_SIP_HASHER_64_MAGIC;
b8 rounds = _checkRounds(&io->params);
wpRuntimeAssert(magic_match && rounds, "Invalid Siphash 64 IO");
}
wp_intern inline b8 _checkRounds(const WpSipHasherParams *params) {
b8 rounds24 = params->compression == 2 && params->finalisation == 4;
b8 rounds48 = params->compression == 4 && params->finalisation == 8;
return rounds24 || rounds48;
}
+103
View File
@@ -0,0 +1,103 @@
// vim:fileencoding=utf-8:foldmethod=marker
/**
* Implementations of the SipHash-2-4-128, SipHash4-8-128, SipHash-2-4-64 and SipHash4-8-64
* algorithms based on https://github.com/veorq/SipHash/blob/master/siphash.c
*/
#ifndef SIPHASH_H
#define SIPHASH_H
#include "../../stream/stream.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#ifdef WP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP
#define WP_SIP_HASHER_128_MAGIC ((u64)0x5750534950313238)
#define WP_SIP_HASHER_64_MAGIC ((u64)0x57505349503634)
typedef struct {
u64 lo;
u64 hi;
} WpSipHasherKey;
typedef struct {
WpSipHasherKey key;
u64 magic;
u64 compression;
u64 finalisation;
} WpSipHasherParams;
typedef struct {
WpSipHasherParams params;
u64 hash[2];
} WpSipHasher128IO;
typedef struct {
WpSipHasherParams params;
u64 hash;
} WpSipHasher64IO;
#ifdef WP_PLATFORM_CPP
#define wpSip24Hasher128IO(KEY) (WpSipHasher128IO{ \
WpSipHasherParams{KEY, WP_SIP_HASHER_128_MAGIC, 2, 4}, \
{}, \
})
#define wpSip48Hasher128IO(KEY) (WpSipHasher128IO{ \
WpSipHasherParams{KEY, WP_SIP_HASHER_128_MAGIC, 4, 8}, \
{}, \
})
#define wpSip24Hasher64IO(KEY) (WpSipHasher64IO{ \
WpSipHasherParams{KEY, WP_SIP_HASHER_64_MAGIC, 2, 4}, \
0, \
})
#define wpSip48Hasher64IO(KEY) (WpSipHasher64IO{ \
WpSipHasherParams{KEY, WP_SIP_HASHER_64_MAGIC, 4, 8}, \
0, \
})
#else
#define wpSip24Hasher128IO(KEY) ((WpSipHasher128IO){ \
.params = (WpSipHasherParams){ \
.key = KEY, \
.magic = WP_SIP_HASHER_128_MAGIC, \
.compression = 2, \
.finalisation = 4, \
} \
})
#define wpSip48Hasher128IO(KEY) ((WpSipHasher128IO){ \
.params = (WpSipHasherParams){ \
.key = KEY, \
.magic = WP_SIP_HASHER_128_MAGIC, \
.compression = 4, \
.finalisation = 8, \
} \
})
#define wpSip24Hasher64IO(KEY) ((WpSipHasher64IO){ \
.params = (WpSipHasherParams){ \
.key = KEY, \
.magic = WP_SIP_HASHER_64_MAGIC, \
.compression = 2, \
.finalisation = 4, \
} \
})
#define wpSip48Hasher64IO(KEY) ((WpSipHasher64IO){ \
.params = (WpSipHasherParams){ \
.key = KEY, \
.magic = WP_SIP_HASHER_64_MAGIC, \
.compression = 4, \
.finalisation = 8, \
} \
})
#endif
void wpSipHasher128(WpU8Stream *bytes, void *hasher_io);
void wpSipHasher64(WpU8Stream *bytes, void *hasher_io);
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WP_PLATFORM_CPP
#endif // !SIPHASH_H
+2
View File
@@ -6,6 +6,8 @@
#include "wapp_base.h"
#include "array/array.c"
#include "dbl_list/dbl_list.c"
#include "hash/hasher/murmur3.c"
#include "hash/hasher/siphash.c"
#include "queue/queue.c"
#include "stream/stream.c"
#include "mem/allocator/mem_allocator.c"
+3
View File
@@ -5,6 +5,9 @@
#include "array/array.h"
#include "dbl_list/dbl_list.h"
#include "hash/hasher/hasher.h"
#include "hash/hasher/murmur3.h"
#include "hash/hasher/siphash.h"
#include "queue/queue.h"
#include "stream/stream.h"
#include "mem/allocator/mem_allocator.h"
+4
View File
@@ -50,6 +50,10 @@ BEGIN_C_LINKAGE
#define wpMiscUtilsIsPowerOfTwo(NUM) ((NUM & (NUM - 1)) == 0)
#define wpMiscUtilsOffsetPointer(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
wp_intern inline u64 wpMiscUtilsRotl64(u64 x, i8 rotation) {
return (x << rotation) | (x >> (64 - rotation));
}
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
+335
View File
@@ -0,0 +1,335 @@
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
#include "MurmurHash3.h"
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#include <stdlib.h>
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // defined(_MSC_VER)
#define FORCE_INLINE inline __attribute__((always_inline))
static inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
static inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
{
return p[i];
}
FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock32(blocks,i);
k1 *= c1;
k1 = ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
uint32_t k1 = 0;
switch(len & 3)
{
case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix32(h1);
*(uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void * key, const int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint32_t h1 = seed;
uint32_t h2 = seed;
uint32_t h3 = seed;
uint32_t h4 = seed;
const uint32_t c1 = 0x239b961b;
const uint32_t c2 = 0xab0e9789;
const uint32_t c3 = 0x38b34ae5;
const uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock32(blocks,i*4+0);
uint32_t k2 = getblock32(blocks,i*4+1);
uint32_t k3 = getblock32(blocks,i*4+2);
uint32_t k4 = getblock32(blocks,i*4+3);
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
switch(len & 15)
{
case 15: k4 ^= tail[14] << 16;
case 14: k4 ^= tail[13] << 8;
case 13: k4 ^= tail[12] << 0;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
case 12: k3 ^= tail[11] << 24;
case 11: k3 ^= tail[10] << 16;
case 10: k3 ^= tail[ 9] << 8;
case 9: k3 ^= tail[ 8] << 0;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
case 8: k2 ^= tail[ 7] << 24;
case 7: k2 ^= tail[ 6] << 16;
case 6: k2 ^= tail[ 5] << 8;
case 5: k2 ^= tail[ 4] << 0;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
case 4: k1 ^= tail[ 3] << 24;
case 3: k1 ^= tail[ 2] << 16;
case 2: k1 ^= tail[ 1] << 8;
case 1: k1 ^= tail[ 0] << 0;
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
h1 = fmix32(h1);
h2 = fmix32(h2);
h3 = fmix32(h3);
h4 = fmix32(h4);
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
((uint32_t*)out)[0] = h1;
((uint32_t*)out)[1] = h2;
((uint32_t*)out)[2] = h3;
((uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void * key, const int len,
const uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
//----------
// body
const uint64_t * blocks = (const uint64_t *)(data);
for(int i = 0; i < nblocks; i++)
{
uint64_t k1 = getblock64(blocks,i*2+0);
uint64_t k2 = getblock64(blocks,i*2+1);
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch(len & 15)
{
case 15: k2 ^= ((uint64_t)tail[14]) << 48;
case 14: k2 ^= ((uint64_t)tail[13]) << 40;
case 13: k2 ^= ((uint64_t)tail[12]) << 32;
case 12: k2 ^= ((uint64_t)tail[11]) << 24;
case 11: k2 ^= ((uint64_t)tail[10]) << 16;
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((uint64_t)tail[ 7]) << 56;
case 7: k1 ^= ((uint64_t)tail[ 6]) << 48;
case 6: k1 ^= ((uint64_t)tail[ 5]) << 40;
case 5: k1 ^= ((uint64_t)tail[ 4]) << 32;
case 4: k1 ^= ((uint64_t)tail[ 3]) << 24;
case 3: k1 ^= ((uint64_t)tail[ 2]) << 16;
case 2: k1 ^= ((uint64_t)tail[ 1]) << 8;
case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
//-----------------------------------------------------------------------------
+335
View File
@@ -0,0 +1,335 @@
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
#include "MurmurHash3.h"
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#include <stdlib.h>
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // defined(_MSC_VER)
#define FORCE_INLINE inline __attribute__((always_inline))
inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
{
return p[i];
}
FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 4;
uint32_t h1 = seed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock32(blocks,i);
k1 *= c1;
k1 = ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
uint32_t k1 = 0;
switch(len & 3)
{
case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix32(h1);
*(uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void * key, const int len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint32_t h1 = seed;
uint32_t h2 = seed;
uint32_t h3 = seed;
uint32_t h4 = seed;
const uint32_t c1 = 0x239b961b;
const uint32_t c2 = 0xab0e9789;
const uint32_t c3 = 0x38b34ae5;
const uint32_t c4 = 0xa1e38b93;
//----------
// body
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
for(int i = -nblocks; i; i++)
{
uint32_t k1 = getblock32(blocks,i*4+0);
uint32_t k2 = getblock32(blocks,i*4+1);
uint32_t k3 = getblock32(blocks,i*4+2);
uint32_t k4 = getblock32(blocks,i*4+3);
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
switch(len & 15)
{
case 15: k4 ^= tail[14] << 16;
case 14: k4 ^= tail[13] << 8;
case 13: k4 ^= tail[12] << 0;
k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
case 12: k3 ^= tail[11] << 24;
case 11: k3 ^= tail[10] << 16;
case 10: k3 ^= tail[ 9] << 8;
case 9: k3 ^= tail[ 8] << 0;
k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
case 8: k2 ^= tail[ 7] << 24;
case 7: k2 ^= tail[ 6] << 16;
case 6: k2 ^= tail[ 5] << 8;
case 5: k2 ^= tail[ 4] << 0;
k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
case 4: k1 ^= tail[ 3] << 24;
case 3: k1 ^= tail[ 2] << 16;
case 2: k1 ^= tail[ 1] << 8;
case 1: k1 ^= tail[ 0] << 0;
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
h1 = fmix32(h1);
h2 = fmix32(h2);
h3 = fmix32(h3);
h4 = fmix32(h4);
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
((uint32_t*)out)[0] = h1;
((uint32_t*)out)[1] = h2;
((uint32_t*)out)[2] = h3;
((uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void * key, const int len,
const uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
//----------
// body
const uint64_t * blocks = (const uint64_t *)(data);
for(int i = 0; i < nblocks; i++)
{
uint64_t k1 = getblock64(blocks,i*2+0);
uint64_t k2 = getblock64(blocks,i*2+1);
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch(len & 15)
{
case 15: k2 ^= ((uint64_t)tail[14]) << 48;
case 14: k2 ^= ((uint64_t)tail[13]) << 40;
case 13: k2 ^= ((uint64_t)tail[12]) << 32;
case 12: k2 ^= ((uint64_t)tail[11]) << 24;
case 11: k2 ^= ((uint64_t)tail[10]) << 16;
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((uint64_t)tail[ 7]) << 56;
case 7: k1 ^= ((uint64_t)tail[ 6]) << 48;
case 6: k1 ^= ((uint64_t)tail[ 5]) << 40;
case 5: k1 ^= ((uint64_t)tail[ 4]) << 32;
case 4: k1 ^= ((uint64_t)tail[ 3]) << 24;
case 3: k1 ^= ((uint64_t)tail[ 2]) << 16;
case 2: k1 ^= ((uint64_t)tail[ 1]) << 8;
case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
//-----------------------------------------------------------------------------
+37
View File
@@ -0,0 +1,37 @@
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
#ifndef _MURMURHASH3_H_
#define _MURMURHASH3_H_
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
// Other compilers
#else // defined(_MSC_VER)
#include <stdint.h>
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out );
void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
//-----------------------------------------------------------------------------
#endif // _MURMURHASH3_H_
+185
View File
@@ -0,0 +1,185 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2022 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "siphash.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/* default: SipHash-2-4 */
#ifndef cROUNDS
#define cROUNDS 2
#endif
#ifndef dROUNDS
#define dROUNDS 4
#endif
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
#ifdef DEBUG_SIPHASH
#include <stdio.h>
#define TRACE \
do { \
printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \
printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \
printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \
printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \
} while (0)
#else
#define TRACE
#endif
/*
Computes a SipHash value
*in: pointer to input data (read-only)
inlen: input data length in bytes (any size_t value)
*k: pointer to the key data (read-only), must be 16 bytes
*out: pointer to output data (write-only), outlen bytes must be allocated
outlen: length of the output in bytes, must be 8 or 16
*/
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen) {
const unsigned char *ni = (const unsigned char *)in;
const unsigned char *kk = (const unsigned char *)k;
assert((outlen == 8) || (outlen == 16));
uint64_t v0 = UINT64_C(0x736f6d6570736575);
uint64_t v1 = UINT64_C(0x646f72616e646f6d);
uint64_t v2 = UINT64_C(0x6c7967656e657261);
uint64_t v3 = UINT64_C(0x7465646279746573);
uint64_t k0 = U8TO64_LE(kk);
uint64_t k1 = U8TO64_LE(kk + 8);
uint64_t m;
int i;
const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t));
const int left = inlen & 7;
uint64_t b = ((uint64_t)inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16)
v1 ^= 0xee;
for (; ni != end; ni += 8) {
m = U8TO64_LE(ni);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 7:
b |= ((uint64_t)ni[6]) << 48;
/* FALLTHRU */
case 6:
b |= ((uint64_t)ni[5]) << 40;
/* FALLTHRU */
case 5:
b |= ((uint64_t)ni[4]) << 32;
/* FALLTHRU */
case 4:
b |= ((uint64_t)ni[3]) << 24;
/* FALLTHRU */
case 3:
b |= ((uint64_t)ni[2]) << 16;
/* FALLTHRU */
case 2:
b |= ((uint64_t)ni[1]) << 8;
/* FALLTHRU */
case 1:
b |= ((uint64_t)ni[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (outlen == 8)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 0;
}
+185
View File
@@ -0,0 +1,185 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2022 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "siphash.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/* default: SipHash-2-4 */
#ifndef cROUNDS
#define cROUNDS 2
#endif
#ifndef dROUNDS
#define dROUNDS 4
#endif
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
#ifdef DEBUG_SIPHASH
#include <stdio.h>
#define TRACE \
do { \
printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \
printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \
printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \
printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \
} while (0)
#else
#define TRACE
#endif
/*
Computes a SipHash value
*in: pointer to input data (read-only)
inlen: input data length in bytes (any size_t value)
*k: pointer to the key data (read-only), must be 16 bytes
*out: pointer to output data (write-only), outlen bytes must be allocated
outlen: length of the output in bytes, must be 8 or 16
*/
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen) {
const unsigned char *ni = (const unsigned char *)in;
const unsigned char *kk = (const unsigned char *)k;
assert((outlen == 8) || (outlen == 16));
uint64_t v0 = UINT64_C(0x736f6d6570736575);
uint64_t v1 = UINT64_C(0x646f72616e646f6d);
uint64_t v2 = UINT64_C(0x6c7967656e657261);
uint64_t v3 = UINT64_C(0x7465646279746573);
uint64_t k0 = U8TO64_LE(kk);
uint64_t k1 = U8TO64_LE(kk + 8);
uint64_t m;
int i;
const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t));
const int left = inlen & 7;
uint64_t b = ((uint64_t)inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16)
v1 ^= 0xee;
for (; ni != end; ni += 8) {
m = U8TO64_LE(ni);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 7:
b |= ((uint64_t)ni[6]) << 48;
/* FALLTHRU */
case 6:
b |= ((uint64_t)ni[5]) << 40;
/* FALLTHRU */
case 5:
b |= ((uint64_t)ni[4]) << 32;
/* FALLTHRU */
case 4:
b |= ((uint64_t)ni[3]) << 24;
/* FALLTHRU */
case 3:
b |= ((uint64_t)ni[2]) << 16;
/* FALLTHRU */
case 2:
b |= ((uint64_t)ni[1]) << 8;
/* FALLTHRU */
case 1:
b |= ((uint64_t)ni[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (outlen == 8)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2021 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <inttypes.h>
#include <string.h>
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen);
+122
View File
@@ -0,0 +1,122 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "test_hasher.h"
#include "MurmurHash3.h"
#include "siphash.h"
#include "wapp.h"
WpTestFuncResult test_murmur3(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpMur3HasherIO io = wpMur3HasherIO(873923);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash[2] = {0};
// Sring hash
wpX64Mur3Hasher128(&str_bytes, (void *)&io);
MurmurHash3_x64_128(str_bytes.data, str_bytes.count * str_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Array hash
wpX64Mur3Hasher128(&arr_bytes, (void *)&io);
MurmurHash3_x64_128(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Number hash
wpX64Mur3Hasher128(&num_bytes, (void *)&io);
MurmurHash3_x64_128(num_bytes.data, num_bytes.count * num_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
return wpTesterResult(result);
}
WpTestFuncResult test_siphash_128(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpSipHasherKey key = { .lo = 238742, .hi = 671734 };
WpSipHasher128IO io = wpSip24Hasher128IO(key);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash[2] = {0};
// Sring hash
wpSipHasher128(&str_bytes, (void *)&io);
siphash(str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Array hash
wpSipHasher128(&arr_bytes, (void *)&io);
siphash(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Number hash
wpSipHasher128(&num_bytes, (void *)&io);
siphash(num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
return wpTesterResult(result);
}
WpTestFuncResult test_siphash_64(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpSipHasherKey key = { .lo = 238742, .hi = 671734 };
WpSipHasher64IO io = wpSip24Hasher64IO(key);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash = {0};
// Sring hash
wpSipHasher64(&str_bytes, (void *)&io);
siphash(str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
// Array hash
wpSipHasher64(&arr_bytes, (void *)&io);
siphash(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
// Number hash
wpSipHasher64(&num_bytes, (void *)&io);
siphash(num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
return wpTesterResult(result);
}
+122
View File
@@ -0,0 +1,122 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "test_hasher.h"
#include "MurmurHash3.h"
#include "siphash.h"
#include "wapp.h"
WpTestFuncResult test_murmur3(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpMur3HasherIO io = wpMur3HasherIO(873923);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash[2] = {0};
// Sring hash
wpX64Mur3Hasher128(&str_bytes, (void *)&io);
MurmurHash3_x64_128(str_bytes.data, str_bytes.count * str_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Array hash
wpX64Mur3Hasher128(&arr_bytes, (void *)&io);
MurmurHash3_x64_128(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Number hash
wpX64Mur3Hasher128(&num_bytes, (void *)&io);
MurmurHash3_x64_128(num_bytes.data, num_bytes.count * num_bytes.item_size, io.seed, (void *)hash);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
return wpTesterResult(result);
}
WpTestFuncResult test_siphash_128(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpSipHasherKey key = { 238742, 671734 };
WpSipHasher128IO io = wpSip24Hasher128IO(key);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash[2] = {0};
// Sring hash
wpSipHasher128(&str_bytes, (void *)&io);
siphash((void *)str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Array hash
wpSipHasher128(&arr_bytes, (void *)&io);
siphash((void *)arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
// Number hash
wpSipHasher128(&num_bytes, (void *)&io);
siphash((void *)num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&io.params.key,
(u8 *)hash, sizeof(u64) * 2);
result = result && io.hash[0] == hash[0] && io.hash[1] == hash[1];
return wpTesterResult(result);
}
WpTestFuncResult test_siphash_64(void) {
b8 result = true;
WpStr8 str = wpStr8Lit("Hello world");
WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5);
u64 num = 287324;
WpSipHasherKey key = { 238742, 671734 };
WpSipHasher64IO io = wpSip24Hasher64IO(key);
WpU8Stream str_bytes = wpStream(u8, str.buf, str.size);
WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr));
WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64));
u64 hash = {0};
// Sring hash
wpSipHasher64(&str_bytes, (void *)&io);
siphash((void *)str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
// Array hash
wpSipHasher64(&arr_bytes, (void *)&io);
siphash((void *)arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
// Number hash
wpSipHasher64(&num_bytes, (void *)&io);
siphash((void *)num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&io.params.key,
(u8 *)&hash, sizeof(u64));
result = result && io.hash == hash;
return wpTesterResult(result);
}
+15
View File
@@ -0,0 +1,15 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TEST_HASHER_H
#define TEST_HASHER_H
#include "wapp.h"
// Test Murmur3 hash implementation against the reference implementation
WpTestFuncResult test_murmur3(void);
// Test Sip hash implementation against the reference implementation
WpTestFuncResult test_siphash_128(void);
WpTestFuncResult test_siphash_64(void);
#endif // !TEST_HASHER_H
+4
View File
@@ -8,6 +8,7 @@
#include "test_stream.h"
#include "test_cpath.h"
#include "test_file.h"
#include "test_hasher.h"
#include "test_shell_commander.h"
#include "wapp.h"
#include <stdlib.h>
@@ -101,6 +102,9 @@ int main(void) {
test_wapp_file_close,
test_wapp_file_rename,
test_wapp_file_remove,
test_murmur3,
test_siphash_128,
test_siphash_64,
test_commander_cmd_success,
test_commander_cmd_failure,
test_commander_cmd_out_buf_success,
+4
View File
@@ -8,6 +8,7 @@
#include "test_stream.h"
#include "test_cpath.h"
#include "test_file.h"
#include "test_hasher.h"
#include "test_shell_commander.h"
#include "wapp.h"
#include <stdlib.h>
@@ -101,6 +102,9 @@ int main(void) {
test_wapp_file_close,
test_wapp_file_rename,
test_wapp_file_remove,
test_murmur3,
test_siphash_128,
test_siphash_64,
test_commander_cmd_success,
test_commander_cmd_failure,
test_commander_cmd_out_buf_success,