Derive-C
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1#pragma once
2
3#if !defined(__SSE2__)
4 #error "swiss table requires SSE2"
5#endif
6
7#include <stdint.h>
8#include <emmintrin.h>
9
10#include <derive-c/core/math.h>
12
13#define DC_SWISS_INITIAL_CAPACITY 256
14
15// JUSTIFY: Using 16 byte type, rather than 32 byte
16// - Arbitrarily chose to stick with 16 byte.
17// TODO(oliverkillane): Experiment with 32 byte groups
18typedef __m128i _dc_swiss_ctrl_group;
19typedef uint8_t _dc_swiss_ctrl;
20
21// Indexes of groups, and offset within a group
24
25// When searching a group, we get a bitmask back
27
28#define _DC_SWISS_SIMD_PROBE_SIZE sizeof(_dc_swiss_ctrl_group)
29
30// JUSTIFY: Why power of 2?
31// - Has can be done with bitmasking, faster than modulus.
33
34// clang-format off
35#define DC_SWISS_VAL_SENTINEL 0b11111111
36#define DC_SWISS_VAL_DELETED 0b11111110
37#define DC_SWISS_VAL_EMPTY 0b10000000
38// clang-format on
39
41 switch (ctrl) {
45 return false;
46 default:
47 return true;
48 }
49}
50
52 // Taking the top 7 bits for `H2`
53 return (uint8_t)(hash >> (sizeof(size_t) * 8 - 7));
54}
55
56DC_INTERNAL static size_t dc_swiss_capacity(size_t for_items) {
57 if (for_items < _DC_SWISS_SIMD_PROBE_SIZE) {
59 }
60 return dc_math_next_power_of_2(for_items);
61}
62
63DC_INTERNAL static void _dc_swiss_ctrl_set_at(_dc_swiss_ctrl* self, size_t capacity, size_t index,
64 _dc_swiss_ctrl val) {
65 // JUSTIFY: Setting index past capacity
66 // ctrl[..capacity) = (empty or value)
67 // ctrl[capacity] = SENTINEL
68 // ctrl[capacity+1+i] = ctrl[i] for (_DC_SWISS_PROBE_SIZE - 1)
69 self[index] = val;
70 if (index < (_DC_SWISS_SIMD_PROBE_SIZE - 1)) {
71 self[capacity + 1 + index] = val;
72 }
73}
74
80
82_dc_swiss_heuristic_should_extend(size_t tombstones, size_t count, size_t capacity) {
83 DC_ASSUME(capacity > 0);
84
85 const size_t max_load = capacity - (capacity / 8);
86
87 if (count + tombstones >= max_load) {
89 }
90
91 if (tombstones > (count / 2)) {
93 }
94
96}
97
98#define _DC_SWISS_NO_INDEX ((size_t)-1)
100
101// JUSTIFY: Not just size_t
102// - We need to store the NONE index (as the max index)
103// - We have a buffer at the end of the table
104static size_t const _dc_swiss_index_capacity = SIZE_MAX - (1 + _DC_SWISS_SIMD_PROBE_SIZE);
105
107 // Deal with unaligned loads - can be optimised away in release
108 return _mm_loadu_si128((const __m128i_u*)group_ptr);
109}
110
112 uint8_t value) {
113 __m128i cmp = _mm_cmpeq_epi8(group, _mm_set1_epi8((char)value));
114 return (_dc_swiss_ctrl_group_bitmask)_mm_movemask_epi8(cmp);
115}
116
122
127
128// After getting the matches in a group, iterate on the matches
129#define _DC_SWISS_BITMASK_FOR_EACH(mask, idx_var) \
130 for (_dc_swiss_ctrl_group_bitmask _m = (mask); _m != 0; \
131 _m = _dc_swiss_ctrl_group_bitmask_clear_lowest(_m)) \
132 for (_dc_swiss_ctrl_group_offset idx_var = _dc_swiss_ctrl_group_bitmask_lowest(_m), \
133 _once = 1; \
134 _once; _once = 0)
135
136DC_INTERNAL static size_t _dc_swiss_group_index_to_slot(size_t group_start,
138 size_t capacity) {
139 size_t pos = group_start + idx;
140 if (pos < capacity) {
141 return pos;
142 }
143 if (pos == capacity) {
144 // On the sentinel value
145 return _DC_SWISS_NO_INDEX;
146 }
147
148 // After the sentinel
149 return pos - capacity - 1;
150}
#define DC_PURE
Definition attributes.h:5
__m128i _dc_swiss_ctrl_group
Definition utils.h:18
#define DC_SWISS_VAL_EMPTY
Definition utils.h:37
_dc_swiss_rehash_action
Definition utils.h:75
@ DC_SWISS_DO_NOTHING
Definition utils.h:78
@ DC_SWISS_DOUBLE_CAPACITY
Definition utils.h:76
@ DC_SWISS_CLEANUP_TOMBSONES
Definition utils.h:77
uint16_t _dc_swiss_ctrl_group_offset
Definition utils.h:23
#define _DC_SWISS_SIMD_PROBE_SIZE
Definition utils.h:28
size_t _dc_swiss_ctrl_group_index
Definition utils.h:22
static DC_INTERNAL size_t _dc_swiss_group_index_to_slot(size_t group_start, _dc_swiss_ctrl_group_offset idx, size_t capacity)
Definition utils.h:136
static size_t const _dc_swiss_index_capacity
Definition utils.h:104
static DC_INTERNAL _dc_swiss_ctrl_group_offset _dc_swiss_ctrl_group_bitmask_lowest(_dc_swiss_ctrl_group_bitmask mask)
Definition utils.h:118
#define DC_SWISS_VAL_DELETED
Definition utils.h:36
static DC_INTERNAL size_t dc_swiss_capacity(size_t for_items)
Definition utils.h:56
DC_INTERNAL static DC_PURE bool _dc_swiss_is_present(_dc_swiss_ctrl ctrl)
Definition utils.h:40
static DC_INTERNAL void _dc_swiss_ctrl_set_at(_dc_swiss_ctrl *self, size_t capacity, size_t index, _dc_swiss_ctrl val)
Definition utils.h:63
static DC_INTERNAL _dc_swiss_ctrl_group_bitmask _dc_swiss_ctrl_group_bitmask_clear_lowest(_dc_swiss_ctrl_group_bitmask mask)
Definition utils.h:124
uint16_t _dc_swiss_ctrl_group_bitmask
Definition utils.h:26
static DC_INTERNAL _dc_swiss_rehash_action _dc_swiss_heuristic_should_extend(size_t tombstones, size_t count, size_t capacity)
Definition utils.h:82
static DC_INTERNAL _dc_swiss_ctrl_group _dc_swiss_group_load(const _dc_swiss_ctrl *group_ptr)
Definition utils.h:106
static DC_INTERNAL _dc_swiss_ctrl_group_bitmask _dc_swiss_group_match(_dc_swiss_ctrl_group group, uint8_t value)
Definition utils.h:111
uint8_t _dc_swiss_ctrl
Definition utils.h:19
size_t _dc_swiss_optional_index
Definition utils.h:99
static DC_INTERNAL _dc_swiss_ctrl _dc_swiss_ctrl_from_hash(size_t hash)
Definition utils.h:51
#define DC_SWISS_VAL_SENTINEL
Definition utils.h:35
#define _DC_SWISS_NO_INDEX
Definition utils.h:98
#define DC_MATH_IS_POWER_OF_2(x)
Definition math.h:14
static DC_INLINE DC_CONST size_t dc_math_next_power_of_2(size_t x)
Definition math.h:46
#define DC_INTERNAL
Definition namespace.h:30
#define DC_STATIC_ASSERT
Definition panic.h:22
#define DC_ASSUME(expr,...)
Definition panic.h:57