hash.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) 2010-2017 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Upstream site with license notes :
  18. * http://git.sceen.net/rbraun/librbraun.git/
  19. *
  20. *
  21. * Hash functions for integers and strings.
  22. *
  23. * Integer hashing follows Thomas Wang's paper about his 32/64-bits mix
  24. * functions :
  25. * - https://gist.github.com/badboy/6267743
  26. *
  27. * String hashing uses a variant of the djb2 algorithm with k=31, as in
  28. * the implementation of the hashCode() method of the Java String class :
  29. * - http://www.javamex.com/tutorials/collections/hash_function_technical.shtml
  30. *
  31. * Note that this algorithm isn't suitable to obtain usable 64-bits hashes
  32. * and is expected to only serve as an array index producer.
  33. *
  34. * These functions all have a bits parameter that indicates the number of
  35. * relevant bits the caller is interested in. When returning a hash, its
  36. * value must be truncated so that it can fit in the requested bit size.
  37. * It can be used by the implementation to select high or low bits, depending
  38. * on their relative randomness. To get complete, unmasked hashes, use the
  39. * HASH_ALLBITS macro.
  40. */
  41. #ifndef KERN_HASH_H
  42. #define KERN_HASH_H
  43. #include <assert.h>
  44. #include <stdbool.h>
  45. #include <stdint.h>
  46. #ifdef __LP64__
  47. #define HASH_ALLBITS 64
  48. #define hash_long(n, bits) hash_int64(n, bits)
  49. #else /* __LP64__ */
  50. static_assert(sizeof(long) == 4, "unsupported data model");
  51. #define HASH_ALLBITS 32
  52. #define hash_long(n, bits) hash_int32(n, bits)
  53. #endif
  54. static inline bool
  55. hash_bits_valid(unsigned int bits)
  56. {
  57. return (bits != 0) && (bits <= HASH_ALLBITS);
  58. }
  59. static inline uint32_t
  60. hash_int32(uint32_t n, unsigned int bits)
  61. {
  62. uint32_t hash;
  63. assert(hash_bits_valid(bits));
  64. hash = n;
  65. hash = ~hash + (hash << 15);
  66. hash ^= (hash >> 12);
  67. hash += (hash << 2);
  68. hash ^= (hash >> 4);
  69. hash += (hash << 3) + (hash << 11);
  70. hash ^= (hash >> 16);
  71. return hash >> (32 - bits);
  72. }
  73. static inline uint64_t
  74. hash_int64(uint64_t n, unsigned int bits)
  75. {
  76. uint64_t hash;
  77. assert(hash_bits_valid(bits));
  78. hash = n;
  79. hash = ~hash + (hash << 21);
  80. hash ^= (hash >> 24);
  81. hash += (hash << 3) + (hash << 8);
  82. hash ^= (hash >> 14);
  83. hash += (hash << 2) + (hash << 4);
  84. hash ^= (hash >> 28);
  85. hash += (hash << 31);
  86. return hash >> (64 - bits);
  87. }
  88. static inline uintptr_t
  89. hash_ptr(const void *ptr, unsigned int bits)
  90. {
  91. if (sizeof(uintptr_t) == 8) {
  92. return hash_int64((uintptr_t)ptr, bits);
  93. } else {
  94. return hash_int32((uintptr_t)ptr, bits);
  95. }
  96. }
  97. static inline unsigned long
  98. hash_str(const char *str, unsigned int bits)
  99. {
  100. unsigned long hash, mask;
  101. char c;
  102. assert(hash_bits_valid(bits));
  103. for (hash = 0; /* no condition */; str++) {
  104. c = *str;
  105. if (c == '\0') {
  106. break;
  107. }
  108. hash = ((hash << 5) - hash) + c;
  109. }
  110. /*
  111. * This mask construction avoids the undefined behavior that would
  112. * result from directly shifting by the number of bits, if that number
  113. * is equal to the width of the hash.
  114. */
  115. mask = (~0UL >> (HASH_ALLBITS - bits));
  116. return hash & mask;
  117. }
  118. #endif /* KERN_HASH_H */