//======= Copyright © 2005, , Valve Corporation, All rights reserved. ========= // // Purpose: Variant Pearson Hash general purpose hashing algorithm described // by Cargill in C++ Report 1994. Generates a 16-bit result. // //============================================================================= #ifndef GENERICHASH_H #define GENERICHASH_H #if defined(_WIN32) #pragma once #endif //----------------------------------------------------------------------------- unsigned FASTCALL HashString( const char *pszKey ); unsigned FASTCALL HashStringCaseless( const char *pszKey ); unsigned FASTCALL HashStringCaselessConventional( const char *pszKey ); unsigned FASTCALL Hash4( const void *pKey ); unsigned FASTCALL Hash8( const void *pKey ); unsigned FASTCALL Hash12( const void *pKey ); unsigned FASTCALL Hash16( const void *pKey ); unsigned FASTCALL HashBlock( const void *pKey, unsigned size ); unsigned FASTCALL HashInt( const int key ); // hash a uint32 into a uint32 FORCEINLINE uint32 HashIntAlternate( uint32 n) { n = ( n + 0x7ed55d16 ) + ( n << 12 ); n = ( n ^ 0xc761c23c ) ^ ( n >> 19 ); n = ( n + 0x165667b1 ) + ( n << 5 ); n = ( n + 0xd3a2646c ) ^ ( n << 9 ); n = ( n + 0xfd7046c5 ) + ( n << 3 ); n = ( n ^ 0xb55a4f09 ) ^ ( n >> 16 ); return n; } inline uint64 HashUint64( uint64 s ) { // Thomas Wang hash, http://www.concentric.net/~ttwang/tech/inthash.htm s = ( ~s ) + ( s << 21 ); // s = (s << 21) - s - 1; s = s ^ ( s >> 24 ); s = ( s + ( s << 3 ) ) + ( s << 8 ); // s * 265 s = s ^ ( s >> 14 ); s = ( s + ( s << 2 ) ) + ( s << 4 ); // s * 21 s = s ^ ( s >> 28 ); s = s + ( s << 31 ); return s; } inline intp HashIntp( intp s ) { #ifdef PLATFORM_64BITS COMPILE_TIME_ASSERT( sizeof( s ) == sizeof( uint64 ) ); return ( intp )HashUint64( ( uint64 )s ); #else return HashInt( s ); #endif } inline unsigned HashIntConventional( const int n ) // faster but less effective { // first byte unsigned hash = 0xAAAAAAAA + (n & 0xFF); // second byte hash = ( hash << 5 ) + hash + ( (n >> 8) & 0xFF ); // third byte hash = ( hash << 5 ) + hash + ( (n >> 16) & 0xFF ); // fourth byte hash = ( hash << 5 ) + hash + ( (n >> 24) & 0xFF ); return hash; /* this is the old version, which would cause a load-hit-store on every line on a PowerPC, and therefore took hundreds of clocks to execute! byte *p = (byte *)&n; unsigned hash = 0xAAAAAAAA + *p++; hash = ( ( hash << 5 ) + hash ) + *p++; hash = ( ( hash << 5 ) + hash ) + *p++; return ( ( hash << 5 ) + hash ) + *p; */ } //----------------------------------------------------------------------------- template inline unsigned HashItem( const T &item ) { // TODO: Confirm comiler optimizes out unused paths if ( sizeof(item) == 4 ) return Hash4( &item ); else if ( sizeof(item) == 8 ) return Hash8( &item ); else if ( sizeof(item) == 12 ) return Hash12( &item ); else if ( sizeof(item) == 16 ) return Hash16( &item ); else return HashBlock( &item, sizeof(item) ); } template <> inline unsigned HashItem(const int &key ) { return HashInt( key ); } template <> inline unsigned HashItem(const unsigned &key ) { return HashInt( (int)key ); } template<> inline unsigned HashItem(const char * const &pszKey ) { return HashString( pszKey ); } template<> inline unsigned HashItem(char * const &pszKey ) { return HashString( pszKey ); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Murmur hash //----------------------------------------------------------------------------- uint32 MurmurHash2( const void * key, int len, uint32 seed ); // return murmurhash2 of a downcased string uint32 MurmurHash2LowerCase( char const *pString, uint32 nSeed ); uint64 MurmurHash64( const void * key, int len, uint32 seed ); #endif /* !GENERICHASH_H */