From bfc5c76b30910ca2af9ed0e8958270b8810d02cf Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Sun, 31 Mar 2024 21:22:04 -0400 Subject: [PATCH] splay v1/p2; decent cond --- Makefile | 4 ++-- include/sl.h | 63 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 0d230c0..142d61c 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ test: $(TESTS) # env LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test tests/test: $(TEST_OBJS) $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) -pthread + $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) -lm -pthread clean: rm -f $(OBJS) munit.o test.o @@ -61,7 +61,7 @@ examples/mls.c: examples/slm.c # $(CC) $(CFLAGS) -C -E examples/slm.c | sed -e '1,7d' -e 's/^#\( [0-9]* ".*$$\)/\/\* \1 \*\//' | clang-format > examples/mls.c examples/mls: examples/mls.o $(STATIC_LIB) - $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) -pthread + $(CC) $^ -o $@ $(CFLAGS) $(TEST_FLAGS) -lm -pthread #dot: # ./examples/mls diff --git a/include/sl.h b/include/sl.h index b91dc5d..a3d52b0 100644 --- a/include/sl.h +++ b/include/sl.h @@ -31,8 +31,14 @@ * Zhipeng Li */ +#define _USE_MATH_DEFINES // needed to have definition of M_LOG2E +#define _GNU_SOURCE + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" #include #include +#include #include #include #include @@ -41,6 +47,7 @@ #include #include #include +#pragma GCC diagnostic pop #ifndef _SKIPLIST_H_ #define _SKIPLIST_H_ @@ -254,7 +261,8 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li void (*snapshot_record_era)(struct decl *, decl##_node_t *); \ } slh_fns; \ struct { \ - size_t threshold; \ + size_t threshold; /* `k`, the floor of log(max height) */ \ + size_t total_hits; /* total hits across nodes in the list */ \ } slh_splay; \ struct { \ size_t era; \ @@ -403,6 +411,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li slist->slh_max_height = SKIPLIST_MAX_HEIGHT == 1 ? slist->slh_max_height : SKIPLIST_MAX_HEIGHT; \ if (SKIPLIST_MAX_HEIGHT > 1 && slist->slh_max_height > SKIPLIST_MAX_HEIGHT) \ return -1; \ + slist->slh_splay.threshold = floor(log(max) / M_LOG2E); \ slist->slh_fns.free_entry = __skip_free_entry_fn_##decl; \ slist->slh_fns.update_entry = __skip_update_entry_fn_##decl; \ slist->slh_fns.archive_entry = __skip_archive_entry_fn_##decl; \ @@ -579,17 +588,37 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li return nodes; \ } \ \ - /** \ - * -- __skip_rebalance_ TODO \ - * \ - */ \ - static void __skip_rebalance_##decl(decl##_t *slist, size_t len, decl##_node_t **path, size_t par_sum) \ - { \ - ((void)slist); \ - ((void)len); \ - ((void)path); \ - ((void)par_sum); \ - } \ + /** \ + * -- __skip_rebalance_ TODO \ + * \ + */ \ + static void __skip_rebalance_##decl(decl##_t *slist, size_t len, decl##_node_t **path, size_t par_sum) \ + { \ + size_t i; \ + double asc_cond, dsc_cond; \ + \ + /* Moving backwards along the path... */ \ + for (i = 1; i <=len; i++) { \ + if (par_sum > 0) { \ + /* check the decent condition: \ + par_sum <= hits total / (2 ^ (height of head - height of node)) \ + */ \ + dsc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i]->field.sle_height); \ + if (0 && par_sum <= dsc_cond) { \ + /* reduce height by one, change forward pointer */ \ + path[i - 1]->field.sle_next[i] = path[i]->field.sle_next[i]; \ + path[i]->field.sle_next[i] = slist->slh_tail; \ + path[i]->field.sle_height--; \ + } \ + /* check the ascent condition \ + par_sum + node_hits > hits total / (2 ^ (height of head - height of node - 1)) \ + */ \ + asc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i]->field.sle_height - 1); \ + if (+ path[i]->field.sle_hits > asc_cond) { \ + } \ + } \ + } \ + } \ \ /** \ * -- __skip_locate_ \ @@ -706,7 +735,9 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li slist->slh_head->field.sle_height = new_height; \ slist->slh_tail->field.sle_height = new_height; \ } \ - /* Record the era for this node to enable snapshots. */ \ + /* Adjust the splay threshold based on the height. */ \ + slist->slh_splay.threshold = floor(log(slist->slh_head->field.sle_height) / M_LOG2E); \ + /* Record the era for this node to enable snapshots. */ \ if (slist->slh_fns.snapshot_record_era) \ slist->slh_fns.snapshot_record_era(slist, new); \ /* Increase our list length (aka. size, count, etc.) by one. */ \ @@ -1058,12 +1089,14 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li \ slist->slh_fns.free_entry(node); \ \ - /* Reduce the height of the header. */ \ + /* Reduce the height of the head node. */ \ i = 0; \ while (slist->slh_head->field.sle_next[i] != slist->slh_tail && i < slist->slh_head->field.sle_height) \ i++; \ slist->slh_head->field.sle_height = i; \ slist->slh_tail->field.sle_height = i; \ + /* Adjust the splay threshold based on the height. */ \ + slist->slh_splay.threshold = floor(log(slist->slh_head->field.sle_height) / M_LOG2E); \ \ slist->slh_length--; \ } \ @@ -1218,7 +1251,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li } \ \ /** \ - * -- skip_restore_snapshot_ \ + * -- skip_restore_snapshot_ TODO test! \ * \ * Restores the Skiplist to generation `era`. Once you restore `era` you \ * can no longer access any generations > `era`. \