fixedhash.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #if !defined(FIXEDHASH_T__HEADER) && !defined(FIXEDHASH_T__SOURCE)
  2. #include "pocketpy/common/chunkedvector.h"
  3. #include "pocketpy/config.h"
  4. #include <stdint.h>
  5. #define FIXEDHASH_T__HEADER
  6. #define FIXEDHASH_T__SOURCE
  7. /* Input */
  8. #define K int
  9. #define V float
  10. #define NAME c11_fixedhash_d2f
  11. #endif
  12. /* Optional Input */
  13. #ifndef hash
  14. #define hash(a) ((uint64_t)(a))
  15. #endif
  16. #ifndef equal
  17. #define equal(a, b) ((a) == (b))
  18. #endif
  19. /* Temporary macros */
  20. #define CONCAT(A, B) CONCAT_(A, B)
  21. #define CONCAT_(A, B) A##B
  22. #define KV CONCAT(NAME, _KV)
  23. #define METHOD(name) CONCAT(NAME, CONCAT(__, name))
  24. #ifdef FIXEDHASH_T__HEADER
  25. /* Declaration */
  26. typedef struct {
  27. uint64_t hash;
  28. K key;
  29. V val;
  30. } KV;
  31. typedef struct {
  32. int length;
  33. uint16_t indices[0x10000];
  34. c11_chunkedvector /*T=FixedHashEntry*/ entries;
  35. } NAME;
  36. void METHOD(ctor)(NAME* self);
  37. void METHOD(dtor)(NAME* self);
  38. NAME* METHOD(new)();
  39. void METHOD(delete)(NAME* self);
  40. void METHOD(set)(NAME* self, K key, V* value);
  41. V* METHOD(try_get)(NAME* self, K key);
  42. bool METHOD(contains)(NAME* self, K key);
  43. #endif
  44. #ifdef FIXEDHASH_T__SOURCE
  45. /* Implementation */
  46. void METHOD(ctor)(NAME* self) {
  47. self->length = 0;
  48. memset(self->indices, 0xFF, sizeof(self->indices));
  49. c11_chunkedvector__ctor(&self->entries, sizeof(KV), 0);
  50. }
  51. void METHOD(dtor)(NAME* self) { c11_chunkedvector__dtor(&self->entries); }
  52. NAME* METHOD(new)() {
  53. NAME* self = PK_MALLOC(sizeof(NAME));
  54. METHOD(ctor)(self);
  55. return self;
  56. }
  57. void METHOD(delete)(NAME* self) {
  58. METHOD(dtor)(self);
  59. PK_FREE(self);
  60. }
  61. void METHOD(set)(NAME* self, K key, V* value) {
  62. uint64_t hash_value = hash(key);
  63. int index = (uint16_t)(hash_value & 0xFFFF);
  64. while(self->indices[index] != 0xFFFF) {
  65. KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
  66. if(equal(entry->key, key)) {
  67. entry->val = *value;
  68. return;
  69. }
  70. index = ((5 * index) + 1) & 0xFFFF;
  71. }
  72. if(self->length >= 65000) abort();
  73. KV* kv = c11_chunkedvector__emplace(&self->entries);
  74. kv->hash = hash_value;
  75. kv->key = key;
  76. kv->val = *value;
  77. self->indices[index] = self->entries.length - 1;
  78. self->length++;
  79. }
  80. V* METHOD(try_get)(NAME* self, K key) {
  81. uint64_t hash_value = hash(key);
  82. int index = (uint16_t)(hash_value & 0xFFFF);
  83. while(self->indices[index] != 0xFFFF) {
  84. KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
  85. if(equal(entry->key, key)) return &entry->val;
  86. index = ((5 * index) + 1) & 0xFFFF;
  87. }
  88. return NULL;
  89. }
  90. bool METHOD(contains)(NAME* self, K key) {
  91. V* value = METHOD(try_get)(self, key);
  92. return value != NULL;
  93. }
  94. #endif
  95. /* Undefine all macros */
  96. #undef KV
  97. #undef METHOD
  98. #undef CONCAT
  99. #undef CONCAT_
  100. #undef K
  101. #undef V
  102. #undef NAME
  103. #undef less
  104. #undef partial_less
  105. #undef equal
  106. #undef hash