Fixes
This commit is contained in:
parent
0275f505fc
commit
32d06df14e
1 changed files with 25 additions and 11 deletions
36
include/sl.h
36
include/sl.h
|
@ -61,10 +61,10 @@
|
||||||
*
|
*
|
||||||
* A skiplist is a sorted list with O(log(n)) on average for most operations.
|
* A skiplist is a sorted list with O(log(n)) on average for most operations.
|
||||||
* It is a probabilistic datastructure, meaning that it does not guarantee
|
* It is a probabilistic datastructure, meaning that it does not guarantee
|
||||||
* O(log(n)) it approximates it over time. This implementation includes
|
* O(log(n)) it approximates it over time. This implementation improves the
|
||||||
* improves the probability by integrating the splay list algorithm for
|
* probability by integrating the splay list algorithm for rebalancing trading
|
||||||
* rebalancing trading off a bit of computational overhead and code complexity
|
* off a bit of computational overhead and code complexity for a nearly always
|
||||||
* for a nearly always optimal, or "perfect" skiplist.
|
* optimal, or "perfect" skiplist.
|
||||||
*
|
*
|
||||||
* Conceptually, a skiplist is arranged as follows:
|
* Conceptually, a skiplist is arranged as follows:
|
||||||
*
|
*
|
||||||
|
@ -235,8 +235,8 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
#define __SKIP_IS_LAST_ENTRY_T2B() if (lvl == 0)
|
#define __SKIP_IS_LAST_ENTRY_T2B() if (lvl == 0)
|
||||||
|
|
||||||
#define __SKIP_ALL_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl < slist->slh_max_height; lvl++)
|
#define __SKIP_ALL_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl < slist->slh_max_height; lvl++)
|
||||||
#define __SKIP_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl < elm->field.sle_height; lvl++)
|
#define __SKIP_ENTRIES_B2T(field, elm) for (size_t lvl = 0; lvl <= elm->field.sle_height; lvl++)
|
||||||
#define __SKIP_ENTRIES_B2T_FROM(field, elm, off) for (size_t lvl = off; lvl < elm->field.sle_height; lvl++)
|
#define __SKIP_ENTRIES_B2T_FROM(field, elm, off) for (size_t lvl = off; lvl <= elm->field.sle_height; lvl++)
|
||||||
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle_height)
|
#define __SKIP_IS_LAST_ENTRY_B2T() if (lvl + 1 == elm->field.sle_height)
|
||||||
|
|
||||||
/* Iterate over the subtree to the left (v, or 'lt') and right (u) or "CHu" and "CHv". */
|
/* Iterate over the subtree to the left (v, or 'lt') and right (u) or "CHu" and "CHv". */
|
||||||
|
@ -263,6 +263,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
struct decl { \
|
struct decl { \
|
||||||
size_t slh_length, slh_max_height; \
|
size_t slh_length, slh_max_height; \
|
||||||
void *slh_aux; \
|
void *slh_aux; \
|
||||||
|
int slh_prng_state; \
|
||||||
decl##_node_t *slh_head; \
|
decl##_node_t *slh_head; \
|
||||||
decl##_node_t *slh_tail; \
|
decl##_node_t *slh_tail; \
|
||||||
struct { \
|
struct { \
|
||||||
|
@ -289,6 +290,19 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
size_t pu; /* sum of hits from intersection to level[1] */ \
|
size_t pu; /* sum of hits from intersection to level[1] */ \
|
||||||
} __skiplist_path_##decl##_t; \
|
} __skiplist_path_##decl##_t; \
|
||||||
\
|
\
|
||||||
|
/* Xorshift algorithm for PRNG */ \
|
||||||
|
static uint32_t __##decl##_xorshift32(int *state) \
|
||||||
|
{ \
|
||||||
|
uint32_t x = *state; \
|
||||||
|
if (x == 0) \
|
||||||
|
x = 123456789; \
|
||||||
|
x ^= x << 13; \
|
||||||
|
x ^= x >> 17; \
|
||||||
|
x ^= x << 5; \
|
||||||
|
*state = x; \
|
||||||
|
return x; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
/** \
|
/** \
|
||||||
* -- __skip_compare_entries_fn_ \
|
* -- __skip_compare_entries_fn_ \
|
||||||
* \
|
* \
|
||||||
|
@ -379,12 +393,12 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
* Skiplist. For example, when `max = 6` this function returns 0 with \
|
* Skiplist. For example, when `max = 6` this function returns 0 with \
|
||||||
* probability 0.5, 1 with 0.25, 2 with 0.125, etc. until 6 with 0.5^7. \
|
* probability 0.5, 1 with 0.25, 2 with 0.125, etc. until 6 with 0.5^7. \
|
||||||
*/ \
|
*/ \
|
||||||
static int __skip_toss_##decl(size_t max) \
|
static int __skip_toss_##decl(decl##_t *slist, size_t max) \
|
||||||
{ \
|
{ \
|
||||||
size_t level = 0; \
|
size_t level = 0; \
|
||||||
double probability = 0.5; \
|
double probability = 0.5; \
|
||||||
\
|
\
|
||||||
double random_value = (double)rand() / RAND_MAX; /* NOLINT(*-msc50-cpp) */ \
|
double random_value = (double)__##decl##_xorshift32(&slist->slh_prng_state) / RAND_MAX; \
|
||||||
while (random_value < probability && level < max) { \
|
while (random_value < probability && level < max) { \
|
||||||
level++; \
|
level++; \
|
||||||
probability *= 0.5; \
|
probability *= 0.5; \
|
||||||
|
@ -456,9 +470,9 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
* seed the PRNG in a predictable way and have reproducible random numbers. \
|
* seed the PRNG in a predictable way and have reproducible random numbers. \
|
||||||
*/ \
|
*/ \
|
||||||
if (max < 0) \
|
if (max < 0) \
|
||||||
srand(-max); \
|
slist->slh_prng_state = -max; \
|
||||||
else \
|
else \
|
||||||
srand(((unsigned int)time(NULL) ^ getpid())); \
|
slist->slh_prng_state = ((unsigned int)time(NULL) ^ getpid()); \
|
||||||
fail:; \
|
fail:; \
|
||||||
return rc; \
|
return rc; \
|
||||||
} \
|
} \
|
||||||
|
@ -787,7 +801,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
} \
|
} \
|
||||||
/* Coin toss to determine level of this new node [0, max) */ \
|
/* Coin toss to determine level of this new node [0, max) */ \
|
||||||
cur_height = slist->slh_head->field.sle_height; \
|
cur_height = slist->slh_head->field.sle_height; \
|
||||||
new_height = __skip_toss_##decl(slist->slh_max_height - 1); \
|
new_height = __skip_toss_##decl(slist, slist->slh_max_height - 1); \
|
||||||
new->field.sle_height = new_height; \
|
new->field.sle_height = new_height; \
|
||||||
/* Trim the path to at most the new height for the new node. */ \
|
/* Trim the path to at most the new height for the new node. */ \
|
||||||
for (i = cur_height + 1; i <= new_height; i++) { \
|
for (i = cur_height + 1; i <= new_height; i++) { \
|
||||||
|
|
Loading…
Reference in a new issue