WIP
This commit is contained in:
parent
d4813c8ddb
commit
fa0fd4b552
2 changed files with 53 additions and 38 deletions
|
@ -16,7 +16,7 @@
|
|||
#define VALIDATE
|
||||
// define SNAPSHOTS
|
||||
// define TODO_RESTORE_SNAPSHOTS
|
||||
#define STABLE_SEED
|
||||
//define STABLE_SEED
|
||||
#define DOT
|
||||
|
||||
#ifdef DOT
|
||||
|
@ -362,23 +362,31 @@ main()
|
|||
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
|
||||
#endif
|
||||
char *v = api_skip_get_ex(list, array[i]);
|
||||
#ifdef DOT
|
||||
sprintf(msg, "get key: %d", array[i]);
|
||||
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
|
||||
#endif
|
||||
CHECK;
|
||||
char *upper_numeral = calloc(1, strlen(v) + 1);
|
||||
strncpy(upper_numeral, v, strlen(v));
|
||||
assert(strncmp(v, upper_numeral, strlen(upper_numeral)) == 0);
|
||||
to_upper(upper_numeral);
|
||||
api_skip_set_ex(list, array[i], upper_numeral);
|
||||
#ifdef DOT
|
||||
sprintf(msg, "set key: %d value: %s", array[i], upper_numeral);
|
||||
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
|
||||
#endif
|
||||
CHECK;
|
||||
|
||||
for (size_t j = 0; j < api_skip_length_ex(list); j++) {
|
||||
int n = xorshift32() % api_skip_length_ex(list);
|
||||
api_skip_contains_ex(list, n);
|
||||
CHECK;
|
||||
#if 0
|
||||
sprintf(msg, "locate key: %d", n);
|
||||
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
|
||||
#endif
|
||||
}
|
||||
#ifdef DOT
|
||||
sprintf(msg, "locate all the keys!!!");
|
||||
api_skip_dot_ex(of, list, gen++, msg, sprintf_ex_node);
|
||||
#endif
|
||||
}
|
||||
numeral = int_to_roman_numeral(-1);
|
||||
api_skip_dup_ex(list, -1, numeral);
|
||||
|
|
73
include/sl.h
73
include/sl.h
|
@ -247,8 +247,8 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
#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)
|
||||
/* Iterate over a subtree starting at provided path element, u = path.in */
|
||||
#define __SKIP_SUBTREE_CHux(decl, field, list, path, level) \
|
||||
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)
|
||||
#define __SKIP_SUBTREE_CHux(decl, field, list, node, level) \
|
||||
for (decl##_node_t *elm = node->field.sle_levels[level].next->field.sle_prev; elm != node->field.sle_prev; elm = elm->field.sle_prev)
|
||||
|
||||
/*
|
||||
* Skiplist declarations and access methods.
|
||||
|
@ -638,8 +638,8 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
size_t i, lvl, u_hits, hits_CHu = 0, hits_CHv = 0, delta_height; \
|
||||
size_t k_threshold, m_total_hits, expected_height; \
|
||||
double asc_cond, dsc_cond; \
|
||||
__skiplist_path_##decl##_t *p, path_u, path_v, *cur; \
|
||||
decl##_node_t *prv_node; \
|
||||
__skiplist_path_##decl##_t *p, path_u, path_v; \
|
||||
decl##_node_t *node; \
|
||||
\
|
||||
/* Total hits, `k`, across all nodes. */ \
|
||||
m_total_hits = slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].hits; \
|
||||
|
@ -650,6 +650,9 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
if (expected_height > slist->slh_head->field.sle_height && expected_height < SKIPLIST_MAX_HEIGHT - 1) { \
|
||||
slist->slh_head->field.sle_height++; \
|
||||
slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].next = slist->slh_tail; \
|
||||
slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].hits = \
|
||||
slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height - 1].hits; \
|
||||
slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height - 1].hits = 0; \
|
||||
slist->slh_tail->field.sle_height = slist->slh_head->field.sle_height; \
|
||||
} \
|
||||
} \
|
||||
|
@ -670,18 +673,14 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
if (path_u.node == slist->slh_head || path_u.node == slist->slh_tail) \
|
||||
continue; \
|
||||
path_v = *(p + 1); \
|
||||
if ((*(p + 1)).node->field.sle_levels[path_u.in].next != path_u.node) { \
|
||||
path_v.node = (*(p + 1)).node->field.sle_levels[path_u.in].next; \
|
||||
path_v.pu = 0; \
|
||||
} \
|
||||
\
|
||||
/* Evaluate the subtree 'u'. */ \
|
||||
__SKIP_SUBTREE_CHux(decl, field, slist, path_u, path_u.in) \
|
||||
__SKIP_SUBTREE_CHux(decl, field, slist, path_u.node, path_u.in) \
|
||||
{ \
|
||||
hits_CHu += elm->field.sle_levels[0].hits; \
|
||||
} \
|
||||
/* Evaluate the subtree 'v' at the same level. */ \
|
||||
__SKIP_SUBTREE_CHux(decl, field, slist, path_v, path_u.in) \
|
||||
__SKIP_SUBTREE_CHux(decl, field, slist, (*(p + 1)).node->field.sle_levels[path_u.in].next, path_u.in) \
|
||||
{ \
|
||||
hits_CHv += elm->field.sle_levels[0].hits; \
|
||||
} \
|
||||
|
@ -689,25 +688,30 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* (a) Check the decent condition: \
|
||||
* u_hits <= m_total_hits / (2 ^ (k_threshold - height of node)) \
|
||||
* When met we: \
|
||||
* 1) traverse the path backward, and... \
|
||||
* 2) propagate path[i].level[i] hits backward along path, and... \
|
||||
* 3) adjust any forward pointers along the way, then... \
|
||||
* 1) go backwards along path from where we are until head \
|
||||
* 2) adjust any forward pointers, then... \
|
||||
* 3) adjust hits, and... \
|
||||
* 4) lower the path[i]'s node height by 1 \
|
||||
*/ \
|
||||
delta_height = k_threshold - path_u.node->field.sle_height; \
|
||||
dsc_cond = m_total_hits / pow(2.0, delta_height); \
|
||||
u_hits = hits_CHu + hits_CHv; \
|
||||
if (u_hits <= dsc_cond && path_u.node->field.sle_height > 0) { \
|
||||
lvl = path_u.node->field.sle_height; \
|
||||
/* 1) go backwards along path from where we are until head */ \
|
||||
cur = &path[i]; \
|
||||
prv_node = (*(p + 1)).node->field.sle_levels[path_u.in].next; \
|
||||
/* 2) propagate hits */ \
|
||||
prv_node->field.sle_levels[cur->in].hits += 1; \
|
||||
/* 3) adjust forward pointers */ \
|
||||
if (prv_node->field.sle_levels[cur->in].next == cur->node) \
|
||||
prv_node->field.sle_levels[cur->in].next = cur->node->field.sle_levels[cur->in].next; \
|
||||
node = path_u.node; \
|
||||
do { \
|
||||
node = node->field.sle_prev; \
|
||||
/* 2) adjust forward pointers */ \
|
||||
if (node->field.sle_height >= lvl && node->field.sle_levels[lvl].next == path_u.node) { \
|
||||
node->field.sle_levels[lvl].next = path_u.node->field.sle_levels[lvl].next; \
|
||||
/* 3) adjust hits */ \
|
||||
node->field.sle_levels[lvl].hits += 1; \
|
||||
break; \
|
||||
} \
|
||||
} while (node != slist->slh_head); \
|
||||
/* 4) reduce height by one */ \
|
||||
cur->node->field.sle_height--; \
|
||||
path_u.node->field.sle_height--; \
|
||||
} \
|
||||
/* (b) Check the ascent condition: \
|
||||
* path[i].pu + node_hits > hits total / (2 ^ (height of head - height of node - 1)) \
|
||||
|
@ -719,14 +723,16 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
/* 1) check ascent condition */ \
|
||||
asc_cond = m_total_hits / pow(2.0, delta_height - 1); \
|
||||
if (path_u.pu > asc_cond && path_u.node->field.sle_height < SKIPLIST_MAX_HEIGHT - 1) { \
|
||||
/* 2) increase height by one */ \
|
||||
if (path_u.pu > asc_cond && path_u.node->entries.sle_height < 64 - 1) { \
|
||||
if (path_u.node->field.sle_height + 1 > path_v.node->field.sle_height) { \
|
||||
continue; \
|
||||
} \
|
||||
lvl = ++path_u.node->field.sle_height; \
|
||||
/* 3) update hit counter */ \
|
||||
path_u.node->field.sle_levels[lvl].hits = path_v.node->field.sle_levels[lvl].hits; \
|
||||
/* 4) reset the prev node hits to 0 */ \
|
||||
path_v.node->field.sle_levels[lvl].hits = 0; \
|
||||
/* 5) update forward pointers in the level */ \
|
||||
/* Don't adjust hits when the previous node on the path is the head. */ \
|
||||
if (path_v.node != slist->slh_head) { \
|
||||
path_u.node->field.sle_levels[lvl].hits = path_v.node->entries.sle_levels[lvl].hits; \
|
||||
path_v.node->field.sle_levels[lvl].hits = 0; \
|
||||
} \
|
||||
path_u.node->field.sle_levels[lvl].next = path_v.node->field.sle_levels[lvl].next; \
|
||||
path_v.node->field.sle_levels[lvl].next = path_u.node; \
|
||||
} \
|
||||
|
@ -1155,6 +1161,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* Reduce the height of the head/tail nodes. */ \
|
||||
for (i = 0; slist->slh_head->field.sle_levels[i].next != slist->slh_tail && i < SKIPLIST_MAX_HEIGHT; i++) \
|
||||
; \
|
||||
slist->slh_head->field.sle_levels[i].hits = slist->slh_head->field.sle_levels[slist->slh_head->field.sle_height].hits; \
|
||||
slist->slh_head->field.sle_height = slist->slh_tail->field.sle_height = i; \
|
||||
\
|
||||
slist->slh_length--; \
|
||||
|
@ -1937,10 +1944,10 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
\
|
||||
if (slist == NULL || fn == NULL) \
|
||||
return nsg; \
|
||||
if (__skip_integrity_check_##decl(slist, 1) != 0) { \
|
||||
/*if (__skip_integrity_check_##decl(slist, 1) != 0) { \
|
||||
perror("Skiplist failed integrity checks, impossible to diagram."); \
|
||||
return -1; \
|
||||
} \
|
||||
}*/ \
|
||||
if (nsg == 0) { \
|
||||
fprintf(os, "digraph Skiplist {\n"); \
|
||||
fprintf(os, "label = \"Skiplist.\"\n"); \
|
||||
|
@ -1950,9 +1957,9 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
} \
|
||||
fprintf(os, "subgraph cluster%lu {\n", nsg); \
|
||||
fprintf(os, "style=dashed\n"); \
|
||||
fprintf(os, "label=\"Skiplist iteration %lu", nsg); \
|
||||
fprintf(os, "label=\"Skiplist [%lu]", nsg); \
|
||||
if (msg) \
|
||||
fprintf(os, ", %s", msg); \
|
||||
fprintf(os, " %s", msg); \
|
||||
fprintf(os, "\"\n\n"); \
|
||||
fprintf(os, "\"HeadNode%lu\" [\n", nsg); \
|
||||
fprintf(os, "label = \""); \
|
||||
|
@ -2011,7 +2018,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
} \
|
||||
fflush(os); \
|
||||
\
|
||||
/* The tail, sentinal node */ \
|
||||
/* The tail, sentinel node */ \
|
||||
if (letitgo) { \
|
||||
__skip_dot_write_node_##decl(os, nsg, NULL); \
|
||||
fprintf(os, " [label = \""); \
|
||||
|
|
Loading…
Reference in a new issue