gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/third_party/murmurhash/MurmurHash3.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,334 @@
     1.4 +//-----------------------------------------------------------------------------
     1.5 +// MurmurHash3 was written by Austin Appleby, and is placed in the public
     1.6 +// domain. The author hereby disclaims copyright to this source code.
     1.7 +
     1.8 +// Note - The x86 and x64 versions do _not_ produce the same results, as the
     1.9 +// algorithms are optimized for their respective platforms. You can still
    1.10 +// compile and run any of them on any platform, but your performance with the
    1.11 +// non-native version will be less than optimal.
    1.12 +
    1.13 +#include "MurmurHash3.h"
    1.14 +
    1.15 +//-----------------------------------------------------------------------------
    1.16 +// Platform-specific functions and macros
    1.17 +
    1.18 +// Microsoft Visual Studio
    1.19 +
    1.20 +#if defined(_MSC_VER)
    1.21 +
    1.22 +#define FORCE_INLINE	__forceinline
    1.23 +
    1.24 +#include <stdlib.h>
    1.25 +
    1.26 +#define ROTL32(x,y)	_rotl(x,y)
    1.27 +#define ROTL64(x,y)	_rotl64(x,y)
    1.28 +
    1.29 +#define BIG_CONSTANT(x) (x)
    1.30 +
    1.31 +// Other compilers
    1.32 +
    1.33 +#else	// defined(_MSC_VER)
    1.34 +
    1.35 +#define	FORCE_INLINE __attribute__((always_inline))
    1.36 +
    1.37 +inline uint32_t rotl32 ( uint32_t x, int8_t r )
    1.38 +{
    1.39 +  return (x << r) | (x >> (32 - r));
    1.40 +}
    1.41 +
    1.42 +inline uint64_t rotl64 ( uint64_t x, int8_t r )
    1.43 +{
    1.44 +  return (x << r) | (x >> (64 - r));
    1.45 +}
    1.46 +
    1.47 +#define	ROTL32(x,y)	rotl32(x,y)
    1.48 +#define ROTL64(x,y)	rotl64(x,y)
    1.49 +
    1.50 +#define BIG_CONSTANT(x) (x##LLU)
    1.51 +
    1.52 +#endif // !defined(_MSC_VER)
    1.53 +
    1.54 +//-----------------------------------------------------------------------------
    1.55 +// Block read - if your platform needs to do endian-swapping or can only
    1.56 +// handle aligned reads, do the conversion here
    1.57 +
    1.58 +FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i )
    1.59 +{
    1.60 +  return p[i];
    1.61 +}
    1.62 +
    1.63 +FORCE_INLINE uint64_t getblock ( const uint64_t * p, int i )
    1.64 +{
    1.65 +  return p[i];
    1.66 +}
    1.67 +
    1.68 +//-----------------------------------------------------------------------------
    1.69 +// Finalization mix - force all bits of a hash block to avalanche
    1.70 +
    1.71 +FORCE_INLINE uint32_t fmix ( uint32_t h )
    1.72 +{
    1.73 +  h ^= h >> 16;
    1.74 +  h *= 0x85ebca6b;
    1.75 +  h ^= h >> 13;
    1.76 +  h *= 0xc2b2ae35;
    1.77 +  h ^= h >> 16;
    1.78 +
    1.79 +  return h;
    1.80 +}
    1.81 +
    1.82 +//----------
    1.83 +
    1.84 +FORCE_INLINE uint64_t fmix ( uint64_t k )
    1.85 +{
    1.86 +  k ^= k >> 33;
    1.87 +  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
    1.88 +  k ^= k >> 33;
    1.89 +  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
    1.90 +  k ^= k >> 33;
    1.91 +
    1.92 +  return k;
    1.93 +}
    1.94 +
    1.95 +//-----------------------------------------------------------------------------
    1.96 +
    1.97 +void MurmurHash3_x86_32 ( const void * key, int len,
    1.98 +                          uint32_t seed, void * out )
    1.99 +{
   1.100 +  const uint8_t * data = (const uint8_t*)key;
   1.101 +  const int nblocks = len / 4;
   1.102 +
   1.103 +  uint32_t h1 = seed;
   1.104 +
   1.105 +  const uint32_t c1 = 0xcc9e2d51;
   1.106 +  const uint32_t c2 = 0x1b873593;
   1.107 +
   1.108 +  //----------
   1.109 +  // body
   1.110 +
   1.111 +  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
   1.112 +
   1.113 +  for(int i = -nblocks; i; i++)
   1.114 +  {
   1.115 +    uint32_t k1 = getblock(blocks,i);
   1.116 +
   1.117 +    k1 *= c1;
   1.118 +    k1 = ROTL32(k1,15);
   1.119 +    k1 *= c2;
   1.120 +    
   1.121 +    h1 ^= k1;
   1.122 +    h1 = ROTL32(h1,13); 
   1.123 +    h1 = h1*5+0xe6546b64;
   1.124 +  }
   1.125 +
   1.126 +  //----------
   1.127 +  // tail
   1.128 +
   1.129 +  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
   1.130 +
   1.131 +  uint32_t k1 = 0;
   1.132 +
   1.133 +  switch(len & 3)
   1.134 +  {
   1.135 +  case 3: k1 ^= tail[2] << 16;
   1.136 +  case 2: k1 ^= tail[1] << 8;
   1.137 +  case 1: k1 ^= tail[0];
   1.138 +          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
   1.139 +  };
   1.140 +
   1.141 +  //----------
   1.142 +  // finalization
   1.143 +
   1.144 +  h1 ^= len;
   1.145 +
   1.146 +  h1 = fmix(h1);
   1.147 +
   1.148 +  *(uint32_t*)out = h1;
   1.149 +} 
   1.150 +
   1.151 +//-----------------------------------------------------------------------------
   1.152 +
   1.153 +void MurmurHash3_x86_128 ( const void * key, const int len,
   1.154 +                           uint32_t seed, void * out )
   1.155 +{
   1.156 +  const uint8_t * data = (const uint8_t*)key;
   1.157 +  const int nblocks = len / 16;
   1.158 +
   1.159 +  uint32_t h1 = seed;
   1.160 +  uint32_t h2 = seed;
   1.161 +  uint32_t h3 = seed;
   1.162 +  uint32_t h4 = seed;
   1.163 +
   1.164 +  const uint32_t c1 = 0x239b961b; 
   1.165 +  const uint32_t c2 = 0xab0e9789;
   1.166 +  const uint32_t c3 = 0x38b34ae5; 
   1.167 +  const uint32_t c4 = 0xa1e38b93;
   1.168 +
   1.169 +  //----------
   1.170 +  // body
   1.171 +
   1.172 +  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
   1.173 +
   1.174 +  for(int i = -nblocks; i; i++)
   1.175 +  {
   1.176 +    uint32_t k1 = getblock(blocks,i*4+0);
   1.177 +    uint32_t k2 = getblock(blocks,i*4+1);
   1.178 +    uint32_t k3 = getblock(blocks,i*4+2);
   1.179 +    uint32_t k4 = getblock(blocks,i*4+3);
   1.180 +
   1.181 +    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
   1.182 +
   1.183 +    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
   1.184 +
   1.185 +    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
   1.186 +
   1.187 +    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
   1.188 +
   1.189 +    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
   1.190 +
   1.191 +    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
   1.192 +
   1.193 +    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
   1.194 +
   1.195 +    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
   1.196 +  }
   1.197 +
   1.198 +  //----------
   1.199 +  // tail
   1.200 +
   1.201 +  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
   1.202 +
   1.203 +  uint32_t k1 = 0;
   1.204 +  uint32_t k2 = 0;
   1.205 +  uint32_t k3 = 0;
   1.206 +  uint32_t k4 = 0;
   1.207 +
   1.208 +  switch(len & 15)
   1.209 +  {
   1.210 +  case 15: k4 ^= tail[14] << 16;
   1.211 +  case 14: k4 ^= tail[13] << 8;
   1.212 +  case 13: k4 ^= tail[12] << 0;
   1.213 +           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
   1.214 +
   1.215 +  case 12: k3 ^= tail[11] << 24;
   1.216 +  case 11: k3 ^= tail[10] << 16;
   1.217 +  case 10: k3 ^= tail[ 9] << 8;
   1.218 +  case  9: k3 ^= tail[ 8] << 0;
   1.219 +           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
   1.220 +
   1.221 +  case  8: k2 ^= tail[ 7] << 24;
   1.222 +  case  7: k2 ^= tail[ 6] << 16;
   1.223 +  case  6: k2 ^= tail[ 5] << 8;
   1.224 +  case  5: k2 ^= tail[ 4] << 0;
   1.225 +           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
   1.226 +
   1.227 +  case  4: k1 ^= tail[ 3] << 24;
   1.228 +  case  3: k1 ^= tail[ 2] << 16;
   1.229 +  case  2: k1 ^= tail[ 1] << 8;
   1.230 +  case  1: k1 ^= tail[ 0] << 0;
   1.231 +           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
   1.232 +  };
   1.233 +
   1.234 +  //----------
   1.235 +  // finalization
   1.236 +
   1.237 +  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
   1.238 +
   1.239 +  h1 += h2; h1 += h3; h1 += h4;
   1.240 +  h2 += h1; h3 += h1; h4 += h1;
   1.241 +
   1.242 +  h1 = fmix(h1);
   1.243 +  h2 = fmix(h2);
   1.244 +  h3 = fmix(h3);
   1.245 +  h4 = fmix(h4);
   1.246 +
   1.247 +  h1 += h2; h1 += h3; h1 += h4;
   1.248 +  h2 += h1; h3 += h1; h4 += h1;
   1.249 +
   1.250 +  ((uint32_t*)out)[0] = h1;
   1.251 +  ((uint32_t*)out)[1] = h2;
   1.252 +  ((uint32_t*)out)[2] = h3;
   1.253 +  ((uint32_t*)out)[3] = h4;
   1.254 +}
   1.255 +
   1.256 +//-----------------------------------------------------------------------------
   1.257 +
   1.258 +void MurmurHash3_x64_128 ( const void * key, const int len,
   1.259 +                           const uint32_t seed, void * out )
   1.260 +{
   1.261 +  const uint8_t * data = (const uint8_t*)key;
   1.262 +  const int nblocks = len / 16;
   1.263 +
   1.264 +  uint64_t h1 = seed;
   1.265 +  uint64_t h2 = seed;
   1.266 +
   1.267 +  const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
   1.268 +  const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
   1.269 +
   1.270 +  //----------
   1.271 +  // body
   1.272 +
   1.273 +  const uint64_t * blocks = (const uint64_t *)(data);
   1.274 +
   1.275 +  for(int i = 0; i < nblocks; i++)
   1.276 +  {
   1.277 +    uint64_t k1 = getblock(blocks,i*2+0);
   1.278 +    uint64_t k2 = getblock(blocks,i*2+1);
   1.279 +
   1.280 +    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
   1.281 +
   1.282 +    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
   1.283 +
   1.284 +    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
   1.285 +
   1.286 +    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
   1.287 +  }
   1.288 +
   1.289 +  //----------
   1.290 +  // tail
   1.291 +
   1.292 +  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
   1.293 +
   1.294 +  uint64_t k1 = 0;
   1.295 +  uint64_t k2 = 0;
   1.296 +
   1.297 +  switch(len & 15)
   1.298 +  {
   1.299 +  case 15: k2 ^= uint64_t(tail[14]) << 48;
   1.300 +  case 14: k2 ^= uint64_t(tail[13]) << 40;
   1.301 +  case 13: k2 ^= uint64_t(tail[12]) << 32;
   1.302 +  case 12: k2 ^= uint64_t(tail[11]) << 24;
   1.303 +  case 11: k2 ^= uint64_t(tail[10]) << 16;
   1.304 +  case 10: k2 ^= uint64_t(tail[ 9]) << 8;
   1.305 +  case  9: k2 ^= uint64_t(tail[ 8]) << 0;
   1.306 +           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
   1.307 +
   1.308 +  case  8: k1 ^= uint64_t(tail[ 7]) << 56;
   1.309 +  case  7: k1 ^= uint64_t(tail[ 6]) << 48;
   1.310 +  case  6: k1 ^= uint64_t(tail[ 5]) << 40;
   1.311 +  case  5: k1 ^= uint64_t(tail[ 4]) << 32;
   1.312 +  case  4: k1 ^= uint64_t(tail[ 3]) << 24;
   1.313 +  case  3: k1 ^= uint64_t(tail[ 2]) << 16;
   1.314 +  case  2: k1 ^= uint64_t(tail[ 1]) << 8;
   1.315 +  case  1: k1 ^= uint64_t(tail[ 0]) << 0;
   1.316 +           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
   1.317 +  };
   1.318 +
   1.319 +  //----------
   1.320 +  // finalization
   1.321 +
   1.322 +  h1 ^= len; h2 ^= len;
   1.323 +
   1.324 +  h1 += h2;
   1.325 +  h2 += h1;
   1.326 +
   1.327 +  h1 = fmix(h1);
   1.328 +  h2 = fmix(h2);
   1.329 +
   1.330 +  h1 += h2;
   1.331 +  h2 += h1;
   1.332 +
   1.333 +  ((uint64_t*)out)[0] = h1;
   1.334 +  ((uint64_t*)out)[1] = h2;
   1.335 +}
   1.336 +
   1.337 +//-----------------------------------------------------------------------------

mercurial