/************************************************************************* * * Copyright (C) 2018-2023 Ruilin Peng (Nick) . * * 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 . */ #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 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 */