#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #define INIT32 2166136261U #define MULT32 16777619U #define INIT64 14695981039346656037U #define MULT64 1099511628211U static UV fnv1_32 (SV *data, U32 h) { STRLEN l; U8 *p = (U8 *)SvPVbyte (data, l); while (l--) { h *= MULT32; h ^= *p++; } return h; } static UV fnv1a_32 (SV *data, U32 h) { STRLEN l; U8 *p = (U8 *)SvPVbyte (data, l); while (l--) { h ^= *p++; h *= MULT32; } return h; } #if UVSIZE >= 8 static UV fnv1_64 (SV *data, UV h) { STRLEN l; U8 *p = (U8 *)SvPVbyte (data, l); while (l--) { h *= MULT64; h ^= *p++; } return h; } static UV fnv1a_64 (SV *data, UV h) { STRLEN l; U8 *p = (U8 *)SvPVbyte (data, l); while (l--) { h ^= *p++; h *= MULT64; } return h; } #endif #define fnv0_32 fnv1_32 #define fnv0_64 fnv1_64 static UV xorfold (UV hash, int bits, int max) { if (bits < max) hash = ((hash >> (max - bits)) ^ hash) & ((1 << bits) - 1); return hash; } #define xorfold_32(hash,bits) xorfold (hash, bits, 32) #define xorfold_64(hash,bits) xorfold (hash, bits, 64) static UV reduce_32 (U32 hash, U32 range) { U32 retry = 0xffffffffU / range * range; while (hash >= retry) hash = hash * MULT32 + INIT32; return hash % range; } static UV reduce_64 (UV hash, UV range) { U32 retry = 0xffffffffffffffffU / range * range; while (hash >= retry) hash = hash * MULT64 + INIT64; return hash % range; } MODULE = Digest::FNV::XS PACKAGE = Digest::FNV::XS PROTOTYPES: ENABLE UV fnv0_32 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvUV (init) UV fnv1_32 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvOK (init) ? SvUV (init) : INIT32 UV fnv1a_32 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvOK (init) ? SvUV (init) : INIT32 #if UVSIZE >= 8 UV fnv0_64 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvUV (init) UV fnv1_64 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvOK (init) ? SvUV (init) : INIT64 UV fnv1a_64 (SV *data, SV *init = &PL_sv_undef) C_ARGS: data, SvOK (init) ? SvUV (init) : INIT64 #endif UV xorfold_32 (UV hash, int bits) UV xorfold_64 (UV hash, int bits) UV reduce_32 (UV hash, UV range) UV reduce_64 (UV hash, UV range)