cosmopolitan/libc/intrin/tree.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

92 lines
2.4 KiB
C
Raw Normal View History

#ifndef COSMOPOLITAN_TREE_H_
#define COSMOPOLITAN_TREE_H_
#define tree_first __tree_first
#define tree_insert __tree_insert
#define tree_last __tree_last
#define tree_next __tree_next
#define tree_prev __tree_prev
#define tree_remove __tree_remove
COSMOPOLITAN_C_START_
#define TREE_CONTAINER(t, f, p) ((t *)(((char *)(p)) - offsetof(t, f)))
struct Tree {
uintptr_t word;
struct Tree *right;
struct Tree *parent;
};
typedef int tree_search_f(const void *, const struct Tree *);
typedef int tree_cmp_f(const struct Tree *, const struct Tree *);
forceinline struct Tree *tree_get_left(const struct Tree *node) {
return (struct Tree *)(node->word & -2);
}
static inline void tree_set_left(struct Tree *node, struct Tree *left) {
node->word = (uintptr_t)left | (node->word & 1);
}
static inline int tree_get_red(const struct Tree *node) {
return node->word & 1;
}
static inline void tree_set_red(struct Tree *node, int red) {
node->word &= -2;
node->word |= red;
}
forceinline optimizespeed struct Tree *tree_floor(const struct Tree *node,
const void *key,
tree_search_f *cmp) {
struct Tree *left = 0;
while (node) {
if (cmp(key, node) >= 0) {
left = (struct Tree *)node;
node = tree_get_left(node);
} else {
node = node->right;
}
}
return left;
}
static inline struct Tree *tree_ceil(const struct Tree *node, const void *key,
tree_search_f *cmp) {
struct Tree *right = 0;
while (node) {
if (cmp(key, node) < 0) {
right = (struct Tree *)node;
node = tree_get_left(node);
} else {
node = node->right;
}
}
return right;
}
static inline struct Tree *tree_get(const struct Tree *node, const void *key,
tree_search_f *cmp) {
while (node) {
int c = cmp(key, node);
if (c < 0) {
node = tree_get_left(node);
} else if (c > 0) {
node = node->right;
} else {
return (struct Tree *)node;
}
}
return 0;
}
struct Tree *tree_next(struct Tree *) libcesque;
struct Tree *tree_prev(struct Tree *) libcesque;
struct Tree *tree_first(struct Tree *) libcesque;
struct Tree *tree_last(struct Tree *) libcesque;
void tree_remove(struct Tree **, struct Tree *) libcesque;
void tree_insert(struct Tree **, struct Tree *, tree_cmp_f *) libcesque;
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_TREE_H_ */