murmurhash.c revision 1.5
11.5Srmind/* $NetBSD: murmurhash.c,v 1.5 2013/06/30 12:20:32 rmind Exp $ */ 21.1Srmind 31.1Srmind/* 41.1Srmind * MurmurHash2 -- from the original code: 51.1Srmind * 61.1Srmind * "MurmurHash2 was written by Austin Appleby, and is placed in the public 71.1Srmind * domain. The author hereby disclaims copyright to this source code." 81.1Srmind * 91.1Srmind * References: 101.1Srmind * http://code.google.com/p/smhasher/ 111.1Srmind * https://sites.google.com/site/murmurhash/ 121.1Srmind */ 131.1Srmind 141.1Srmind#include <sys/cdefs.h> 151.3Srmind 161.3Srmind#if defined(_KERNEL) || defined(_STANDALONE) 171.5Srmind__KERNEL_RCSID(0, "$NetBSD: murmurhash.c,v 1.5 2013/06/30 12:20:32 rmind Exp $"); 181.4Schristos 191.3Srmind#else 201.4Schristos 211.4Schristos#if defined(LIBC_SCCS) && !defined(lint) 221.5Srmind__RCSID("$NetBSD: murmurhash.c,v 1.5 2013/06/30 12:20:32 rmind Exp $"); 231.4Schristos#endif /* LIBC_SCCS and not lint */ 241.4Schristos 251.4Schristos#include "namespace.h" 261.3Srmind#endif 271.3Srmind 281.1Srmind#include <sys/types.h> 291.1Srmind#include <sys/hash.h> 301.1Srmind 311.5Srmind#if !defined(_KERNEL) && !defined(_STANDALONE) 321.3Srmind#ifdef __weak_alias 331.3Srmind__weak_alias(murmurhash2,_murmurhash2) 341.1Srmind#endif 351.5Srmind#endif 361.1Srmind 371.1Srminduint32_t 381.1Srmindmurmurhash2(const void *key, size_t len, uint32_t seed) 391.1Srmind{ 401.1Srmind /* 411.1Srmind * Note: 'm' and 'r' are mixing constants generated offline. 421.1Srmind * They're not really 'magic', they just happen to work well. 431.1Srmind * Initialize the hash to a 'random' value. 441.1Srmind */ 451.1Srmind const uint32_t m = 0x5bd1e995; 461.1Srmind const int r = 24; 471.1Srmind 481.4Schristos const uint8_t *data = key; 491.2Srmind uint32_t h = seed ^ (uint32_t)len; 501.1Srmind 511.1Srmind while (len >= sizeof(uint32_t)) { 521.1Srmind uint32_t k; 531.1Srmind 541.1Srmind k = data[0]; 551.1Srmind k |= data[1] << 8; 561.1Srmind k |= data[2] << 16; 571.1Srmind k |= data[3] << 24; 581.1Srmind 591.1Srmind k *= m; 601.1Srmind k ^= k >> r; 611.1Srmind k *= m; 621.1Srmind 631.1Srmind h *= m; 641.1Srmind h ^= k; 651.1Srmind 661.1Srmind data += sizeof(uint32_t); 671.1Srmind len -= sizeof(uint32_t); 681.1Srmind } 691.1Srmind 701.1Srmind /* Handle the last few bytes of the input array. */ 711.1Srmind switch (len) { 721.1Srmind case 3: 731.1Srmind h ^= data[2] << 16; 741.2Srmind /* FALLTHROUGH */ 751.1Srmind case 2: 761.1Srmind h ^= data[1] << 8; 771.2Srmind /* FALLTHROUGH */ 781.1Srmind case 1: 791.1Srmind h ^= data[0]; 801.1Srmind h *= m; 811.1Srmind } 821.1Srmind 831.1Srmind /* 841.1Srmind * Do a few final mixes of the hash to ensure the last few 851.1Srmind * bytes are well-incorporated. 861.1Srmind */ 871.1Srmind h ^= h >> 13; 881.1Srmind h *= m; 891.1Srmind h ^= h >> 15; 901.1Srmind 911.1Srmind return h; 921.1Srmind} 93