| /* |
| * C macro implementation of treaps. |
| * |
| * Usage: |
| * #include <stdint.h> |
| * #include "trp.h" |
| * trp_gen(...) |
| * |
| * Licensed under a two-clause BSD-style license. |
| * See LICENSE for details. |
| */ |
| |
| #ifndef TRP_H_ |
| #define TRP_H_ |
| |
| #define MAYBE_UNUSED __attribute__((__unused__)) |
| |
| /* Node structure. */ |
| struct trp_node { |
| uint32_t trpn_left; |
| uint32_t trpn_right; |
| }; |
| |
| /* Root structure. */ |
| struct trp_root { |
| uint32_t trp_root; |
| }; |
| |
| /* Pointer/Offset conversion. */ |
| #define trpn_pointer(a_base, a_offset) (a_base##_pointer(a_offset)) |
| #define trpn_offset(a_base, a_pointer) (a_base##_offset(a_pointer)) |
| #define trpn_modify(a_base, a_offset) \ |
| do { \ |
| if ((a_offset) < a_base##_pool.committed) { \ |
| uint32_t old_offset = (a_offset);\ |
| (a_offset) = a_base##_alloc(1); \ |
| *trpn_pointer(a_base, a_offset) = \ |
| *trpn_pointer(a_base, old_offset); \ |
| } \ |
| } while (0) |
| |
| /* Left accessors. */ |
| #define trp_left_get(a_base, a_field, a_node) \ |
| (trpn_pointer(a_base, a_node)->a_field.trpn_left) |
| #define trp_left_set(a_base, a_field, a_node, a_left) \ |
| do { \ |
| trpn_modify(a_base, a_node); \ |
| trp_left_get(a_base, a_field, a_node) = (a_left); \ |
| } while (0) |
| |
| /* Right accessors. */ |
| #define trp_right_get(a_base, a_field, a_node) \ |
| (trpn_pointer(a_base, a_node)->a_field.trpn_right) |
| #define trp_right_set(a_base, a_field, a_node, a_right) \ |
| do { \ |
| trpn_modify(a_base, a_node); \ |
| trp_right_get(a_base, a_field, a_node) = (a_right); \ |
| } while (0) |
| |
| /* |
| * Fibonacci hash function. |
| * The multiplier is the nearest prime to (2^32 times (√5 - 1)/2). |
| * See Knuth §6.4: volume 3, 3rd ed, p518. |
| */ |
| #define trpn_hash(a_node) (uint32_t) (2654435761u * (a_node)) |
| |
| /* Priority accessors. */ |
| #define trp_prio_get(a_node) trpn_hash(a_node) |
| |
| /* Node initializer. */ |
| #define trp_node_new(a_base, a_field, a_node) \ |
| do { \ |
| trp_left_set(a_base, a_field, (a_node), ~0); \ |
| trp_right_set(a_base, a_field, (a_node), ~0); \ |
| } while (0) |
| |
| /* Internal utility macros. */ |
| #define trpn_first(a_base, a_field, a_root, r_node) \ |
| do { \ |
| (r_node) = (a_root); \ |
| if ((r_node) == ~0) \ |
| return NULL; \ |
| while (~trp_left_get(a_base, a_field, (r_node))) \ |
| (r_node) = trp_left_get(a_base, a_field, (r_node)); \ |
| } while (0) |
| |
| #define trpn_rotate_left(a_base, a_field, a_node, r_node) \ |
| do { \ |
| (r_node) = trp_right_get(a_base, a_field, (a_node)); \ |
| trp_right_set(a_base, a_field, (a_node), \ |
| trp_left_get(a_base, a_field, (r_node))); \ |
| trp_left_set(a_base, a_field, (r_node), (a_node)); \ |
| } while (0) |
| |
| #define trpn_rotate_right(a_base, a_field, a_node, r_node) \ |
| do { \ |
| (r_node) = trp_left_get(a_base, a_field, (a_node)); \ |
| trp_left_set(a_base, a_field, (a_node), \ |
| trp_right_get(a_base, a_field, (r_node))); \ |
| trp_right_set(a_base, a_field, (r_node), (a_node)); \ |
| } while (0) |
| |
| #define trp_gen(a_attr, a_pre, a_type, a_field, a_base, a_cmp) \ |
| a_attr a_type MAYBE_UNUSED *a_pre##first(struct trp_root *treap) \ |
| { \ |
| uint32_t ret; \ |
| trpn_first(a_base, a_field, treap->trp_root, ret); \ |
| return trpn_pointer(a_base, ret); \ |
| } \ |
| a_attr a_type MAYBE_UNUSED *a_pre##next(struct trp_root *treap, a_type *node) \ |
| { \ |
| uint32_t ret; \ |
| uint32_t offset = trpn_offset(a_base, node); \ |
| if (~trp_right_get(a_base, a_field, offset)) { \ |
| trpn_first(a_base, a_field, \ |
| trp_right_get(a_base, a_field, offset), ret); \ |
| } else { \ |
| uint32_t tnode = treap->trp_root; \ |
| ret = ~0; \ |
| while (1) { \ |
| int cmp = (a_cmp)(trpn_pointer(a_base, offset), \ |
| trpn_pointer(a_base, tnode)); \ |
| if (cmp < 0) { \ |
| ret = tnode; \ |
| tnode = trp_left_get(a_base, a_field, tnode); \ |
| } else if (cmp > 0) { \ |
| tnode = trp_right_get(a_base, a_field, tnode); \ |
| } else { \ |
| break; \ |
| } \ |
| } \ |
| } \ |
| return trpn_pointer(a_base, ret); \ |
| } \ |
| a_attr a_type MAYBE_UNUSED *a_pre##search(struct trp_root *treap, a_type *key) \ |
| { \ |
| int cmp; \ |
| uint32_t ret = treap->trp_root; \ |
| while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \ |
| if (cmp < 0) { \ |
| ret = trp_left_get(a_base, a_field, ret); \ |
| } else { \ |
| ret = trp_right_get(a_base, a_field, ret); \ |
| } \ |
| } \ |
| return trpn_pointer(a_base, ret); \ |
| } \ |
| a_attr a_type MAYBE_UNUSED *a_pre##nsearch(struct trp_root *treap, a_type *key) \ |
| { \ |
| int cmp; \ |
| uint32_t ret = treap->trp_root; \ |
| while (~ret && (cmp = (a_cmp)(key, trpn_pointer(a_base, ret)))) { \ |
| if (cmp < 0) { \ |
| if (!~trp_left_get(a_base, a_field, ret)) \ |
| break; \ |
| ret = trp_left_get(a_base, a_field, ret); \ |
| } else { \ |
| ret = trp_right_get(a_base, a_field, ret); \ |
| } \ |
| } \ |
| return trpn_pointer(a_base, ret); \ |
| } \ |
| a_attr uint32_t MAYBE_UNUSED a_pre##insert_recurse(uint32_t cur_node, uint32_t ins_node) \ |
| { \ |
| if (cur_node == ~0) { \ |
| return ins_node; \ |
| } else { \ |
| uint32_t ret; \ |
| int cmp = (a_cmp)(trpn_pointer(a_base, ins_node), \ |
| trpn_pointer(a_base, cur_node)); \ |
| if (cmp < 0) { \ |
| uint32_t left = a_pre##insert_recurse( \ |
| trp_left_get(a_base, a_field, cur_node), ins_node); \ |
| trp_left_set(a_base, a_field, cur_node, left); \ |
| if (trp_prio_get(left) < trp_prio_get(cur_node)) \ |
| trpn_rotate_right(a_base, a_field, cur_node, ret); \ |
| else \ |
| ret = cur_node; \ |
| } else { \ |
| uint32_t right = a_pre##insert_recurse( \ |
| trp_right_get(a_base, a_field, cur_node), ins_node); \ |
| trp_right_set(a_base, a_field, cur_node, right); \ |
| if (trp_prio_get(right) < trp_prio_get(cur_node)) \ |
| trpn_rotate_left(a_base, a_field, cur_node, ret); \ |
| else \ |
| ret = cur_node; \ |
| } \ |
| return ret; \ |
| } \ |
| } \ |
| a_attr void MAYBE_UNUSED a_pre##insert(struct trp_root *treap, a_type *node) \ |
| { \ |
| uint32_t offset = trpn_offset(a_base, node); \ |
| trp_node_new(a_base, a_field, offset); \ |
| treap->trp_root = a_pre##insert_recurse(treap->trp_root, offset); \ |
| } \ |
| a_attr uint32_t MAYBE_UNUSED a_pre##remove_recurse(uint32_t cur_node, uint32_t rem_node) \ |
| { \ |
| int cmp = a_cmp(trpn_pointer(a_base, rem_node), \ |
| trpn_pointer(a_base, cur_node)); \ |
| if (cmp == 0) { \ |
| uint32_t ret; \ |
| uint32_t left = trp_left_get(a_base, a_field, cur_node); \ |
| uint32_t right = trp_right_get(a_base, a_field, cur_node); \ |
| if (left == ~0) { \ |
| if (right == ~0) \ |
| return ~0; \ |
| } else if (right == ~0 || trp_prio_get(left) < trp_prio_get(right)) { \ |
| trpn_rotate_right(a_base, a_field, cur_node, ret); \ |
| right = a_pre##remove_recurse(cur_node, rem_node); \ |
| trp_right_set(a_base, a_field, ret, right); \ |
| return ret; \ |
| } \ |
| trpn_rotate_left(a_base, a_field, cur_node, ret); \ |
| left = a_pre##remove_recurse(cur_node, rem_node); \ |
| trp_left_set(a_base, a_field, ret, left); \ |
| return ret; \ |
| } else if (cmp < 0) { \ |
| uint32_t left = a_pre##remove_recurse( \ |
| trp_left_get(a_base, a_field, cur_node), rem_node); \ |
| trp_left_set(a_base, a_field, cur_node, left); \ |
| return cur_node; \ |
| } else { \ |
| uint32_t right = a_pre##remove_recurse( \ |
| trp_right_get(a_base, a_field, cur_node), rem_node); \ |
| trp_right_set(a_base, a_field, cur_node, right); \ |
| return cur_node; \ |
| } \ |
| } \ |
| a_attr void MAYBE_UNUSED a_pre##remove(struct trp_root *treap, a_type *node) \ |
| { \ |
| treap->trp_root = a_pre##remove_recurse(treap->trp_root, \ |
| trpn_offset(a_base, node)); \ |
| } \ |
| |
| #endif |