Restore "Add new hashing and "hash with state" infrastructure"
authorYves Orton <demerphq@gmail.com>
Thu, 1 Jun 2017 13:00:13 +0000 (15:00 +0200)
committerYves Orton <demerphq@gmail.com>
Thu, 1 Jun 2017 14:16:16 +0000 (16:16 +0200)
This reverts commit e6a172f358c0f48c4b744dbd5e9ef6ff0b4ff289,
which was a revert of a3bf60fbb1f05cd2c69d4ff0a2ef99537afdaba7.

Add new hashing and "hash with state" infrastructure

This adds support for three new hash functions: StadtX, Zaphod32 and SBOX,
and reworks some of our hash internals infrastructure to do so.

SBOX is special in that it is designed to be used in conjuction with any
other hash function for hashing short strings very efficiently and very
securely. It features compile time options on how much memory and startup
time are traded off to control the length of keys that SBOX hashes.

This also adds support for caching the hash values of single byte characters
which can be used in conjuction with any other hash, including SBOX, although
SBOX itself is as fast as the lookup cache, so typically you wouldnt use both
at the same time.

This also *removes* support for Jenkins One-At-A-Time. It has served us
well, but it's day is done.

This patch adds three new files: zaphod32_hash.h, stadtx_hash.h,
sbox32_hash.h

MANIFEST
embedvar.h
hv_func.h
perl.c
perlapi.h
perlvars.h
sbox32_hash.h [new file with mode: 0644]
stadtx_hash.h [new file with mode: 0644]
t/porting/globvar.t
zaphod32_hash.h [new file with mode: 0644]

index 7dd0cbf..bd02337 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -5200,8 +5200,10 @@ regexp.h                 Public declarations for the above
 regnodes.h                     Description of nodes of RE engine
 run.c                          The interpreter loop
 runtests.SH                    A script that generates runtests
+sbox32_hash.h                  SBox hash code (32 Bit SBOX based hash function)
 scope.c                                Scope entry and exit code
 scope.h                                Scope entry and exit header
+stadtx_hash.h                  StadtX hash code (64 Bit fast hash function)
 sv.c                           Scalar value code
 sv.h                           Scalar value header
 symbian/bld.inf                        Symbian sample app build config
@@ -6020,3 +6022,4 @@ win32/wince.h                     WinCE port
 win32/wincesck.c               WinCE port
 write_buildcustomize.pl                Generate lib/buildcustomize.pl
 XSUB.h                         Include file for extension subroutines
+zaphod32_hash.h                        Zaphod32 hash code (32 bit fast hash function)
index e8cab91..1e3f9a2 100644 (file)
 #define PL_Gdollarzero_mutex   (my_vars->Gdollarzero_mutex)
 #define PL_fold_locale         (my_vars->Gfold_locale)
 #define PL_Gfold_locale                (my_vars->Gfold_locale)
+#define PL_hash_chars          (my_vars->Ghash_chars)
+#define PL_Ghash_chars         (my_vars->Ghash_chars)
 #define PL_hash_seed           (my_vars->Ghash_seed)
 #define PL_Ghash_seed          (my_vars->Ghash_seed)
 #define PL_hash_seed_set       (my_vars->Ghash_seed_set)
 #define PL_Ghash_seed_set      (my_vars->Ghash_seed_set)
+#define PL_hash_state          (my_vars->Ghash_state)
+#define PL_Ghash_state         (my_vars->Ghash_state)
 #define PL_hints_mutex         (my_vars->Ghints_mutex)
 #define PL_Ghints_mutex                (my_vars->Ghints_mutex)
 #define PL_keyword_plugin      (my_vars->Gkeyword_plugin)
index f0afe27..b05eb87 100644 (file)
--- a/hv_func.h
+++ b/hv_func.h
 #ifndef PERL_SEEN_HV_FUNC_H /* compile once */
 #define PERL_SEEN_HV_FUNC_H
 
-#if IVSZIE == 8
+#if IVSIZE == 8
 #define CAN64BITHASH
 #endif
 
-#if !( 0 \
-        || defined(PERL_HASH_FUNC_SIPHASH) \
-        || defined(PERL_HASH_FUNC_SIPHASH13) \
-        || defined(PERL_HASH_FUNC_HYBRID_OAATHU_SIPHASH13) \
-        || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD) \
-    )
-#ifdef CAN64BITHASH
-#define PERL_HASH_FUNC_HYBRID_OAATHU_SIPHASH13
-#else
-#define PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
-#endif
-#endif
-
-#if defined(PERL_HASH_FUNC_SIPHASH)
-#   define PERL_HASH_FUNC "SIPHASH_2_4"
-#   define PERL_HASH_SEED_BYTES 16
-#   define PERL_HASH_WITH_SEED(seed,hash,str,len) (hash)= S_perl_hash_siphash_2_4((seed),(U8*)(str),(len))
-#elif defined(PERL_HASH_FUNC_SIPHASH13)
-#   define PERL_HASH_FUNC "SIPHASH_1_3"
-#   define PERL_HASH_SEED_BYTES 16
-#   define PERL_HASH_WITH_SEED(seed,hash,str,len) (hash)= S_perl_hash_siphash_1_3((seed),(U8*)(str),(len))
-#elif defined(PERL_HASH_FUNC_HYBRID_OAATHU_SIPHASH13)
-#   define PERL_HASH_FUNC "HYBRID_OAATHU_SIPHASH_1_3"
-#   define PERL_HASH_SEED_BYTES 24
-#   define PERL_HASH_WITH_SEED(seed,hash,str,len) (hash)= S_perl_hash_oaathu_siphash_1_3((seed),(U8*)(str),(len))
-#elif defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD)
-#   define PERL_HASH_FUNC "ONE_AT_A_TIME_HARD"
-#   define PERL_HASH_SEED_BYTES 8
-#   define PERL_HASH_WITH_SEED(seed,hash,str,len) (hash)= S_perl_hash_one_at_a_time_hard((seed),(U8*)(str),(len))
-#endif
-
-#ifndef PERL_HASH_WITH_SEED
-#error "No hash function defined!"
-#endif
-#ifndef PERL_HASH_SEED_BYTES
-#error "PERL_HASH_SEED_BYTES not defined"
-#endif
-#ifndef PERL_HASH_FUNC
-#error "PERL_HASH_FUNC not defined"
-#endif
-
-#ifndef PERL_HASH_SEED
-#   if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
-#       define PERL_HASH_SEED PL_hash_seed
-#   elif PERL_HASH_SEED_BYTES == 4
-#       define PERL_HASH_SEED ((const U8 *)"PeRl")
-#   elif PERL_HASH_SEED_BYTES == 8
-#       define PERL_HASH_SEED ((const U8 *)"PeRlHaSh")
-#   elif PERL_HASH_SEED_BYTES == 16
-#       define PERL_HASH_SEED ((const U8 *)"PeRlHaShhAcKpErl")
-#   else
-#       error "No PERL_HASH_SEED definition for " PERL_HASH_FUNC
-#   endif
-#endif
-
-#define PERL_HASH(hash,str,len) PERL_HASH_WITH_SEED(PERL_HASH_SEED,hash,str,len)
-
-/* legacy - only mod_perl should be doing this.  */
-#ifdef PERL_HASH_INTERNAL_ACCESS
-#define PERL_HASH_INTERNAL(hash,str,len) PERL_HASH(hash,str,len)
-#endif
-
 /*-----------------------------------------------------------------------------
  * Endianess, misalignment capabilities and util macros
  *
  * The following 3 macros are defined in this section. The other macros defined
  * are only needed to help derive these 3.
  *
+ * U8TO16_LE(x)   Read a little endian unsigned 32-bit int
  * U8TO32_LE(x)   Read a little endian unsigned 32-bit int
- * UNALIGNED_SAFE   Defined if unaligned access is safe
+ * U8TO28_LE(x)   Read a little endian unsigned 32-bit int
  * ROTL32(x,r)      Rotate x left by r bits
+ * ROTL64(x,r)      Rotate x left by r bits
+ * ROTR32(x,r)      Rotate x right by r bits
+ * ROTR64(x,r)      Rotate x right by r bits
  */
 
-#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
-  || defined(_MSC_VER) || defined (__TURBOC__)
-#define U8TO16_LE(d) (*((const U16 *) (d)))
-#endif
-
-#if !defined (U8TO16_LE)
-#define U8TO16_LE(d) ((((const U8 *)(d))[1] << 8)\
-                      +((const U8 *)(d))[0])
+#ifndef U32_ALIGNMENT_REQUIRED
+  #if (BYTEORDER == 0x1234 || BYTEORDER == 0x12345678)
+    #define U8TO16_LE(ptr)   (*((const U16*)(ptr)))
+    #define U8TO32_LE(ptr)   (*((const U32*)(ptr)))
+    #define U8TO64_LE(ptr)   (*((const U64*)(ptr)))
+  #elif (BYTEORDER == 0x4321 || BYTEORDER == 0x87654321)
+    #if defined(__GNUC__) && (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3))
+      #define U8TO16_LE(ptr)   (__builtin_bswap16(*((U16*)(ptr))))
+      #define U8TO32_LE(ptr)   (__builtin_bswap32(*((U32*)(ptr))))
+      #define U8TO64_LE(ptr)   (__builtin_bswap64(*((U64*)(ptr))))
+    #endif
+  #endif
 #endif
 
-#if (BYTEORDER == 0x1234 || BYTEORDER == 0x12345678) && U32SIZE == 4
-  /* CPU endian matches murmurhash algorithm, so read 32-bit word directly */
-  #define U8TO32_LE(ptr)   (*((const U32*)(ptr)))
-#elif BYTEORDER == 0x4321 || BYTEORDER == 0x87654321
-  /* TODO: Add additional cases below where a compiler provided bswap32 is available */
-  #if defined(__GNUC__) && (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3))
-    #define U8TO32_LE(ptr)   (__builtin_bswap32(*((U32*)(ptr))))
-  #else
+#ifndef U8TO16_LE
     /* Without a known fast bswap32 we're just as well off doing this */
-    #define U8TO32_LE(ptr)   (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
-    #define UNALIGNED_SAFE
-  #endif
-#else
-  /* Unknown endianess so last resort is to read individual bytes */
-  #define U8TO32_LE(ptr)   (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
-  /* Since we're not doing word-reads we can skip the messing about with realignment */
-  #define UNALIGNED_SAFE
+  #define U8TO16_LE(ptr)   ((U32)(ptr)[0]|(U32)(ptr)[1]<<8)
+  #define U8TO32_LE(ptr)   ((U32)(ptr)[0]|(U32)(ptr)[1]<<8|(U32)(ptr)[2]<<16|(U32)(ptr)[3]<<24)
+  #define U8TO64_LE(ptr)   ((U64)(ptr)[0]|(U64)(ptr)[1]<<8|(U64)(ptr)[2]<<16|(U64)(ptr)[3]<<24|\
+                            (U64)(ptr)[4]<<32|(U64)(ptr)[5]<<40|\
+                            (U64)(ptr)[6]<<48|(U64)(ptr)[7]<<56)
 #endif
 
 #ifdef CAN64BITHASH
-#ifndef U64TYPE
-/* This probably isn't going to work, but failing with a compiler error due to
+  #ifndef U64TYPE
+  /* This probably isn't going to work, but failing with a compiler error due to
    lack of uint64_t is no worse than failing right now with an #error.  */
-#define U64 uint64_t
-#endif
+  #define U64 uint64_t
+  #endif
 #endif
 
 /* Find best way to ROTL32/ROTL64 */
 #if defined(_MSC_VER)
   #include <stdlib.h>  /* Microsoft put _rotl declaration in here */
   #define ROTL32(x,r)  _rotl(x,r)
-  #ifdef CAN64BITHASH
-    #define ROTL64(x,r)  _rotl64(x,r)
-  #endif
+  #define ROTR32(x,r)  _rotr(x,r)
+  #define ROTL64(x,r)  _rotl64(x,r)
+  #define ROTR64(x,r)  _rotr64(x,r)
 #else
   /* gcc recognises this code and generates a rotate instruction for CPUs with one */
-  #define ROTL32(x,r)  (((U32)x << r) | ((U32)x >> (32 - r)))
-  #ifdef CAN64BITHASH
-    #define ROTL64(x,r)  (((U64)x << r) | ((U64)x >> (64 - r)))
-  #endif
+  #define ROTL32(x,r)  (((U32)(x) << (r)) | ((U32)(x) >> (32 - (r))))
+  #define ROTR32(x,r)  (((U32)(x) << (32 - (r))) | ((U32)(x) >> (r)))
+  #define ROTL64(x,r)  ( ( (U64)(x) << (r) ) | ( (U64)(x) >> ( 64 - (r) ) ) )
+  #define ROTR64(x,r)  ( ( (U64)(x) << ( 64 - (r) ) ) | ( (U64)(x) >> (r) ) )
 #endif
 
 
 #ifdef UV_IS_QUAD
 #define ROTL_UV(x,r) ROTL64(x,r)
+#define ROTR_UV(x,r) ROTL64(x,r)
 #else
 #define ROTL_UV(x,r) ROTL32(x,r)
