247 lines
11 KiB
C
247 lines
11 KiB
C
/*************************************************************************
|
|
*
|
|
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
|
*
|
|
* smartdns is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* smartdns is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _GENERIC_HASH_H
|
|
#define _GENERIC_HASH_H
|
|
|
|
#include "bitmap.h"
|
|
#include "jhash.h"
|
|
|
|
/* Fast hashing routine for ints, longs and pointers.
|
|
(C) 2002 Nadia Yvette Chambers, IBM */
|
|
#ifndef __WORDSIZE
|
|
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
|
#endif
|
|
|
|
#ifndef BITS_PER_LONG
|
|
#define BITS_PER_LONG __WORDSIZE
|
|
#endif
|
|
|
|
/*
|
|
* non-constant log of base 2 calculators
|
|
* - the arch may override these in asm/bitops.h if they can be implemented
|
|
* more efficiently than using fls() and fls64()
|
|
* - the arch is not required to handle n==0 if implementing the fallback
|
|
*/
|
|
static inline __attribute__((const)) int __ilog2_u32(uint32_t n)
|
|
{
|
|
return fls(n) - 1;
|
|
}
|
|
|
|
static inline __attribute__((const)) int __ilog2_u64(uint64_t n)
|
|
{
|
|
return fls64(n) - 1;
|
|
}
|
|
|
|
/**
|
|
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
|
* @n - parameter
|
|
*
|
|
* constant-capable log of base 2 calculation
|
|
* - this can be used to initialise global variables from constant data, hence
|
|
* the massive ternary operator construction
|
|
*
|
|
* selects the appropriately-sized optimised version depending on sizeof(n)
|
|
*/
|
|
#define ilog2(n) \
|
|
(__builtin_constant_p(n) ? ((n) < 2 ? 0 \
|
|
: (n) & (1ULL << 63) ? 63 \
|
|
: (n) & (1ULL << 62) ? 62 \
|
|
: (n) & (1ULL << 61) ? 61 \
|
|
: (n) & (1ULL << 60) ? 60 \
|
|
: (n) & (1ULL << 59) ? 59 \
|
|
: (n) & (1ULL << 58) ? 58 \
|
|
: (n) & (1ULL << 57) ? 57 \
|
|
: (n) & (1ULL << 56) ? 56 \
|
|
: (n) & (1ULL << 55) ? 55 \
|
|
: (n) & (1ULL << 54) ? 54 \
|
|
: (n) & (1ULL << 53) ? 53 \
|
|
: (n) & (1ULL << 52) ? 52 \
|
|
: (n) & (1ULL << 51) ? 51 \
|
|
: (n) & (1ULL << 50) ? 50 \
|
|
: (n) & (1ULL << 49) ? 49 \
|
|
: (n) & (1ULL << 48) ? 48 \
|
|
: (n) & (1ULL << 47) ? 47 \
|
|
: (n) & (1ULL << 46) ? 46 \
|
|
: (n) & (1ULL << 45) ? 45 \
|
|
: (n) & (1ULL << 44) ? 44 \
|
|
: (n) & (1ULL << 43) ? 43 \
|
|
: (n) & (1ULL << 42) ? 42 \
|
|
: (n) & (1ULL << 41) ? 41 \
|
|
: (n) & (1ULL << 40) ? 40 \
|
|
: (n) & (1ULL << 39) ? 39 \
|
|
: (n) & (1ULL << 38) ? 38 \
|
|
: (n) & (1ULL << 37) ? 37 \
|
|
: (n) & (1ULL << 36) ? 36 \
|
|
: (n) & (1ULL << 35) ? 35 \
|
|
: (n) & (1ULL << 34) ? 34 \
|
|
: (n) & (1ULL << 33) ? 33 \
|
|
: (n) & (1ULL << 32) ? 32 \
|
|
: (n) & (1ULL << 31) ? 31 \
|
|
: (n) & (1ULL << 30) ? 30 \
|
|
: (n) & (1ULL << 29) ? 29 \
|
|
: (n) & (1ULL << 28) ? 28 \
|
|
: (n) & (1ULL << 27) ? 27 \
|
|
: (n) & (1ULL << 26) ? 26 \
|
|
: (n) & (1ULL << 25) ? 25 \
|
|
: (n) & (1ULL << 24) ? 24 \
|
|
: (n) & (1ULL << 23) ? 23 \
|
|
: (n) & (1ULL << 22) ? 22 \
|
|
: (n) & (1ULL << 21) ? 21 \
|
|
: (n) & (1ULL << 20) ? 20 \
|
|
: (n) & (1ULL << 19) ? 19 \
|
|
: (n) & (1ULL << 18) ? 18 \
|
|
: (n) & (1ULL << 17) ? 17 \
|
|
: (n) & (1ULL << 16) ? 16 \
|
|
: (n) & (1ULL << 15) ? 15 \
|
|
: (n) & (1ULL << 14) ? 14 \
|
|
: (n) & (1ULL << 13) ? 13 \
|
|
: (n) & (1ULL << 12) ? 12 \
|
|
: (n) & (1ULL << 11) ? 11 \
|
|
: (n) & (1ULL << 10) ? 10 \
|
|
: (n) & (1ULL << 9) ? 9 \
|
|
: (n) & (1ULL << 8) ? 8 \
|
|
: (n) & (1ULL << 7) ? 7 \
|
|
: (n) & (1ULL << 6) ? 6 \
|
|
: (n) & (1ULL << 5) ? 5 \
|
|
: (n) & (1ULL << 4) ? 4 \
|
|
: (n) & (1ULL << 3) ? 3 \
|
|
: (n) & (1ULL << 2) ? 2 \
|
|
: 1) \
|
|
: (sizeof(n) <= 4) ? __ilog2_u32(n) \
|
|
: __ilog2_u64(n))
|
|
|
|
#if BITS_PER_LONG == 32
|
|
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
|
|
#define hash_long(val, bits) hash_32(val, bits)
|
|
#elif BITS_PER_LONG == 64
|
|
#define hash_long(val, bits) hash_64(val, bits)
|
|
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
|
|
#else
|
|
#error Wordsize not 32 or 64
|
|
#endif
|
|
|
|
/*
|
|
* This hash multiplies the input by a large odd number and takes the
|
|
* high bits. Since multiplication propagates changes to the most
|
|
* significant end only, it is essential that the high bits of the
|
|
* product be used for the hash value.
|
|
*
|
|
* Chuck Lever verified the effectiveness of this technique:
|
|
* http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
|
|
*
|
|
* Although a random odd number will do, it turns out that the golden
|
|
* ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
|
|
* properties. (See Knuth vol 3, section 6.4, exercise 9.)
|
|
*
|
|
* These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
|
|
* which is very slightly easier to multiply by and makes no
|
|
* difference to the hash distribution.
|
|
*/
|
|
#define GOLDEN_RATIO_32 0x61C88647
|
|
#define GOLDEN_RATIO_64 0x61C8864680B583EBull
|
|
|
|
/*
|
|
* The _generic versions exist only so lib/test_hash.c can compare
|
|
* the arch-optimized versions with the generic.
|
|
*
|
|
* Note that if you change these, any <asm/hash.h> that aren't updated
|
|
* to match need to have their HAVE_ARCH_* define values updated so the
|
|
* self-test will not false-positive.
|
|
*/
|
|
#ifndef HAVE_ARCH__HASH_32
|
|
#define __hash_32 __hash_32_generic
|
|
#endif
|
|
static inline uint32_t __hash_32_generic(uint32_t val)
|
|
{
|
|
return val * GOLDEN_RATIO_32;
|
|
}
|
|
|
|
#ifndef HAVE_ARCH_HASH_32
|
|
#define hash_32 hash_32_generic
|
|
#endif
|
|
static inline uint32_t hash_32_generic(uint32_t val, unsigned int bits)
|
|
{
|
|
/* High bits are more random, so use them. */
|
|
return __hash_32(val) >> (32 - bits);
|
|
}
|
|
|
|
#ifndef HAVE_ARCH_HASH_64
|
|
#define hash_64 hash_64_generic
|
|
#endif
|
|
static inline uint32_t hash_64(uint64_t val, unsigned int bits)
|
|
{
|
|
#if BITS_PER_LONG == 64
|
|
/* 64x64-bit multiply is efficient on all 64-bit processors */
|
|
return val * GOLDEN_RATIO_64 >> (64 - bits);
|
|
#else
|
|
/* Hash 64 bits using only 32x32-bit multiply. */
|
|
return hash_32((uint32_t)val ^ __hash_32(val >> 32), bits);
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t hash_ptr(const void *ptr, unsigned int bits)
|
|
{
|
|
return hash_long((unsigned long)ptr, bits);
|
|
}
|
|
|
|
/* This really should be called fold32_ptr; it does no hashing to speak of. */
|
|
static inline uint32_t hash32_ptr(const void *ptr)
|
|
{
|
|
unsigned long val = (unsigned long)ptr;
|
|
|
|
#if BITS_PER_LONG == 64
|
|
val ^= (val >> 32);
|
|
#endif
|
|
return (uint32_t)val;
|
|
}
|
|
|
|
static inline uint32_t hash_string_initval(const char *s, uint32_t initval)
|
|
{
|
|
uint32_t h = initval;
|
|
|
|
while (*s) {
|
|
h = h * 31 + *s;
|
|
s++;
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
static inline uint32_t hash_string(const char *s)
|
|
{
|
|
return hash_string_initval(s, 0);
|
|
}
|
|
|
|
static inline uint32_t hash_string_array(const char **a)
|
|
{
|
|
uint32_t h = 0;
|
|
|
|
const char *s;
|
|
while ((s = *a++)) {
|
|
while (*s) {
|
|
h = h * 31 + *s;
|
|
s++;
|
|
}
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
#endif /* _GENERIC_HASH_H */
|