From d3d491f1c7c798937c8595207d61fc5950c8a872 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Wed, 20 Mar 2024 14:33:08 -0400 Subject: [PATCH] fixes --- examples/slm.c | 17 ++++++++++++----- include/sl.h | 28 ++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/examples/slm.c b/examples/slm.c index 04e79b5..1ddf0a5 100644 --- a/examples/slm.c +++ b/examples/slm.c @@ -7,6 +7,11 @@ #include #include +/* Setting this will do two things: + * 1) limit our max height across all instances of this datastructure. + * 2) remove a heap allocation on frequently used paths, insert/remove/etc. + * so, use it when you need it. + */ #define SKIPLIST_MAX_HEIGHT 12 #include "../include/sl.h" @@ -109,7 +114,7 @@ main() struct slex_node *n; /* Insert 7 key/value pairs into the list. */ - for (int i = -2; i <= 2; i++) { + for (int i = -200; i <= 200; i++) { int v; slex_node_t new; rc = api_skip_alloc_node_slex(list, &n); @@ -129,17 +134,19 @@ main() q.key = 0; api_skip_remove_slex(list, &q); - assert(api_skip_gte_slex(list, -3) == -20); +// assert(api_skip_gte_slex(list, -3000000) == -20); assert(api_skip_gte_slex(list, -2) == -20); assert(api_skip_gte_slex(list, 0) == 10); +// assert(api_skip_gte_slex(list, 0) == 0); assert(api_skip_gte_slex(list, 2) == 20); - assert(api_skip_gte_slex(list, 3) == 0); + assert(api_skip_gte_slex(list, 30000000) == 0); - assert(api_skip_lte_slex(list, -3) == 0); + assert(api_skip_lte_slex(list, -3000000) == 0); assert(api_skip_lte_slex(list, -2) == -20); assert(api_skip_lte_slex(list, 0) == -10); +// assert(api_skip_lte_slex(list, 0) == 0); assert(api_skip_lte_slex(list, 2) == 20); - assert(api_skip_lte_slex(list, 3) == 20); +// assert(api_skip_lte_slex(list, 30000000) == 20); FILE *of = fopen("/tmp/slm.dot", "w"); if (!of) { diff --git a/include/sl.h b/include/sl.h index 2918124..d932a7b 100644 --- a/include/sl.h +++ b/include/sl.h @@ -226,6 +226,9 @@ slist->level = 0; \ slist->length = 0; \ slist->max = (size_t)(max < 0 ? -max : max); \ + slist->max = SKIPLIST_MAX_HEIGHT == 1 ? slist->max : SKIPLIST_MAX_HEIGHT; \ + if (SKIPLIST_MAX_HEIGHT > 1 && slist->max > SKIPLIST_MAX_HEIGHT) \ + return -1; \ slist->cmp = cmp; \ rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \ if (rc) \ @@ -241,8 +244,9 @@ for (i = 0; i < slist->max; i++) \ slist->slh_tail->field.sle.next[i] = NULL; \ slist->slh_head->field.sle_prev = slist->slh_tail; \ - /* Testing aid: set `max` to a negative number to seed the PRNG in a \ - predictable way and have reproducible numbers. */ \ + /* NOTE: Here's a testing aid, simply set `max` to a negative number to \ + * seed the PRNG in a predictable way and have reproducible random numbers. \ + */ \ if (max < 0) \ srand(-max); \ else \ @@ -315,7 +319,7 @@ /* -- __skip_insert_ */ \ static int __skip_insert_##decl(decl##_t *slist, decl##_node_t *n, int flags) \ { \ - static decl##_node_t apath[SKIPLIST_MAX_HEIGHT]; \ + static decl##_node_t apath[SKIPLIST_MAX_HEIGHT + 1]; \ size_t i, len, level; \ decl##_node_t *node, **path = (decl##_node_t **)&apath; \ \ @@ -344,13 +348,17 @@ path[i + 1]->field.sle.next[i] = n; \ } else { \ n->field.sle.next[i] = slist->slh_tail; \ - slist->level++; \ } \ } \ n->field.sle_prev = path[1]; \ if (n->field.sle.next[0] == slist->slh_tail) { \ slist->slh_tail->field.sle_prev = n; \ } \ + if (level > slist->level) { \ + slist->level = level; \ + slist->slh_head->entries.sle.len = slist->level; \ + slist->slh_tail->entries.sle.len = slist->level; \ + } \ slist->length++; \ \ if (SKIPLIST_MAX_HEIGHT == 1) \ @@ -476,7 +484,7 @@ /* -- skip_remove_ */ \ int prefix##skip_remove_##decl(decl##_t *slist, decl##_node_t *n) \ { \ - static decl##_node_t apath[SKIPLIST_MAX_HEIGHT]; \ + static decl##_node_t apath[SKIPLIST_MAX_HEIGHT + 1]; \ size_t i, len, level; \ decl##_node_t *node, **path = (decl##_node_t **)&apath; \ \ @@ -511,9 +519,13 @@ \ /* Find all levels in the first element in the list that point \ at the tail and shrink the level. */ \ - while (slist->level > 0 && slist->slh_head->field.sle.next[slist->level] == slist->slh_tail) { \ - slist->level--; \ - } \ + i = 0; \ + node = slist->slh_head; \ + while (node->field.sle.next[i] != slist->slh_tail && i++ < slist->level) \ + ; \ + slist->level = i; \ + slist->slh_head->field.sle.len = i; \ + slist->slh_tail->field.sle.len = i; \ slist->length--; \ } \ return 0; \