Our hash function is MurmurHash2, 64 bit version. * It was modified for Redis in order to provide the same result in * big and little endian archs (endian neutral). */
| 396 | * It was modified for Redis in order to provide the same result in |
| 397 | * big and little endian archs (endian neutral). */ |
| 398 | uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) { |
| 399 | const uint64_t m = 0xc6a4a7935bd1e995; |
| 400 | const int r = 47; |
| 401 | uint64_t h = seed ^ (len * m); |
| 402 | const uint8_t *data = (const uint8_t *)key; |
| 403 | const uint8_t *end = data + (len-(len&7)); |
| 404 | |
| 405 | while(data != end) { |
| 406 | uint64_t k; |
| 407 | |
| 408 | #if (BYTE_ORDER == LITTLE_ENDIAN) |
| 409 | #ifdef USE_ALIGNED_ACCESS |
| 410 | memcpy(&k,data,sizeof(uint64_t)); |
| 411 | #else |
| 412 | k = *((uint64_t*)data); |
| 413 | #endif |
| 414 | #else |
| 415 | k = (uint64_t) data[0]; |
| 416 | k |= (uint64_t) data[1] << 8; |
| 417 | k |= (uint64_t) data[2] << 16; |
| 418 | k |= (uint64_t) data[3] << 24; |
| 419 | k |= (uint64_t) data[4] << 32; |
| 420 | k |= (uint64_t) data[5] << 40; |
| 421 | k |= (uint64_t) data[6] << 48; |
| 422 | k |= (uint64_t) data[7] << 56; |
| 423 | #endif |
| 424 | |
| 425 | k *= m; |
| 426 | k ^= k >> r; |
| 427 | k *= m; |
| 428 | h ^= k; |
| 429 | h *= m; |
| 430 | data += 8; |
| 431 | } |
| 432 | |
| 433 | switch(len & 7) { |
| 434 | case 7: h ^= (uint64_t)data[6] << 48; /* fall-thru */ |
| 435 | case 6: h ^= (uint64_t)data[5] << 40; /* fall-thru */ |
| 436 | case 5: h ^= (uint64_t)data[4] << 32; /* fall-thru */ |
| 437 | case 4: h ^= (uint64_t)data[3] << 24; /* fall-thru */ |
| 438 | case 3: h ^= (uint64_t)data[2] << 16; /* fall-thru */ |
| 439 | case 2: h ^= (uint64_t)data[1] << 8; /* fall-thru */ |
| 440 | case 1: h ^= (uint64_t)data[0]; |
| 441 | h *= m; /* fall-thru */ |
| 442 | }; |
| 443 | |
| 444 | h ^= h >> r; |
| 445 | h *= m; |
| 446 | h ^= h >> r; |
| 447 | return h; |
| 448 | } |
| 449 | |
| 450 | /* Given a string element to add to the HyperLogLog, returns the length |
| 451 | * of the pattern 000..1 of the element hash. As a side effect 'regp' is |