libosmocore 1.9.0.196-9975
Osmocom core library
hash.h
Go to the documentation of this file.
1#pragma once
2#include <osmocom/core/log2.h>
3/* Fast hashing routine for ints, longs and pointers.
4 (C) 2002 Nadia Yvette Chambers, IBM */
5
6#include <limits.h>
7#if ULONG_MAX == 4294967295
8#define BITS_PER_LONG 32
9#else
10#define BITS_PER_LONG 64
11#endif
12
13/*
14 * The "GOLDEN_RATIO_PRIME" is used in ifs/btrfs/brtfs_inode.h and
15 * fs/inode.c. It's not actually prime any more (the previous primes
16 * were actively bad for hashing), but the name remains.
17 */
18#if BITS_PER_LONG == 32
19#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
20#define hash_long(val, bits) hash_32(val, bits)
21#elif BITS_PER_LONG == 64
22#define hash_long(val, bits) hash_64(val, bits)
23#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
24#else
25#error Wordsize not 32 or 64
26#endif
27
28/*
29 * This hash multiplies the input by a large odd number and takes the
30 * high bits. Since multiplication propagates changes to the most
31 * significant end only, it is essential that the high bits of the
32 * product be used for the hash value.
33 *
34 * Chuck Lever verified the effectiveness of this technique:
35 * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
36 *
37 * Although a random odd number will do, it turns out that the golden
38 * ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
39 * properties. (See Knuth vol 3, section 6.4, exercise 9.)
40 *
41 * These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
42 * which is very slightly easier to multiply by and makes no
43 * difference to the hash distribution.
44 */
45#define GOLDEN_RATIO_32 0x61C88647
46#define GOLDEN_RATIO_64 0x61C8864680B583EBull
47
48/*
49 * The _generic versions exist only so lib/test_hash.c can compare
50 * the arch-optimized versions with the generic.
51 *
52 * Note that if you change these, any <asm/hash.h> that aren't updated
53 * to match need to have their HAVE_ARCH_* define values updated so the
54 * self-test will not false-positive.
55 */
56#ifndef HAVE_ARCH__HASH_32
57#define __hash_32 __hash_32_generic
58#endif
59static inline uint32_t __hash_32_generic(uint32_t val)
60{
61 return val * GOLDEN_RATIO_32;
62}
63
64#ifndef HAVE_ARCH_HASH_32
65#define hash_32 hash_32_generic
66#endif
67static inline uint32_t hash_32_generic(uint32_t val, unsigned int bits)
68{
69 /* High bits are more random, so use them. */
70 return __hash_32(val) >> (32 - bits);
71}
72
73#ifndef HAVE_ARCH_HASH_64
74#define hash_64 hash_64_generic
75#endif
76static __always_inline uint32_t hash_64_generic(uint64_t val, unsigned int bits)
77{
78#if BITS_PER_LONG == 64
79 /* 64x64-bit multiply is efficient on all 64-bit processors */
80 return val * GOLDEN_RATIO_64 >> (64 - bits);
81#else
82 /* Hash 64 bits using only 32x32-bit multiply. */
83 return hash_32((uint32_t)val ^ __hash_32(val >> 32), bits);
84#endif
85}
86
87static inline uint32_t hash_ptr(const void *ptr, unsigned int bits)
88{
89 return hash_long((unsigned long)ptr, bits);
90}
91
92/* This really should be called fold32_ptr; it does no hashing to speak of. */
93static inline uint32_t hash32_ptr(const void *ptr)
94{
95 unsigned long val = (unsigned long)ptr;
96
97#if BITS_PER_LONG == 64
98 val ^= (val >> 32);
99#endif
100 return (uint32_t)val;
101}
#define __always_inline
Definition: conv_acc_neon_impl.h:26
#define hash_32
Definition: hash.h:65
#define hash_long(val, bits)
Definition: hash.h:22
static uint32_t __hash_32_generic(uint32_t val)
Definition: hash.h:59
static uint32_t hash_32_generic(uint32_t val, unsigned int bits)
Definition: hash.h:67
static uint32_t hash32_ptr(const void *ptr)
Definition: hash.h:93
#define GOLDEN_RATIO_32
Definition: hash.h:45
#define __hash_32
Definition: hash.h:57
#define GOLDEN_RATIO_64
Definition: hash.h:46
static uint32_t hash_ptr(const void *ptr, unsigned int bits)
Definition: hash.h:87
static __always_inline uint32_t hash_64_generic(uint64_t val, unsigned int bits)
Definition: hash.h:76