Adding untested classic functions for tree (_init_set, _set, _equal, _hash, ...)
This commit is contained in:
1 parent
b22a844007
commit
950ea224ff
1 file changed
+164
-7
@@ -186,6 +186,11 @@ typedef int32_t m_tr33_index_t;
|
||||
m_tr33_index_t index; \
|
||||
} it_t; \
|
||||
\
|
||||
M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \
|
||||
M_TR33_DEF_P4_CLASSIC(name, type, oplist, tree_t, it_t)
|
||||
|
||||
/* Define the core & unique methods of a tree */
|
||||
#define M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \
|
||||
static inline void \
|
||||
M_C(name, _init)(tree_t tree) { \
|
||||
tree->size = 0; \
|
||||
@@ -232,12 +237,6 @@ typedef int32_t m_tr33_index_t;
|
||||
tree->tab = NULL; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const tree_t tree) { \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
return M_ASSIGN_CAST(size_t, tree->size); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _reserve)(tree_t tree, size_t alloc) { \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
@@ -987,8 +986,166 @@ typedef int32_t m_tr33_index_t;
|
||||
, /* No CMP */ ) \
|
||||
|
||||
|
||||
/* Define the classic missing methods of a tree */
|
||||
#define M_TR33_DEF_P4_CLASSIC(name, type, oplist, tree_t, it_t) \
|
||||
static inline void \
|
||||
M_C(name, _init_set)(tree_t tree, const tree_t ref) { \
|
||||
tree->size = ref->size; \
|
||||
tree->capacity = ref->capacity; \
|
||||
tree->root_index = ref->root_index; \
|
||||
tree->free_index = ref->free_index; \
|
||||
tree->allow_realloc = ref->allow_realloc; \
|
||||
size_t alloc = M_ASSIGN_CAST(size_t, ref->capacity); \
|
||||
struct M_C(name, _node_s) *ptr = \
|
||||
M_CALL_REALLOC(oplist, struct M_C(name, _node_s), NULL, alloc); \
|
||||
if (M_UNLIKELY (ptr == NULL) ) { \
|
||||
M_MEMORY_FULL(sizeof(struct M_C(name, _node_s)) * alloc); \
|
||||
return; \
|
||||
} \
|
||||
tree->tab = ptr; \
|
||||
/* We don't scan recursively the node tree, but sequentially */ \
|
||||
for(m_tr33_index_t i = 0 ; i < ref->capacity ; i ++) { \
|
||||
tree->tab[i].parent = ref->tab[i].parent; \
|
||||
tree->tab[i].child = ref->tab[i].child; \
|
||||
tree->tab[i].left = ref->tab[i].left; \
|
||||
tree->tab[i].right = ref->tab[i].right; \
|
||||
/* If the node is not a free node, copy the data */ \
|
||||
if (tree->tab[i].parent != M_TR33_NO_NODE) { \
|
||||
M_CALL_INIT_SET(oplist, tree->tab[i].data, ref->tab[i].data); \
|
||||
} \
|
||||
} \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _set)(tree_t tree, const tree_t ref) { \
|
||||
/* No optimum, but good enought for present time */ \
|
||||
M_C(name, _clear)(tree); \
|
||||
M_C(name, _init_set)(tree, ref); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _init_move)(tree_t tree, tree_t ref) { \
|
||||
tree->size = ref->size; \
|
||||
tree->capacity = ref->capacity; \
|
||||
tree->root_index = ref->root_index; \
|
||||
tree->free_index = ref->free_index; \
|
||||
tree->allow_realloc = ref->allow_realloc; \
|
||||
tree->tab = ref->tab; \
|
||||
/* This is so reusing the object implies an assertion failure */ \
|
||||
ref->size = 1; \
|
||||
ref->tab = NULL; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _move)(tree_t tree, tree_t ref) { \
|
||||
M_C(name, _clear)(tree); \
|
||||
M_C(name, _init_move)(tree, ref); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
M_C(name, _swap)(tree_t tree1, tree_t tree2) { \
|
||||
M_TR33_CONTRACT(tree1); \
|
||||
M_TR33_CONTRACT(tree2); \
|
||||
M_SWAP(m_tr33_index_t, tree1->size, tree2->size); \
|
||||
M_SWAP(m_tr33_index_t, tree1->capacity, tree2->capacity); \
|
||||
M_SWAP(m_tr33_index_t, tree1->root_index, tree2->root_index); \
|
||||
M_SWAP(m_tr33_index_t, tree1->free_index, tree2->free_index); \
|
||||
M_SWAP(unsigned, tree1->allow_realloc, tree2->allow_realloc); \
|
||||
M_SWAP(M_C(name, _node_ct) *, tree1->tab, tree2->tab); \
|
||||
M_TR33_CONTRACT(tree1); \
|
||||
M_TR33_CONTRACT(tree2); \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _size)(const tree_t tree) { \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
return M_ASSIGN_CAST(size_t, tree->size); \
|
||||
} \
|
||||
\
|
||||
static inline bool \
|
||||
M_C(name, _empty_p)(const tree_t tree) { \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
return tree->size == 0; \
|
||||
} \
|
||||
\
|
||||
static inline size_t \
|
||||
M_C(name, _capacity)(const tree_t tree) { \
|
||||
M_TR33_CONTRACT(tree); \
|
||||
return M_ASSIGN_CAST(size_t, tree->capacity); \
|
||||
} \
|
||||
\
|
||||
/* Service not really usefull as the affectation operator works with it */\
|
||||
static inline void \
|
||||
M_C(name, _it_set)(it_t *dst, it_t src ){ \
|
||||
*dst = src; \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(EQUAL, oplist)( \
|
||||
static inline bool \
|
||||
M_C(name, _equal_p)(/*const*/ tree_t t1, /*const*/ tree_t t2) { \
|
||||
M_TR33_CONTRACT(t1); \
|
||||
M_TR33_CONTRACT(t2); \
|
||||
/* Fast case if the sizes don't match */ \
|
||||
if (M_LIKELY(t1->size != t2->size)) { \
|
||||
return false; \
|
||||
} \
|
||||
/* Slow case. We need to scan both tree \
|
||||
and check if we move in the same way \
|
||||
while checking also the data \
|
||||
*/ \
|
||||
it_t it1 = M_C(name, _it)(t1); \
|
||||
it_t it2 = M_C(name, _it)(t2); \
|
||||
while (!M_C(name, _end_p)(it1)) { \
|
||||
if (M_C(name, _end_p)(it2)) return false; \
|
||||
bool b = M_CALL_EQUAL(oplist, *M_C(name, _cref)(it1), *M_C(name, _cref)(it2)); \
|
||||
if (!b) return false; \
|
||||
/* First go down, if impossible go right */ \
|
||||
if (M_C(name, _it_down)(&it1) ) { \
|
||||
b = M_C(name, _it_down)(&it2); \
|
||||
if (!b) return false; \
|
||||
continue; \
|
||||
} \
|
||||
if (M_C(name, _it_right)(&it1)) { \
|
||||
b = M_C(name, _it_right)(&it2); \
|
||||
if (!b) return false; \
|
||||
continue; \
|
||||
} \
|
||||
/* If impossible, move up and then right until impossible */ \
|
||||
while (M_C(name, _it_up)(&it1)) { \
|
||||
b = M_C(name, _it_up)(&it2); \
|
||||
if (!b) return false; \
|
||||
if (M_C(name, _it_right)(&it1)) { \
|
||||
b = M_C(name, _it_right)(&it2); \
|
||||
if (!b) return false; \
|
||||
goto do_continue; \
|
||||
} \
|
||||
} \
|
||||
/* Reach end of tree */ \
|
||||
do_continue: \
|
||||
continue; \
|
||||
} \
|
||||
return M_C(name, _end_p)(it2); \
|
||||
} \
|
||||
, /* No EQUAL */ ) \
|
||||
\
|
||||
M_IF_METHOD(HASH, oplist)( \
|
||||
static size_t \
|
||||
M_C(name, _hash)(/* const */ tree_t t1) { \
|
||||
M_HASH_DECL(hash); \
|
||||
for(it_t it = M_C(name, _it)(t1); \
|
||||
!M_C(name, _end_p)(it) ; \
|
||||
M_C(name, _next)(&it)) { \
|
||||
size_t h = M_CALL_HASH(oplist, *M_C(name, _cref)(it)); \
|
||||
M_HASH_UP(hash, h); \
|
||||
} \
|
||||
return M_HASH_FINAL(hash); \
|
||||
} \
|
||||
, /* No HASH */ ) \
|
||||
|
||||
// TODO:
|
||||
// * insertion function with move semantics (or _raw methods?)
|
||||
// * Sort the nodes of a child in function of a userfunction
|
||||
// * emplace insertion
|
||||
// * I/O
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user