+#define ROTR_UV(x,r) ROTR32(x,r)
+#endif
+
+/*-----------------------------------------------------------------------------*
+ * And now set up the actual hashing macros
+ *-----------------------------------------------------------------------------*/
+#define PERL_HASH_FUNC_ZAPHOD32
+
+#if !( 0 \
+        || defined(PERL_HASH_FUNC_SIPHASH) \
+        || defined(PERL_HASH_FUNC_SIPHASH13) \
+        || defined(PERL_HASH_FUNC_STADTX) \
+        || defined(PERL_HASH_FUNC_ZAPHOD32) \
+    )
+#   ifdef CAN64BITHASH
+#       define PERL_HASH_FUNC_STADTX
+#   else
+#       define PERL_HASH_FUNC_ZAPHOD32
+#   endif
+#endif
+
+#ifndef PERL_HASH_USE_SBOX32_ALSO
+#define PERL_HASH_USE_SBOX32_ALSO 1
+#endif
+
+#ifndef SBOX32_MAX_LEN
+#define SBOX32_MAX_LEN 24
+#endif
+
+/* this must be after the SBOX32_MAX_LEN define */
+#include "sbox32_hash.h"
+
+#if defined(PERL_HASH_FUNC_SIPHASH)
+# define __PERL_HASH_FUNC "SIPHASH_2_4"
+# define __PERL_HASH_SEED_BYTES 16
+# define __PERL_HASH_STATE_BYTES 32
+# define __PERL_HASH_SEED_STATE(seed,state) S_perl_siphash_seed_state(seed,state)
+# define __PERL_HASH_WITH_STATE(state,str,len) S_perl_hash_siphash_2_4_with_state((state),(U8*)(str),(len))
+#elif defined(PERL_HASH_FUNC_SIPHASH13)
+# define __PERL_HASH_FUNC "SIPHASH_1_3"
+# define __PERL_HASH_SEED_BYTES 16
+# define __PERL_HASH_STATE_BYTES 32
+# define __PERL_HASH_SEED_STATE(seed,state) S_perl_siphash_seed_state(seed,state)
+# define __PERL_HASH_WITH_STATE(state,str,len) S_perl_hash_siphash_1_3_with_state((state),(U8*)(str),(len))
+#elif defined(PERL_HASH_FUNC_STADTX)
+# define __PERL_HASH_FUNC "STATDX"
+# define __PERL_HASH_SEED_BYTES 16
+# define __PERL_HASH_STATE_BYTES 32
+# define __PERL_HASH_SEED_STATE(seed,state) stadtx_seed_state(seed,state)
+# define __PERL_HASH_WITH_STATE(state,str,len) (U32)stadtx_hash_with_state((state),(U8*)(str),(len))
+# include "stadtx_hash.h"
+#elif defined(PERL_HASH_FUNC_ZAPHOD32)
+# define __PERL_HASH_FUNC "ZAPHOD32"
+# define __PERL_HASH_SEED_BYTES 12
+# define __PERL_HASH_STATE_BYTES 12
+# define __PERL_HASH_SEED_STATE(seed,state) zaphod32_seed_state(seed,state)
+# define __PERL_HASH_WITH_STATE(state,str,len) (U32)zaphod32_hash_with_state((state),(U8*)(str),(len))
+# include "zaphod32_hash.h"
+#endif
+
+#ifndef __PERL_HASH_WITH_STATE
+#error "No hash function defined!"
+#endif
+#ifndef __PERL_HASH_SEED_BYTES
+#error "__PERL_HASH_SEED_BYTES not defined"
+#endif
+#ifndef __PERL_HASH_FUNC
+#error "__PERL_HASH_FUNC not defined"
+#endif
+
+
+#if PERL_HASH_USE_SBOX32_ALSO == 1
+# define _PERL_HASH_FUNC                        __PERL_HASH_FUNC
+# define _PERL_HASH_SEED_BYTES                  __PERL_HASH_SEED_BYTES
+# define _PERL_HASH_STATE_BYTES                 __PERL_HASH_STATE_BYTES
+# define _PERL_HASH_SEED_STATE(seed,state)      __PERL_HASH_SEED_STATE(seed,state)
+# define _PERL_HASH_WITH_STATE(state,str,len)   __PERL_HASH_WITH_STATE(state,str,len)
+#else
+
+#define _PERL_HASH_FUNC         "SBOX32_WITH_" __PERL_HASH_FUNC
+
+#define _PERL_HASH_SEED_BYTES   ( __PERL_HASH_SEED_BYTES + ( 3 * sizeof(U32) ) )
+
+#define _PERL_HASH_STATE_BYTES  \
+    ( __PERL_HASH_SEED_BYTES + ( ( 1 + ( 256 * SBOX32_MAX_LEN ) ) * sizeof(U32) ) )
+
+#define _PERL_HASH_SEED_STATE(seed,state) STMT_START {                                      \
+    __PERL_HASH_SEED_STATE(seed,state);                                                     \
+    sbox32_seed_state96(seed + __PERL_HASH_SEED_BYTES , state + __PERL_HASH_STATE_BYTES);   \
+} STMT_END
+
+#define _PERL_HASH_WITH_STATE(state,str,len)                                                \
+    ((len <= SBOX32_MAX_LEN)                                                                \
+        ? sbox32_hash_with_state((state + __PERL_HASH_STATE_BYTES),(U8*)(str),(len))        \
+        : __PERL_HASH_WITH_STATE((state),(str),(len)))
+
+#endif
+
+PERL_STATIC_INLINE
+U32 S_perl_hash_with_seed(const U8 * const seed, const U8 * const str, const STRLEN len)
+{
+    U8 state[_PERL_HASH_STATE_BYTES];
+    _PERL_HASH_SEED_STATE(seed,state);
+    return _PERL_HASH_WITH_STATE(state,str,len);
+}
+
+#define PERL_HASH_WITH_SEED(seed,hash,str,len) \
+    (hash) = S_perl_hash_with_seed(seed,str,len)
+#define PERL_HASH_WITH_STATE(state,hash,str,len) \
+    (hash) = _PERL_HASH_WITH_STATE((state),(U8*)(str),(len))
+#define PERL_HASH_SEED_STATE(seed,state) _PERL_HASH_SEED_STATE(seed,state)
+#define PERL_HASH_SEED_BYTES _PERL_HASH_SEED_BYTES
+#define PERL_HASH_STATE_BYTES _PERL_HASH_STATE_BYTES
+#define PERL_HASH_FUNC        _PERL_HASH_FUNC
+
+#ifdef PERL_USE_SINGLE_CHAR_HASH_CACHE
+#define PERL_HASH(state,str,len) \
+    (hash) = ((len) < 2 ? ( (len) == 0 ? PL_hash_chars[256] : PL_hash_chars[(U8)(str)[0]] ) \
+                       : _PERL_HASH_WITH_STATE(PL_hash_state,(U8*)(str),(len)))
+#else
+#define PERL_HASH(hash,str,len) \
+    PERL_HASH_WITH_STATE(PL_hash_state,hash,(U8*)(str),(len))
+#endif
+
+/* Setup the hash seed, either we do things dynamically at start up,
+ * including reading from the environment, or we randomly setup the
+ * seed. The seed will be passed into the PERL_HASH_SEED_STATE() function
+ * defined for the configuration defined for this perl, which will then
+ * initialze whatever state it might need later in hashing. */
+
+#ifndef PERL_HASH_SEED
+#   if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
+#       define PERL_HASH_SEED PL_hash_seed
+#   else
+       /* this is a 512 bit seed, which should be more than enough for the
+        * configuration of any of our hash functions (with or without sbox).
+        * If you actually use a hard coded seed, you are strongly encouraged
+        * to replace this with something else of the correct length
+        * for the hash function you are using (24-32 bytes depending on build
+        * options). Repeat, you are *STRONGLY* encouraged not to use the value
+        * provided here.
+        */
+#       define PERL_HASH_SEED \
+           ((const U8 *)"A long string of pseudorandomly "  \
+                        "chosen bytes for hashing in Perl")
+#   endif
+#endif
+
+/* legacy - only mod_perl should be doing this.  */
+#ifdef PERL_HASH_INTERNAL_ACCESS
+#define PERL_HASH_INTERNAL(hash,str,len) PERL_HASH(hash,str,len)
 #endif
 
 /* This is SipHash by Jean-Philippe Aumasson and Daniel J. Bernstein.
 
 #ifdef CAN64BITHASH
 
-#define U8TO64_LE(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            \
   STMT_START {              \
     v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
     v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
   } STMT_END
 
-/* SipHash-2-4 */
-
+#define SIPHASH_SEED_STATE(key,v0,v1,v2,v3) \
+do {                                    \
+    v0 = v2 = U8TO64_LE(key + 0);       \
+    v1 = v3 = U8TO64_LE(key + 8);       \
+  /* "somepseudorandomlygeneratedbytes" */  \
+    v0 ^= 0x736f6d6570736575ull;        \
+    v1 ^= 0x646f72616e646f6dull;        \
+    v2 ^= 0x6c7967656e657261ull;        \
+    v3 ^= 0x7465646279746573ull;        \
+} while (0)
+
+PERL_STATIC_INLINE
+void S_perl_siphash_seed_state(const unsigned char * const seed_buf, unsigned char * state_buf) {
+    U64 *v= (U64*) state_buf;
+    SIPHASH_SEED_STATE(seed_buf, v[0],v[1],v[2],v[3]);
+}
 
 #define PERL_SIPHASH_FNC(FNC,SIP_ROUNDS,SIP_FINAL_ROUNDS) \
 PERL_STATIC_INLINE U32 \
