diff --git a/src/__internal/rbtree.h b/src/__internal/rbtree.h index 8564bc1..01a5c10 100644 --- a/src/__internal/rbtree.h +++ b/src/__internal/rbtree.h @@ -29,17 +29,4 @@ extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node) #define rbnode_is_empty(n) ((n) == rbnode_empty) #define rbnode_is_root(n) rbnode_is_empty((n)->parent) -extern void* libcdsb_rbtree_duplicate(const rbnode_t* s, void* (*node_duplicate)(void* src, void* parent, void* info), void* info) wur__ Nonnull__(1); -extern int libcdsb_rbtree_compare (const rbnode_t* s0, const rbnode_t* s1, int (*node_compare)(const rbnode_t* s0, const rbnode_t* s1, void* info), void* info) pure__ wur__ Nonnull__(1,2); - -extern hash_t libcdsb_rbtree_hash(const void* s, hash_t (*node_hash)(const void* s, void* info), void* info) pure__ wur__ Nonnull__(1); -extern size_t libcdsb_rbtree_size(const void* s) pure__ wur__ Nonnull__(1); -extern void libcdsb_rbtree_free(void* x, void (*node_free)(void* x, void* info), void* info) Nonnull__(1); - -#define rbtree_duplicate libcdsb_rbtree_duplicate -#define rbtree_compare libcdsb_rbtree_compare -#define rbtree_hash libcdsb_rbtree_hash -#define rbtree_size libcdsb_rbtree_size -#define rbtree_free libcdsb_rbtree_free - #endif /* LIBCDSB_SRC_INTERNAL_RBTREE_H */ diff --git a/src/map/base.c b/src/map/base.c index de82733..026f180 100644 --- a/src/map/base.c +++ b/src/map/base.c @@ -3,89 +3,158 @@ #include "include.h" -#define mtree_duplicate(s, t) rbtree_duplicate((rbnode_t*)s, (void*)mnode_duplicate, t) -#define mtree_compare(s0, s1, t) rbtree_compare((void*)s0, (void*)s1, (void*)mnode_compare, (void*)t) +/*#####################################################################################################################*/ -static mnode_t* mnode_duplicate(const mnode_t* s, mnode_t* p, const vtype* t) { - mnode_t* x; - - x = mnode_create(vnode_duplicate(&s->key, *t), p, s->colored); - x->type = s->type; - x->value = vnode_duplicate(&s->value, s->type); - - return x; -} - -static int mnode_compare(const mnode_t* s0, const mnode_t* s1, vtype* t) { - int c = vnode_compare_eq(&s0->key, &s1->key, *t); +static inline int mnode_compare(const mnode_t* s0, const mnode_t* s1, vtype t) { + int c = vnode_compare_eq(&s0->key, &s1->key, t); return !c ? vnode_compare(&s0->value, s0->type, &s1->value, s1->type) : c; } -static hash_t mnode_hash(const mnode_t* s, vtype* tp) { - vtype t = (!is_null(tp)) ? *tp : VTYPE_POINTER; - return vnode_hash(s->key, t) + vnode_hash(s->value, s->type) + t; -} - -void libcdsb_mnode_free(mnode_t* x, vtype* t) { - vnode_free(&x->key, *t); - vnode_free(&x->value, x->type); +static inline hash_t mnode_hash(const mnode_t* s, vtype t) { + return vnode_hash(&s->key, t) + vnode_hash(&s->value, s->type) + t; } /*#####################################################################################################################*/ hash_t map_hash(const map_t* s) { - return rbtree_hash(s->root, (void*)mnode_hash, (void*)&s->type) + VTYPE_MAP; + + mnode_t *c0, *c1; + hash_t hash, v; + stack_t z; + + if (mnode_is_empty(s->root)) return 0; + + z.prev = 0; + hash = 1; + c1 = s->root; + + if (!rbnode_is_empty(z.value = c1->left)) { + do { + c0 = stack_pop(&z); + ++hash; + + if (!mnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); + if (!mnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); + } while (!is_null(z.value)); + } + + v = mnode_hash(c1, s->type); + c1 = s->root; + + if (!rbnode_is_empty(z.value = c1->right)) { + do { + c0 = stack_pop(&z); + ++hash; + + if (!mnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); + if (!mnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); + } while (!is_null(z.value)); + } + + v += mnode_hash(c1, s->type); + + return (hash ^ v) + VTYPE_MAP; } +/*#####################################################################################################################*/ + void map_init(map_t* x, vtype t) { x->root = mnode_empty; x->type = t; } void map_free(map_t* x) { - rbtree_free(x->root, (void*)mnode_free, &x->type); + mnode_t *t, *c; + + c = x->root; + + while (!mnode_is_empty(x->root)) { + if (!mnode_is_empty(c->left)) { + c = c->left; + } else if (!mnode_is_empty(c->right)) { + c = c->right; + } else if (!mnode_is_root(c)) { + vnode_free(&c->key, x->type); + vnode_free(&c->value, c->type); + + t = c; + c = c->parent; + + if (t == c->left) c->left = mnode_empty; + else c->right = mnode_empty; + + free(t); + } else { + vnode_free(&c->key, x->type); + vnode_free(&c->value, c->type); + x->root = mnode_empty; + } + } - x->root = mnode_empty; x->type = 0; } /*#####################################################################################################################*/ size_t map_size(const map_t* x) { - return rbtree_size(x->root); + stack_t z = { .prev = 0, .value = x->root }; + size_t n = 0; + rbnode_t* c; + + if (!mnode_is_empty(x->root)) { + while ((c = stack_pop(&z))) { + ++n; + if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); + if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); + } + } + + return n; } /*#####################################################################################################################*/ int map_compare(const map_t* s0, const map_t* s1) { - if (s0 == s1) return 0; - if (s0->type != s1->type) return s0->type - s1->type; + mnode_t *c0, *c1; + stack_t z; + int c = 0; - return mtree_compare(s0->root, s1->root, &s0->type); -} - -/*#####################################################################################################################*/ - -map_t map_copy(const map_t* s) { - map_t x; - - x.type = s->type; - x.root = mtree_duplicate(s->root, &x.type); - - return x; -} - -map_t* map_duplicate(const map_t* s) { - map_t *x = malloc(sizeof(*x)); - - x->type = s->type; - x->root = mtree_duplicate(s->root, &x->type); - - return x; -} - -void map_copy_init(map_t* x, const map_t* s) { - x->type = s->type; - x->root = mtree_duplicate(s->root, &x->type); + if (s0 == s1 || s0->root == s1->root) + return 0; + if (s0->type != s1->type) + return s0->type - s1->type; + + z.prev = 0; + z.value = 0; + + stack_push_many(&z, 2, (void*)s1, (void*)s0); + + do { + c0 = stack_pop(&z); + c1 = stack_pop(&z); + + if (mnode_is_empty(c0) || mnode_is_empty(c1)) { + if (c0 != c1) { + stack_flush(&z); + return mnode_is_empty(c0) ? -1 : 1; + } + } else if ((c = mnode_compare(c0, c1, s0->type))) { + if (c0->left == c1->right) { // == mnode_empty + c = mnode_compare(c0->right, c1, s0->type); + if (!c) c = mnode_compare(c0, c1->left, s0->type); + } else if (c0->right == c1->left) { // == mnode_empty + c = mnode_compare(c0, c1->right, s0->type); + if (!c) c = mnode_compare(c0->left, c1, s0->type); + } + + if (c) { + stack_flush(&z); + return c; + } + } else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left); + + } while (!is_null(z.value)); + + return 0; } diff --git a/src/map/copy.c b/src/map/copy.c new file mode 100644 index 0000000..7a3948f --- /dev/null +++ b/src/map/copy.c @@ -0,0 +1,113 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +/*#####################################################################################################################*/ + +static inline mnode_t* mnode_duplicate(const mnode_t* s, mnode_t* p, const vtype t) { + mnode_t* x; + + x = mnode_create(vnode_duplicate(&s->key, t), p, s->colored); + x->type = s->type; + x->value = vnode_duplicate(&s->value, s->type); + + return x; +} + +/*#####################################################################################################################*/ + +map_t map_copy(const map_t* s) { + + map_t x; + stack_t z = { .prev = 0, .value = s->root }; + + x.type = s->type; + + if (!mnode_is_empty(s->root)) { + x.root = mnode_duplicate(s->root, mnode_empty, s->type); + stack_push(&z, x.root); + + do { + mnode_t *p0 = stack_pop(&z); + mnode_t *p1 = stack_pop(&z); + + if (!mnode_is_empty(p1->left)) { + p0->left = mnode_duplicate(p1->left, p0, s->type); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!mnode_is_empty(p1->right)) { + p0->right = mnode_duplicate(p1->right, p0, s->type); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x.root = mnode_empty; + + return x; +} + + +map_t* map_duplicate(const map_t* s) { + + map_t* x = malloc(sizeof(*x)); + stack_t z = { .prev = 0, .value = s->root }; + + x->type = s->type; + + if (!mnode_is_empty(s->root)) { + x->root = mnode_duplicate(s->root, mnode_empty, s->type); + stack_push(&z, x->root); + + do { + mnode_t *p0 = stack_pop(&z); + mnode_t *p1 = stack_pop(&z); + + if (!mnode_is_empty(p1->left)) { + p0->left = mnode_duplicate(p1->left, p0, s->type); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!mnode_is_empty(p1->right)) { + p0->right = mnode_duplicate(p1->right, p0, s->type); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x->root = mnode_empty; + + return x; +} + + +void map_copy_init(map_t* x, const map_t* s) { + + stack_t z = { .prev = 0, .value = s->root }; + + x->type = s->type; + + if (!mnode_is_empty(s->root)) { + x->root = mnode_duplicate(s->root, mnode_empty, s->type); + stack_push(&z, x->root); + + do { + mnode_t *p0 = stack_pop(&z); + mnode_t *p1 = stack_pop(&z); + + if (!mnode_is_empty(p1->left)) { + p0->left = mnode_duplicate(p1->left, p0, s->type); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!mnode_is_empty(p1->right)) { + p0->right = mnode_duplicate(p1->right, p0, s->type); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x->root = mnode_empty; +} diff --git a/src/map/extra.c b/src/map/extra.c index 5f28450..b587b17 100644 --- a/src/map/extra.c +++ b/src/map/extra.c @@ -20,7 +20,8 @@ bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype cmp = vtype_compare(k, kt, vnode_peek(&n->key, kt), kt); if (cmp == 0) { - mnode_free(n, &kt); + vnode_free(&n->key, x->type); + vnode_free(&n->value, n->type); n->key = kn; n->value = vnode_create(v, vt); @@ -65,7 +66,8 @@ int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callb if (cut) { c = mnode_delete(&x->root, c); - mnode_free(c, &x->type); + vnode_free(&c->key, x->type); + vnode_free(&c->value, c->type); free(c); } @@ -92,7 +94,8 @@ int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool f if (!mnode_is_empty(c->left)) stack_push(&z, c->left); if (flush) { - mnode_free(c, &x->type); + vnode_free(&c->key, x->type); + vnode_free(&c->value, c->type); free(c); } } @@ -102,7 +105,8 @@ int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool f if (!mnode_is_empty(c->right)) stack_push(&z, c->right); if (!mnode_is_empty(c->left)) stack_push(&z, c->left); - mnode_free(c, &x->type); + vnode_free(&c->key, x->type); + vnode_free(&c->value, c->type); free(c); c = stack_pop(&z); diff --git a/src/map/include.h b/src/map/include.h index 59f1c5b..fe07b6b 100644 --- a/src/map/include.h +++ b/src/map/include.h @@ -28,8 +28,6 @@ static_assert(offsetof(struct libcdsb_rbtree_node, value) == offsetof(struct lib static_assert(offsetof(struct libcdsb_set, root) == offsetof(struct libcdsb_map, root), "Implementation assert"); static_assert(offsetof(struct libcdsb_set, type) == offsetof(struct libcdsb_map, type), "Implementation assert"); -extern void libcdsb_mnode_free(mnode_t* x, vtype* t); - #define mnode_empty ((mnode_t*)LIBCDSB_RBTREE_NODE_EMPTY) #define mnode_create(k, p, c) ((mnode_t*)libcdsb_rbtree_node_create(k, (rbnode_t*)p, c, sizeof(mnode_t))) #define mnode_fixup(r, n) libcdsb_rbtree_node_fixup((rbnode_t**)(r), (rbnode_t*)(n)) @@ -38,6 +36,4 @@ extern void libcdsb_mnode_free(mnode_t* x, vtype* t); #define mnode_is_empty(n) ((n) == mnode_empty) #define mnode_is_root(n) mnode_is_empty((n)->parent) -#define mnode_free libcdsb_mnode_free - #endif /* LIBCDSB_SRC_MAP_INCLUDE_H */ diff --git a/src/rbtree-extra.c b/src/rbtree-extra.c deleted file mode 100644 index 40b2821..0000000 --- a/src/rbtree-extra.c +++ /dev/null @@ -1,206 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "__internal/rbtree.h" - -/*#####################################################################################################################*/ - -static rbnode_t* rbnode_duplicate(const rbnode_t* s, rbnode_t* p, const vtype* info) { - return rbnode_create(vnode_duplicate(&s->value, (info) ? *info : VTYPE_POINTER), p, s->colored); -} - -static int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype* tp) { - vtype t = !is_null(tp) ? *tp : VTYPE_POINTER; - return vnode_compare(s0->value, t, s1->value, t); -} - -static hash_t rbnode_hash(const rbnode_t* s, vtype* tp) { - vtype t = (!is_null(tp)) ? *tp : VTYPE_POINTER; - return vnode_hash(s->value, t); -} - -static void rbnode_free(rbnode_t* x, vtype *t) { - if (!is_null(t)) vnode_free(&x->value, *t); -} - -/*#####################################################################################################################*/ - -hash_t libcdsb_rbtree_hash(const void* s, hash_t (*node_hash)(const void* s, void* info), void* info) { - - rbnode_t *c0, *c1; - hash_t hash, v; - stack_t z; - - if (rbnode_is_empty(s)) return 0; - if (is_null(node_hash)) node_hash = (void*)rbnode_hash; - - z.prev = 0; - hash = 1; - c1 = (void*)s; - - if (!rbnode_is_empty(z.value = c1->left)) do { - c0 = stack_pop(&z); - ++hash; - if (!rbnode_is_empty(c0->left)) - stack_push(&z, c1 = c0->left); - if (!rbnode_is_empty(c0->right)) - stack_push(&z, c0->right); - } while (!is_null(z.value)); - - v = node_hash(c1, info); - c1 = (void*)s; - - if (!rbnode_is_empty(z.value = c1->right)) do { - c0 = stack_pop(&z); - ++hash; - if (!rbnode_is_empty(c0->left)) - stack_push(&z, c1 = c0->left); - if (!rbnode_is_empty(c0->right)) - stack_push(&z, c0->right); - } while (!is_null(z.value)); - - v += node_hash(c1, info); - - return hash ^ v; -} - -/*#####################################################################################################################*/ - -void* libcdsb_rbtree_duplicate(const rbnode_t* s, void* (*node_duplicate)(void* src, void* parent, void* info), void* info) { - rbnode_t *p0, *p1, *x; - stack_t z; - - z.prev = 0; - z.value = (void*)s; - - if (is_null(node_duplicate)) { - node_duplicate = (void*)rbnode_duplicate; - } - - if (!rbnode_is_empty(s)) { - x = node_duplicate(z.value, rbnode_empty, info); - stack_push(&z, x); - - do { - p0 = stack_pop(&z); - p1 = stack_pop(&z); - - if (!rbnode_is_empty(p1->left)) { - p0->left = node_duplicate(p1->left, p0, info); - - stack_push(&z, p1->left); - stack_push(&z, p0->left); - } - - if (!rbnode_is_empty(p1->right)) { - p0->right = node_duplicate(p1->right, p0, info); - - stack_push(&z, p1->right); - stack_push(&z, p0->right); - } - - } while (!is_null(z.value)); - - } else x = rbnode_empty; - - return x; -} - -/*#####################################################################################################################*/ - -int libcdsb_rbtree_compare(const rbnode_t* s0, const rbnode_t* s1, int (*node_compare)(const rbnode_t* s0, const rbnode_t* s1, void* info), void* info) { - - rbnode_t *c0, *c1; - stack_t z; - int c = 0; - - if (s0 == s1) return 0; - if (is_null(node_compare)) node_compare = (void*)rbnode_compare; - - z.prev = 0; - z.value = 0; - - stack_push(&z, (void*)s1); - stack_push(&z, (void*)s0); - - do { - c0 = stack_pop(&z); - c1 = stack_pop(&z); - - if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) { - if (c0 != c1) { - stack_flush(&z); - return rbnode_is_empty(c0) ? -1 : 1; - } - } else if ((c = node_compare(c0, c1, info))) { - if (c0->left == c1->right) { // <-- rbnode_empty - c = node_compare(c0->right, c1, info); - if (!c) c = node_compare(c0, c1->left, info); - } else if (c0->right == c1->left) { // <-- rbnode_empty - c = node_compare(c0, c1->right, info); - if (!c) c = node_compare(c0->left, c1, info); - } - - if (c) { - stack_flush(&z); - return c; - } - } else { - stack_push(&z, c1->right); - stack_push(&z, c0->right); - stack_push(&z, c1->left); - stack_push(&z, c0->left); - } - - } while (!is_null(z.value)); - - return 0; -} - - -size_t libcdsb_rbtree_size(const void* s) { - stack_t z = { .prev = 0, .value = (void*)s }; - size_t n = 0; - rbnode_t* c; - - if (!rbnode_is_empty(s)) { - while ((c = stack_pop(&z))) { - ++n; - if (!rbnode_is_empty(c->left)) - stack_push(&z, c->left); - if (!rbnode_is_empty(c->right)) - stack_push(&z, c->right); - } - } - - return n; -} - - -void libcdsb_rbtree_free(void* x, void (*node_free)(void* x, void* info), void* info) { - rbnode_t *t, *c; - - c = x; - if (is_null(node_free)) node_free = (void*)rbnode_free; - - while (!rbnode_is_empty(x)) { - if (!rbnode_is_empty(c->left)) { - c = c->left; - } else if (!rbnode_is_empty(c->right)) { - c = c->right; - } else if (!rbnode_is_root(c)) { - node_free(c, info); - - t = c; - c = c->parent; - - if (t == c->left) c->left = rbnode_empty; - else c->right = rbnode_empty; - - free(t); - } else { - node_free(c, info); - x = rbnode_empty; - } - } -} diff --git a/src/set/base.c b/src/set/base.c index 17d5427..f10f02b 100644 --- a/src/set/base.c +++ b/src/set/base.c @@ -6,10 +6,58 @@ /*#####################################################################################################################*/ -hash_t vset_hash(const set_t* s) { - return rbtree_hash(s->root, nullptr, (void*)&s->type) + VTYPE_SET; +static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) { + return vnode_compare(s0->value, t, s1->value, t); } +static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) { + return vnode_hash(&s->value, t); +} + +/*#####################################################################################################################*/ + +hash_t vset_hash(const set_t* s) { + + rbnode_t *c0, *c1; + hash_t hash, v; + stack_t z; + + if (rbnode_is_empty(s->root)) return 0; + + z.prev = 0; + hash = 1; + c1 = s->root; + + if (!rbnode_is_empty(z.value = c1->left)) { + do { + c0 = stack_pop(&z); + ++hash; + + if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); + if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); + } while (!is_null(z.value)); + } + + v = rbnode_hash(c1, s->type); + c1 = s->root; + + if (!rbnode_is_empty(z.value = c1->right)) { + do { + c0 = stack_pop(&z); + ++hash; + + if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); + if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); + } while (!is_null(z.value)); + } + + v += rbnode_hash(c1, s->type); + + return (hash ^ v) + VTYPE_SET; +} + +/*#####################################################################################################################*/ + void vset_init(set_t* x, vtype t) { x->root = rbnode_empty; x->type = t; @@ -17,48 +65,94 @@ void vset_init(set_t* x, vtype t) { void vset_free(set_t* x) { - rbtree_free(x->root, nullptr, &x->type); + rbnode_t *t, *c; + + c = x->root; + + while (!rbnode_is_empty(x->root)) { + if (!rbnode_is_empty(c->left)) { + c = c->left; + } else if (!rbnode_is_empty(c->right)) { + c = c->right; + } else if (!rbnode_is_root(c)) { + vnode_free(&c->value, x->type); + + t = c; + c = c->parent; + + if (t == c->left) c->left = rbnode_empty; + else c->right = rbnode_empty; + + free(t); + } else { + vnode_free(&c->value, x->type); + x->root = rbnode_empty; + } + } - x->root = rbnode_empty; x->type = 0; } /*#####################################################################################################################*/ size_t vset_size(const set_t* x) { - return rbtree_size(x->root); + stack_t z = { .prev = 0, .value = x->root }; + size_t n = 0; + rbnode_t* c; + + if (!rbnode_is_empty(x->root)) { + while ((c = stack_pop(&z))) { + ++n; + if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); + if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); + } + } + + return n; } /*#####################################################################################################################*/ int vset_compare(const set_t* s0, const set_t* s1) { - if (s0 == s1) return 0; - if (s0->type != s1->type) return s0->type - s1->type; + rbnode_t *c0, *c1; + stack_t z; + int c = 0; - return rbtree_compare(s0->root, s1->root, nullptr, (void*)&s0->type); -} - -/*#####################################################################################################################*/ - -set_t vset_copy(const set_t* s) { - set_t x; - - x.type = s->type; - x.root = rbtree_duplicate(s->root, nullptr, &x.type); - - return x; -} - -set_t* vset_duplicate(const set_t* s) { - set_t *x = malloc(sizeof(*x)); - - x->type = s->type; - x->root = rbtree_duplicate(s->root, nullptr, &x->type); - - return x; -} - -void vset_copy_init(set_t* x, const set_t* s) { - x->type = s->type; - x->root = rbtree_duplicate(s->root, nullptr, &x->type); + if (s0 == s1 || s0->root == s1->root) + return 0; + if (s0->type != s1->type) + return s0->type - s1->type; + + z.prev = 0; + z.value = 0; + + stack_push_many(&z, 2, (void*)s1, (void*)s0); + + do { + c0 = stack_pop(&z); + c1 = stack_pop(&z); + + if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) { + if (c0 != c1) { + stack_flush(&z); + return rbnode_is_empty(c0) ? -1 : 1; + } + } else if ((c = rbnode_compare(c0, c1, s0->type))) { + if (c0->left == c1->right) { // == rbnode_empty + c = rbnode_compare(c0->right, c1, s0->type); + if (!c) c = rbnode_compare(c0, c1->left, s0->type); + } else if (c0->right == c1->left) { // == rbnode_empty + c = rbnode_compare(c0, c1->right, s0->type); + if (!c) c = rbnode_compare(c0->left, c1, s0->type); + } + + if (c) { + stack_flush(&z); + return c; + } + } else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left); + + } while (!is_null(z.value)); + + return 0; } diff --git a/src/set/copy.c b/src/set/copy.c new file mode 100644 index 0000000..a074b0b --- /dev/null +++ b/src/set/copy.c @@ -0,0 +1,97 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/set.h" +#include "../__internal/rbtree.h" + +set_t vset_copy(const set_t* s) { + + set_t x = { .type = s->type }; + stack_t z = { .prev = 0, .value = s->root }; + vtype t = s->type; + + if (!rbnode_is_empty(s->root)) { + x.root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0); + stack_push(&z, x.root); + + do { + rbnode_t *p0 = stack_pop(&z); + rbnode_t *p1 = stack_pop(&z); + + if (!rbnode_is_empty(p1->left)) { + p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!rbnode_is_empty(p1->right)) { + p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x.root = rbnode_empty; + + return x; +} + + +set_t* vset_duplicate(const set_t* s) { + + set_t* x = malloc(sizeof(*x)); + stack_t z = { .prev = 0, .value = s->root }; + vtype t = x->type = s->type; + + if (!rbnode_is_empty(s->root)) { + x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0); + stack_push(&z, x->root); + + do { + rbnode_t *p0 = stack_pop(&z); + rbnode_t *p1 = stack_pop(&z); + + if (!rbnode_is_empty(p1->left)) { + p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!rbnode_is_empty(p1->right)) { + p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x->root = rbnode_empty; + + return x; +} + + +void vset_copy_init(set_t* x, const set_t* s) { + + stack_t z = { .prev = 0, .value = s->root }; + vtype t = x->type = s->type; + + if (!rbnode_is_empty(s->root)) { + x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0); + stack_push(&z, x->root); + + do { + rbnode_t *p0 = stack_pop(&z); + rbnode_t *p1 = stack_pop(&z); + + if (!rbnode_is_empty(p1->left)) { + p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored); + stack_push_many(&z, 2, p1->left, p0->left); + } + + if (!rbnode_is_empty(p1->right)) { + p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored); + stack_push_many(&z, 2, p1->right, p0->right); + } + + } while (!is_null(z.value)); + + } else x->root = rbnode_empty; +}