11.9Schristos/* $NetBSD: murmurhash.c,v 1.9 2025/09/15 21:26:19 christos 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.9Schristos__KERNEL_RCSID(0, "$NetBSD: murmurhash.c,v 1.9 2025/09/15 21:26:19 christos Exp $"); 181.8Spara 191.8Spara#include <lib/libkern/libkern.h> 201.4Schristos 211.3Srmind#else 221.4Schristos 231.4Schristos#if defined(LIBC_SCCS) && !defined(lint) 241.9Schristos__RCSID("$NetBSD: murmurhash.c,v 1.9 2025/09/15 21:26:19 christos Exp $"); 251.4Schristos#endif /* LIBC_SCCS and not lint */ 261.4Schristos 271.4Schristos#include "namespace.h" 281.8Spara#include <string.h> 291.8Spara 301.3Srmind#endif 311.3Srmind 321.1Srmind#include <sys/types.h> 331.6Srmind#include <sys/param.h> 341.1Srmind#include <sys/hash.h> 351.1Srmind 361.5Srmind#if !defined(_KERNEL) && !defined(_STANDALONE) 371.3Srmind#ifdef __weak_alias 381.3Srmind__weak_alias(murmurhash2,_murmurhash2) 391.1Srmind#endif 401.5Srmind#endif 411.1Srmind 421.1Srminduint32_t 431.1Srmindmurmurhash2(const void *key, size_t len, uint32_t seed) 441.1Srmind{ 451.1Srmind /* 461.1Srmind * Note: 'm' and 'r' are mixing constants generated offline. 471.1Srmind * They're not really 'magic', they just happen to work well. 481.1Srmind * Initialize the hash to a 'random' value. 491.1Srmind */ 501.1Srmind const uint32_t m = 0x5bd1e995; 511.1Srmind const int r = 24; 521.1Srmind 531.4Schristos const uint8_t *data = key; 541.2Srmind uint32_t h = seed ^ (uint32_t)len; 551.1Srmind 561.6Srmind if (__predict_true(ALIGNED_POINTER(key, uint32_t))) { 571.6Srmind while (len >= sizeof(uint32_t)) { 581.7Sriastrad uint32_t k; 591.7Sriastrad 601.7Sriastrad ALIGNED_POINTER_LOAD(&k, data, uint32_t); 611.7Sriastrad k = htole32(k); 621.6Srmind 631.6Srmind k *= m; 641.6Srmind k ^= k >> r; 651.6Srmind k *= m; 661.6Srmind 671.6Srmind h *= m; 681.6Srmind h ^= k; 691.6Srmind 701.6Srmind data += sizeof(uint32_t); 711.6Srmind len -= sizeof(uint32_t); 721.6Srmind } 731.6Srmind } else { 741.6Srmind while (len >= sizeof(uint32_t)) { 751.6Srmind uint32_t k; 761.6Srmind 771.6Srmind k = data[0]; 781.6Srmind k |= data[1] << 8; 791.6Srmind k |= data[2] << 16; 801.9Schristos k |= (uint32_t)data[3] << 24; 811.6Srmind 821.6Srmind k *= m; 831.6Srmind k ^= k >> r; 841.6Srmind k *= m; 851.6Srmind 861.6Srmind h *= m; 871.6Srmind h ^= k; 881.6Srmind 891.6Srmind data += sizeof(uint32_t); 901.6Srmind len -= sizeof(uint32_t); 911.6Srmind } 921.1Srmind } 931.1Srmind 941.1Srmind /* Handle the last few bytes of the input array. */ 951.1Srmind switch (len) { 961.1Srmind case 3: 971.1Srmind h ^= data[2] << 16; 981.2Srmind /* FALLTHROUGH */ 991.1Srmind case 2: 1001.1Srmind h ^= data[1] << 8; 1011.2Srmind /* FALLTHROUGH */ 1021.1Srmind case 1: 1031.1Srmind h ^= data[0]; 1041.1Srmind h *= m; 1051.1Srmind } 1061.1Srmind 1071.1Srmind /* 1081.1Srmind * Do a few final mixes of the hash to ensure the last few 1091.1Srmind * bytes are well-incorporated. 1101.1Srmind */ 1111.1Srmind h ^= h >> 13; 1121.1Srmind h *= m; 1131.1Srmind h ^= h >> 15; 1141.1Srmind 1151.1Srmind return h; 1161.1Srmind} 117