-FNC(const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) { \
-  /* "somepseudorandomlygeneratedbytes" */  \
-  U64 v0 = UINT64_C(0x736f6d6570736575);    \
-  U64 v1 = UINT64_C(0x646f72616e646f6d);    \
-  U64 v2 = UINT64_C(0x6c7967656e657261);    \
-  U64 v3 = UINT64_C(0x7465646279746573);    \
-                                            \
-  U64 b;                                    \
-  U64 k0 = ((const U64*)seed)[0];           \
-  U64 k1 = ((const U64*)seed)[1];           \
-  U64 m;                                    \
+FNC ## _with_state \
+  (const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \
+{                                           \
   const int left = inlen & 7;               \
   const U8 *end = in + inlen - left;        \
                                             \
-  b = ( ( U64 )(inlen) ) << 56;             \
-  v3 ^= k1;                                 \
-  v2 ^= k0;                                 \
-  v1 ^= k1;                                 \
-  v0 ^= k0;                                 \
+  U64 b = ( ( U64 )(inlen) ) << 56;         \
+  U64 m;                                    \
+  U64 v0 = U8TO64_LE(state);                \
+  U64 v1 = U8TO64_LE(state+8);              \
+  U64 v2 = U8TO64_LE(state+16);             \
+  U64 v3 = U8TO64_LE(state+24);             \
                                             \
   for ( ; in != end; in += 8 )              \
   {                                         \
@@ -241,8 +326,17 @@ FNC(const unsigned char * const seed, const unsigned char *in, const STRLEN inle
                                             \
   b = v0 ^ v1 ^ v2  ^ v3;                   \
   return (U32)(b & U32_MAX);                \
+}                                           \
+                                            \
+PERL_STATIC_INLINE U32                      \
+FNC (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((U8*)state,in,inlen);                 \
 }
 
+
 PERL_SIPHASH_FNC(
     S_perl_hash_siphash_1_3
     ,SIPROUND;
@@ -254,152 +348,10 @@ PERL_SIPHASH_FNC(
     ,SIPROUND;SIPROUND;
     ,SIPROUND;SIPROUND;SIPROUND;SIPROUND;
 )
-
 #endif /* defined(CAN64BITHASH) */
 
-/* - ONE_AT_A_TIME_HARD is the 5.17+ recommend ONE_AT_A_TIME variant */
 
-/* This is derived from the "One-at-a-Time" algorithm by Bob Jenkins
- * from requirements by Colin Plumb.
- * (http://burtleburtle.net/bob/hash/doobs.html)
- * Modified by Yves Orton to increase security for Perl 5.17 and later.
- */
-PERL_STATIC_INLINE U32
-S_perl_hash_one_at_a_time_hard(const unsigned char * const seed, const unsigned char *str, const STRLEN len) {
-    const unsigned char * const end = (const unsigned char *)str + len;
-    U32 hash = *((const U32*)seed) + (U32)len;
-    
-    while (str < end) {
-        hash += (hash << 10);
-        hash ^= (hash >> 6);
-        hash += *str++;
-    }
-    
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-    hash += seed[4];
-    
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-    hash += seed[5];
-    
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-    hash += seed[6];
-    
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-    hash += seed[7];
-    
-    hash += (hash << 10);
-    hash ^= (hash >> 6);
-
-    hash += (hash << 3);
-    hash ^= (hash >> 11);
-    return (hash + (hash << 15));
-}
 
-#ifdef CAN64BITHASH
-
-/* Hybrid hash function
- *
- * For short strings, 16 bytes or shorter, we use an optimised variant
- * of One At A Time Hard, and for longer strings, we use siphash_1_3.
- *
- * The optimisation of One At A Time Hard means we read the key in
- * reverse from normal, but by doing so we avoid the loop overhead.
- */
-PERL_STATIC_INLINE U32
-S_perl_hash_oaathu_siphash_1_3(const unsigned char * const seed, const unsigned char *str, const STRLEN len) {
-    U32 hash = *((const U32*)seed) + (U32)len;
-    switch (len) {
-        case 16:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[15];
-        case 15:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[14];
-        case 14:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[13];
-        case 13:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[12];
-        case 12:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[11];
-        case 11:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[10];
-        case 10:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[9];
-        case 9:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[8];
-        case 8:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[7];
-        case 7:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[6];
-        case 6:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[5];
-        case 5:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[4];
-        case 4:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[3];
-        case 3:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[2];
-        case 2:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[1];
-        case 1:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += str[0];
-        case 0:
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += seed[4];
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += seed[5];
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += seed[6];
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-            hash += seed[7];
-            hash += (hash << 10);
-            hash ^= (hash >> 6);
-
-            hash += (hash << 3);
-            hash ^= (hash >> 11);
-            return (hash + (hash << 15));
-    }
-    return S_perl_hash_siphash_1_3(seed+8, str, len);
-}
-#endif /* defined(CAN64BITHASH) */
 
 
 #endif /*compile once*/
diff --git a/perl.c b/perl.c
index 658f260..125afae 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -308,27 +308,54 @@ perl_construct(pTHXx)
 #ifdef USE_REENTRANT_API
     Perl_reentrant_init(aTHX);
 #endif
-#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
-        /* [perl #22371] Algorimic Complexity Attack on Perl 5.6.1, 5.8.0
-         * This MUST be done before any hash stores or fetches take place.
-         * If you set PL_hash_seed (and presumably also PL_hash_seed_set)
-         * yourself, it is your responsibility to provide a good random seed!
-         * You can also define PERL_HASH_SEED in compile time, see hv.h.
-         *
-         * XXX: fix this comment */
     if (PL_hash_seed_set == FALSE) {
+        /* Initialize the hash seed and state at startup. This must be
+         * done very early, before ANY hashes are constructed, and once
+         * setup is fixed for the lifetime of the process.
+         *
+         * If you decide to disable the seeding process you should choose
+         * a suitable seed yourself and define PERL_HASH_SEED to a well chosen
+         * string. See hv_func.h for details.
+         */
+#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
+        /* get the hash seed from the environment or from an RNG */
         Perl_get_hash_seed(aTHX_ PL_hash_seed);
-        PL_hash_seed_set= TRUE;
-    }
+#else /*if !(defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)) */
+        /* they want a hard coded seed, check that it is long enough */
+        assert( strlen(PERL_HASH_SEED) >= PERL_HASH_SEED_BYTES );
 #endif /* #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) */
 
+        /* now we use the chosen seed to initialize the state -
+         * in some configurations this may be a relatively speaking
+         * expensive operation, but we only have to do it once at startup */
+        PERL_HASH_SEED_STATE(PERL_HASH_SEED,PL_hash_state);
+
+#ifdef PERL_USE_SINGLE_CHAR_HASH_CACHE
+        /* we can build a special cache for 0/1 byte keys, if people choose
+         * I suspect most of the time it is not worth it */
+        {
+            char str[2]="\0";
+            int i;
+            for (i=0;i<256;i++) {
+                str[0]= i;
+                PERL_HASH_WITH_STATE(PL_hash_state,PL_hash_chars[i],str,1);
+            }
+            PERL_HASH_WITH_STATE(PL_hash_state,PL_hash_chars[256],str,0);
+        }
+#endif
+        /* at this point we have initialezed the hash function, and we can start
+         * constructing hashes */
+        PL_hash_seed_set= TRUE;
+    }
     /* Note that strtab is a rather special HV.  Assumptions are made
        about not iterating on it, and not adding tie magic to it.
        It is properly deallocated in perl_destruct() */
     PL_strtab = newHV();
 
+    /* SHAREKEYS tells us that the hash has its keys shared with PL_strtab,
+     * which is not the case with PL_strtab itself */
     HvSHAREKEYS_off(PL_strtab);                        /* mandatory */
-    hv_ksplit(PL_strtab, 512);
+    hv_ksplit(PL_strtab, 1 << 11);
 
     Zero(PL_sv_consts, SV_CONSTS_COUNT, SV*);
 
index 91f50eb..af0c2d5 100644 (file)
--- a/perlapi.h
+++ b/perlapi.h
@@ -117,10 +117,14 @@ END_EXTERN_C
 #define PL_dollarzero_mutex    (*Perl_Gdollarzero_mutex_ptr(NULL))
 #undef  PL_fold_locale
 #define PL_fold_locale         (*Perl_Gfold_locale_ptr(NULL))
+#undef  PL_hash_chars
+#define PL_hash_chars          (*Perl_Ghash_chars_ptr(NULL))
 #undef  PL_hash_seed
 #define PL_hash_seed           (*Perl_Ghash_seed_ptr(NULL))
 #undef  PL_hash_seed_set
 #define PL_hash_seed_set       (*Perl_Ghash_seed_set_ptr(NULL))
+#undef  PL_hash_state
+#define PL_hash_state          (*Perl_Ghash_state_ptr(NULL))
 #undef  PL_hints_mutex
 #define PL_hints_mutex         (*Perl_Ghints_mutex_ptr(NULL))
 #undef  PL_keyword_plugin
index 884d57c..bdc8467 100644 (file)
@@ -248,6 +248,12 @@ PERLVAR(G, malloc_mutex, perl_mutex)       /* Mutex for malloc */
 
 PERLVARI(G, hash_seed_set, bool, FALSE)        /* perl.c */
 PERLVARA(G, hash_seed, PERL_HASH_SEED_BYTES, unsigned char) /* perl.c and hv.h */
+#if defined(PERL_HASH_STATE_BYTES)
+PERLVARA(G, hash_state, PERL_HASH_STATE_BYTES, unsigned char) /* perl.c and hv.h */
+#endif
+#if defined(PERL_USE_SINGLE_CHAR_HASH_CACHE)
+PERLVARA(G, hash_chars, (1+256) * sizeof(U32), unsigned char) /* perl.c and hv.h */
+#endif
 
 /* The path separator can vary depending on whether we're running under DCL or
  * a Unix shell.
diff --git a/sbox32_hash.h b/sbox32_hash.h
new file mode 100644 (file)
index 0000000..9c98195
--- /dev/null
@@ -0,0 +1,1777 @@
+#ifndef DEBUG_SBOX32_HASH
+#define DEBUG_SBOX32_HASH 0
+
+#include "zaphod32_hash.h"
+
+#if DEBUG_SBOX32_HASH == 1
+#include <stdio.h>
+#define SBOX32_WARN6(pat,v0,v1,v2,v3,v4,v5)    printf(pat, v0, v1, v2, v3, v4, v5)
+#define SBOX32_WARN5(pat,v0,v1,v2,v3,v4)       printf(pat, v0, v1, v2, v3, v4)
+#define SBOX32_WARN4(pat,v0,v1,v2,v3)          printf(pat, v0, v1, v2, v3)
+#define SBOX32_WARN3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#define SBOX32_WARN2(pat,v0,v1)                printf(pat, v0, v1)
+#define NOTE3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#elif DEBUG_SBOX32_HASH == 2
+#define SBOX32_WARN6(pat,v0,v1,v2,v3,v4,v5)
+#define SBOX32_WARN5(pat,v0,v1,v2,v3,v4)
+#define SBOX32_WARN4(pat,v0,v1,v2,v3)
+#define SBOX32_WARN3(pat,v0,v1,v2)
+#define SBOX32_WARN2(pat,v0,v1)
+#define NOTE3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#else
+#define SBOX32_WARN6(pat,v0,v1,v2,v3,v4,v5)
+#define SBOX32_WARN5(pat,v0,v1,v2,v3,v4)
+#define SBOX32_WARN4(pat,v0,v1,v2,v3)
+#define SBOX32_WARN3(pat,v0,v1,v2)
+#define NOTE3(pat,v0,v1,v2)
+#define SBOX32_WARN2(pat,v0,v1)
+#endif
+
+#ifndef PERL_SEEN_HV_FUNC_H
+#if !defined(U32) 
+    #include <stdint.h>
+    #define U32 uint32_t
+#endif
+
+#if !defined(U8)
+    #define U8 unsigned char
+#endif
+
+#if !defined(U16)
+    #define U16 uint16_t
+#endif
+
+#ifndef STRLEN
+#define STRLEN int
+#endif
+#endif
+
+#ifndef SBOX32_STATIC_INLINE
+#ifdef PERL_STATIC_INLINE
+#define SBOX32_STATIC_INLINE PERL_STATIC_INLINE
+#else
+#define SBOX32_STATIC_INLINE static inline
+#endif
+#endif
+
+#ifndef STMT_START
+#define STMT_START do
+#define STMT_END while(0)
+#endif
+
+#ifndef U8TO32_LE
+#define U8TO32_LE(ptr)  (*((const U32 *)(ptr)))
+#endif
+#ifndef U8TO16_LE
+#define U8TO16_LE(ptr)  (*((const U16 *)(ptr)))
+#endif
+
+#ifndef SBOX32_MAX_LEN
+#define SBOX32_MAX_LEN 256
+#endif
+
+#ifndef SBOX32_STATE_WORDS
+#define SBOX32_STATE_WORDS (1 + (SBOX32_MAX_LEN * 256))
+#define SBOX32_STATE_BYTES (SBOX32_STATE_WORDS * sizeof(U32))
+#define SBOX32_STATE_BITS (SBOX32_STATE_BYTES * 8)
+#endif
+
+#define SBOX32_MIX4(v0,v1,v2,v3,text) STMT_START { \
+        SBOX32_WARN5("v0=%08x v1=%08x v2=%08x v3=%08x - SBOX32_MIX4 %s\n", \
+                            (unsigned int)v0, (unsigned int)v1,    \
+                            (unsigned int)v2, (unsigned int)v3, text);   \
+        v0 = ROTL32(v0,13) - v3;    \
+        v1 ^= v2;                   \
+        v3 = ROTL32(v3, 9) + v1;    \
+        v2 ^= v0;                   \
+        v0 = ROTL32(v0,14) ^ v3;    \
+        v1 = ROTL32(v1,25) - v2;    \
+        v3 ^= v1;                   \
+        v2 = ROTL32(v2, 4) - v0;    \
+} STMT_END
+
+#define SBOX32_MIX3(v0,v1,v2,text) STMT_START {                               \
+    SBOX32_WARN4("v0=%08x v1=%08x v2=%08x - SBOX32_MIX3 %s\n",              \
+            (unsigned int)v0,(unsigned int)v1,(unsigned int)v2, text );     \
+    v0 = ROTL32(v0,16) - v2;   \
+    v1 = ROTR32(v1,13) ^ v2;   \
+    v2 = ROTL32(v2,17) + v1;   \
+    v0 = ROTR32(v0, 2) + v1;   \
+    v1 = ROTR32(v1,17) - v0;   \
+    v2 = ROTR32(v2, 7) ^ v0;   \
+} STMT_END
+
+#if SBOX32_MAX_LEN > 256
+#error "SBOX32_MAX_LEN is set too high!"
+#elif SBOX32_MAX_LEN == 256
+#define case_256_SBOX32(hash,state,key) _SBOX32_CASE(256,hash,state,key)
+#else
+#define case_256_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 255
+#define case_255_SBOX32(hash,state,key) _SBOX32_CASE(255,hash,state,key)
+#else
+#define case_255_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 254
+#define case_254_SBOX32(hash,state,key) _SBOX32_CASE(254,hash,state,key)
+#else
+#define case_254_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 253
+#define case_253_SBOX32(hash,state,key) _SBOX32_CASE(253,hash,state,key)
+#else
+#define case_253_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 252
+#define case_252_SBOX32(hash,state,key) _SBOX32_CASE(252,hash,state,key)
+#else
+#define case_252_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 251
+#define case_251_SBOX32(hash,state,key) _SBOX32_CASE(251,hash,state,key)
+#else
+#define case_251_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 250
+#define case_250_SBOX32(hash,state,key) _SBOX32_CASE(250,hash,state,key)
+#else
+#define case_250_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 249
+#define case_249_SBOX32(hash,state,key) _SBOX32_CASE(249,hash,state,key)
+#else
+#define case_249_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 248
+#define case_248_SBOX32(hash,state,key) _SBOX32_CASE(248,hash,state,key)
+#else
+#define case_248_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 247
+#define case_247_SBOX32(hash,state,key) _SBOX32_CASE(247,hash,state,key)
+#else
+#define case_247_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 246
+#define case_246_SBOX32(hash,state,key) _SBOX32_CASE(246,hash,state,key)
+#else
+#define case_246_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 245
+#define case_245_SBOX32(hash,state,key) _SBOX32_CASE(245,hash,state,key)
+#else
+#define case_245_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 244
+#define case_244_SBOX32(hash,state,key) _SBOX32_CASE(244,hash,state,key)
+#else
+#define case_244_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 243
+#define case_243_SBOX32(hash,state,key) _SBOX32_CASE(243,hash,state,key)
+#else
+#define case_243_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 242
+#define case_242_SBOX32(hash,state,key) _SBOX32_CASE(242,hash,state,key)
+#else
+#define case_242_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 241
+#define case_241_SBOX32(hash,state,key) _SBOX32_CASE(241,hash,state,key)
+#else
+#define case_241_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 240
+#define case_240_SBOX32(hash,state,key) _SBOX32_CASE(240,hash,state,key)
+#else
+#define case_240_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 239
+#define case_239_SBOX32(hash,state,key) _SBOX32_CASE(239,hash,state,key)
+#else
+#define case_239_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 238
+#define case_238_SBOX32(hash,state,key) _SBOX32_CASE(238,hash,state,key)
+#else
+#define case_238_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 237
+#define case_237_SBOX32(hash,state,key) _SBOX32_CASE(237,hash,state,key)
+#else
+#define case_237_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 236
+#define case_236_SBOX32(hash,state,key) _SBOX32_CASE(236,hash,state,key)
+#else
+#define case_236_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 235
+#define case_235_SBOX32(hash,state,key) _SBOX32_CASE(235,hash,state,key)
+#else
+#define case_235_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 234
+#define case_234_SBOX32(hash,state,key) _SBOX32_CASE(234,hash,state,key)
+#else
+#define case_234_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 233
+#define case_233_SBOX32(hash,state,key) _SBOX32_CASE(233,hash,state,key)
+#else
+#define case_233_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 232
+#define case_232_SBOX32(hash,state,key) _SBOX32_CASE(232,hash,state,key)
+#else
+#define case_232_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 231
+#define case_231_SBOX32(hash,state,key) _SBOX32_CASE(231,hash,state,key)
+#else
+#define case_231_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 230
+#define case_230_SBOX32(hash,state,key) _SBOX32_CASE(230,hash,state,key)
+#else
+#define case_230_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 229
+#define case_229_SBOX32(hash,state,key) _SBOX32_CASE(229,hash,state,key)
+#else
+#define case_229_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 228
+#define case_228_SBOX32(hash,state,key) _SBOX32_CASE(228,hash,state,key)
+#else
+#define case_228_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 227
+#define case_227_SBOX32(hash,state,key) _SBOX32_CASE(227,hash,state,key)
+#else
+#define case_227_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 226
+#define case_226_SBOX32(hash,state,key) _SBOX32_CASE(226,hash,state,key)
+#else
+#define case_226_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 225
+#define case_225_SBOX32(hash,state,key) _SBOX32_CASE(225,hash,state,key)
+#else
+#define case_225_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 224
+#define case_224_SBOX32(hash,state,key) _SBOX32_CASE(224,hash,state,key)
+#else
+#define case_224_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 223
+#define case_223_SBOX32(hash,state,key) _SBOX32_CASE(223,hash,state,key)
+#else
+#define case_223_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 222
+#define case_222_SBOX32(hash,state,key) _SBOX32_CASE(222,hash,state,key)
+#else
+#define case_222_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 221
+#define case_221_SBOX32(hash,state,key) _SBOX32_CASE(221,hash,state,key)
+#else
+#define case_221_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 220
+#define case_220_SBOX32(hash,state,key) _SBOX32_CASE(220,hash,state,key)
+#else
+#define case_220_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 219
+#define case_219_SBOX32(hash,state,key) _SBOX32_CASE(219,hash,state,key)
+#else
+#define case_219_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 218
+#define case_218_SBOX32(hash,state,key) _SBOX32_CASE(218,hash,state,key)
+#else
+#define case_218_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 217
+#define case_217_SBOX32(hash,state,key) _SBOX32_CASE(217,hash,state,key)
+#else
+#define case_217_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 216
+#define case_216_SBOX32(hash,state,key) _SBOX32_CASE(216,hash,state,key)
+#else
+#define case_216_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 215
+#define case_215_SBOX32(hash,state,key) _SBOX32_CASE(215,hash,state,key)
+#else
+#define case_215_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 214
+#define case_214_SBOX32(hash,state,key) _SBOX32_CASE(214,hash,state,key)
+#else
+#define case_214_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 213
+#define case_213_SBOX32(hash,state,key) _SBOX32_CASE(213,hash,state,key)
+#else
+#define case_213_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 212
+#define case_212_SBOX32(hash,state,key) _SBOX32_CASE(212,hash,state,key)
+#else
+#define case_212_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 211
+#define case_211_SBOX32(hash,state,key) _SBOX32_CASE(211,hash,state,key)
+#else
+#define case_211_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 210
+#define case_210_SBOX32(hash,state,key) _SBOX32_CASE(210,hash,state,key)
+#else
+#define case_210_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 209
+#define case_209_SBOX32(hash,state,key) _SBOX32_CASE(209,hash,state,key)
+#else
+#define case_209_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 208
+#define case_208_SBOX32(hash,state,key) _SBOX32_CASE(208,hash,state,key)
+#else
+#define case_208_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 207
+#define case_207_SBOX32(hash,state,key) _SBOX32_CASE(207,hash,state,key)
+#else
+#define case_207_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 206
+#define case_206_SBOX32(hash,state,key) _SBOX32_CASE(206,hash,state,key)
+#else
+#define case_206_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 205
+#define case_205_SBOX32(hash,state,key) _SBOX32_CASE(205,hash,state,key)
+#else
+#define case_205_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 204
+#define case_204_SBOX32(hash,state,key) _SBOX32_CASE(204,hash,state,key)
+#else
+#define case_204_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 203
+#define case_203_SBOX32(hash,state,key) _SBOX32_CASE(203,hash,state,key)
+#else
+#define case_203_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 202
+#define case_202_SBOX32(hash,state,key) _SBOX32_CASE(202,hash,state,key)
+#else
+#define case_202_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 201
+#define case_201_SBOX32(hash,state,key) _SBOX32_CASE(201,hash,state,key)
+#else
+#define case_201_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 200
+#define case_200_SBOX32(hash,state,key) _SBOX32_CASE(200,hash,state,key)
+#else
+#define case_200_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 199
+#define case_199_SBOX32(hash,state,key) _SBOX32_CASE(199,hash,state,key)
+#else
+#define case_199_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 198
+#define case_198_SBOX32(hash,state,key) _SBOX32_CASE(198,hash,state,key)
+#else
+#define case_198_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 197
+#define case_197_SBOX32(hash,state,key) _SBOX32_CASE(197,hash,state,key)
+#else
+#define case_197_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 196
+#define case_196_SBOX32(hash,state,key) _SBOX32_CASE(196,hash,state,key)
+#else
+#define case_196_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 195
+#define case_195_SBOX32(hash,state,key) _SBOX32_CASE(195,hash,state,key)
+#else
+#define case_195_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 194
+#define case_194_SBOX32(hash,state,key) _SBOX32_CASE(194,hash,state,key)
+#else
+#define case_194_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 193
+#define case_193_SBOX32(hash,state,key) _SBOX32_CASE(193,hash,state,key)
+#else
+#define case_193_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 192
+#define case_192_SBOX32(hash,state,key) _SBOX32_CASE(192,hash,state,key)
+#else
+#define case_192_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 191
+#define case_191_SBOX32(hash,state,key) _SBOX32_CASE(191,hash,state,key)
+#else
+#define case_191_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 190
+#define case_190_SBOX32(hash,state,key) _SBOX32_CASE(190,hash,state,key)
+#else
+#define case_190_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 189
+#define case_189_SBOX32(hash,state,key) _SBOX32_CASE(189,hash,state,key)
+#else
+#define case_189_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 188
+#define case_188_SBOX32(hash,state,key) _SBOX32_CASE(188,hash,state,key)
+#else
+#define case_188_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 187
+#define case_187_SBOX32(hash,state,key) _SBOX32_CASE(187,hash,state,key)
+#else
+#define case_187_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 186
+#define case_186_SBOX32(hash,state,key) _SBOX32_CASE(186,hash,state,key)
+#else
+#define case_186_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 185
+#define case_185_SBOX32(hash,state,key) _SBOX32_CASE(185,hash,state,key)
+#else
+#define case_185_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 184
+#define case_184_SBOX32(hash,state,key) _SBOX32_CASE(184,hash,state,key)
+#else
+#define case_184_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 183
+#define case_183_SBOX32(hash,state,key) _SBOX32_CASE(183,hash,state,key)
+#else
+#define case_183_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 182
+#define case_182_SBOX32(hash,state,key) _SBOX32_CASE(182,hash,state,key)
+#else
+#define case_182_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 181
+#define case_181_SBOX32(hash,state,key) _SBOX32_CASE(181,hash,state,key)
+#else
+#define case_181_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 180
+#define case_180_SBOX32(hash,state,key) _SBOX32_CASE(180,hash,state,key)
+#else
+#define case_180_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 179
+#define case_179_SBOX32(hash,state,key) _SBOX32_CASE(179,hash,state,key)
+#else
+#define case_179_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 178
+#define case_178_SBOX32(hash,state,key) _SBOX32_CASE(178,hash,state,key)
+#else
+#define case_178_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 177
+#define case_177_SBOX32(hash,state,key) _SBOX32_CASE(177,hash,state,key)
+#else
+#define case_177_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 176
+#define case_176_SBOX32(hash,state,key) _SBOX32_CASE(176,hash,state,key)
+#else
+#define case_176_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 175
+#define case_175_SBOX32(hash,state,key) _SBOX32_CASE(175,hash,state,key)
+#else
+#define case_175_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 174
+#define case_174_SBOX32(hash,state,key) _SBOX32_CASE(174,hash,state,key)
+#else
+#define case_174_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 173
+#define case_173_SBOX32(hash,state,key) _SBOX32_CASE(173,hash,state,key)
+#else
+#define case_173_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 172
+#define case_172_SBOX32(hash,state,key) _SBOX32_CASE(172,hash,state,key)
+#else
+#define case_172_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 171
+#define case_171_SBOX32(hash,state,key) _SBOX32_CASE(171,hash,state,key)
+#else
+#define case_171_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 170
+#define case_170_SBOX32(hash,state,key) _SBOX32_CASE(170,hash,state,key)
+#else
+#define case_170_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 169
+#define case_169_SBOX32(hash,state,key) _SBOX32_CASE(169,hash,state,key)
+#else
+#define case_169_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 168
+#define case_168_SBOX32(hash,state,key) _SBOX32_CASE(168,hash,state,key)
+#else
+#define case_168_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 167
+#define case_167_SBOX32(hash,state,key) _SBOX32_CASE(167,hash,state,key)
+#else
+#define case_167_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 166
+#define case_166_SBOX32(hash,state,key) _SBOX32_CASE(166,hash,state,key)
+#else
+#define case_166_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 165
+#define case_165_SBOX32(hash,state,key) _SBOX32_CASE(165,hash,state,key)
+#else
+#define case_165_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 164
+#define case_164_SBOX32(hash,state,key) _SBOX32_CASE(164,hash,state,key)
+#else
+#define case_164_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 163
+#define case_163_SBOX32(hash,state,key) _SBOX32_CASE(163,hash,state,key)
+#else
+#define case_163_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 162
+#define case_162_SBOX32(hash,state,key) _SBOX32_CASE(162,hash,state,key)
+#else
+#define case_162_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 161
+#define case_161_SBOX32(hash,state,key) _SBOX32_CASE(161,hash,state,key)
+#else
+#define case_161_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 160
+#define case_160_SBOX32(hash,state,key) _SBOX32_CASE(160,hash,state,key)
+#else
+#define case_160_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 159
+#define case_159_SBOX32(hash,state,key) _SBOX32_CASE(159,hash,state,key)
+#else
+#define case_159_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 158
+#define case_158_SBOX32(hash,state,key) _SBOX32_CASE(158,hash,state,key)
+#else
+#define case_158_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 157
+#define case_157_SBOX32(hash,state,key) _SBOX32_CASE(157,hash,state,key)
+#else
+#define case_157_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 156
+#define case_156_SBOX32(hash,state,key) _SBOX32_CASE(156,hash,state,key)
+#else
+#define case_156_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 155
+#define case_155_SBOX32(hash,state,key) _SBOX32_CASE(155,hash,state,key)
+#else
+#define case_155_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 154
+#define case_154_SBOX32(hash,state,key) _SBOX32_CASE(154,hash,state,key)
+#else
+#define case_154_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 153
+#define case_153_SBOX32(hash,state,key) _SBOX32_CASE(153,hash,state,key)
+#else
+#define case_153_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 152
+#define case_152_SBOX32(hash,state,key) _SBOX32_CASE(152,hash,state,key)
+#else
+#define case_152_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 151
+#define case_151_SBOX32(hash,state,key) _SBOX32_CASE(151,hash,state,key)
+#else
+#define case_151_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 150
+#define case_150_SBOX32(hash,state,key) _SBOX32_CASE(150,hash,state,key)
+#else
+#define case_150_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 149
+#define case_149_SBOX32(hash,state,key) _SBOX32_CASE(149,hash,state,key)
+#else
+#define case_149_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 148
+#define case_148_SBOX32(hash,state,key) _SBOX32_CASE(148,hash,state,key)
+#else
+#define case_148_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 147
+#define case_147_SBOX32(hash,state,key) _SBOX32_CASE(147,hash,state,key)
+#else
+#define case_147_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 146
+#define case_146_SBOX32(hash,state,key) _SBOX32_CASE(146,hash,state,key)
+#else
+#define case_146_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 145
+#define case_145_SBOX32(hash,state,key) _SBOX32_CASE(145,hash,state,key)
+#else
+#define case_145_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 144
+#define case_144_SBOX32(hash,state,key) _SBOX32_CASE(144,hash,state,key)
+#else
+#define case_144_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 143
+#define case_143_SBOX32(hash,state,key) _SBOX32_CASE(143,hash,state,key)
+#else
+#define case_143_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 142
+#define case_142_SBOX32(hash,state,key) _SBOX32_CASE(142,hash,state,key)
+#else
+#define case_142_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 141
+#define case_141_SBOX32(hash,state,key) _SBOX32_CASE(141,hash,state,key)
+#else
+#define case_141_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 140
+#define case_140_SBOX32(hash,state,key) _SBOX32_CASE(140,hash,state,key)
+#else
+#define case_140_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 139
+#define case_139_SBOX32(hash,state,key) _SBOX32_CASE(139,hash,state,key)
+#else
+#define case_139_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 138
+#define case_138_SBOX32(hash,state,key) _SBOX32_CASE(138,hash,state,key)
+#else
+#define case_138_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 137
+#define case_137_SBOX32(hash,state,key) _SBOX32_CASE(137,hash,state,key)
+#else
+#define case_137_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 136
+#define case_136_SBOX32(hash,state,key) _SBOX32_CASE(136,hash,state,key)
+#else
+#define case_136_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 135
+#define case_135_SBOX32(hash,state,key) _SBOX32_CASE(135,hash,state,key)
+#else
+#define case_135_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 134
+#define case_134_SBOX32(hash,state,key) _SBOX32_CASE(134,hash,state,key)
+#else
+#define case_134_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 133
+#define case_133_SBOX32(hash,state,key) _SBOX32_CASE(133,hash,state,key)
+#else
+#define case_133_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 132
+#define case_132_SBOX32(hash,state,key) _SBOX32_CASE(132,hash,state,key)
+#else
+#define case_132_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 131
+#define case_131_SBOX32(hash,state,key) _SBOX32_CASE(131,hash,state,key)
+#else
+#define case_131_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 130
+#define case_130_SBOX32(hash,state,key) _SBOX32_CASE(130,hash,state,key)
+#else
+#define case_130_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 129
+#define case_129_SBOX32(hash,state,key) _SBOX32_CASE(129,hash,state,key)
+#else
+#define case_129_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 128
+#define case_128_SBOX32(hash,state,key) _SBOX32_CASE(128,hash,state,key)
+#else
+#define case_128_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 127
+#define case_127_SBOX32(hash,state,key) _SBOX32_CASE(127,hash,state,key)
+#else
+#define case_127_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 126
+#define case_126_SBOX32(hash,state,key) _SBOX32_CASE(126,hash,state,key)
+#else
+#define case_126_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 125
+#define case_125_SBOX32(hash,state,key) _SBOX32_CASE(125,hash,state,key)
+#else
+#define case_125_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 124
+#define case_124_SBOX32(hash,state,key) _SBOX32_CASE(124,hash,state,key)
+#else
+#define case_124_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 123
+#define case_123_SBOX32(hash,state,key) _SBOX32_CASE(123,hash,state,key)
+#else
+#define case_123_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 122
+#define case_122_SBOX32(hash,state,key) _SBOX32_CASE(122,hash,state,key)
+#else
+#define case_122_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 121
+#define case_121_SBOX32(hash,state,key) _SBOX32_CASE(121,hash,state,key)
+#else
+#define case_121_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 120
+#define case_120_SBOX32(hash,state,key) _SBOX32_CASE(120,hash,state,key)
+#else
+#define case_120_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 119
+#define case_119_SBOX32(hash,state,key) _SBOX32_CASE(119,hash,state,key)
+#else
+#define case_119_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 118
+#define case_118_SBOX32(hash,state,key) _SBOX32_CASE(118,hash,state,key)
+#else
+#define case_118_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 117
+#define case_117_SBOX32(hash,state,key) _SBOX32_CASE(117,hash,state,key)
+#else
+#define case_117_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 116
+#define case_116_SBOX32(hash,state,key) _SBOX32_CASE(116,hash,state,key)
+#else
+#define case_116_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 115
+#define case_115_SBOX32(hash,state,key) _SBOX32_CASE(115,hash,state,key)
+#else
+#define case_115_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 114
+#define case_114_SBOX32(hash,state,key) _SBOX32_CASE(114,hash,state,key)
+#else
+#define case_114_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 113
+#define case_113_SBOX32(hash,state,key) _SBOX32_CASE(113,hash,state,key)
+#else
+#define case_113_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 112
+#define case_112_SBOX32(hash,state,key) _SBOX32_CASE(112,hash,state,key)
+#else
+#define case_112_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 111
+#define case_111_SBOX32(hash,state,key) _SBOX32_CASE(111,hash,state,key)
+#else
+#define case_111_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 110
+#define case_110_SBOX32(hash,state,key) _SBOX32_CASE(110,hash,state,key)
+#else
+#define case_110_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 109
+#define case_109_SBOX32(hash,state,key) _SBOX32_CASE(109,hash,state,key)
+#else
+#define case_109_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 108
+#define case_108_SBOX32(hash,state,key) _SBOX32_CASE(108,hash,state,key)
+#else
+#define case_108_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 107
+#define case_107_SBOX32(hash,state,key) _SBOX32_CASE(107,hash,state,key)
+#else
+#define case_107_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 106
+#define case_106_SBOX32(hash,state,key) _SBOX32_CASE(106,hash,state,key)
+#else
+#define case_106_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 105
+#define case_105_SBOX32(hash,state,key) _SBOX32_CASE(105,hash,state,key)
+#else
+#define case_105_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 104
+#define case_104_SBOX32(hash,state,key) _SBOX32_CASE(104,hash,state,key)
+#else
+#define case_104_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 103
+#define case_103_SBOX32(hash,state,key) _SBOX32_CASE(103,hash,state,key)
+#else
+#define case_103_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 102
+#define case_102_SBOX32(hash,state,key) _SBOX32_CASE(102,hash,state,key)
+#else
+#define case_102_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 101
+#define case_101_SBOX32(hash,state,key) _SBOX32_CASE(101,hash,state,key)
+#else
+#define case_101_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 100
+#define case_100_SBOX32(hash,state,key) _SBOX32_CASE(100,hash,state,key)
+#else
+#define case_100_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 99
+#define case_99_SBOX32(hash,state,key) _SBOX32_CASE(99,hash,state,key)
+#else
+#define case_99_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 98
+#define case_98_SBOX32(hash,state,key) _SBOX32_CASE(98,hash,state,key)
+#else
+#define case_98_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 97
+#define case_97_SBOX32(hash,state,key) _SBOX32_CASE(97,hash,state,key)
+#else
+#define case_97_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 96
+#define case_96_SBOX32(hash,state,key) _SBOX32_CASE(96,hash,state,key)
+#else
+#define case_96_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 95
+#define case_95_SBOX32(hash,state,key) _SBOX32_CASE(95,hash,state,key)
+#else
+#define case_95_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 94
+#define case_94_SBOX32(hash,state,key) _SBOX32_CASE(94,hash,state,key)
+#else
+#define case_94_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 93
+#define case_93_SBOX32(hash,state,key) _SBOX32_CASE(93,hash,state,key)
+#else
+#define case_93_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 92
+#define case_92_SBOX32(hash,state,key) _SBOX32_CASE(92,hash,state,key)
+#else
+#define case_92_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 91
+#define case_91_SBOX32(hash,state,key) _SBOX32_CASE(91,hash,state,key)
+#else
+#define case_91_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 90
+#define case_90_SBOX32(hash,state,key) _SBOX32_CASE(90,hash,state,key)
+#else
+#define case_90_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 89
+#define case_89_SBOX32(hash,state,key) _SBOX32_CASE(89,hash,state,key)
+#else
+#define case_89_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 88
+#define case_88_SBOX32(hash,state,key) _SBOX32_CASE(88,hash,state,key)
+#else
+#define case_88_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 87
+#define case_87_SBOX32(hash,state,key) _SBOX32_CASE(87,hash,state,key)
+#else
+#define case_87_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 86
+#define case_86_SBOX32(hash,state,key) _SBOX32_CASE(86,hash,state,key)
+#else
+#define case_86_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 85
+#define case_85_SBOX32(hash,state,key) _SBOX32_CASE(85,hash,state,key)
+#else
+#define case_85_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 84
+#define case_84_SBOX32(hash,state,key) _SBOX32_CASE(84,hash,state,key)
+#else
+#define case_84_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 83
+#define case_83_SBOX32(hash,state,key) _SBOX32_CASE(83,hash,state,key)
+#else
+#define case_83_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 82
+#define case_82_SBOX32(hash,state,key) _SBOX32_CASE(82,hash,state,key)
+#else
+#define case_82_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 81
+#define case_81_SBOX32(hash,state,key) _SBOX32_CASE(81,hash,state,key)
+#else
+#define case_81_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 80
+#define case_80_SBOX32(hash,state,key) _SBOX32_CASE(80,hash,state,key)
+#else
+#define case_80_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 79
+#define case_79_SBOX32(hash,state,key) _SBOX32_CASE(79,hash,state,key)
+#else
+#define case_79_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 78
+#define case_78_SBOX32(hash,state,key) _SBOX32_CASE(78,hash,state,key)
+#else
+#define case_78_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 77
+#define case_77_SBOX32(hash,state,key) _SBOX32_CASE(77,hash,state,key)
+#else
+#define case_77_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 76
+#define case_76_SBOX32(hash,state,key) _SBOX32_CASE(76,hash,state,key)
+#else
+#define case_76_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 75
+#define case_75_SBOX32(hash,state,key) _SBOX32_CASE(75,hash,state,key)
+#else
+#define case_75_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 74
+#define case_74_SBOX32(hash,state,key) _SBOX32_CASE(74,hash,state,key)
+#else
+#define case_74_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 73
+#define case_73_SBOX32(hash,state,key) _SBOX32_CASE(73,hash,state,key)
+#else
+#define case_73_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 72
+#define case_72_SBOX32(hash,state,key) _SBOX32_CASE(72,hash,state,key)
+#else
+#define case_72_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 71
+#define case_71_SBOX32(hash,state,key) _SBOX32_CASE(71,hash,state,key)
+#else
+#define case_71_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 70
+#define case_70_SBOX32(hash,state,key) _SBOX32_CASE(70,hash,state,key)
+#else
+#define case_70_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 69
+#define case_69_SBOX32(hash,state,key) _SBOX32_CASE(69,hash,state,key)
+#else
+#define case_69_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 68
+#define case_68_SBOX32(hash,state,key) _SBOX32_CASE(68,hash,state,key)
+#else
+#define case_68_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 67
+#define case_67_SBOX32(hash,state,key) _SBOX32_CASE(67,hash,state,key)
+#else
+#define case_67_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 66
+#define case_66_SBOX32(hash,state,key) _SBOX32_CASE(66,hash,state,key)
+#else
+#define case_66_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 65
+#define case_65_SBOX32(hash,state,key) _SBOX32_CASE(65,hash,state,key)
+#else
+#define case_65_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 64
+#define case_64_SBOX32(hash,state,key) _SBOX32_CASE(64,hash,state,key)
+#else
+#define case_64_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 63
+#define case_63_SBOX32(hash,state,key) _SBOX32_CASE(63,hash,state,key)
+#else
+#define case_63_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 62
+#define case_62_SBOX32(hash,state,key) _SBOX32_CASE(62,hash,state,key)
+#else
+#define case_62_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 61
+#define case_61_SBOX32(hash,state,key) _SBOX32_CASE(61,hash,state,key)
+#else
+#define case_61_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 60
+#define case_60_SBOX32(hash,state,key) _SBOX32_CASE(60,hash,state,key)
+#else
+#define case_60_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 59
+#define case_59_SBOX32(hash,state,key) _SBOX32_CASE(59,hash,state,key)
+#else
+#define case_59_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 58
+#define case_58_SBOX32(hash,state,key) _SBOX32_CASE(58,hash,state,key)
+#else
+#define case_58_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 57
+#define case_57_SBOX32(hash,state,key) _SBOX32_CASE(57,hash,state,key)
+#else
+#define case_57_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 56
+#define case_56_SBOX32(hash,state,key) _SBOX32_CASE(56,hash,state,key)
+#else
+#define case_56_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 55
+#define case_55_SBOX32(hash,state,key) _SBOX32_CASE(55,hash,state,key)
+#else
+#define case_55_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 54
+#define case_54_SBOX32(hash,state,key) _SBOX32_CASE(54,hash,state,key)
+#else
+#define case_54_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 53
+#define case_53_SBOX32(hash,state,key) _SBOX32_CASE(53,hash,state,key)
+#else
+#define case_53_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 52
+#define case_52_SBOX32(hash,state,key) _SBOX32_CASE(52,hash,state,key)
+#else
+#define case_52_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 51
+#define case_51_SBOX32(hash,state,key) _SBOX32_CASE(51,hash,state,key)
+#else
+#define case_51_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 50
+#define case_50_SBOX32(hash,state,key) _SBOX32_CASE(50,hash,state,key)
+#else
+#define case_50_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 49
+#define case_49_SBOX32(hash,state,key) _SBOX32_CASE(49,hash,state,key)
+#else
+#define case_49_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 48
+#define case_48_SBOX32(hash,state,key) _SBOX32_CASE(48,hash,state,key)
+#else
+#define case_48_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 47
+#define case_47_SBOX32(hash,state,key) _SBOX32_CASE(47,hash,state,key)
+#else
+#define case_47_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 46
+#define case_46_SBOX32(hash,state,key) _SBOX32_CASE(46,hash,state,key)
+#else
+#define case_46_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 45
+#define case_45_SBOX32(hash,state,key) _SBOX32_CASE(45,hash,state,key)
+#else
+#define case_45_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 44
+#define case_44_SBOX32(hash,state,key) _SBOX32_CASE(44,hash,state,key)
+#else
+#define case_44_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 43
+#define case_43_SBOX32(hash,state,key) _SBOX32_CASE(43,hash,state,key)
+#else
+#define case_43_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 42
+#define case_42_SBOX32(hash,state,key) _SBOX32_CASE(42,hash,state,key)
+#else
+#define case_42_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 41
+#define case_41_SBOX32(hash,state,key) _SBOX32_CASE(41,hash,state,key)
+#else
+#define case_41_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 40
+#define case_40_SBOX32(hash,state,key) _SBOX32_CASE(40,hash,state,key)
+#else
+#define case_40_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 39
+#define case_39_SBOX32(hash,state,key) _SBOX32_CASE(39,hash,state,key)
+#else
+#define case_39_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 38
+#define case_38_SBOX32(hash,state,key) _SBOX32_CASE(38,hash,state,key)
+#else
+#define case_38_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 37
+#define case_37_SBOX32(hash,state,key) _SBOX32_CASE(37,hash,state,key)
+#else
+#define case_37_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 36
+#define case_36_SBOX32(hash,state,key) _SBOX32_CASE(36,hash,state,key)
+#else
+#define case_36_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 35
+#define case_35_SBOX32(hash,state,key) _SBOX32_CASE(35,hash,state,key)
+#else
+#define case_35_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 34
+#define case_34_SBOX32(hash,state,key) _SBOX32_CASE(34,hash,state,key)
+#else
+#define case_34_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 33
+#define case_33_SBOX32(hash,state,key) _SBOX32_CASE(33,hash,state,key)
+#else
+#define case_33_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 32
+#define case_32_SBOX32(hash,state,key) _SBOX32_CASE(32,hash,state,key)
+#else
+#define case_32_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 31
+#define case_31_SBOX32(hash,state,key) _SBOX32_CASE(31,hash,state,key)
+#else
+#define case_31_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 30
+#define case_30_SBOX32(hash,state,key) _SBOX32_CASE(30,hash,state,key)
+#else
+#define case_30_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 29
+#define case_29_SBOX32(hash,state,key) _SBOX32_CASE(29,hash,state,key)
+#else
+#define case_29_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 28
+#define case_28_SBOX32(hash,state,key) _SBOX32_CASE(28,hash,state,key)
+#else
+#define case_28_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 27
+#define case_27_SBOX32(hash,state,key) _SBOX32_CASE(27,hash,state,key)
+#else
+#define case_27_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 26
+#define case_26_SBOX32(hash,state,key) _SBOX32_CASE(26,hash,state,key)
+#else
+#define case_26_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 25
+#define case_25_SBOX32(hash,state,key) _SBOX32_CASE(25,hash,state,key)
+#else
+#define case_25_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 24
+#define case_24_SBOX32(hash,state,key) _SBOX32_CASE(24,hash,state,key)
+#else
+#define case_24_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 23
+#define case_23_SBOX32(hash,state,key) _SBOX32_CASE(23,hash,state,key)
+#else
+#define case_23_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 22
+#define case_22_SBOX32(hash,state,key) _SBOX32_CASE(22,hash,state,key)
+#else
+#define case_22_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 21
+#define case_21_SBOX32(hash,state,key) _SBOX32_CASE(21,hash,state,key)
+#else
+#define case_21_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 20
+#define case_20_SBOX32(hash,state,key) _SBOX32_CASE(20,hash,state,key)
+#else
+#define case_20_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 19
+#define case_19_SBOX32(hash,state,key) _SBOX32_CASE(19,hash,state,key)
+#else
+#define case_19_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 18
+#define case_18_SBOX32(hash,state,key) _SBOX32_CASE(18,hash,state,key)
+#else
+#define case_18_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 17
+#define case_17_SBOX32(hash,state,key) _SBOX32_CASE(17,hash,state,key)
+#else
+#define case_17_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 16
+#define case_16_SBOX32(hash,state,key) _SBOX32_CASE(16,hash,state,key)
+#else
+#define case_16_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 15
+#define case_15_SBOX32(hash,state,key) _SBOX32_CASE(15,hash,state,key)
+#else
+#define case_15_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 14
+#define case_14_SBOX32(hash,state,key) _SBOX32_CASE(14,hash,state,key)
+#else
+#define case_14_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 13
+#define case_13_SBOX32(hash,state,key) _SBOX32_CASE(13,hash,state,key)
+#else
+#define case_13_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 12
+#define case_12_SBOX32(hash,state,key) _SBOX32_CASE(12,hash,state,key)
+#else
+#define case_12_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 11
+#define case_11_SBOX32(hash,state,key) _SBOX32_CASE(11,hash,state,key)
+#else
+#define case_11_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 10
+#define case_10_SBOX32(hash,state,key) _SBOX32_CASE(10,hash,state,key)
+#else
+#define case_10_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 9
+#define case_9_SBOX32(hash,state,key) _SBOX32_CASE(9,hash,state,key)
+#else
+#define case_9_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 8
+#define case_8_SBOX32(hash,state,key) _SBOX32_CASE(8,hash,state,key)
+#else
+#define case_8_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 7
+#define case_7_SBOX32(hash,state,key) _SBOX32_CASE(7,hash,state,key)
+#else
+#define case_7_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 6
+#define case_6_SBOX32(hash,state,key) _SBOX32_CASE(6,hash,state,key)
+#else
+#define case_6_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 5
+#define case_5_SBOX32(hash,state,key) _SBOX32_CASE(5,hash,state,key)
+#else
+#define case_5_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 4
+#define case_4_SBOX32(hash,state,key) _SBOX32_CASE(4,hash,state,key)
+#else
+#define case_4_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 3
+#define case_3_SBOX32(hash,state,key) _SBOX32_CASE(3,hash,state,key)
+#else
+#define case_3_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 2
+#define case_2_SBOX32(hash,state,key) _SBOX32_CASE(2,hash,state,key)
+#else
+#define case_2_SBOX32(hash,state,key) /**/
+#endif
+#if SBOX32_MAX_LEN >= 1
+#define case_1_SBOX32(hash,state,key) _SBOX32_CASE(1,hash,state,key)
+#else
+#define case_1_SBOX32(hash,state,key) /**/
+#endif
+
+#define XORSHIFT96_set(r,x,y,z,t) STMT_START {          \
+    t = (x ^ ( x << 10 ) );                             \
+    x = y; y = z;                                       \
+    r = z = (z ^ ( z >> 26 ) ) ^ ( t ^ ( t >> 5 ) );    \
+} STMT_END
+
+#define XORSHIFT128_set(r,x,y,z,w,t) STMT_START {       \
+    t = ( x ^ ( x << 5 ) );                             \
+    x = y; y = z; z = w;                                \
+    r = w = ( w ^ ( w >> 29 ) ) ^ ( t ^ ( t >> 12 ) );  \
+} STMT_END
+
+#define SBOX32_SCRAMBLE32(v,prime) STMT_START {  \
+    v ^= (v>>9);                        \
+    v ^= (v<<21);                       \
+    v ^= (v>>16);                       \
+    v *= prime;                         \
+    v ^= (v>>17);                       \
+    v ^= (v<<15);                       \
+    v ^= (v>>23);                       \
+} STMT_END
+
+#ifndef SBOX32_CHURN_ROUNDS 
+#define SBOX32_CHURN_ROUNDS 5
+#endif
+#ifndef SBOX32_SKIP_MASK
+#define SBOX32_SKIP_MASK 0x3
+#endif
+
+#define _SBOX32_CASE(len,hash,state,key) \
+    case len: hash ^= state[ 1 + ( 256 * ( len - 1 ) ) + key[ len - 1 ] ];
+
+
+SBOX32_STATIC_INLINE void sbox32_seed_state96 (
+    const U8 *seed_ch,
+    U8 *state_ch
+) {
+    U32 *seed= (U32 *)seed_ch;
+    U32 *state= (U32 *)state_ch;
+    U32 *state_cursor = state + 1;
+    U32 *sbox32_end = state + 1 + (256 * SBOX32_MAX_LEN);
+    U32 s0 = seed[0] ^ 0x68736168; /* sbox */
+    U32 s1 = seed[1] ^ 0x786f6273; /* hash */
+    U32 s2 = seed[2] ^ 0x646f6f67; /* good */
+    U32 t1,t2,i;
+
+    /* make sure we have all non-zero state elements */
+    if (!s0) s0 = 1;
+    if (!s1) s1 = 2;
+    if (!s2) s2 = 4;
+
+    /* Do a bunch of mix rounds to avalanche the seedbits
+     * before we use them for the XORSHIFT rng. */
+    for ( i = 0; i < SBOX32_CHURN_ROUNDS; i++ )
+        SBOX32_MIX3(s0,s1,s2,"SEED STATE");
+
+    while ( state_cursor < sbox32_end ) {
+        U32 *row_end = state_cursor + 256; 
+        for ( ; state_cursor < row_end; state_cursor++ ) {
+            XORSHIFT96_set(*state_cursor,s0,s1,s2,t1);
+        }
+    }
+    XORSHIFT96_set(*state,s0,s1,s2,t2);
+}
+
+SBOX32_STATIC_INLINE void sbox32_seed_state128 (
+    const U8 *seed_ch,
+    U8 *state_ch
+) {
+    U32 *seed= (U32 *)seed_ch;
+    U32 *state= (U32 *)state_ch;
+    U32 *state_cursor = state + 1;
+    U32 *sbox32_end = state + 1 + (256 * SBOX32_MAX_LEN);
+    U32 s0 = seed[0] ^ 0x68736168; /* sbox */
+    U32 s1 = seed[1] ^ 0x786f6273; /* hash */
+    U32 s2 = seed[2] ^ 0x646f6f67; /* good */
+    U32 s3 = seed[3] ^ 0x74736166; /* fast */
+    U32 t1,t2,i;
+
+    /* make sure we have all non-zero state elements */
+    if (!s0) s0 = 1;
+    if (!s1) s1 = 2;
+    if (!s2) s2 = 4;
+    if (!s3) s3 = 8;
+    
+    /* Do a bunch of mix rounds to avalanche the seedbits
+     * before we use them for the XORSHIFT rng. */
+    for ( i = 0; i < SBOX32_CHURN_ROUNDS; i++ )
+        SBOX32_MIX4(s0,s1,s2,s3,"SEED STATE");
+
+    while ( state_cursor < sbox32_end ) {
+        U32 *row_end = state_cursor + 256; 
+        for ( ; state_cursor < row_end; state_cursor++ ) {
+            XORSHIFT128_set(*state_cursor,s0,s1,s2,s3,t1);
+        }
+    }
+    XORSHIFT128_set(*state,s0,s1,s2,s3,t2);
+}
+
+SBOX32_STATIC_INLINE U32 sbox32_hash_with_state(
+    const U8 *state_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U32 *state= (U32 *)state_ch;
+    U32 hash = *state;
+    switch (key_len) {
+        default: return zaphod32_hash_with_state(state_ch, key, key_len);
+        case_256_SBOX32(hash,state,key)
+        case_255_SBOX32(hash,state,key)
+        case_254_SBOX32(hash,state,key)
+        case_253_SBOX32(hash,state,key)
+        case_252_SBOX32(hash,state,key)
+        case_251_SBOX32(hash,state,key)
+        case_250_SBOX32(hash,state,key)
+        case_249_SBOX32(hash,state,key)
+        case_248_SBOX32(hash,state,key)
+        case_247_SBOX32(hash,state,key)
+        case_246_SBOX32(hash,state,key)
+        case_245_SBOX32(hash,state,key)
+        case_244_SBOX32(hash,state,key)
+        case_243_SBOX32(hash,state,key)
+        case_242_SBOX32(hash,state,key)
+        case_241_SBOX32(hash,state,key)
+        case_240_SBOX32(hash,state,key)
+        case_239_SBOX32(hash,state,key)
+        case_238_SBOX32(hash,state,key)
+        case_237_SBOX32(hash,state,key)
+        case_236_SBOX32(hash,state,key)
+        case_235_SBOX32(hash,state,key)
+        case_234_SBOX32(hash,state,key)
+        case_233_SBOX32(hash,state,key)
+        case_232_SBOX32(hash,state,key)
+        case_231_SBOX32(hash,state,key)
+        case_230_SBOX32(hash,state,key)
+        case_229_SBOX32(hash,state,key)
+        case_228_SBOX32(hash,state,key)
+        case_227_SBOX32(hash,state,key)
+        case_226_SBOX32(hash,state,key)
+        case_225_SBOX32(hash,state,key)
+        case_224_SBOX32(hash,state,key)
+        case_223_SBOX32(hash,state,key)
+        case_222_SBOX32(hash,state,key)
+        case_221_SBOX32(hash,state,key)
+        case_220_SBOX32(hash,state,key)
+        case_219_SBOX32(hash,state,key)
+        case_218_SBOX32(hash,state,key)
+        case_217_SBOX32(hash,state,key)
+        case_216_SBOX32(hash,state,key)
+        case_215_SBOX32(hash,state,key)
+        case_214_SBOX32(hash,state,key)
+        case_213_SBOX32(hash,state,key)
+        case_212_SBOX32(hash,state,key)
+        case_211_SBOX32(hash,state,key)
+        case_210_SBOX32(hash,state,key)
+        case_209_SBOX32(hash,state,key)
+        case_208_SBOX32(hash,state,key)
+        case_207_SBOX32(hash,state,key)
+        case_206_SBOX32(hash,state,key)
+        case_205_SBOX32(hash,state,key)
+        case_204_SBOX32(hash,state,key)
+        case_203_SBOX32(hash,state,key)
+        case_202_SBOX32(hash,state,key)
+        case_201_SBOX32(hash,state,key)
+        case_200_SBOX32(hash,state,key)
+        case_199_SBOX32(hash,state,key)
+        case_198_SBOX32(hash,state,key)
+        case_197_SBOX32(hash,state,key)
+        case_196_SBOX32(hash,state,key)
+        case_195_SBOX32(hash,state,key)
+        case_194_SBOX32(hash,state,key)
+        case_193_SBOX32(hash,state,key)
+        case_192_SBOX32(hash,state,key)
+        case_191_SBOX32(hash,state,key)
+        case_190_SBOX32(hash,state,key)
+        case_189_SBOX32(hash,state,key)
+        case_188_SBOX32(hash,state,key)
+        case_187_SBOX32(hash,state,key)
+        case_186_SBOX32(hash,state,key)
+        case_185_SBOX32(hash,state,key)
+        case_184_SBOX32(hash,state,key)
+        case_183_SBOX32(hash,state,key)
+        case_182_SBOX32(hash,state,key)
+        case_181_SBOX32(hash,state,key)
+        case_180_SBOX32(hash,state,key)
+        case_179_SBOX32(hash,state,key)
+        case_178_SBOX32(hash,state,key)
+        case_177_SBOX32(hash,state,key)
+        case_176_SBOX32(hash,state,key)
+        case_175_SBOX32(hash,state,key)
+        case_174_SBOX32(hash,state,key)
+        case_173_SBOX32(hash,state,key)
+        case_172_SBOX32(hash,state,key)
+        case_171_SBOX32(hash,state,key)
+        case_170_SBOX32(hash,state,key)
+        case_169_SBOX32(hash,state,key)
+        case_168_SBOX32(hash,state,key)
+        case_167_SBOX32(hash,state,key)
+        case_166_SBOX32(hash,state,key)
+        case_165_SBOX32(hash,state,key)
+        case_164_SBOX32(hash,state,key)
+        case_163_SBOX32(hash,state,key)
+        case_162_SBOX32(hash,state,key)
+        case_161_SBOX32(hash,state,key)
+        case_160_SBOX32(hash,state,key)
+        case_159_SBOX32(hash,state,key)
+        case_158_SBOX32(hash,state,key)
+        case_157_SBOX32(hash,state,key)
+        case_156_SBOX32(hash,state,key)
+        case_155_SBOX32(hash,state,key)
+        case_154_SBOX32(hash,state,key)
+        case_153_SBOX32(hash,state,key)
+        case_152_SBOX32(hash,state,key)
+        case_151_SBOX32(hash,state,key)
+        case_150_SBOX32(hash,state,key)
+        case_149_SBOX32(hash,state,key)
+        case_148_SBOX32(hash,state,key)
+        case_147_SBOX32(hash,state,key)
+        case_146_SBOX32(hash,state,key)
+        case_145_SBOX32(hash,state,key)
+        case_144_SBOX32(hash,state,key)
+        case_143_SBOX32(hash,state,key)
+        case_142_SBOX32(hash,state,key)
+        case_141_SBOX32(hash,state,key)
+        case_140_SBOX32(hash,state,key)
+        case_139_SBOX32(hash,state,key)
+        case_138_SBOX32(hash,state,key)
+        case_137_SBOX32(hash,state,key)
+        case_136_SBOX32(hash,state,key)
+        case_135_SBOX32(hash,state,key)
+        case_134_SBOX32(hash,state,key)
+        case_133_SBOX32(hash,state,key)
+        case_132_SBOX32(hash,state,key)
+        case_131_SBOX32(hash,state,key)
+        case_130_SBOX32(hash,state,key)
+        case_129_SBOX32(hash,state,key)
+        case_128_SBOX32(hash,state,key)
+        case_127_SBOX32(hash,state,key)
+        case_126_SBOX32(hash,state,key)
+        case_125_SBOX32(hash,state,key)
+        case_124_SBOX32(hash,state,key)
+        case_123_SBOX32(hash,state,key)
+        case_122_SBOX32(hash,state,key)
+        case_121_SBOX32(hash,state,key)
+        case_120_SBOX32(hash,state,key)
+        case_119_SBOX32(hash,state,key)
+        case_118_SBOX32(hash,state,key)
+        case_117_SBOX32(hash,state,key)
+        case_116_SBOX32(hash,state,key)
+        case_115_SBOX32(hash,state,key)
+        case_114_SBOX32(hash,state,key)
+        case_113_SBOX32(hash,state,key)
+        case_112_SBOX32(hash,state,key)
+        case_111_SBOX32(hash,state,key)
+        case_110_SBOX32(hash,state,key)
+        case_109_SBOX32(hash,state,key)
+        case_108_SBOX32(hash,state,key)
+        case_107_SBOX32(hash,state,key)
+        case_106_SBOX32(hash,state,key)
+        case_105_SBOX32(hash,state,key)
+        case_104_SBOX32(hash,state,key)
+        case_103_SBOX32(hash,state,key)
+        case_102_SBOX32(hash,state,key)
+        case_101_SBOX32(hash,state,key)
+        case_100_SBOX32(hash,state,key)
+        case_99_SBOX32(hash,state,key)
+        case_98_SBOX32(hash,state,key)
+        case_97_SBOX32(hash,state,key)
+        case_96_SBOX32(hash,state,key)
+        case_95_SBOX32(hash,state,key)
+        case_94_SBOX32(hash,state,key)
+        case_93_SBOX32(hash,state,key)
+        case_92_SBOX32(hash,state,key)
+        case_91_SBOX32(hash,state,key)
+        case_90_SBOX32(hash,state,key)
+        case_89_SBOX32(hash,state,key)
+        case_88_SBOX32(hash,state,key)
+        case_87_SBOX32(hash,state,key)
+        case_86_SBOX32(hash,state,key)
+        case_85_SBOX32(hash,state,key)
+        case_84_SBOX32(hash,state,key)
+        case_83_SBOX32(hash,state,key)
+        case_82_SBOX32(hash,state,key)
+        case_81_SBOX32(hash,state,key)
+        case_80_SBOX32(hash,state,key)
+        case_79_SBOX32(hash,state,key)
+        case_78_SBOX32(hash,state,key)
+        case_77_SBOX32(hash,state,key)
+        case_76_SBOX32(hash,state,key)
+        case_75_SBOX32(hash,state,key)
+        case_74_SBOX32(hash,state,key)
+        case_73_SBOX32(hash,state,key)
+        case_72_SBOX32(hash,state,key)
+        case_71_SBOX32(hash,state,key)
+        case_70_SBOX32(hash,state,key)
+        case_69_SBOX32(hash,state,key)
+        case_68_SBOX32(hash,state,key)
+        case_67_SBOX32(hash,state,key)
+        case_66_SBOX32(hash,state,key)
+        case_65_SBOX32(hash,state,key)
+        case_64_SBOX32(hash,state,key)
+        case_63_SBOX32(hash,state,key)
+        case_62_SBOX32(hash,state,key)
+        case_61_SBOX32(hash,state,key)
+        case_60_SBOX32(hash,state,key)
+        case_59_SBOX32(hash,state,key)
+        case_58_SBOX32(hash,state,key)
+        case_57_SBOX32(hash,state,key)
+        case_56_SBOX32(hash,state,key)
+        case_55_SBOX32(hash,state,key)
+        case_54_SBOX32(hash,state,key)
+        case_53_SBOX32(hash,state,key)
+        case_52_SBOX32(hash,state,key)
+        case_51_SBOX32(hash,state,key)
+        case_50_SBOX32(hash,state,key)
+        case_49_SBOX32(hash,state,key)
+        case_48_SBOX32(hash,state,key)
+        case_47_SBOX32(hash,state,key)
+        case_46_SBOX32(hash,state,key)
+        case_45_SBOX32(hash,state,key)
+        case_44_SBOX32(hash,state,key)
+        case_43_SBOX32(hash,state,key)
+        case_42_SBOX32(hash,state,key)
+        case_41_SBOX32(hash,state,key)
+        case_40_SBOX32(hash,state,key)
+        case_39_SBOX32(hash,state,key)
+        case_38_SBOX32(hash,state,key)
+        case_37_SBOX32(hash,state,key)
+        case_36_SBOX32(hash,state,key)
+        case_35_SBOX32(hash,state,key)
+        case_34_SBOX32(hash,state,key)
+        case_33_SBOX32(hash,state,key)
+        case_32_SBOX32(hash,state,key)
+        case_31_SBOX32(hash,state,key)
+        case_30_SBOX32(hash,state,key)
+        case_29_SBOX32(hash,state,key)
+        case_28_SBOX32(hash,state,key)
+        case_27_SBOX32(hash,state,key)
+        case_26_SBOX32(hash,state,key)
+        case_25_SBOX32(hash,state,key)
+        case_24_SBOX32(hash,state,key)
+        case_23_SBOX32(hash,state,key)
+        case_22_SBOX32(hash,state,key)
+        case_21_SBOX32(hash,state,key)
+        case_20_SBOX32(hash,state,key)
+        case_19_SBOX32(hash,state,key)
+        case_18_SBOX32(hash,state,key)
+        case_17_SBOX32(hash,state,key)
+        case_16_SBOX32(hash,state,key)
+        case_15_SBOX32(hash,state,key)
+        case_14_SBOX32(hash,state,key)
+        case_13_SBOX32(hash,state,key)
+        case_12_SBOX32(hash,state,key)
+        case_11_SBOX32(hash,state,key)
+        case_10_SBOX32(hash,state,key)
+        case_9_SBOX32(hash,state,key)
+        case_8_SBOX32(hash,state,key)
+        case_7_SBOX32(hash,state,key)
+        case_6_SBOX32(hash,state,key)
+        case_5_SBOX32(hash,state,key)
+        case_4_SBOX32(hash,state,key)
+        case_3_SBOX32(hash,state,key)
+        case_2_SBOX32(hash,state,key)
+        case_1_SBOX32(hash,state,key)
+        case 0: break;
+    }
+    return hash;
+}
+
+SBOX32_STATIC_INLINE U32 sbox32_hash96(
+    const U8 *seed_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U32 state[SBOX32_STATE_WORDS];
+    sbox32_seed_state96(seed_ch,(U8*)state);
+    return sbox32_hash_with_state((U8*)state,key,key_len);
+}
+
+SBOX32_STATIC_INLINE U32 sbox32_hash128(
+    const U8 *seed_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U32 state[SBOX32_STATE_WORDS];
+    sbox32_seed_state128(seed_ch,(U8*)state);
+    return sbox32_hash_with_state((U8*)state,key,key_len);
+}
+
+
+#endif
diff --git a/stadtx_hash.h b/stadtx_hash.h
new file mode 100644 (file)
index 0000000..3a5d81e
--- /dev/null
@@ -0,0 +1,301 @@
+#ifndef STADTX_HASH_H
+#define STADTX_HASH_H
+
+#ifndef DEBUG_STADTX_HASH
+#define DEBUG_STADTX_HASH 0
+#endif
+
+
+#ifndef ROTL64
+#define _ROTL_SIZED(x,r,s) ( ((x) << (r)) | ((x) >> ((s) - (r))) )
+#define _ROTR_SIZED(x,r,s) ( ((x) << ((s) - (r))) | ((x) >> (r)) )
+#define ROTL64(x,r) _ROTL_SIZED(x,r,64)
+#define ROTR64(x,r) _ROTR_SIZED(x,r,64)
+#endif
+
+#ifndef PERL_SEEN_HV_FUNC_H
+
+#if !defined(U64)
+    #include <stdint.h>
+    #define U64 uint64_t
+#endif
+
+#if !defined(U32)
+  #define U32 uint32_t
+#endif
+
+#if !defined(U8)
+    #define U8 unsigned char
+#endif
+
+#if !defined(U16)
+    #define U16 uint16_t
+#endif
+
+#ifndef STRLEN
+#define STRLEN int
+#endif
+#endif
+
+#ifndef STADTX_STATIC_INLINE
+#ifdef PERL_STATIC_INLINE
+#define STADTX_STATIC_INLINE PERL_STATIC_INLINE
+#else
+#define STADTX_STATIC_INLINE static inline
+#endif
+#endif
+
+#ifndef STMT_START
+#define STMT_START do
+#define STMT_END while(0)
+#endif
+
+#ifndef STADTX_UNALIGNED_AND_LITTLE_ENDIAN
+#define STADTX_UNALIGNED_AND_LITTLE_ENDIAN 1
+#endif
+
+#if STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
+  #ifndef U8TO64_LE
+    #define U8TO64_LE(ptr)  (*((const U64 *)(ptr)))
+  #endif
+  #ifndef U8TO32_LE
+    #define U8TO32_LE(ptr)  (*((const U32 *)(ptr)))
+  #endif
+  #ifndef U8TO16_LE
+    #define U8TO16_LE(ptr)  (*((const U16 *)(ptr)))
+  #endif
+#else
+  #ifndef U8TO64_LE
+    #define U8TO64_LE(ptr)  (\
+        (U64)(ptr)[7] << 56 | \
+        (U64)(ptr)[6] << 48 | \
+        (U64)(ptr)[5] << 40 | \
+        (U64)(ptr)[4] << 32 | \
+        (U64)(ptr)[3] << 24 | \
+        (U64)(ptr)[2] << 16 | \
+        (U64)(ptr)[1] << 8  | \
+        (U64)(ptr)[0]         \
+    )
+  #endif
+  #ifndef U8TO32_LE
+    #define U8TO32_LE(ptr)  (\
+        (U32)(ptr)[3] << 24 | \
+        (U32)(ptr)[2] << 16 | \
+        (U32)(ptr)[1] << 8  | \
+        (U32)(ptr)[0]         \
+    )
+  #endif
+  #ifndef U8TO16_LE
+    #define U8TO16_LE(ptr)  (\
+        (U16)(ptr)[1] << 8  | \
+        (U16)(ptr)[0]         \
+    )
+  #endif
+#endif
+
+/* do a marsaglia xor-shift permutation followed by a
+ * multiply by a prime (presumably large) and another
+ * marsaglia xor-shift permutation.
+ * One of these thoroughly changes the bits of the input.
+ * Two of these with different primes passes the Strict Avalanche Criteria
+ * in all the tests I did.
+ *
+ * Note that v cannot end up zero after a scramble64 unless it
+ * was zero in the first place.
+ */
+#define STADTX_SCRAMBLE64(v,prime) STMT_START {    \
+    v ^= (v >> 13);                         \
+    v ^= (v << 35);                         \
+    v ^= (v >> 30);                         \
+    v *= prime;                             \
+    v ^= (v >> 19);                         \
+    v ^= (v << 15);                         \
+    v ^= (v >> 46);                         \
+} STMT_END
+
+
+STADTX_STATIC_INLINE void stadtx_seed_state (
+    const U8 *seed_ch,
+    U8 *state_ch
+) {
+    U64 *seed= (U64 *)seed_ch;
+    U64 *state= (U64 *)state_ch;
+    /* first we apply two masks to each word of the seed, this means that
+     * a) at least one of state[0] and state[2] is nonzero,
+     * b) at least one of state[1] and state[3] is nonzero
+     * c) that state[0] and state[2] are different
+     * d) that state[1] and state[3] are different
+     * e) that the replacement value for any zero's is a totally different from the seed value.
+     *    (iow, if seed[0] is 0x43f6a8885a308d31UL then state[0] becomes 0, which is the replaced
+     *    with 1, which is totally different.). */
+    /* hex expansion of pi, skipping first two digits. pi= 3.2[43f6...]*/
+    /* pi value in hex from here:
+     * http://turner.faculty.swau.edu/mathematics/materialslibrary/pi/pibases.html*/
+    state[0]= seed[0] ^ 0x43f6a8885a308d31UL;
+    state[1]= seed[1] ^ 0x3198a2e03707344aUL;
+    state[2]= seed[0] ^ 0x4093822299f31d00UL;
+    state[3]= seed[1] ^ 0x82efa98ec4e6c894UL;
+    if (!state[0]) state[0]=1;
+    if (!state[1]) state[1]=2;
+    if (!state[2]) state[2]=4;
+    if (!state[3]) state[3]=8;
+    /* and now for good measure we double scramble all four -
+     * a double scramble guarantees a complete avalanche of all the
+     * bits in the seed - IOW, by the time we are hashing the
+     * four state vectors should be completely different and utterly
+     * uncognizable from the input seed bits */
+    STADTX_SCRAMBLE64(state[0],0x801178846e899d17UL);
+    STADTX_SCRAMBLE64(state[0],0xdd51e5d1c9a5a151UL);
+    STADTX_SCRAMBLE64(state[1],0x93a7d6c8c62e4835UL);
+    STADTX_SCRAMBLE64(state[1],0x803340f36895c2b5UL);
+    STADTX_SCRAMBLE64(state[2],0xbea9344eb7565eebUL);
+    STADTX_SCRAMBLE64(state[2],0xcd95d1e509b995cdUL);
+    STADTX_SCRAMBLE64(state[3],0x9999791977e30c13UL);
+    STADTX_SCRAMBLE64(state[3],0xaab8b6b05abfc6cdUL);
+}
+
+#define STADTX_K0_U64 0xb89b0f8e1655514fUL
+#define STADTX_K1_U64 0x8c6f736011bd5127UL
+#define STADTX_K2_U64 0x8f29bd94edce7b39UL
+#define STADTX_K3_U64 0x9c1b8e1e9628323fUL
+
+#define STADTX_K2_U32 0x802910e3
+#define STADTX_K3_U32 0x819b13af
+#define STADTX_K4_U32 0x91cb27e5
+#define STADTX_K5_U32 0xc1a269c1
+
+STADTX_STATIC_INLINE U64 stadtx_hash_with_state(
+    const U8 *state_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U64 *state= (U64 *)state_ch;
+    U64 len = key_len;
+    U64 v0= state[0] ^ ((key_len+1) * STADTX_K0_U64);
+    U64 v1= state[1] ^ ((key_len+2) * STADTX_K1_U64);
+    if (len < 32) {
+        switch(len >> 3) {
+            case 3:
+            v0 += U8TO64_LE(key) * STADTX_K3_U64;
+            v0= ROTR64(v0, 17) ^ v1;
+            v1= ROTR64(v1, 53) + v0;
+            key += 8;
+            case 2:
+            v0 += U8TO64_LE(key) * STADTX_K3_U64;
+            v0= ROTR64(v0, 17) ^ v1;
+            v1= ROTR64(v1, 53) + v0;
+            key += 8;
+            case 1:
+            v0 += U8TO64_LE(key) * STADTX_K3_U64;
+            v0= ROTR64(v0, 17) ^ v1;
+            v1= ROTR64(v1, 53) + v0;
+            key += 8;
+            case 0:
+            default: break;
+        }
+        switch ( len & 0x7 ) {
+            case 7: v0 += (U64)key[6] << 32;
+            case 6: v1 += (U64)key[5] << 48;
+            case 5: v0 += (U64)key[4] << 16;
+            case 4: v1 += (U64)U8TO32_LE(key);
+                    break;
+            case 3: v0 += (U64)key[2] << 48;
+            case 2: v1 += (U64)U8TO16_LE(key);
+                    break;
+            case 1: v0 += (U64)key[0];
+            case 0: v1 = ROTL64(v1, 32) ^ 0xFF;
+                    break;
+        }
+        v1 ^= v0;
+        v0 = ROTR64(v0,33) + v1;
+        v1 = ROTL64(v1,17) ^ v0;
+        v0 = ROTL64(v0,43) + v1;
+        v1 = ROTL64(v1,31) - v0;
+        v0 = ROTL64(v0,13) ^ v1;
+        v1 -= v0;
+        v0 = ROTL64(v0,41) + v1;
+        v1 = ROTL64(v1,37) ^ v0;
+        v0 = ROTR64(v0,39) + v1;
+        v1 = ROTR64(v1,15) + v0;
+        v0 = ROTL64(v0,15) ^ v1;
+        v1 = ROTR64(v1, 5);
+        return v0 ^ v1;
+    } else {
+        U64 v2= state[2] ^ ((key_len+3) * STADTX_K2_U64);
+        U64 v3= state[3] ^ ((key_len+4) * STADTX_K3_U64);
+
+        do {
+            v0 += (U64)U8TO64_LE(key+ 0) * STADTX_K2_U32; v0= ROTL64(v0,57) ^ v3;
+            v1 += (U64)U8TO64_LE(key+ 8) * STADTX_K3_U32; v1= ROTL64(v1,63) ^ v2;
+            v2 += (U64)U8TO64_LE(key+16) * STADTX_K4_U32; v2= ROTR64(v2,47) + v0;
+            v3 += (U64)U8TO64_LE(key+24) * STADTX_K5_U32; v3= ROTR64(v3,11) - v1;
+            key += 32;
+            len -= 32;
+        } while ( len >= 32 );
+
+        switch ( len >> 3 ) {
+            case 3: v0 += ((U64)U8TO64_LE(key) * STADTX_K2_U32); key += 8; v0= ROTL64(v0,57) ^ v3;
+            case 2: v1 += ((U64)U8TO64_LE(key) * STADTX_K3_U32); key += 8; v1= ROTL64(v1,63) ^ v2;
+            case 1: v2 += ((U64)U8TO64_LE(key) * STADTX_K4_U32); key += 8; v2= ROTR64(v2,47) + v0;
+            case 0: v3 = ROTR64(v3,11) - v1;
+        }
+        v0 ^= (len+1) * STADTX_K3_U64;
+        switch ( len & 0x7 ) {
+            case 7: v1 += (U64)key[6];
+            case 6: v2 += (U64)U8TO16_LE(key+4);
+                    v3 += (U64)U8TO32_LE(key);
+                    break;
+            case 5: v1 += (U64)key[4];
+            case 4: v2 += (U64)U8TO32_LE(key);
+                    break;
+            case 3: v3 += (U64)key[2];
+            case 2: v1 += (U64)U8TO16_LE(key);
+                    break;
+            case 1: v2 += (U64)key[0];
+            case 0: v3 = ROTL64(v3, 32) ^ 0xFF;
+                    break;
+        }
+
+        v1 -= v2;
+        v0 = ROTR64(v0,19);
+        v1 -= v0;
+        v1 = ROTR64(v1,53);
+        v3 ^= v1;
+        v0 -= v3;
+        v3 = ROTL64(v3,43);
+        v0 += v3;
+        v0 = ROTR64(v0, 3);
+        v3 -= v0;
+        v2 = ROTR64(v2,43) - v3;
+        v2 = ROTL64(v2,55) ^ v0;
+        v1 -= v2;
+        v3 = ROTR64(v3, 7) - v2;
+        v2 = ROTR64(v2,31);
+        v3 += v2;
+        v2 -= v1;
+        v3 = ROTR64(v3,39);
+        v2 ^= v3;
+        v3 = ROTR64(v3,17) ^ v2;
+        v1 += v3;
+        v1 = ROTR64(v1, 9);
+        v2 ^= v1;
+        v2 = ROTL64(v2,24);
+        v3 ^= v2;
+        v3 = ROTR64(v3,59);
+        v0 = ROTR64(v0, 1) - v1;
+
+        return v0 ^ v1 ^ v2 ^ v3;
+    }
+}
+
+STADTX_STATIC_INLINE U64 stadtx_hash(
+    const U8 *seed_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U64 state[4];
+    stadtx_seed_state(seed_ch,(U8*)state);
+    return stadtx_hash_with_state((U8*)state,key,key_len);
+}
+
+#endif
index 605eba0..1db0ae7 100644 (file)
@@ -15,7 +15,7 @@ my %skip = map { ("PL_$_", 1) }
     qw(
          DBcv bitcount cshname force_link_funcs generation lastgotoprobe
          mod_latin1_uc modcount no_symref_sv uudmap
-         watchaddr watchok warn_uninit_sv
+         watchaddr watchok warn_uninit_sv hash_chars
      );
 
 $skip{PL_hash_rand_bits}= $skip{PL_hash_rand_bits_enabled}= 1; # we can be compiled without these, so skip testing them
