1 | /*
|
---|
2 | * C macro implementation of treaps.
|
---|
3 | *
|
---|
4 | * Usage:
|
---|
5 | * #include <stdint.h>
|
---|
6 | * #include "trp.h"
|
---|
7 | * trp_gen(...)
|
---|
8 | *
|
---|
9 | * Licensed under a two-clause BSD-style license.
|
---|
10 | * See LICENSE for details.
|
---|
11 | */
|
---|
12 |
|
---|
13 | #ifndef TRP_H_
|
---|
14 | #define TRP_H_
|
---|
15 |
|
---|
16 | #define MAYBE_UNUSED __attribute__((__unused__))
|
---|
17 |
|
---|
18 | /* Node structure. */
|
---|
19 | struct trp_node {
|
---|
20 | uint32_t trpn_left;
|
---|
21 | uint32_t trpn_right;
|
---|
22 | };
|
---|
23 |
|
---|
24 | /* Root structure. */
|
---|
25 | struct trp_root {
|
---|
26 | uint32_t trp_root;
|
---|
27 | };
|
---|
28 |
|
---|
29 | /* Pointer/Offset conversion. */
|
---|
30 | #define trpn_pointer(a_base, a_offset) (a_base##_pointer(a_offset))
|
---|
31 | #define trpn_offset(a_base, a_pointer) (a_base##_offset(a_pointer))
|
---|
32 | #define trpn_modify(a_base, a_offset) \
|
---|
33 | do { \
|
---|
34 | if ((a_offset) < a_base##_pool.committed) { \
|
---|
35 | uint32_t old_offset = (a_offset);\
|
---|
36 | (a_offset) = a_base##_alloc(1); \
|
---|
37 | *trpn_pointer(a_base, a_offset) = \
|
---|
38 | *trpn_pointer(a_base, old_offset); \
|
---|
39 | } \
|
---|
40 | } while (0)
|
---|
41 |
|
---|
42 | /* Left accessors. */
|
---|
43 | #define trp_left_get(a_base, a_field, a_node) \
|
---|
44 | (trpn_pointer(a_base, a_node)->a_field.trpn_left)
|
---|
45 | #define trp_left_set(a_base, a_field, a_node, a_left) \
|
---|
46 | do { \
|
---|
47 | trpn_modify(a_base, a_node); \
|
---|
48 | trp_left_get(a_base, a_field, a_node) = (a_left); \
|
---|
49 | } while (0)
|
---|
50 |
|
---|
51 | /* Right accessors. */
|
---|
52 | #define trp_right_get(a_base, a_field, a_node) \
|
---|
53 | (trpn_pointer(a_base, a_node)->a_field.trpn_right)
|
---|
54 | #define trp_right_set(a_base, a_field, a_node, a_right) \
|
---|
55 | do { \
|
---|
56 | trpn_modify(a_base, a_node); \
|
---|
57 | trp_right_get(a_base, a_field, a_node) = (a_right); \
|
---|
58 | } while (0)
|
---|
59 |
|
---|
60 | /*
|
---|
61 | * Fibonacci hash function.
|
---|
62 | * The multiplier is the nearest prime to (2^32 times (â5 - 1)/2).
|
---|
63 | * See Knuth §6.4: volume 3, 3rd ed, p518.
|
---|
64 | */
|
---|
65 | #define trpn_hash(a_node) (uint32_t) (2654435761u * (a_node))
|
---|
66 |
|
---|
67 | /* Priority accessors. */
|
---|
68 | #define trp_prio_get(a_node) trpn_hash(a_node)
|
---|
69 |
|
---|
70 | /* Node initializer. */
|
---|
71 | #define trp_node_new(a_base, a_field, a_node) \
|
---|
72 | do { \
|
---|
73 | trp_left_set(a_base, a_field, (a_node), ~0); \
|
---|
74 | trp_right_set(a_base, a_field, (a_node), ~0); \
|
---|
75 | } while (0)
|
---|
76 |
|
---|
77 | /* Internal utility macros. */
|
---|
78 | #define trpn_first(a_base, a_field, a_root, r_node) \
|
---|
79 | do { \
|
---|
80 | (r_node) = (a_root); \
|
---|
81 | if ((r_node) == ~0) \
|
---|
82 | return NULL; \
|
---|
83 | while (~trp_left_get(a_base, a_field, (r_node))) \
|
---|
84 | (r_node) = trp_left_get(a_base, a_field, (r_node)); \
|
---|
85 | } while (0)
|
---|
86 |
|
---|
87 | #define trpn_rotate_left(a_base, a_field, a_node, r_node) \
|
---|
88 | do { \
|
---|
89 | (r_node) = trp_right_get(a_base, a_field, (a_node)); \
|
---|
90 | trp_right_set(a_base, a_field, (a_node), \
|
---|
91 | trp_left_get(a_base, a_field, (r_node))); \
|
---|
92 | trp_left_set(a_base, a_field, (r_node), (a_node)); \
|
---|
93 | } while (0)
|
---|
94 |
|
---|
95 | #define trpn_rotate_right(a_base, a_field, a_node, r_node) \
|
---|
96 | do { \
|
---|
97 | (r_node) = trp_left_get(a_base, a_field, (a_node)); \
|
---|
98 | trp_left_set(a_base, a_field, (a_node), \
|
---|
99 | trp_right_get(a_base, a_field, (r_node))); \
|
---|
100 | trp_right_set(a_base, a_field, (r_node), (a_node)); \
|
---|
101 | } while (0)
|
---|
102 |
|
---|
103 | #define trp_gen(a_attr, a_pre, a_type, a_field, a_base, a_cmp) \
|
---|
104 | a_attr a_type MAYBE_UNUSED *a_pre##first(struct trp_root *treap) \
|
---|
105 | { \
|
---|
106 | uint32_t ret; \
|
---|
107 | trpn_first(a_base, a_field, treap->trp_root, ret); \
|
---|
108 | return trpn_pointer(a_base, ret); \
|
---|
109 | } \
|
---|
110 | a_attr a_type MAYBE_UNUSED *a_pre##next(struct trp_root *treap, a_type *node) \
|
---|
111 | { \
|
---|
112 | uint32_t ret; \
|
---|
113 | uint32_t offset = trpn_offset(a_base, node); \
|
---|
114 | if (~trp_right_get(a_base, a_field, offset)) { \
|
---|
115 | trpn_first(a_base, a_field, \
|
---|
116 | trp_right_get(a_base, a_field, offset), ret); \
|
---|
117 | } else { \
|
---|
118 | uint32_t tnode = treap->trp_root; \
|
---|
119 | ret = ~0; \
|
---|
120 | while (1) { \
|
---|
121 | int cmp = (a_cmp)(trpn_pointer(a_base, offset), \
|
---|
122 | trpn_pointer(a_base, tnode)); \
|
---|
123 | if (cmp < 0) { \
|
---|
124 | ret = tnode; \
|
---|
125 | tnode = trp_left_get(a_base, a_field, tnode); \
|
---|
126 | } else if (cmp > 0) { \
|
---|
127 | tnode = trp_right_get(a_base, a_field, tnode); \
|
---|
128 | } else { \
|
---|
129 | break; \
|
---|
130 | } \
|
---|
131 | } \
|
---|
132 | } \
|
---|
133 | return trpn_pointer(a_base, ret); \
|
---|
134 | } \
|
---|
135 | a_attr a_type MAYBE_UNUSED *a_pre##search(struct trp_root *treap, a_type *key) \
|
---|
136 | { \
|
---|
137 | int cmp; \
|
---|
138 | uint32_t ret = treap->trp_root; \
|
---|
139 | while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \
|
---|
140 | if (cmp < 0) { \
|
---|
141 | ret = trp_left_get(a_base, a_field, ret); \
|
---|
142 | } else { \
|
---|
143 | ret = trp_right_get(a_base, a_field, ret); \
|
---|
144 | } \
|
---|
145 | } \
|
---|
146 | return trpn_pointer(a_base, ret); \
|
---|
147 | } \
|
---|
148 | a_attr a_type MAYBE_UNUSED *a_pre##nsearch(struct trp_root *treap, a_type *key) \
|
---|
149 | { \
|
---|
150 | int cmp; \
|
---|
151 | uint32_t ret = treap->trp_root; \
|
---|
152 | while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \
|
---|
153 | if (cmp < 0) { \
|
---|
154 | if (!~trp_left_get(a_base, a_field, ret)) \
|
---|
155 | break; \
|
---|
156 | ret = trp_left_get(a_base, a_field, ret); \
|
---|
157 | } else { \
|
---|
158 | ret = trp_right_get(a_base, a_field, ret); \
|
---|
159 | } \
|
---|
160 | } \
|
---|
161 | return trpn_pointer(a_base, ret); \
|
---|
162 | } \
|
---|
163 | a_attr uint32_t MAYBE_UNUSED a_pre##insert_recurse(uint32_t cur_node, uint32_t ins_node) \
|
---|
164 | { \
|
---|
165 | if (cur_node == ~0) { \
|
---|
166 | return ins_node; \
|
---|
167 | } else { \
|
---|
168 | uint32_t ret; \
|
---|
169 | int cmp = (a_cmp)(trpn_pointer(a_base, ins_node), \
|
---|
170 | trpn_pointer(a_base, cur_node)); \
|
---|
171 | if (cmp < 0) { \
|
---|
172 | uint32_t left = a_pre##insert_recurse( \
|
---|
173 | trp_left_get(a_base, a_field, cur_node), ins_node); \
|
---|
174 | trp_left_set(a_base, a_field, cur_node, left); \
|
---|
175 | if (trp_prio_get(left) < trp_prio_get(cur_node)) \
|
---|
176 | trpn_rotate_right(a_base, a_field, cur_node, ret); \
|
---|
177 | else \
|
---|
178 | ret = cur_node; \
|
---|
179 | } else { \
|
---|
180 | uint32_t right = a_pre##insert_recurse( \
|
---|
181 | trp_right_get(a_base, a_field, cur_node), ins_node); \
|
---|
182 | trp_right_set(a_base, a_field, cur_node, right); \
|
---|
183 | if (trp_prio_get(right) < trp_prio_get(cur_node)) \
|
---|
184 | trpn_rotate_left(a_base, a_field, cur_node, ret); \
|
---|
185 | else \
|
---|
186 | ret = cur_node; \
|
---|
187 | } \
|
---|
188 | return ret; \
|
---|
189 | } \
|
---|
190 | } \
|
---|
191 | a_attr a_type *MAYBE_UNUSED a_pre##insert(struct trp_root *treap, a_type *node) \
|
---|
192 | { \
|
---|
193 | uint32_t offset = trpn_offset(a_base, node); \
|
---|
194 | trp_node_new(a_base, a_field, offset); \
|
---|
195 | treap->trp_root = a_pre##insert_recurse(treap->trp_root, offset); \
|
---|
196 | return trpn_pointer(a_base, offset); \
|
---|
197 | } \
|
---|
198 | a_attr uint32_t MAYBE_UNUSED a_pre##remove_recurse(uint32_t cur_node, uint32_t rem_node) \
|
---|
199 | { \
|
---|
200 | int cmp = a_cmp(trpn_pointer(a_base, rem_node), \
|
---|
201 | trpn_pointer(a_base, cur_node)); \
|
---|
202 | if (cmp == 0) { \
|
---|
203 | uint32_t ret; \
|
---|
204 | uint32_t left = trp_left_get(a_base, a_field, cur_node); \
|
---|
205 | uint32_t right = trp_right_get(a_base, a_field, cur_node); \
|
---|
206 | if (left == ~0) { \
|
---|
207 | if (right == ~0) \
|
---|
208 | return ~0; \
|
---|
209 | } else if (right == ~0 || trp_prio_get(left) < trp_prio_get(right)) { \
|
---|
210 | trpn_rotate_right(a_base, a_field, cur_node, ret); \
|
---|
211 | right = a_pre##remove_recurse(cur_node, rem_node); \
|
---|
212 | trp_right_set(a_base, a_field, ret, right); \
|
---|
213 | return ret; \
|
---|
214 | } \
|
---|
215 | trpn_rotate_left(a_base, a_field, cur_node, ret); \
|
---|
216 | left = a_pre##remove_recurse(cur_node, rem_node); \
|
---|
217 | trp_left_set(a_base, a_field, ret, left); \
|
---|
218 | return ret; \
|
---|
219 | } else if (cmp < 0) { \
|
---|
220 | uint32_t left = a_pre##remove_recurse( \
|
---|
221 | trp_left_get(a_base, a_field, cur_node), rem_node); \
|
---|
222 | trp_left_set(a_base, a_field, cur_node, left); \
|
---|
223 | return cur_node; \
|
---|
224 | } else { \
|
---|
225 | uint32_t right = a_pre##remove_recurse( \
|
---|
226 | trp_right_get(a_base, a_field, cur_node), rem_node); \
|
---|
227 | trp_right_set(a_base, a_field, cur_node, right); \
|
---|
228 | return cur_node; \
|
---|
229 | } \
|
---|
230 | } \
|
---|
231 | a_attr void MAYBE_UNUSED a_pre##remove(struct trp_root *treap, a_type *node) \
|
---|
232 | { \
|
---|
233 | treap->trp_root = a_pre##remove_recurse(treap->trp_root, \
|
---|
234 | trpn_offset(a_base, node)); \
|
---|
235 | } \
|
---|
236 |
|
---|
237 | #endif
|
---|