Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add find existant vs non-existant keys #46

Merged
merged 12 commits into from
Dec 13, 2024
49 changes: 25 additions & 24 deletions src/flat_hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ first thought. However, improvements can still be made. */
#include "impl/impl_types.h"
#include "types.h"

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -198,7 +197,7 @@ ccc_fhm_size(ccc_flat_hash_map const *const h)
}

ccc_fhmap_entry
ccc_fhm_entry(ccc_flat_hash_map *h, void const *const key)
ccc_fhm_entry(ccc_flat_hash_map *const h, void const *const key)
{
if (unlikely(!h || !key))
{
Expand Down Expand Up @@ -269,7 +268,7 @@ ccc_fhm_and_modify(ccc_fhmap_entry *const e, ccc_update_fn *const fn)

ccc_fhmap_entry *
ccc_fhm_and_modify_aux(ccc_fhmap_entry *const e, ccc_update_fn *const fn,
void *aux)
void *const aux)
{
if (unlikely(!e))
{
Expand All @@ -283,7 +282,7 @@ ccc_fhm_and_modify_aux(ccc_fhmap_entry *const e, ccc_update_fn *const fn,
}

ccc_entry
ccc_fhm_insert(ccc_flat_hash_map *h, ccc_fhmap_elem *const out_handle)
ccc_fhm_insert(ccc_flat_hash_map *const h, ccc_fhmap_elem *const out_handle)
{
if (unlikely(!h || !out_handle))
{
Expand Down Expand Up @@ -332,7 +331,8 @@ ccc_fhm_try_insert(ccc_flat_hash_map *const h,
}

ccc_entry
ccc_fhm_insert_or_assign(ccc_flat_hash_map *h, ccc_fhmap_elem *key_val_handle)
ccc_fhm_insert_or_assign(ccc_flat_hash_map *const h,
ccc_fhmap_elem *const key_val_handle)
{
if (unlikely(!h || !key_val_handle))
{
Expand Down Expand Up @@ -442,28 +442,28 @@ ccc_fhm_begin(ccc_flat_hash_map const *const h)
{
return NULL;
}
void *iter = ccc_buf_begin(&h->buf_);
void const *iter = ccc_buf_begin(&h->buf_);
for (; iter != ccc_buf_capacity_end(&h->buf_)
&& elem_in_slot(h, iter)->hash_ == CCC_FHM_EMPTY;
iter = ccc_buf_next(&h->buf_, iter))
{}
return iter == ccc_buf_capacity_end(&h->buf_) ? NULL : iter;
return (void *)(iter == ccc_buf_capacity_end(&h->buf_) ? NULL : iter);
}

void *
ccc_fhm_next(ccc_flat_hash_map const *const h, ccc_fhmap_elem const *iter)
ccc_fhm_next(ccc_flat_hash_map const *const h, ccc_fhmap_elem const *const iter)
{
if (unlikely(!h))
{
return NULL;
}
void *i = struct_base(h, iter);
void const *i = struct_base(h, iter);
for (i = ccc_buf_next(&h->buf_, i);
i != ccc_buf_capacity_end(&h->buf_)
&& elem_in_slot(h, i)->hash_ == CCC_FHM_EMPTY;
i = ccc_buf_next(&h->buf_, i))
{}
return i == ccc_buf_capacity_end(&h->buf_) ? NULL : i;
return (void *)(i == ccc_buf_capacity_end(&h->buf_) ? NULL : i);
}

void *
Expand All @@ -473,7 +473,7 @@ ccc_fhm_end(ccc_flat_hash_map const *const)
}

size_t
ccc_fhm_next_prime(size_t n)
ccc_fhm_next_prime(size_t const n)
{
return next_prime(n);
}
Expand Down Expand Up @@ -607,7 +607,8 @@ ccc_fhm_validate(ccc_flat_hash_map const *const h)
}

static bool
valid_distance_from_home(struct ccc_fhmap_ const *h, void const *slot)
valid_distance_from_home(struct ccc_fhmap_ const *const h,
void const *const slot)
{
size_t const cap = ccc_buf_capacity(&h->buf_);
uint64_t const hash = elem_in_slot(h, slot)->hash_;
Expand Down Expand Up @@ -640,7 +641,7 @@ valid_distance_from_home(struct ccc_fhmap_ const *h, void const *slot)
/*======================= Private Interface =============================*/

struct ccc_fhash_entry_
ccc_impl_fhm_entry(struct ccc_fhmap_ *h, void const *key)
ccc_impl_fhm_entry(struct ccc_fhmap_ *const h, void const *const key)
{
return container_entry(h, key);
}
Expand All @@ -667,7 +668,7 @@ ccc_impl_fhm_insert(struct ccc_fhmap_ *const h, void const *const e,
}

ccc_result
ccc_impl_fhm_maybe_resize(struct ccc_fhmap_ *h)
ccc_impl_fhm_maybe_resize(struct ccc_fhmap_ *const h)
{
return maybe_resize(h);
}
Expand All @@ -679,7 +680,8 @@ ccc_impl_fhm_in_slot(struct ccc_fhmap_ const *const h, void const *const slot)
}

void *
ccc_impl_fhm_key_in_slot(struct ccc_fhmap_ const *h, void const *slot)
ccc_impl_fhm_key_in_slot(struct ccc_fhmap_ const *const h,
void const *const slot)
{
return key_in_slot(h, slot);
}
Expand All @@ -691,7 +693,7 @@ ccc_impl_fhm_distance(size_t const capacity, size_t const i, size_t const j)
}

size_t
ccc_impl_fhm_increment(size_t const capacity, size_t i)
ccc_impl_fhm_increment(size_t const capacity, size_t const i)
{
return increment(capacity, i);
}
Expand All @@ -717,7 +719,7 @@ ccc_impl_fhm_filter(struct ccc_fhmap_ const *const h, void const *const key)
/*======================= Static Helpers =============================*/

static inline struct ccc_ent_
entry(struct ccc_fhmap_ *const h, void const *key, uint64_t const hash)
entry(struct ccc_fhmap_ *const h, void const *const key, uint64_t const hash)
{
char upcoming_insertion_error = 0;
if (maybe_resize(h) != CCC_OK)
Expand Down Expand Up @@ -923,9 +925,9 @@ maybe_resize(struct ccc_fhmap_ *const h)
}

static inline size_t
next_prime(size_t n)
next_prime(size_t const n)
{
/* Compiler should help us out here. No need to do fancy bit tricks to
/* Compiler should help us out here. No fancy binary search/tricks to
tell how far along the list we are. The table is small already. */
for (size_t i = 0; i < PRIMES_SIZE; ++i)
{
Expand Down Expand Up @@ -972,16 +974,15 @@ distance(size_t const capacity, size_t const i, size_t const j)
}

static inline size_t
increment(size_t const capacity, size_t i)
increment(size_t const capacity, size_t const i)
{
return (i + 1) >= capacity ? last_swap_slot + 1 : i + 1;
}

static inline size_t
decrement(size_t const capacity, size_t i)
decrement(size_t const capacity, size_t const i)
{
i = i ? i - 1 : capacity - 1;
return i <= last_swap_slot ? capacity - 1 : i;
return i <= num_swap_slots ? capacity - 1 : i - 1;
}

static inline void *
Expand All @@ -992,7 +993,7 @@ struct_base(struct ccc_fhmap_ const *const h,
}

static inline void
swap(char tmp[], void *const a, void *const b, size_t ab_size)
swap(char tmp[const], void *const a, void *const b, size_t const ab_size)
{
if (a == b)
{
Expand Down
6 changes: 3 additions & 3 deletions src/flat_ordered_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ ccc_fom_insert(ccc_flat_ordered_map *const fom,
{
return (ccc_entry){{.stats_ = CCC_ENTRY_INPUT_ERROR}};
}
void *found = find(fom, key_from_node(fom, out_handle));
void *const found = find(fom, key_from_node(fom, out_handle));
if (found)
{
assert(fom->root_);
Expand All @@ -211,9 +211,9 @@ ccc_fom_insert(ccc_flat_ordered_map *const fom,
void *const ret = base_at(fom, fom->root_);
void *const tmp = ccc_buf_at(&fom->buf_, 0);
swap(tmp, user_struct, ret, ccc_buf_elem_size(&fom->buf_));
return (ccc_entry){{.e_ = ret, .stats_ = CCC_ENTRY_OCCUPIED}};
return (ccc_entry){{.e_ = user_struct, .stats_ = CCC_ENTRY_OCCUPIED}};
}
void *inserted = maybe_alloc_insert(fom, out_handle);
void *const inserted = maybe_alloc_insert(fom, out_handle);
if (!inserted)
{
return (ccc_entry){{.e_ = NULL, .stats_ = CCC_ENTRY_INSERT_ERROR}};
Expand Down
34 changes: 25 additions & 9 deletions src/flat_priority_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

static size_t const swap_space = 1;

/*===================== Prototypes ================================*/

static void *at(struct ccc_fpq_ const *, size_t);
static size_t index_of(struct ccc_fpq_ const *, void const *);
static bool wins(struct ccc_fpq_ const *, void const *winner,
Expand All @@ -19,6 +21,8 @@ static size_t bubble_up(struct ccc_fpq_ *fpq, char tmp[], size_t i);
static size_t bubble_down(struct ccc_fpq_ *, char tmp[], size_t);
static size_t update_fixup(struct ccc_fpq_ *, void *e);

/*===================== Interface ================================*/

ccc_result
ccc_fpq_alloc(ccc_flat_priority_queue *const fpq, size_t const new_capacity,
ccc_alloc_fn *const fn)
Expand Down Expand Up @@ -155,7 +159,7 @@ ccc_fpq_erase(ccc_flat_priority_queue *const fpq, void *const e)

void *
ccc_fpq_update(ccc_flat_priority_queue *const fpq, void *const e,
ccc_update_fn *fn, void *aux)
ccc_update_fn *const fn, void *const aux)
{
if (!fpq || !e || !fn || ccc_buf_is_empty(&fpq->buf_))
{
Expand Down Expand Up @@ -335,7 +339,7 @@ ccc_fpq_validate(ccc_flat_priority_queue const *const fpq)
return true;
}

/*=========================== Implementation ========================== */
/*=================== Private Interface =============================*/

size_t
ccc_impl_fpq_bubble_up(struct ccc_fpq_ *const fpq, char tmp[], size_t i)
Expand Down Expand Up @@ -364,8 +368,9 @@ ccc_impl_fpq_in_place_heapify(struct ccc_fpq_ *const fpq, size_t const n)
}
}

/*=============================== Static Helpers =========================*/
/*==================== Static Helpers ===============================*/

/* Fixes the position of element e after its key value has been changed. */
static inline size_t
update_fixup(struct ccc_fpq_ *const fpq, void *const e)
{
Expand All @@ -389,11 +394,13 @@ update_fixup(struct ccc_fpq_ *const fpq, void *const e)
return i;
}

/* Returns the sorted position of the element starting at position i. */
static inline size_t
bubble_up(struct ccc_fpq_ *const fpq, char tmp[], size_t i)
bubble_up(struct ccc_fpq_ *const fpq, char tmp[const], size_t i)
{
for (size_t parent = (i - 1) / 2; i; i = parent, parent = (parent - 1) / 2)
{
/* Not winning here means we are in correct order or equal. */
if (!wins(fpq, at(fpq, i), at(fpq, parent)))
{
return i;
Expand All @@ -403,16 +410,17 @@ bubble_up(struct ccc_fpq_ *const fpq, char tmp[], size_t i)
return 0;
}

/* Returns the sorted position of the element starting at position i. */
static inline size_t
bubble_down(struct ccc_fpq_ *const fpq, char tmp[], size_t i)
bubble_down(struct ccc_fpq_ *const fpq, char tmp[const], size_t i)
{
size_t const sz = ccc_buf_size(&fpq->buf_);
for (size_t next = i, left = (i * 2) + 1, right = left + 1; left < sz;
i = next, left = (i * 2) + 1, right = left + 1)
{
/* Avoid one comparison call if there is no right child. */
next = right < sz && wins(fpq, at(fpq, right), at(fpq, left)) ? right
: left;
next = (right < sz && wins(fpq, at(fpq, right), at(fpq, left))) ? right
: left;
/* If the child beats the parent we must swap. Equal is ok to break. */
if (!wins(fpq, at(fpq, next), at(fpq, i)))
{
Expand All @@ -423,8 +431,11 @@ bubble_down(struct ccc_fpq_ *const fpq, char tmp[], size_t i)
return i;
}

/* Swaps i and j using the underlying buffer capabilities. Not checked for
an error in release. */
static inline void
swap(struct ccc_fpq_ *const fpq, char tmp[], size_t const i, size_t const j)
swap(struct ccc_fpq_ *const fpq, char tmp[const], size_t const i,
size_t const j)
{
[[maybe_unused]] ccc_result const res = ccc_buf_swap(&fpq->buf_, tmp, i, j);
assert(res == CCC_OK);
Expand All @@ -440,7 +451,7 @@ at(struct ccc_fpq_ const *const fpq, size_t const i)
return addr;
}

/* Flat pqueue code that uses indices of the underlying buffer should always
/* Flat pq code that uses indices of the underlying buffer should always
be within the buffer range. It should never exceed the current size and
start at or after the buffer base. Only checked in debug. */
static inline size_t
Expand All @@ -453,6 +464,11 @@ index_of(struct ccc_fpq_ const *const fpq, void const *const slot)
return i;
}

/* Returns true if the winner (the "left hand side") wins the comparison.
Winning in a three-way comparison means satisfying the total order of the
priority queue. So, there is no winner if the elements are equal and this
function would return false. If the winner is in the wrong order, thus
losing the total order comparison, the function also returns false. */
static inline bool
wins(struct ccc_fpq_ const *const fpq, void const *const winner,
void const *const loser)
Expand Down
Loading
Loading