diff --git a/zaphod32_hash.h b/zaphod32_hash.h
new file mode 100644 (file)
index 0000000..71a2faa
--- /dev/null
@@ -0,0 +1,287 @@
+#ifndef DEBUG_ZAPHOD32_HASH
+#define DEBUG_ZAPHOD32_HASH 0
+
+#if DEBUG_ZAPHOD32_HASH == 1
+#include <stdio.h>
+#define ZAPHOD32_WARN6(pat,v0,v1,v2,v3,v4,v5)    printf(pat, v0, v1, v2, v3, v4, v5)
+#define ZAPHOD32_WARN5(pat,v0,v1,v2,v3,v4)       printf(pat, v0, v1, v2, v3, v4)
+#define ZAPHOD32_WARN4(pat,v0,v1,v2,v3)          printf(pat, v0, v1, v2, v3)
+#define ZAPHOD32_WARN3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#define ZAPHOD32_WARN2(pat,v0,v1)                printf(pat, v0, v1)
+#define NOTE3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#elif DEBUG_ZAPHOD32_HASH == 2
+#define ZAPHOD32_WARN6(pat,v0,v1,v2,v3,v4,v5)
+#define ZAPHOD32_WARN5(pat,v0,v1,v2,v3,v4)
+#define ZAPHOD32_WARN4(pat,v0,v1,v2,v3)
+#define ZAPHOD32_WARN3(pat,v0,v1,v2)
+#define ZAPHOD32_WARN2(pat,v0,v1)
+#define NOTE3(pat,v0,v1,v2)             printf(pat, v0, v1, v2)
+#else
+#define ZAPHOD32_WARN6(pat,v0,v1,v2,v3,v4,v5)
+#define ZAPHOD32_WARN5(pat,v0,v1,v2,v3,v4)
+#define ZAPHOD32_WARN4(pat,v0,v1,v2,v3)
+#define ZAPHOD32_WARN3(pat,v0,v1,v2)
+#define NOTE3(pat,v0,v1,v2)
+#define ZAPHOD32_WARN2(pat,v0,v1)
+#endif
+
+#ifndef ROTL32
+#define _ROTL_SIZED(x,r,s) ( ((x) << (r)) | ((x) >> ((s) - (r))) )
+#define _ROTR_SIZED(x,r,s) ( ((x) << ((s) - (r))) | ((x) >> (r)) )
+#define ROTL32(x,r) _ROTL_SIZED(x,r,32)
+#define ROTR32(x,r) _ROTR_SIZED(x,r,32)
+#endif
+
+#ifndef PERL_SEEN_HV_FUNC_H
+#if !defined(U64)
+    #include <stdint.h>
+    #define U64 uint64_t
+#endif
+
+#if !defined(U32)
+  #define U32 uint32_t
+#endif
+
+#if !defined(U8)
+    #define U8 unsigned char
+#endif
+
+#if !defined(U16)
+    #define U16 uint16_t
+#endif
+
+#ifndef STRLEN
+#define STRLEN int
+#endif
+#endif
+
+#ifndef ZAPHOD32_STATIC_INLINE
+#ifdef PERL_STATIC_INLINE
+#define ZAPHOD32_STATIC_INLINE PERL_STATIC_INLINE
+#else
+#define ZAPHOD32_STATIC_INLINE static inline
+#endif
+#endif
+
+#ifndef STMT_START
+#define STMT_START do
+#define STMT_END while(0)
+#endif
+
+#ifndef U8TO64_LE
+#define U8TO64_LE(ptr)  (*((const U64 *)(ptr)))
+#endif
+#ifndef U8TO32_LE
+#define U8TO32_LE(ptr)  (*((const U32 *)(ptr)))
+#endif
+#ifndef U8TO16_LE
+#define U8TO16_LE(ptr)  (*((const U16 *)(ptr)))
+#endif
+
+/* This is two marsaglia xor-shift permutes, with a prime-multiple
+ * sandwiched inside. The end result of doing this twice with different
+ * primes is a completely avalanched v.  */
+#define ZAPHOD32_SCRAMBLE32(v,prime) STMT_START {  \
+    v ^= (v>>9);                        \
+    v ^= (v<<21);                       \
+    v ^= (v>>16);                       \
+    v *= prime;                         \
+    v ^= (v>>17);                       \
+    v ^= (v<<15);                       \
+    v ^= (v>>23);                       \
+} STMT_END
+
+#define ZAPHOD32_FINALIZE(v0,v1,v2) STMT_START {          \
+    ZAPHOD32_WARN3("v0=%08x v1=%08x v2=%08x - ZAPHOD32 FINALIZE\n", \
+            (unsigned int)v0, (unsigned int)v1, (unsigned int)v2);  \
+    v2 += v0;                       \
+    v1 -= v2;                       \
+    v1 = ROTL32(v1,  6);           \
+    v2 ^= v1;                       \
+    v2 = ROTL32(v2, 28);           \
+    v1 ^= v2;                       \
+    v0 += v1;                       \
+    v1 = ROTL32(v1, 24);           \
+    v2 += v1;                       \
+    v2 = ROTL32(v2, 18) + v1;      \
+    v0 ^= v2;                       \
+    v0 = ROTL32(v0, 20);           \
+    v2 += v0;                       \
+    v1 ^= v2;                       \
+    v0 += v1;                       \
+    v0 = ROTL32(v0,  5);           \
+    v2 += v0;                       \
+    v2 = ROTL32(v2, 22);           \
+    v0 -= v1;                       \
+    v1 -= v2;                       \
+    v1 = ROTL32(v1, 17);           \
+} STMT_END
+
+#define ZAPHOD32_MIX(v0,v1,v2,text) STMT_START {                              \
+    ZAPHOD32_WARN4("v0=%08x v1=%08x v2=%08x - ZAPHOD32 %s MIX\n",                   \
+            (unsigned int)v0,(unsigned int)v1,(unsigned int)v2, text );  \
+    v0 = ROTL32(v0,16) - v2;   \
+    v1 = ROTR32(v1,13) ^ v2;   \
+    v2 = ROTL32(v2,17) + v1;   \
+    v0 = ROTR32(v0, 2) + v1;   \
+    v1 = ROTR32(v1,17) - v0;   \
+    v2 = ROTR32(v2, 7) ^ v0;   \
+} STMT_END
+
+
+ZAPHOD32_STATIC_INLINE
+void zaphod32_seed_state (
+    const U8 *seed_ch,
+    U8 *state_ch
+) {
+    U32 *seed= (U32 *)seed_ch;
+    U32 *state= (U32 *)state_ch;
+  
+    /* hex expansion of pi, skipping first two digits. pi= 3.2[43f6...]*/
+    /* pi value in hex from here:
+     * http://turner.faculty.swau.edu/mathematics/materialslibrary/pi/pibases.html*/
+    /* Ensure that the three state vectors are nonzero regardless of the seed. */
+    /* The idea of these two steps is to ensure that the 0 state comes from a seed
+     * utterly unlike that of the value we replace it with.*/
+    state[0]= seed[0] ^ 0x43f6a888;
+    state[1]= seed[1] ^ 0x5a308d31;
+    state[2]= seed[2] ^ 0x3198a2e0;
+    if (!state[0]) state[0] = 1;
+    if (!state[1]) state[1] = 2;
+    if (!state[2]) state[2] = 4;
+    /* these are pseduo-randomly selected primes between 2**31 and 2**32
+     * (I generated a big list and then randomly chose some from the list) */
+    ZAPHOD32_SCRAMBLE32(state[0],0x9fade23b);
+    ZAPHOD32_SCRAMBLE32(state[1],0xaa6f908d);
+    ZAPHOD32_SCRAMBLE32(state[2],0xcdf6b72d);
+    /* now that we have scrambled we do some mixing to avalanche the
+     * state bits to gether */
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE A 1/4");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE A 2/4");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE A 3/4");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE A 4/4");
+
+    /* and then scramble them again with different primes */
+    ZAPHOD32_SCRAMBLE32(state[0],0xc95d22a9);
+    ZAPHOD32_SCRAMBLE32(state[1],0x8497242b);
+    ZAPHOD32_SCRAMBLE32(state[2],0x9c5cc4e9);
+    /* and one final mix */
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE 3/3");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE 3/3");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE 3/3");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE 3/3");
+    ZAPHOD32_MIX(state[0],state[1],state[2],"ZAPHOD32 SEED-STATE 3/3");
+
+    /* so now state contains 4 + ( 7 * 256 ) == 1796 U32's, which is 57472 bits */
+    
+}
+
+ZAPHOD32_STATIC_INLINE
+U32 zaphod32_hash_with_state(
+    const U8 *state_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U32 *state= (U32 *)state_ch;
+    const U8 *end;
+    U32 len = key_len; 
+    U32 v0= state[0];
+    U32 v1= state[1];
+    U32 v2= state[2] ^ (0xC41A7AB1 * (key_len + 1));
+
+    ZAPHOD32_WARN4("v0=%08x v1=%08x v2=%08x ln=%08x HASH START\n",
+            (unsigned int)state[0], (unsigned int)state[1],
+            (unsigned int)state[2], (unsigned int)key_len);
+    {
+        switch (len) {
+            default: goto zaphod32_read8;
+            case 12: v2 += (U32)key[11] << 24;
+            case 11: v2 += (U32)key[10] << 16;
+            case 10: v2 += (U32)U8TO16_LE(key+8);
+                     v1 -= U8TO32_LE(key+4);
+                     v0 += U8TO32_LE(key+0);
+                     goto zaphod32_finalize;
+            case 9: v2 += (U32)key[8];
+            case 8: v1 -= U8TO32_LE(key+4);
+                    v0 += U8TO32_LE(key+0);
+                    goto zaphod32_finalize;
+            case 7: v2 += (U32)key[6];
+            case 6: v0 += (U32)U8TO16_LE(key+4);
+                    v1 -= U8TO32_LE(key+0);
+                    goto zaphod32_finalize;
+            case 5: v0 += (U32)key[4];
+            case 4: v1 -= U8TO32_LE(key+0);
+                    goto zaphod32_finalize;
+            case 3: v2 += (U32)key[2];
+            case 2: v0 += (U32)U8TO16_LE(key);
+                    break;
+            case 1: v0 += (U32)key[0];
+                    break;
+            case 0: v2 ^= 0xFF;
+                    break;
+
+        }
+        v0 -= v2;
+        v2 = ROTL32(v2, 8) ^ v0;
+        v0 = ROTR32(v0,16) + v2;
+        v2 += v0;
+        v0 += v0 >> 9;
+        v0 += v2;
+        v2 ^= v0;
+        v2 += v2 << 4;
+        v0 -= v2;
+        v2 = ROTR32(v2, 8) ^ v0;
+        v0 = ROTL32(v0,16) ^ v2;
+        v2 = ROTL32(v2,10) + v0;
+        v0 = ROTR32(v0,30) + v2;
+        v2 = ROTR32(v2,12);
+        return v0 ^ v2;
+    }
+
+    if (len >= 8) {
+zaphod32_read8:
+        len = key_len & 0x7;
+        end = key + key_len - len;
+        do {
+            v1 -= U8TO32_LE(key+0);
+            v0 += U8TO32_LE(key+4);
+            ZAPHOD32_MIX(v0,v1,v2,"MIX 2-WORDS A");
+            key += 8;
+        } while ( key < end );
+    }
+
+    if ( len >= 4 ) {
+        v1 -= U8TO32_LE(key);
+        key += 4;
+    }
+
+    v0 += (U32)(key_len) << 24;
+    switch (len & 0x3) {
+        case 3: v2 += (U32)key[2];
+        case 2: v0 += (U32)U8TO16_LE(key);
+                break;
+        case 1: v0 += (U32)key[0];
+                break;
+        case 0: v2 ^= 0xFF;
+    }
+zaphod32_finalize:
+    ZAPHOD32_FINALIZE(v0,v1,v2);
+
+    ZAPHOD32_WARN4("v0=%08x v1=%08x v2=%08x hh=%08x - FINAL\n\n",
+            (unsigned int)v0, (unsigned int)v1, (unsigned int)v2,
+            (unsigned int)v0 ^ v1 ^ v2);
+
+    return v0 ^ v1 ^ v2;
+}
+
+ZAPHOD32_STATIC_INLINE U32 zaphod32_hash(
+    const U8 *seed_ch,
+    const U8 *key,
+    const STRLEN key_len
+) {
+    U32 state[1796];
+    zaphod32_seed_state(seed_ch,(U8*)state);
+    return zaphod32_hash_with_state((U8*)state,key,key_len);
+}
+
+#endif