This commit is contained in:
Gregory Burd 2024-05-28 11:05:39 -04:00
parent ded941b5ee
commit d327c256af
2 changed files with 929 additions and 924 deletions

View file

@ -365,12 +365,12 @@ main()
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node); api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
#endif #endif
printf("m = %ld\n", splay_list_m(list)); printf("m = %ld; ", splay_list_m(list));
printf("(⌊log2(m)⌋) = %d\n", floor_log2(splay_list_m(list))); printf("(⌊log2(m)⌋) = %d\n", floor_log2(splay_list_m(list)));
if (!(rc = api_skip_contains_ex(list, 5))) if (!(rc = api_skip_contains_ex(list, 5)))
perror("missing element 5"); perror("missing element 5");
CHECK;
#ifdef DOT #ifdef DOT
sprintf(msg, "contains(5)"); sprintf(msg, "contains(5)");
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node); api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);

View file

@ -246,9 +246,9 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
for (decl##_node_t *elm = path[nth].node; elm->field.sle_levels[path[nth].in].next == path[nth].node; elm = elm->field.sle_prev) for (decl##_node_t *elm = path[nth].node; elm->field.sle_levels[path[nth].in].next == path[nth].node; elm = elm->field.sle_prev)
#define __SKIP_SUBTREE_CHu(decl, field, list, path, nth) \ #define __SKIP_SUBTREE_CHu(decl, field, list, path, nth) \
for (decl##_node_t *elm = path[nth].node; elm != path[nth].node->field.sle_levels[0].next; elm = elm->field.sle_levels[0].next) for (decl##_node_t *elm = path[nth].node; elm != path[nth].node->field.sle_levels[0].next; elm = elm->field.sle_levels[0].next)
#define __SKIP_SUBTREE_CHhx(decl, field, list, path, nth) \ /* Iterate over a subtree starting at provided path element, u = path.in */
for (decl##_node_t *elm = path[nth].node->field.sle_levels[path[nth].in].next->field.sle_prev; elm != path[nth].node->field.sle_prev; \ #define __SKIP_SUBTREE_CHux(decl, field, list, path, level) \
elm = elm->field.sle_prev) for (decl##_node_t *elm = path.node->field.sle_levels[level].next->field.sle_prev; elm != path.node->field.sle_prev; elm = elm->field.sle_prev)
/* /*
* Skiplist declarations and access methods. * Skiplist declarations and access methods.
@ -635,9 +635,10 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
*/ \ */ \
static void __skip_rebalance_##decl(decl##_t *slist, size_t len, __skiplist_path_##decl##_t path[]) \ static void __skip_rebalance_##decl(decl##_t *slist, size_t len, __skiplist_path_##decl##_t path[]) \
{ \ { \
size_t i, j, u_hits, hits_CHu = 0, hits_CHv = 0, delta_height, new_height, cur_hits, prev_hits; \ size_t i, j, u_hits, hits_CHu = 0, hits_CHv = 0, delta_height, cur_hits, prev_hits; \
size_t k_threshold, m_total_hits; \ size_t k_threshold, m_total_hits; \
double asc_cond, dsc_cond; \ double asc_cond, dsc_cond; \
__skiplist_path_##decl##_t cur, prv; \
\ \
/* Total hits, `k`, across all nodes. */ \ /* Total hits, `k`, across all nodes. */ \
m_total_hits = slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].hits; \ m_total_hits = slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].hits; \
@ -657,11 +658,11 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
if (path[i].node == slist->slh_head || path[i].node == slist->slh_tail) \ if (path[i].node == slist->slh_head || path[i].node == slist->slh_tail) \
continue; \ continue; \
\ \
__SKIP_SUBTREE_CHhx(decl, field, slist, path, i) \ __SKIP_SUBTREE_CHux(decl, field, slist, path[i], path[i].in) \
{ \ { \
hits_CHu += elm->field.sle_levels[0].hits; \ hits_CHu += elm->field.sle_levels[0].hits; \
} \ } \
__SKIP_SUBTREE_CHhx(decl, field, slist, path, i + 1) \ __SKIP_SUBTREE_CHux(decl, field, slist, path[i + 1], path[i].in) \
{ \ { \
hits_CHv += elm->field.sle_levels[0].hits; \ hits_CHv += elm->field.sle_levels[0].hits; \
} \ } \
@ -675,24 +676,26 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
* 3) adjust any forward pointers along the way, then... \ * 3) adjust any forward pointers along the way, then... \
* 4) lower the path[i]'s node height by 1 \ * 4) lower the path[i]'s node height by 1 \
*/ \ */ \
delta_height = k_threshold - path[i].node->field.sle_height + 1; \ delta_height = k_threshold - path[i].node->field.sle_height; \
dsc_cond = m_total_hits / pow(2.0, delta_height); \ dsc_cond = m_total_hits / pow(2.0, delta_height); \
if (u_hits <= dsc_cond && path[i].node->field.sle_height > 0) { \ if (0 && u_hits <= dsc_cond && path[i].node->field.sle_height > 0) { \
if (path[i - 1].node->field.sle_prev != slist->slh_head) { \ if (path[i].node->field.sle_prev != slist->slh_head) { \
/* 1) go backwards along path from where we are until head */ \ /* 1) go backwards along path from where we are until head */ \
j = i; \ j = i; \
cur_hits = path[j].node->field.sle_levels[path[j].in].hits; \ cur = path[j]; \
prv = path[j + 1]; \
cur_hits = cur.node->field.sle_levels[cur.in].hits; \
do { \ do { \
/* 2) propagate hits */ \ /* 2) propagate hits */ \
prev_hits = path[j - 1].node->field.sle_levels[path[j - 1].in].hits; \ prev_hits = prv.node->field.sle_levels[prv.in].hits; \
path[j - 1].node->field.sle_levels[path[j - 1].in].hits += cur_hits; \ prv.node->field.sle_levels[prv.in].hits += cur_hits; \
cur_hits = prev_hits; \ cur_hits = prev_hits; \
/* 3) adjust forward pointers */ \ /* 3) adjust forward pointers */ \
if (path[j - 1].node->field.sle_levels[j].next == path[i].node) \ if (prv.node->field.sle_levels[j].next == cur.node) \
path[j - 1].node->field.sle_levels[j].next = path[i].node->field.sle_levels[j].next; \ prv.node->field.sle_levels[j].next = cur.node->field.sle_levels[j].next; \
} while (j-- > 1); \ } while (j-- > 1); \
/* 4) reduce height by one */ \ /* 4) reduce height by one */ \
path[i].node->field.sle_height--; \ cur.node->field.sle_height--; \
} \ } \
} \ } \
/* (b) Check the ascent condition: \ /* (b) Check the ascent condition: \
@ -704,16 +707,19 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
* 4) set prev node hits to 0 and forward to this new level \ * 4) set prev node hits to 0 and forward to this new level \
*/ \ */ \
/* 1) check ascent condition */ \ /* 1) check ascent condition */ \
asc_cond = m_total_hits / pow(2.0, delta_height == 0 ? 0 : delta_height - 1); \ asc_cond = m_total_hits / pow(2.0, delta_height - 1); \
if (path[i - 1].pu > asc_cond && path[i].node->field.sle_height < SKIPLIST_MAX_HEIGHT) { \ if (path[i + 1].pu + hits_CHv > asc_cond && path[i].node->field.sle_height < SKIPLIST_MAX_HEIGHT) { \
cur = path[i]; \
prv = path[i + 1]; \
/* 2) increase height by one */ \ /* 2) increase height by one */ \
new_height = path[i].node->field.sle_height++; \ cur.node->field.sle_height++; \
/* 3) update hit counter */ \ /* 3) update hit counter */ \
path[i].node->field.sle_levels[new_height].hits += path[i - 1].node->field.sle_levels[path[i - 1].in].hits; \ cur.node->field.sle_levels[prv.in].hits = prv.node->field.sle_levels[prv.in].hits; \
/* 4) reset the prev node hits to 0 */ \ /* 4) reset the prev node hits to 0 */ \
path[i - 1].node->field.sle_levels[path[i - 1].in].hits = 0; \ prv.node->field.sle_levels[prv.in].hits = 0; \
if (path[i - 1].in != 0) \ /* 5) update forward pointers in the level */ \
path[i - 1].node->field.sle_levels[path[i - 1].in].next->field.sle_levels[path[i - 1].in].next = path[i].node; \ cur.node->field.sle_levels[prv.in].next = prv.node->field.sle_levels[prv.in].next; \
prv.node->field.sle_levels[prv.in].next = cur.node; \
} \ } \
} while (i++ < len); \ } while (i++ < len); \
} \ } \
@ -740,16 +746,15 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
/* Find the node that matches `node` or NULL. */ \ /* Find the node that matches `node` or NULL. */ \
i = slist->slh_head->field.sle_height - 1; \ i = slist->slh_head->field.sle_height - 1; \
do { \ do { \
path[i + 1].pu = 0; \ __skiplist_path_##decl##_t *pe = &path[i + 1]; \
while (elm != slist->slh_tail && elm->field.sle_levels[i].next && \ pe->pu = 0; \
__skip_compare_nodes_##decl(slist, elm->field.sle_levels[i].next, n, slist->slh_aux) < 0) { \ while (elm != slist->slh_tail && __skip_compare_nodes_##decl(slist, elm->field.sle_levels[i].next, n, slist->slh_aux) < 0) { \
pe->in = i; \
pe->pu += elm->field.sle_levels[0].hits; \
elm = elm->field.sle_levels[i].next; \ elm = elm->field.sle_levels[i].next; \
path[i + 1].in = i; \
path[i + 1].pu += elm->field.sle_levels[path[i + 1].in].hits; \
} \ } \
path[i + 1].node = elm; \ pe->node = elm; \
if (path[i + 1].in > 0) \ pe->node->field.sle_levels[pe->in].hits += i ? 1 : 0; \
path[i + 1].node->field.sle_levels[path[i + 1].in].hits++; \
len++; \ len++; \
} while (i--); \ } while (i--); \
elm = elm->field.sle_levels[0].next; \ elm = elm->field.sle_levels[0].next; \