perl_siphash.h - add a 64 bit variant for testing, cleanup line endings

Scott Baker wanted a 64 bit general purpose hash function. Currently our
Siphash implementation is optimized for use in the internal hash tables
by having its state initialization separated from the main hash
function. We have a 32 bit variant we use for testing that takes a seed
and not a state, but our only 64 bit support has the seeding step split
out. This patch exposes a seedable 64 bit function.

Note, that Siphash *is* a 64 bit hash function, however historically
we only use 32 bit hashes in our hash tables. The new variant we
expose here basically just exposes the normal Siphash that most people
would use.

A follow up patch will add documentation.
This commit is contained in:
Yves Orton 2025-02-27 22:55:21 +01:00
parent 82a05dc6fa
commit eb5a17c893

View File

@ -43,29 +43,29 @@ void S_perl_siphash_seed_state(const unsigned char * const seed_buf, unsigned ch
PERL_STATIC_INLINE U64 \ PERL_STATIC_INLINE U64 \
FNC ## _with_state_64 \ FNC ## _with_state_64 \
(const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \ (const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \
{ \ { \
const int left = inlen & 7; \ const int left = inlen & 7; \
const U8 *end = in + inlen - left; \ const U8 *end = in + inlen - left;\
\ \
U64 b = ( ( U64 )(inlen) ) << 56; \ U64 b = ( ( U64 )(inlen) ) << 56; \
U64 m; \ U64 m; \
U64 v0 = U8TO64_LE(state); \ U64 v0 = U8TO64_LE(state); \
U64 v1 = U8TO64_LE(state+8); \ U64 v1 = U8TO64_LE(state+8); \
U64 v2 = U8TO64_LE(state+16); \ U64 v2 = U8TO64_LE(state+16); \
U64 v3 = U8TO64_LE(state+24); \ U64 v3 = U8TO64_LE(state+24); \
\ \
for ( ; in != end; in += 8 ) \ for ( ; in != end; in += 8 ) \
{ \ { \
m = U8TO64_LE( in ); \ m = U8TO64_LE( in ); \
v3 ^= m; \ v3 ^= m; \
\ \
SIP_ROUNDS; \ SIP_ROUNDS; \
\ \
v0 ^= m; \ v0 ^= m; \
} \ } \
\ \
switch( left ) \ switch( left ) \
{ \ { \
case 7: b |= ( ( U64 )in[ 6] ) << 48; /*FALLTHROUGH*/ \ case 7: b |= ( ( U64 )in[ 6] ) << 48; /*FALLTHROUGH*/ \
case 6: b |= ( ( U64 )in[ 5] ) << 40; /*FALLTHROUGH*/ \ case 6: b |= ( ( U64 )in[ 5] ) << 40; /*FALLTHROUGH*/ \
case 5: b |= ( ( U64 )in[ 4] ) << 32; /*FALLTHROUGH*/ \ case 5: b |= ( ( U64 )in[ 4] ) << 32; /*FALLTHROUGH*/ \
@ -73,45 +73,52 @@ FNC ## _with_state_64 \
case 3: b |= ( ( U64 )in[ 2] ) << 16; /*FALLTHROUGH*/ \ case 3: b |= ( ( U64 )in[ 2] ) << 16; /*FALLTHROUGH*/ \
case 2: b |= ( ( U64 )in[ 1] ) << 8; /*FALLTHROUGH*/ \ case 2: b |= ( ( U64 )in[ 1] ) << 8; /*FALLTHROUGH*/ \
case 1: b |= ( ( U64 )in[ 0] ); break; \ case 1: b |= ( ( U64 )in[ 0] ); break; \
case 0: break; \ case 0: break; \
} \ } \
\ \
v3 ^= b; \ v3 ^= b; \
\ \
SIP_ROUNDS; \ SIP_ROUNDS; \
\ \
v0 ^= b; \ v0 ^= b; \
\ \
v2 ^= 0xff; \ v2 ^= 0xff; \
\ \
SIP_FINAL_ROUNDS \ SIP_FINAL_ROUNDS \
\ \
b = v0 ^ v1 ^ v2 ^ v3; \ b = v0 ^ v1 ^ v2 ^ v3; \
return b; \ return b; \
} \ } \
\ \
PERL_STATIC_INLINE U32 \ PERL_STATIC_INLINE U32 \
FNC ## _with_state \ FNC ## _with_state \
(const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \ (const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \
{ \ { \
union { \ union { \
U64 h64; \ U64 h64; \
U32 h32[2]; \ U32 h32[2]; \
} h; \ } h; \
h.h64= FNC ## _with_state_64(state,in,inlen); \ h.h64= FNC ## _with_state_64(state,in,inlen); \
return h.h32[0] ^ h.h32[1]; \ return h.h32[0] ^ h.h32[1]; \
} \ } \
\ \
\ \
PERL_STATIC_INLINE U32 \ PERL_STATIC_INLINE U32 \
FNC (const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) \ FNC (const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) \
{ \ { \
U64 state[4]; \ U64 state[4]; \
SIPHASH_SEED_STATE(seed,state[0],state[1],state[2],state[3]); \ SIPHASH_SEED_STATE(seed,state[0],state[1],state[2],state[3]); \
return FNC ## _with_state((U8*)state,in,inlen); \ return FNC ## _with_state((U8*)state,in,inlen); \
} \
\
PERL_STATIC_INLINE U64 \
FNC ## _64 (const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) \
{ \
U64 state[4]; \
SIPHASH_SEED_STATE(seed,state[0],state[1],state[2],state[3]); \
return FNC ## _with_state_64((U8*)state,in,inlen); \
} }
PERL_SIPHASH_FNC( PERL_SIPHASH_FNC(
S_perl_hash_siphash_1_3 S_perl_hash_siphash_1_3
,SIPROUND; ,SIPROUND;