From 254bb3eacc1a8395f1851582dd06e3dae7e69a51 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 5 May 2020 18:13:17 -0300 Subject: [PATCH] Renamed multiset to hashmultiset --- autogen.py | 2 +- src/cmc/{multiset.h => hashmultiset.h} | 75 +- tests/main/main.c | 4 +- tests/main/src/hashmultiset.c | 1069 ++++++++++++++++++++++++ tests/main/unt/bitset.c | 3 +- tests/main/unt/hashbidimap.c | 78 +- tests/main/unt/hashmultimap.c | 50 +- tests/main/unt/hashmultiset.c | 426 ++++++++++ tests/main/unt/multiset.c | 425 ---------- 9 files changed, 1607 insertions(+), 525 deletions(-) rename src/cmc/{multiset.h => hashmultiset.h} (98%) create mode 100644 tests/main/src/hashmultiset.c create mode 100644 tests/main/unt/hashmultiset.c delete mode 100644 tests/main/unt/multiset.c diff --git a/autogen.py b/autogen.py index c2ce318..751bca7 100644 --- a/autogen.py +++ b/autogen.py @@ -30,12 +30,12 @@ collections = [ {'t': 'HASHBIDIMAP', 'h': '"cmc/hashbidimap.h"', 'pfx': 'hbm', 'sname': 'hashbidimap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'}, {'t': 'HASHMULTIMAP', 'h': '"cmc/hashmultimap.h"', 'pfx': 'hmm', 'sname': 'hashmultimap', 'key': 'size_t', 'val': 'size_t'}, + {'t': 'HASHMULTISET', 'h': '"cmc/hashmultiset.h"', 'pfx': 'hms', 'sname': 'hashmultiset', 'key': '', 'val': 'size_t'}, {'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'}, {'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'}, {'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'}, {'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'}, {'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'}, - {'t': 'MULTISET', 'h': '"cmc/multiset.h"', 'pfx': 'ms', 'sname': 'multiset', 'key': '', 'val': 'size_t'}, {'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'}, {'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'}, {'t': 'STACK', 'h': '"cmc/stack.h"', 'pfx': 's', 'sname': 'stack', 'key': '', 'val': 'size_t'}, diff --git a/src/cmc/multiset.h b/src/cmc/hashmultiset.h similarity index 98% rename from src/cmc/multiset.h rename to src/cmc/hashmultiset.h index ff6045c..6344058 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/hashmultiset.h @@ -1,5 +1,5 @@ /** - * multiset.h + * hashmultiset.h * * Creation Date: 10/04/2019 * @@ -9,17 +9,22 @@ */ /** - * MultiSet + * HashMultiSet * * In mathematics, a multiset is a modification of the concept of a set that, * unlike a set, allows for multiple instances for each of its elements. The * positive integer number of instances, given for each element is called the - * multiplicity of this element in the multiset. A MultiSet also has a + * multiplicity of this element in the multiset. A multiSet also has a * cardinality which equals the sum of the multiplicities of its elements. + * + * Implementation + * + * In this implementation, the values are stored in a flat hashtable and are + * mapped to their multiplicity. */ -#ifndef CMC_MULTISET_H -#define CMC_MULTISET_H +#ifndef CMC_HASHMULTISET_H +#define CMC_HASHMULTISET_H /* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library @@ -32,37 +37,37 @@ #include "../cor/hashtable.h" /* ------------------------------------------------------------------------- - * MultiSet specific + * HashMultiSet specific * ------------------------------------------------------------------------- */ /* to_string format */ -static const char *cmc_string_fmt_multiset = "struct %s<%s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "cardinality:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }"; +static const char *cmc_string_fmt_hashmultiset = "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "cardinality:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }"; -#define CMC_GENERATE_MULTISET(PFX, SNAME, V) \ - CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ - CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) +#define CMC_GENERATE_HASHMULTISET(PFX, SNAME, V) \ + CMC_GENERATE_HASHMULTISET_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_HASHMULTISET_SOURCE(PFX, SNAME, V) -#define CMC_WRAPGEN_MULTISET_HEADER(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) +#define CMC_WRAPGEN_HASHMULTISET_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTISET_HEADER(PFX, SNAME, V) -#define CMC_WRAPGEN_MULTISET_SOURCE(PFX, SNAME, K, V) \ - CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) +#define CMC_WRAPGEN_HASHMULTISET_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMULTISET_SOURCE(PFX, SNAME, V) /* ------------------------------------------------------------------------- * Header * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ +#define CMC_GENERATE_HASHMULTISET_HEADER(PFX, SNAME, V) \ \ - /* Hashset Structure */ \ + /* HashMultiset Structure */ \ struct SNAME \ { \ /* Array of Entries */ \ @@ -92,10 +97,10 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " /* Custom callback functions */ \ struct cmc_callbacks *callbacks; \ \ - /* Function that returns an iterator to the start of the hashset */ \ + /* Returns an iterator to the start of the hashmultiset */ \ struct SNAME##_iter (*it_start)(struct SNAME *); \ \ - /* Function that returns an iterator to the end of the hashset */ \ + /* Returns an iterator to the end of the hashmultiset */ \ struct SNAME##_iter (*it_end)(struct SNAME *); \ }; \ \ @@ -107,8 +112,8 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " /* The element's multiplicity */ \ size_t multiplicity; \ \ - /* The distance of this node to its original position, used by \ - * robin-hood hashing */ \ + /* The distance of this node to its original position, used by */ \ + /* robin-hood hashing */ \ size_t dist; \ \ /* The sate of this node (DELETED, EMPTY, FILLED) */ \ @@ -137,10 +142,10 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " int (*pri)(V, V); \ }; \ \ - /* Hashset Iterator */ \ + /* HashMultiset Iterator */ \ struct SNAME##_iter \ { \ - /* Target Hashset */ \ + /* Target HashMultiset */ \ struct SNAME *target; \ \ /* Cursor's position (index) */ \ @@ -240,7 +245,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " /* ------------------------------------------------------------------------- * Source * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) \ +#define CMC_GENERATE_HASHMULTISET_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static size_t PFX##_impl_multiplicity_of(struct SNAME *_set_, V value); \ @@ -867,7 +872,7 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " struct cmc_string str; \ struct SNAME *s_ = _set_; \ \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmultiset, \ #SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \ s_->cardinality, s_->load, s_->flag, s_->f_val, \ s_->alloc, s_->callbacks); \ @@ -1537,4 +1542,4 @@ static const char *cmc_string_fmt_multiset = "struct %s<%s> " return iter; \ } -#endif /* CMC_MULTISET_H */ +#endif /* CMC_HASHMULTISET_H */ diff --git a/tests/main/main.c b/tests/main/main.c index ad5422e..85b5410 100644 --- a/tests/main/main.c +++ b/tests/main/main.c @@ -5,12 +5,12 @@ #include "unt/hashbidimap.c" #include "unt/hashmap.c" #include "unt/hashmultimap.c" +#include "unt/hashmultiset.c" #include "unt/hashset.c" #include "unt/heap.c" #include "unt/intervalheap.c" #include "unt/linkedlist.c" #include "unt/list.c" -#include "unt/multiset.c" #include "unt/queue.c" #include "unt/sortedlist.c" #include "unt/stack.c" @@ -55,12 +55,12 @@ int main(void) cmc_run(HashMap, units, tests); cmc_run(HashMapIter, units, tests); cmc_run(HashMultiMap, units, tests); + cmc_run(HashMultiSet, units, tests); cmc_run(HashSet, units, tests); cmc_run(Heap, units, tests); cmc_run(IntervalHeap, units, tests); cmc_run(LinkedList, units, tests); cmc_run(List, units, tests); - cmc_run(MultiSet, units, tests); cmc_run(Queue, units, tests); cmc_run(SortedList, units, tests); cmc_run(Stack, units, tests); diff --git a/tests/main/src/hashmultiset.c b/tests/main/src/hashmultiset.c new file mode 100644 index 0000000..dc709c8 --- /dev/null +++ b/tests/main/src/hashmultiset.c @@ -0,0 +1,1069 @@ +#include "cmc/hashmultiset.h" + +struct hashmultiset +{ + struct hashmultiset_entry *buffer; + size_t capacity; + size_t count; + size_t cardinality; + double load; + int flag; + struct hashmultiset_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; + struct hashmultiset_iter (*it_start)(struct hashmultiset *); + struct hashmultiset_iter (*it_end)(struct hashmultiset *); +}; +struct hashmultiset_entry +{ + size_t value; + size_t multiplicity; + size_t dist; + enum cmc_entry_state state; +}; +struct hashmultiset_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmultiset_iter +{ + struct hashmultiset *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashmultiset *hms_new(size_t capacity, double load, + struct hashmultiset_fval *f_val); +struct hashmultiset *hms_new_custom(size_t capacity, double load, + struct hashmultiset_fval *f_val, + struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void hms_clear(struct hashmultiset *_set_); +void hms_free(struct hashmultiset *_set_); +void hms_customize(struct hashmultiset *_set_, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +_Bool hms_insert(struct hashmultiset *_set_, size_t value); +_Bool hms_insert_many(struct hashmultiset *_set_, size_t value, size_t count); +_Bool hms_update(struct hashmultiset *_set_, size_t value, size_t multiplicity); +_Bool hms_remove(struct hashmultiset *_set_, size_t value); +size_t hms_remove_all(struct hashmultiset *_set_, size_t value); +_Bool hms_max(struct hashmultiset *_set_, size_t *value); +_Bool hms_min(struct hashmultiset *_set_, size_t *value); +size_t hms_multiplicity_of(struct hashmultiset *_set_, size_t value); +_Bool hms_contains(struct hashmultiset *_set_, size_t value); +_Bool hms_empty(struct hashmultiset *_set_); +_Bool hms_full(struct hashmultiset *_set_); +size_t hms_count(struct hashmultiset *_set_); +size_t hms_cardinality(struct hashmultiset *_set_); +size_t hms_capacity(struct hashmultiset *_set_); +double hms_load(struct hashmultiset *_set_); +int hms_flag(struct hashmultiset *_set_); +_Bool hms_resize(struct hashmultiset *_set_, size_t capacity); +struct hashmultiset *hms_copy_of(struct hashmultiset *_set_); +_Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct cmc_string hms_to_string(struct hashmultiset *_set_); +_Bool hms_print(struct hashmultiset *_set_, FILE *fptr); +struct hashmultiset *hms_union(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +struct hashmultiset *hms_intersection(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +struct hashmultiset *hms_difference(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +struct hashmultiset *hms_summation(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +struct hashmultiset *hms_symmetric_difference(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +_Bool hms_is_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_proper_subset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +_Bool hms_is_proper_superset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +_Bool hms_is_disjointset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_); +struct hashmultiset_iter *hms_iter_new(struct hashmultiset *target); +void hms_iter_free(struct hashmultiset_iter *iter); +void hms_iter_init(struct hashmultiset_iter *iter, struct hashmultiset *target); +_Bool hms_iter_start(struct hashmultiset_iter *iter); +_Bool hms_iter_end(struct hashmultiset_iter *iter); +void hms_iter_to_start(struct hashmultiset_iter *iter); +void hms_iter_to_end(struct hashmultiset_iter *iter); +_Bool hms_iter_next(struct hashmultiset_iter *iter); +_Bool hms_iter_prev(struct hashmultiset_iter *iter); +_Bool hms_iter_advance(struct hashmultiset_iter *iter, size_t steps); +_Bool hms_iter_rewind(struct hashmultiset_iter *iter, size_t steps); +_Bool hms_iter_go_to(struct hashmultiset_iter *iter, size_t index); +size_t hms_iter_value(struct hashmultiset_iter *iter); +size_t hms_iter_multiplicity(struct hashmultiset_iter *iter); +size_t hms_iter_index(struct hashmultiset_iter *iter); +static size_t hms_impl_multiplicity_of(struct hashmultiset *_set_, + size_t value); +static struct hashmultiset_entry * +hms_impl_insert_and_return(struct hashmultiset *_set_, size_t value, + _Bool *new_node); +static struct hashmultiset_entry *hms_impl_get_entry(struct hashmultiset *_set_, + size_t value); +static size_t hms_impl_calculate_size(size_t required); +static struct hashmultiset_iter hms_impl_it_start(struct hashmultiset *_set_); +static struct hashmultiset_iter hms_impl_it_end(struct hashmultiset *_set_); +struct hashmultiset *hms_new(size_t capacity, double load, + struct hashmultiset_fval *f_val) +{ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_val) + return ((void *)0); + size_t real_capacity = hms_impl_calculate_size(capacity / load); + struct hashmultiset *_set_ = alloc->malloc(sizeof(struct hashmultiset)); + if (!_set_) + return ((void *)0); + _set_->buffer = + alloc->calloc(real_capacity, sizeof(struct hashmultiset_entry)); + if (!_set_->buffer) + { + alloc->free(_set_); + return ((void *)0); + } + _set_->count = 0; + _set_->cardinality = 0; + _set_->capacity = real_capacity; + _set_->load = load; + _set_->flag = cmc_flags.OK; + _set_->f_val = f_val; + _set_->alloc = alloc; + _set_->callbacks = ((void *)0); + _set_->it_start = hms_impl_it_start; + _set_->it_end = hms_impl_it_end; + return _set_; +} +struct hashmultiset *hms_new_custom(size_t capacity, double load, + struct hashmultiset_fval *f_val, + struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_val) + return ((void *)0); + size_t real_capacity = hms_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct hashmultiset *_set_ = alloc->malloc(sizeof(struct hashmultiset)); + if (!_set_) + return ((void *)0); + _set_->buffer = + alloc->calloc(real_capacity, sizeof(struct hashmultiset_entry)); + if (!_set_->buffer) + { + alloc->free(_set_); + return ((void *)0); + } + _set_->count = 0; + _set_->cardinality = 0; + _set_->capacity = real_capacity; + _set_->load = load; + _set_->flag = cmc_flags.OK; + _set_->f_val = f_val; + _set_->alloc = alloc; + _set_->callbacks = callbacks; + _set_->it_start = hms_impl_it_start; + _set_->it_end = hms_impl_it_end; + return _set_; +} +void hms_clear(struct hashmultiset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + memset(_set_->buffer, 0, + sizeof(struct hashmultiset_entry) * _set_->capacity); + _set_->count = 0; + _set_->flag = cmc_flags.OK; +} +void hms_free(struct hashmultiset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + _set_->alloc->free(_set_->buffer); + _set_->alloc->free(_set_); +} +void hms_customize(struct hashmultiset *_set_, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + if (!alloc) + _set_->alloc = &cmc_alloc_node_default; + else + _set_->alloc = alloc; + _set_->callbacks = callbacks; + _set_->flag = cmc_flags.OK; +} +_Bool hms_insert(struct hashmultiset *_set_, size_t value) +{ + _Bool new_node; + struct hashmultiset_entry *entry = + hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + { + _set_->flag = cmc_flags.ERROR; + return 0; + } + if (!new_node) + entry->multiplicity++; + _set_->cardinality++; + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->create) + _set_->callbacks->create(); + return 1; +} +_Bool hms_insert_many(struct hashmultiset *_set_, size_t value, size_t count) +{ + if (count == 0) + goto success; + _Bool new_node; + struct hashmultiset_entry *entry = + hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + { + _set_->flag = cmc_flags.ERROR; + return 0; + } + if (new_node) + entry->multiplicity = count; + else + entry->multiplicity += count; + _set_->cardinality += count; +success: + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->create) + _set_->callbacks->create(); + return 1; +} +_Bool hms_update(struct hashmultiset *_set_, size_t value, size_t multiplicity) +{ + if (multiplicity == 0) + { + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + goto success; + _set_->count--; + _set_->cardinality -= result->multiplicity; + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + goto success; + } + _Bool new_node; + struct hashmultiset_entry *entry = + hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + return 0; + if (new_node) + _set_->cardinality++; + _set_->cardinality = + (_set_->cardinality - entry->multiplicity) + multiplicity; + entry->multiplicity = multiplicity; +success: + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->update) + _set_->callbacks->update(); + return 1; +} +_Bool hms_remove(struct hashmultiset *_set_, size_t value) +{ + if (hms_empty(_set_)) + { + _set_->flag = cmc_flags.EMPTY; + return 0; + } + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + { + _set_->flag = cmc_flags.NOT_FOUND; + return 0; + } + if (result->multiplicity > 1) + result->multiplicity--; + else + { + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + _set_->count--; + } + _set_->cardinality--; + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->delete) + _set_->callbacks->delete (); + return 1; +} +size_t hms_remove_all(struct hashmultiset *_set_, size_t value) +{ + if (hms_empty(_set_)) + { + _set_->flag = cmc_flags.EMPTY; + return 0; + } + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + { + _set_->flag = cmc_flags.NOT_FOUND; + return 0; + } + size_t removed = result->multiplicity; + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + _set_->count--; + _set_->cardinality -= removed; + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->delete) + _set_->callbacks->delete (); + return removed; +} +_Bool hms_max(struct hashmultiset *_set_, size_t *value) +{ + if (hms_empty(_set_)) + { + _set_->flag = cmc_flags.EMPTY; + return 0; + } + size_t max_val; + struct hashmultiset_iter iter; + for (hms_iter_init(&iter, _set_); !hms_iter_end(&iter); + hms_iter_next(&iter)) + { + size_t result = hms_iter_value(&iter); + size_t index = hms_iter_index(&iter); + if (index == 0) + max_val = result; + else if (_set_->f_val->cmp(result, max_val) > 0) + max_val = result; + } + if (value) + *value = max_val; + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->read) + _set_->callbacks->read(); + return 1; +} +_Bool hms_min(struct hashmultiset *_set_, size_t *value) +{ + if (hms_empty(_set_)) + { + _set_->flag = cmc_flags.EMPTY; + return 0; + } + size_t min_val; + struct hashmultiset_iter iter; + for (hms_iter_init(&iter, _set_); !hms_iter_end(&iter); + hms_iter_next(&iter)) + { + size_t result = hms_iter_value(&iter); + size_t index = hms_iter_index(&iter); + if (index == 0) + min_val = result; + else if (_set_->f_val->cmp(result, min_val) < 0) + min_val = result; + } + if (value) + *value = min_val; + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->read) + _set_->callbacks->read(); + return 1; +} +size_t hms_multiplicity_of(struct hashmultiset *_set_, size_t value) +{ + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + _set_->flag = cmc_flags.OK; + if (_set_->callbacks && _set_->callbacks->read) + _set_->callbacks->read(); + if (!entry) + return 0; + return entry->multiplicity; +} +_Bool hms_contains(struct hashmultiset *_set_, size_t value) +{ + _set_->flag = cmc_flags.OK; + _Bool result = hms_impl_get_entry(_set_, value) != ((void *)0); + if (_set_->callbacks && _set_->callbacks->read) + _set_->callbacks->read(); + return result; +} +_Bool hms_empty(struct hashmultiset *_set_) +{ + return _set_->count == 0; +} +_Bool hms_full(struct hashmultiset *_set_) +{ + return (double)_set_->capacity * _set_->load <= (double)_set_->count; +} +size_t hms_count(struct hashmultiset *_set_) +{ + return _set_->count; +} +size_t hms_cardinality(struct hashmultiset *_set_) +{ + return _set_->cardinality; +} +size_t hms_capacity(struct hashmultiset *_set_) +{ + return _set_->capacity; +} +double hms_load(struct hashmultiset *_set_) +{ + return _set_->load; +} +int hms_flag(struct hashmultiset *_set_) +{ + return _set_->flag; +} +_Bool hms_resize(struct hashmultiset *_set_, size_t capacity) +{ + _set_->flag = cmc_flags.OK; + if (_set_->capacity == capacity) + goto success; + if (_set_->capacity > capacity / _set_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _set_->load) + { + _set_->flag = cmc_flags.ERROR; + return 0; + } + size_t theoretical_size = hms_impl_calculate_size(capacity); + if (theoretical_size < _set_->count / _set_->load) + { + _set_->flag = cmc_flags.INVALID; + return 0; + } + struct hashmultiset *_new_set_ = hms_new_custom( + capacity, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); + if (!_new_set_) + { + _set_->flag = cmc_flags.ERROR; + return 0; + } + struct hashmultiset_iter iter; + for (hms_iter_init(&iter, _set_); !hms_iter_end(&iter); + hms_iter_next(&iter)) + { + hms_insert_many(_new_set_, hms_iter_value(&iter), + hms_iter_multiplicity(&iter)); + } + if (_set_->count != _new_set_->count) + { + hms_free(_new_set_); + _set_->flag = cmc_flags.ERROR; + return 0; + } + struct hashmultiset_entry *tmp_b = _set_->buffer; + _set_->buffer = _new_set_->buffer; + _new_set_->buffer = tmp_b; + size_t tmp_c = _set_->capacity; + _set_->capacity = _new_set_->capacity; + _new_set_->capacity = tmp_c; + _new_set_->f_val = &(struct hashmultiset_fval){ ((void *)0) }; + hms_free(_new_set_); +success: + if (_set_->callbacks && _set_->callbacks->resize) + _set_->callbacks->resize(); + return 1; +} +struct hashmultiset *hms_copy_of(struct hashmultiset *_set_) +{ + struct hashmultiset *result = + hms_new_custom(_set_->capacity * _set_->load, _set_->load, _set_->f_val, + _set_->alloc, _set_->callbacks); + if (!result) + { + _set_->flag = cmc_flags.ERROR; + return ((void *)0); + } + if (_set_->f_val->cpy) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *scan = &(_set_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + struct hashmultiset_entry *target = &(result->buffer[i]); + if (scan->state == CMC_ES_DELETED) + target->state = CMC_ES_DELETED; + else + { + target->state = scan->state; + target->dist = scan->dist; + target->multiplicity = scan->multiplicity; + target->value = _set_->f_val->cpy(scan->value); + } + } + } + } + else + memcpy(result->buffer, _set_->buffer, + sizeof(struct hashmultiset_entry) * _set_->capacity); + result->count = _set_->count; + result->cardinality = _set_->cardinality; + _set_->flag = cmc_flags.OK; + return result; +} +_Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + _set1_->flag = cmc_flags.OK; + _set2_->flag = cmc_flags.OK; + if (_set1_->count != _set2_->count) + return 0; + if (_set1_->cardinality != _set2_->cardinality) + return 0; + if (_set1_->count == 0) + return 1; + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set1_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + struct hashmultiset_entry *entry = + hms_impl_get_entry(_set2_, hms_iter_value(&iter)); + if (!entry) + return 0; + if (entry->multiplicity != hms_iter_multiplicity(&iter)) + return 0; + } + return 1; +} +struct cmc_string hms_to_string(struct hashmultiset *_set_) +{ + struct cmc_string str; + struct hashmultiset *s_ = _set_; + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmultiset, + "hashmultiset", "size_t", s_, s_->buffer, s_->capacity, + s_->count, s_->cardinality, s_->load, s_->flag, s_->f_val, + s_->alloc, s_->callbacks); + return n >= 0 ? str : (struct cmc_string){ 0 }; +} +_Bool hms_print(struct hashmultiset *_set_, FILE *fptr) +{ + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (!_set_->f_val->str(fptr, entry->value)) + return 0; + } + } + return 1; +} +struct hashmultiset *hms_union(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, + _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1, iter2; + hms_iter_init(&iter1, _set1_); + hms_iter_init(&iter2, _set2_); + for (hms_iter_to_start(&iter1); !hms_iter_end(&iter1); + hms_iter_next(&iter1)) + { + size_t value = hms_iter_value(&iter1); + size_t m1 = hms_iter_multiplicity(&iter1); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + size_t max_ = m1 > m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + for (hms_iter_to_start(&iter2); !hms_iter_end(&iter2); + hms_iter_next(&iter2)) + { + size_t value = hms_iter_value(&iter2); + size_t m1 = hms_impl_multiplicity_of(_set1_, value); + size_t m2 = hms_iter_multiplicity(&iter2); + size_t max_ = m1 > m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + _set_r_->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_intersection(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, + _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset *_set_A_ = + _set1_->count < _set2_->count ? _set1_ : _set2_; + struct hashmultiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set_A_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set_B_, value); + size_t max_ = m1 < m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + _set_r_->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_difference(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, + _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set1_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + } + _set_r_->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_summation(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, + _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1, iter2; + hms_iter_init(&iter1, _set1_); + hms_iter_init(&iter2, _set2_); + for (hms_iter_to_start(&iter1); !hms_iter_end(&iter1); + hms_iter_next(&iter1)) + { + hms_insert_many(_set_r_, hms_iter_value(&iter1), + hms_iter_multiplicity(&iter1)); + } + for (hms_iter_to_start(&iter2); !hms_iter_end(&iter2); + hms_iter_next(&iter2)) + { + hms_insert_many(_set_r_, hms_iter_value(&iter2), + hms_iter_multiplicity(&iter2)); + } + _set_r_->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_symmetric_difference(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, + _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1, iter2; + hms_iter_init(&iter1, _set1_); + hms_iter_init(&iter2, _set2_); + for (hms_iter_to_start(&iter1); !hms_iter_end(&iter1); + hms_iter_next(&iter1)) + { + size_t value = hms_iter_value(&iter1); + size_t m1 = hms_iter_multiplicity(&iter1); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 != m2) + { + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + else + hms_update(_set_r_, value, m2 - m1); + } + } + for (hms_iter_to_start(&iter2); !hms_iter_end(&iter2); + hms_iter_next(&iter2)) + { + size_t value = hms_iter_value(&iter2); + size_t m1 = hms_impl_multiplicity_of(_set1_, value); + size_t m2 = hms_iter_multiplicity(&iter2); + if (m1 != m2) + { + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + else + hms_update(_set_r_, value, m2 - m1); + } + } + _set_r_->callbacks = _set1_->callbacks; + return _set_r_; +} +_Bool hms_is_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + if (_set1_->count > _set2_->count) + return 0; + if (hms_empty(_set1_)) + return 1; + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set1_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 > m2) + return 0; + } + return 1; +} +_Bool hms_is_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + return hms_is_subset(_set2_, _set1_); +} +_Bool hms_is_proper_subset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + if (_set1_->count >= _set2_->count) + return 0; + if (hms_empty(_set1_)) + { + if (!hms_empty(_set2_)) + return 1; + else + return 0; + } + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set1_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 >= m2) + return 0; + } + return 1; +} +_Bool hms_is_proper_superset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + return hms_is_proper_subset(_set2_, _set1_); +} +_Bool hms_is_disjointset(struct hashmultiset *_set1_, + struct hashmultiset *_set2_) +{ + if (hms_empty(_set1_)) + return 1; + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set1_); + for (hms_iter_to_start(&iter); !hms_iter_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + if (hms_impl_get_entry(_set2_, value) != ((void *)0)) + return 0; + } + return 1; +} +struct hashmultiset_iter *hms_iter_new(struct hashmultiset *target) +{ + struct hashmultiset_iter *iter = + target->alloc->malloc(sizeof(struct hashmultiset_iter)); + if (!iter) + return ((void *)0); + hms_iter_init(iter, target); + return iter; +} +void hms_iter_free(struct hashmultiset_iter *iter) +{ + iter->target->alloc->free(iter); +} +void hms_iter_init(struct hashmultiset_iter *iter, struct hashmultiset *target) +{ + memset(iter, 0, sizeof(struct hashmultiset_iter)); + iter->target = target; + iter->start = 1; + iter->end = hms_empty(target); + if (!hms_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter->first = i; + break; + } + } + iter->cursor = iter->first; + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter->last = i - 1; + break; + } + } + } +} +_Bool hms_iter_start(struct hashmultiset_iter *iter) +{ + return hms_empty(iter->target) || iter->start; +} +_Bool hms_iter_end(struct hashmultiset_iter *iter) +{ + return hms_empty(iter->target) || iter->end; +} +void hms_iter_to_start(struct hashmultiset_iter *iter) +{ + if (!hms_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hms_empty(iter->target); + } +} +void hms_iter_to_end(struct hashmultiset_iter *iter) +{ + if (!hms_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = hms_empty(iter->target); + iter->end = 1; + } +} +_Bool hms_iter_next(struct hashmultiset_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = hms_empty(iter->target); + struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index++; + while (1) + { + iter->cursor++; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hms_iter_prev(struct hashmultiset_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = hms_empty(iter->target); + struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index--; + while (1) + { + iter->cursor--; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hms_iter_advance(struct hashmultiset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hms_iter_next(iter); + return 1; +} +_Bool hms_iter_rewind(struct hashmultiset_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hms_iter_prev(iter); + return 1; +} +_Bool hms_iter_go_to(struct hashmultiset_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hms_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hms_iter_advance(iter, index - iter->index); + return 1; +} +size_t hms_iter_value(struct hashmultiset_iter *iter) +{ + if (hms_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor].value; +} +size_t hms_iter_multiplicity(struct hashmultiset_iter *iter) +{ + if (hms_empty(iter->target)) + return 0; + return iter->target->buffer[iter->cursor].multiplicity; +} +size_t hms_iter_index(struct hashmultiset_iter *iter) +{ + return iter->index; +} +static size_t hms_impl_multiplicity_of(struct hashmultiset *_set_, size_t value) +{ + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + if (!entry) + return 0; + return entry->multiplicity; +} +static struct hashmultiset_entry * +hms_impl_insert_and_return(struct hashmultiset *_set_, size_t value, + _Bool *new_node) +{ + *new_node = 0; + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + if (entry != ((void *)0)) + return entry; + *new_node = 1; + if (hms_full(_set_)) + { + if (!hms_resize(_set_, _set_->capacity + 1)) + return ((void *)0); + } + size_t hash = _set_->f_val->hash(value); + size_t original_pos = hash % _set_->capacity; + size_t pos = original_pos; + size_t curr_mul = 1; + struct hashmultiset_entry *target = &(_set_->buffer[pos]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->value = value; + target->multiplicity = curr_mul; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + } + else + { + while (1) + { + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + if (target->state == CMC_ES_EMPTY || + target->state == CMC_ES_DELETED) + { + target->value = value; + target->multiplicity = curr_mul; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + break; + } + else if (target->dist < pos - original_pos) + { + size_t tmp = target->value; + size_t tmp_dist = target->dist; + size_t tmp_mul = target->multiplicity; + target->value = value; + target->dist = pos - original_pos; + target->multiplicity = curr_mul; + value = tmp; + original_pos = pos - tmp_dist; + curr_mul = tmp_mul; + } + } + } + _set_->count++; + return target; +} +static struct hashmultiset_entry *hms_impl_get_entry(struct hashmultiset *_set_, + size_t value) +{ + size_t hash = _set_->f_val->hash(value); + size_t pos = hash % _set_->capacity; + struct hashmultiset_entry *target = &(_set_->buffer[pos]); + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) + { + if (_set_->f_val->cmp(target->value, value) == 0) + return target; + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + } + return ((void *)0); +} +static size_t hms_impl_calculate_size(size_t required) +{ + const size_t count = + sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +static struct hashmultiset_iter hms_impl_it_start(struct hashmultiset *_set_) +{ + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set_); + return iter; +} +static struct hashmultiset_iter hms_impl_it_end(struct hashmultiset *_set_) +{ + struct hashmultiset_iter iter; + hms_iter_init(&iter, _set_); + hms_iter_to_end(&iter); + return iter; +} diff --git a/tests/main/unt/bitset.c b/tests/main/unt/bitset.c index 78314e7..33e75fe 100644 --- a/tests/main/unt/bitset.c +++ b/tests/main/unt/bitset.c @@ -215,7 +215,8 @@ CMC_CREATE_UNIT(BitSet, true, { cmc_assert(bs_set_range(bs, word_bits * 20, word_bits * 21 - 1)); cmc_assert(bs_clear_range(bs, word_bits * 20, word_bits * 21 - 1)); - cmc_assert_equals(uint32_t, 0, bs->buffer[bs_bit_to_index(word_bits * 20)]); + cmc_assert_equals(uint32_t, 0, + bs->buffer[bs_bit_to_index(word_bits * 20)]); bs_free(bs); }); diff --git a/tests/main/unt/hashbidimap.c b/tests/main/unt/hashbidimap.c index 1c1f3a4..85033cf 100644 --- a/tests/main/unt/hashbidimap.c +++ b/tests/main/unt/hashbidimap.c @@ -4,33 +4,37 @@ #include "../src/hashbidimap.c" -struct hashbidimap_fkey *hbm_fkey = &(struct hashbidimap_fkey){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; +struct hashbidimap_fkey *hbm_fkey = + &(struct hashbidimap_fkey){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; -struct hashbidimap_fval *hbm_fval = &(struct hashbidimap_fval){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; +struct hashbidimap_fval *hbm_fval = + &(struct hashbidimap_fval){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; -struct hashbidimap_fkey *hbm_fkey_counter = &(struct hashbidimap_fkey){ .cmp = k_c_cmp, - .cpy = k_c_cpy, - .str = k_c_str, - .free = k_c_free, - .hash = k_c_hash, - .pri = k_c_pri }; +struct hashbidimap_fkey *hbm_fkey_counter = + &(struct hashbidimap_fkey){ .cmp = k_c_cmp, + .cpy = k_c_cpy, + .str = k_c_str, + .free = k_c_free, + .hash = k_c_hash, + .pri = k_c_pri }; -struct hashbidimap_fval *hbm_fval_counter = &(struct hashbidimap_fval){ .cmp = v_c_cmp, - .cpy = v_c_cpy, - .str = v_c_str, - .free = v_c_free, - .hash = v_c_hash, - .pri = v_c_pri }; +struct hashbidimap_fval *hbm_fval_counter = + &(struct hashbidimap_fval){ .cmp = v_c_cmp, + .cpy = v_c_cpy, + .str = v_c_str, + .free = v_c_free, + .hash = v_c_hash, + .pri = v_c_pri }; struct cmc_alloc_node *hbm_alloc_node = &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free @@ -83,8 +87,8 @@ CMC_CREATE_UNIT(HashBidiMap, true, { }); CMC_CREATE_TEST(PFX##_new_custom(), { - struct hashbidimap *map = hbm_new_custom(943722, 0.6, hbm_fkey, hbm_fval, - hbm_alloc_node, callbacks); + struct hashbidimap *map = hbm_new_custom( + 943722, 0.6, hbm_fkey, hbm_fval, hbm_alloc_node, callbacks); cmc_assert_not_equals(ptr, NULL, map); cmc_assert_not_equals(ptr, NULL, map->buffer); @@ -466,11 +470,11 @@ CMC_CREATE_UNIT(HashBidiMap, true, { CMC_CREATE_TEST(remove_by_key[cleanup custom], { struct hashbidimap *map = hbm_new_custom(10000, 0.6, hbm_fkey, hbm_fval, - &(struct cmc_alloc_node){ .malloc = malloc, - .calloc = calloc, - .realloc = realloc, - .free = free }, - &(struct cmc_callbacks){ 0 }); + &(struct cmc_alloc_node){ .malloc = malloc, + .calloc = calloc, + .realloc = realloc, + .free = free }, + &(struct cmc_callbacks){ 0 }); cmc_assert_not_equals(ptr, NULL, map); @@ -499,11 +503,11 @@ CMC_CREATE_UNIT(HashBidiMap, true, { CMC_CREATE_TEST(remove_by_val[cleanup custom], { struct hashbidimap *map = hbm_new_custom(10000, 0.6, hbm_fkey, hbm_fval, - &(struct cmc_alloc_node){ .malloc = malloc, - .calloc = calloc, - .realloc = realloc, - .free = free }, - &(struct cmc_callbacks){ 0 }); + &(struct cmc_alloc_node){ .malloc = malloc, + .calloc = calloc, + .realloc = realloc, + .free = free }, + &(struct cmc_callbacks){ 0 }); cmc_assert_not_equals(ptr, NULL, map); @@ -598,7 +602,7 @@ CMC_CREATE_UNIT(HashBidiMap, true, { // customize hbm_customize(map, &cmc_alloc_node_default, - &(struct cmc_callbacks){ 0 }); + &(struct cmc_callbacks){ 0 }); cmc_assert_equals(int32_t, cmc_flags.OK, hbm_flag(map)); // Insert diff --git a/tests/main/unt/hashmultimap.c b/tests/main/unt/hashmultimap.c index 03b376c..08bf285 100644 --- a/tests/main/unt/hashmultimap.c +++ b/tests/main/unt/hashmultimap.c @@ -4,35 +4,37 @@ #include "../src/hashmultimap.c" -struct hashmultimap_fkey *hmm_fkey = &(struct hashmultimap_fkey){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; +struct hashmultimap_fkey *hmm_fkey = + &(struct hashmultimap_fkey){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; -struct hashmultimap_fval *hmm_fval = &(struct hashmultimap_fval){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; +struct hashmultimap_fval *hmm_fval = + &(struct hashmultimap_fval){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; struct hashmultimap_fkey *hmm_fkey_counter = &(struct hashmultimap_fkey){ .cmp = k_c_cmp, - .cpy = k_c_cpy, - .str = k_c_str, - .free = k_c_free, - .hash = k_c_hash, - .pri = k_c_pri }; + .cpy = k_c_cpy, + .str = k_c_str, + .free = k_c_free, + .hash = k_c_hash, + .pri = k_c_pri }; struct hashmultimap_fval *hmm_fval_counter = &(struct hashmultimap_fval){ .cmp = v_c_cmp, - .cpy = v_c_cpy, - .str = v_c_str, - .free = v_c_free, - .hash = v_c_hash, - .pri = v_c_pri }; + .cpy = v_c_cpy, + .str = v_c_str, + .free = v_c_free, + .hash = v_c_hash, + .pri = v_c_pri }; struct cmc_alloc_node *hmm_alloc_node = &(struct cmc_alloc_node){ .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free @@ -85,8 +87,8 @@ CMC_CREATE_UNIT(HashMultiMap, true, { }); CMC_CREATE_TEST(PFX##_new_custom(), { - struct hashmultimap *map = hmm_new_custom(943722, 0.6, hmm_fkey, hmm_fval, - hmm_alloc_node, callbacks); + struct hashmultimap *map = hmm_new_custom( + 943722, 0.6, hmm_fkey, hmm_fval, hmm_alloc_node, callbacks); cmc_assert_not_equals(ptr, NULL, map); cmc_assert_not_equals(ptr, NULL, map->buffer); diff --git a/tests/main/unt/hashmultiset.c b/tests/main/unt/hashmultiset.c new file mode 100644 index 0000000..18a6efc --- /dev/null +++ b/tests/main/unt/hashmultiset.c @@ -0,0 +1,426 @@ +#include "utl.c" +#include "utl/assert.h" +#include "utl/test.h" + +#include "../src/hashmultiset.c" + +struct hashmultiset_fval *hms_fval = + &(struct hashmultiset_fval){ .cmp = cmc_size_cmp, + .cpy = NULL, + .str = cmc_size_str, + .free = NULL, + .hash = cmc_size_hash, + .pri = cmc_size_cmp }; + +struct hashmultiset_fval *hms_fval_counter = + &(struct hashmultiset_fval){ .cmp = v_c_cmp, + .cpy = v_c_cpy, + .str = v_c_str, + .free = v_c_free, + .hash = v_c_hash, + .pri = v_c_pri }; + +struct cmc_alloc_node *hms_alloc_node = &(struct cmc_alloc_node){ + .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free +}; + +CMC_CREATE_UNIT(HashMultiSet, true, { + CMC_CREATE_TEST(PFX##_new(), { + struct hashmultiset *set = hms_new(943722, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + cmc_assert_not_equals(ptr, NULL, set->buffer); + cmc_assert_equals(size_t, 0, set->count); + cmc_assert_equals(double, 0.6, set->load); + cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); + cmc_assert_equals(ptr, hms_fval, set->f_val); + cmc_assert_equals(ptr, &cmc_alloc_node_default, set->alloc); + cmc_assert_equals(ptr, NULL, set->callbacks); + + cmc_assert_greater_equals(size_t, (943722 / 0.6), hms_capacity(set)); + + hms_free(set); + + set = hms_new(0, 0.6, hms_fval); + cmc_assert_equals(ptr, NULL, set); + + set = hms_new(UINT64_MAX, 0.99, hms_fval); + cmc_assert_equals(ptr, NULL, set); + + set = hms_new(1000, 0.6, NULL); + cmc_assert_equals(ptr, NULL, set); + + set = hms_new(1000, 0.6, NULL); + cmc_assert_equals(ptr, NULL, set); + }); + + CMC_CREATE_TEST(PFX##_new_custom(), { + struct hashmultiset *set = + hms_new_custom(943722, 0.6, hms_fval, hms_alloc_node, callbacks); + + cmc_assert_not_equals(ptr, NULL, set); + cmc_assert_not_equals(ptr, NULL, set->buffer); + cmc_assert_equals(size_t, 0, set->count); + cmc_assert_equals(double, 0.6, set->load); + cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); + cmc_assert_equals(ptr, hms_fval, set->f_val); + cmc_assert_equals(ptr, hms_alloc_node, set->alloc); + cmc_assert_equals(ptr, callbacks, set->callbacks); + + cmc_assert_greater_equals(size_t, (943722 / 0.6), hms_capacity(set)); + + hms_free(set); + + set = hms_new_custom(0, 0.6, hms_fval, NULL, NULL); + cmc_assert_equals(ptr, NULL, set); + + set = hms_new_custom(UINT64_MAX, 0.99, hms_fval, NULL, NULL); + cmc_assert_equals(ptr, NULL, set); + + set = hms_new_custom(1000, 0.6, NULL, NULL, NULL); + cmc_assert_equals(ptr, NULL, set); + }); + + CMC_CREATE_TEST(PFX##_clear(), { + v_total_free = 0; + struct hashmultiset *set = hms_new(100, 0.6, hms_fval_counter); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 1; i <= 1000; i++) + hms_insert(set, i); + + cmc_assert_equals(size_t, 1000, set->count); + + set->flag = cmc_flags.ERROR; + hms_clear(set); + + cmc_assert_equals(size_t, 0, set->count); + cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); + cmc_assert_equals(int32_t, 1000, v_total_free); + + hms_free(set); + v_total_free = 0; + }); + + CMC_CREATE_TEST(PFX##_free(), { + v_total_free = 0; + struct hashmultiset *set = hms_new(100, 0.6, hms_fval_counter); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 1; i <= 1000; i++) + hms_insert(set, i); + + cmc_assert_equals(size_t, 1000, set->count); + + hms_free(set); + + cmc_assert_equals(int32_t, 1000, v_total_free); + + set = hms_new(1000, 0.6, hms_fval_counter); + + cmc_assert_not_equals(ptr, NULL, set); + cmc_assert_not_equals(ptr, NULL, set->buffer); + + hms_free(set); + + cmc_assert_equals(int32_t, 1000, v_total_free); + v_total_free = 0; + }); + + CMC_CREATE_TEST(insert[count cardinality multiplicity], { + struct hashmultiset *set = hms_new(100, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hms_insert(set, 1)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + + cmc_assert_equals(size_t, 3, hms_count(set)); + cmc_assert_equals(size_t, 6, hms_cardinality(set)); + + for (size_t i = 0; i <= 3; i++) + cmc_assert_equals(size_t, i, hms_multiplicity_of(set, i)); + + hms_free(set); + }); + + CMC_CREATE_TEST(remove[count cardinality multiplicity], { + struct hashmultiset *set = hms_new(100, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hms_insert(set, 1)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + + cmc_assert_equals(size_t, 3, hms_count(set)); + cmc_assert_equals(size_t, 6, hms_cardinality(set)); + + for (size_t i = 0; i <= 3; i++) + cmc_assert_equals(size_t, i, hms_multiplicity_of(set, i)); + + cmc_assert(hms_remove(set, 1)); + cmc_assert(hms_remove(set, 2)); + cmc_assert(hms_remove(set, 3)); + + cmc_assert_equals(size_t, 2, hms_count(set)); + cmc_assert_equals(size_t, 3, hms_cardinality(set)); + + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 0)); + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 1)); + cmc_assert_equals(size_t, 1, hms_multiplicity_of(set, 2)); + cmc_assert_equals(size_t, 2, hms_multiplicity_of(set, 3)); + + hms_free(set); + }); + + CMC_CREATE_TEST(remove_all[count cardinality multiplicity], { + struct hashmultiset *set = hms_new(100, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hms_insert(set, 1)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 2)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + cmc_assert(hms_insert(set, 3)); + + cmc_assert_equals(size_t, 3, hms_count(set)); + cmc_assert_equals(size_t, 6, hms_cardinality(set)); + + for (size_t i = 0; i <= 3; i++) + cmc_assert_equals(size_t, i, hms_multiplicity_of(set, i)); + + cmc_assert(hms_remove_all(set, 1)); + cmc_assert(hms_remove_all(set, 3)); + + cmc_assert_equals(size_t, 1, hms_count(set)); + cmc_assert_equals(size_t, 2, hms_cardinality(set)); + + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 0)); + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 1)); + cmc_assert_equals(size_t, 2, hms_multiplicity_of(set, 2)); + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 3)); + + hms_free(set); + }); + + CMC_CREATE_TEST(multiplicity, { + struct hashmultiset *set = hms_new(50, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 0; i < 1000; i++) + cmc_assert(hms_insert(set, i % 20)); + + cmc_assert_equals(size_t, 20, hms_count(set)); + cmc_assert_equals(size_t, 1000, hms_cardinality(set)); + + for (size_t i = 0; i < 20; i++) + cmc_assert_equals(size_t, 50, hms_multiplicity_of(set, i)); + + hms_free(set); + }); + + CMC_CREATE_TEST(flags, { + struct hashmultiset *set = hms_new(100, 0.6, hms_fval); + + cmc_assert_not_equals(ptr, NULL, set); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // clear + set->flag = cmc_flags.ERROR; + hms_clear(set); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // customize + set->flag = cmc_flags.ERROR; + hms_customize(set, NULL, NULL); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // insert + set->flag = cmc_flags.ERROR; + cmc_assert(hms_insert(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(hms_insert(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // insert_many + set->flag = cmc_flags.ERROR; + cmc_assert(hms_insert_many(set, 1, 0)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(hms_insert_many(set, 1, 2)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // update + set->flag = cmc_flags.ERROR; + cmc_assert(hms_update(set, 1, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + set->flag = cmc_flags.ERROR; + cmc_assert(hms_update(set, 10, 0)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // remove + cmc_assert(!hms_remove(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hms_flag(set)); + + cmc_assert(hms_remove(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // remove_all + cmc_assert_equals(size_t, 0, hms_remove_all(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hms_flag(set)); + + cmc_assert(hms_insert_many(set, 1, 10)); + cmc_assert_equals(size_t, 0, hms_remove_all(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, hms_flag(set)); + + cmc_assert_equals(size_t, 10, hms_remove_all(set, 1)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // max min + cmc_assert(!hms_max(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hms_flag(set)); + set->flag = cmc_flags.ERROR; + cmc_assert(!hms_min(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, hms_flag(set)); + + cmc_assert(hms_insert(set, 1)); + set->flag = cmc_flags.ERROR; + cmc_assert(hms_max(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + set->flag = cmc_flags.ERROR; + cmc_assert(hms_min(set, NULL)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // multiplicity_of + set->flag = cmc_flags.ERROR; + cmc_assert_equals(size_t, 0, hms_multiplicity_of(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // contains + set->flag = cmc_flags.ERROR; + cmc_assert(!hms_contains(set, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + + // copy_of + set->flag = cmc_flags.ERROR; + struct hashmultiset *set2 = hms_copy_of(set); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set2)); + + // equals + set->flag = cmc_flags.ERROR; + set2->flag = cmc_flags.ERROR; + cmc_assert(hms_equals(set, set2)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set)); + cmc_assert_equals(int32_t, cmc_flags.OK, hms_flag(set2)); + + hms_free(set); + hms_free(set2); + }); + + CMC_CREATE_TEST(callbacks, { + struct hashmultiset *set = + hms_new_custom(100, 0.8, hms_fval, NULL, callbacks); + + cmc_assert_not_equals(ptr, NULL, set); + + total_create = 0; + total_read = 0; + total_update = 0; + total_delete = 0; + total_resize = 0; + + cmc_assert(hms_insert(set, 1)); + cmc_assert_equals(int32_t, 1, total_create); + + cmc_assert(hms_insert_many(set, 1, 3)); + cmc_assert_equals(int32_t, 2, total_create); + + cmc_assert(hms_update(set, 1, 0)); + cmc_assert_equals(int32_t, 1, total_update); + + cmc_assert(hms_update(set, 1, 10)); + cmc_assert_equals(int32_t, 2, total_update); + + cmc_assert(hms_remove(set, 1)); + cmc_assert_equals(int32_t, 1, total_delete); + + cmc_assert(hms_remove_all(set, 1)); + cmc_assert_equals(int32_t, 2, total_delete); + + cmc_assert(hms_update(set, 1, 10)); + cmc_assert_equals(int32_t, 3, total_update); + + cmc_assert(hms_max(set, NULL)); + cmc_assert_equals(int32_t, 1, total_read); + + cmc_assert(hms_min(set, NULL)); + cmc_assert_equals(int32_t, 2, total_read); + + cmc_assert(hms_contains(set, 1)); + cmc_assert_equals(int32_t, 3, total_read); + + cmc_assert(hms_resize(set, 1000)); + cmc_assert_equals(int32_t, 1, total_resize); + + cmc_assert(hms_resize(set, 100)); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 3, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + hms_customize(set, NULL, NULL); + + cmc_assert_equals(ptr, NULL, set->callbacks); + + hms_clear(set); + cmc_assert(hms_insert(set, 1)); + cmc_assert(hms_insert_many(set, 1, 3)); + cmc_assert(hms_update(set, 1, 0)); + cmc_assert(hms_update(set, 1, 10)); + cmc_assert(hms_remove(set, 1)); + cmc_assert(hms_remove_all(set, 1)); + cmc_assert(hms_update(set, 1, 10)); + cmc_assert(hms_max(set, NULL)); + cmc_assert(hms_min(set, NULL)); + cmc_assert(hms_contains(set, 1)); + cmc_assert(hms_resize(set, 1000)); + cmc_assert(hms_resize(set, 100)); + + cmc_assert_equals(int32_t, 2, total_create); + cmc_assert_equals(int32_t, 3, total_read); + cmc_assert_equals(int32_t, 3, total_update); + cmc_assert_equals(int32_t, 2, total_delete); + cmc_assert_equals(int32_t, 2, total_resize); + + cmc_assert_equals(ptr, NULL, set->callbacks); + + hms_free(set); + + total_create = 0; + total_read = 0; + total_update = 0; + total_delete = 0; + total_resize = 0; + }); +}); diff --git a/tests/main/unt/multiset.c b/tests/main/unt/multiset.c deleted file mode 100644 index 5ff6900..0000000 --- a/tests/main/unt/multiset.c +++ /dev/null @@ -1,425 +0,0 @@ -#include "utl.c" -#include "utl/assert.h" -#include "utl/test.h" - -#include "../src/multiset.c" - -struct multiset_fval *ms_fval = &(struct multiset_fval){ .cmp = cmc_size_cmp, - .cpy = NULL, - .str = cmc_size_str, - .free = NULL, - .hash = cmc_size_hash, - .pri = cmc_size_cmp }; - -struct multiset_fval *ms_fval_counter = - &(struct multiset_fval){ .cmp = v_c_cmp, - .cpy = v_c_cpy, - .str = v_c_str, - .free = v_c_free, - .hash = v_c_hash, - .pri = v_c_pri }; - -struct cmc_alloc_node *ms_alloc_node = &(struct cmc_alloc_node){ - .malloc = malloc, .calloc = calloc, .realloc = realloc, .free = free -}; - -CMC_CREATE_UNIT(MultiSet, true, { - CMC_CREATE_TEST(PFX##_new(), { - struct multiset *set = ms_new(943722, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - cmc_assert_not_equals(ptr, NULL, set->buffer); - cmc_assert_equals(size_t, 0, set->count); - cmc_assert_equals(double, 0.6, set->load); - cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); - cmc_assert_equals(ptr, ms_fval, set->f_val); - cmc_assert_equals(ptr, &cmc_alloc_node_default, set->alloc); - cmc_assert_equals(ptr, NULL, set->callbacks); - - cmc_assert_greater_equals(size_t, (943722 / 0.6), ms_capacity(set)); - - ms_free(set); - - set = ms_new(0, 0.6, ms_fval); - cmc_assert_equals(ptr, NULL, set); - - set = ms_new(UINT64_MAX, 0.99, ms_fval); - cmc_assert_equals(ptr, NULL, set); - - set = ms_new(1000, 0.6, NULL); - cmc_assert_equals(ptr, NULL, set); - - set = ms_new(1000, 0.6, NULL); - cmc_assert_equals(ptr, NULL, set); - }); - - CMC_CREATE_TEST(PFX##_new_custom(), { - struct multiset *set = - ms_new_custom(943722, 0.6, ms_fval, ms_alloc_node, callbacks); - - cmc_assert_not_equals(ptr, NULL, set); - cmc_assert_not_equals(ptr, NULL, set->buffer); - cmc_assert_equals(size_t, 0, set->count); - cmc_assert_equals(double, 0.6, set->load); - cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); - cmc_assert_equals(ptr, ms_fval, set->f_val); - cmc_assert_equals(ptr, ms_alloc_node, set->alloc); - cmc_assert_equals(ptr, callbacks, set->callbacks); - - cmc_assert_greater_equals(size_t, (943722 / 0.6), ms_capacity(set)); - - ms_free(set); - - set = ms_new_custom(0, 0.6, ms_fval, NULL, NULL); - cmc_assert_equals(ptr, NULL, set); - - set = ms_new_custom(UINT64_MAX, 0.99, ms_fval, NULL, NULL); - cmc_assert_equals(ptr, NULL, set); - - set = ms_new_custom(1000, 0.6, NULL, NULL, NULL); - cmc_assert_equals(ptr, NULL, set); - }); - - CMC_CREATE_TEST(PFX##_clear(), { - v_total_free = 0; - struct multiset *set = ms_new(100, 0.6, ms_fval_counter); - - cmc_assert_not_equals(ptr, NULL, set); - - for (size_t i = 1; i <= 1000; i++) - ms_insert(set, i); - - cmc_assert_equals(size_t, 1000, set->count); - - set->flag = cmc_flags.ERROR; - ms_clear(set); - - cmc_assert_equals(size_t, 0, set->count); - cmc_assert_equals(int32_t, cmc_flags.OK, set->flag); - cmc_assert_equals(int32_t, 1000, v_total_free); - - ms_free(set); - v_total_free = 0; - }); - - CMC_CREATE_TEST(PFX##_free(), { - v_total_free = 0; - struct multiset *set = ms_new(100, 0.6, ms_fval_counter); - - cmc_assert_not_equals(ptr, NULL, set); - - for (size_t i = 1; i <= 1000; i++) - ms_insert(set, i); - - cmc_assert_equals(size_t, 1000, set->count); - - ms_free(set); - - cmc_assert_equals(int32_t, 1000, v_total_free); - - set = ms_new(1000, 0.6, ms_fval_counter); - - cmc_assert_not_equals(ptr, NULL, set); - cmc_assert_not_equals(ptr, NULL, set->buffer); - - ms_free(set); - - cmc_assert_equals(int32_t, 1000, v_total_free); - v_total_free = 0; - }); - - CMC_CREATE_TEST(insert[count cardinality multiplicity], { - struct multiset *set = ms_new(100, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - - cmc_assert(ms_insert(set, 1)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - - cmc_assert_equals(size_t, 3, ms_count(set)); - cmc_assert_equals(size_t, 6, ms_cardinality(set)); - - for (size_t i = 0; i <= 3; i++) - cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); - - ms_free(set); - }); - - CMC_CREATE_TEST(remove[count cardinality multiplicity], { - struct multiset *set = ms_new(100, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - - cmc_assert(ms_insert(set, 1)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - - cmc_assert_equals(size_t, 3, ms_count(set)); - cmc_assert_equals(size_t, 6, ms_cardinality(set)); - - for (size_t i = 0; i <= 3; i++) - cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); - - cmc_assert(ms_remove(set, 1)); - cmc_assert(ms_remove(set, 2)); - cmc_assert(ms_remove(set, 3)); - - cmc_assert_equals(size_t, 2, ms_count(set)); - cmc_assert_equals(size_t, 3, ms_cardinality(set)); - - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0)); - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1)); - cmc_assert_equals(size_t, 1, ms_multiplicity_of(set, 2)); - cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 3)); - - ms_free(set); - }); - - CMC_CREATE_TEST(remove_all[count cardinality multiplicity], { - struct multiset *set = ms_new(100, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - - cmc_assert(ms_insert(set, 1)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 2)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - cmc_assert(ms_insert(set, 3)); - - cmc_assert_equals(size_t, 3, ms_count(set)); - cmc_assert_equals(size_t, 6, ms_cardinality(set)); - - for (size_t i = 0; i <= 3; i++) - cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); - - cmc_assert(ms_remove_all(set, 1)); - cmc_assert(ms_remove_all(set, 3)); - - cmc_assert_equals(size_t, 1, ms_count(set)); - cmc_assert_equals(size_t, 2, ms_cardinality(set)); - - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0)); - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1)); - cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 2)); - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 3)); - - ms_free(set); - }); - - CMC_CREATE_TEST(multiplicity, { - struct multiset *set = ms_new(50, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - - for (size_t i = 0; i < 1000; i++) - cmc_assert(ms_insert(set, i % 20)); - - cmc_assert_equals(size_t, 20, ms_count(set)); - cmc_assert_equals(size_t, 1000, ms_cardinality(set)); - - for (size_t i = 0; i < 20; i++) - cmc_assert_equals(size_t, 50, ms_multiplicity_of(set, i)); - - ms_free(set); - }); - - CMC_CREATE_TEST(flags, { - struct multiset *set = ms_new(100, 0.6, ms_fval); - - cmc_assert_not_equals(ptr, NULL, set); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // clear - set->flag = cmc_flags.ERROR; - ms_clear(set); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // customize - set->flag = cmc_flags.ERROR; - ms_customize(set, NULL, NULL); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // insert - set->flag = cmc_flags.ERROR; - cmc_assert(ms_insert(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - set->flag = cmc_flags.ERROR; - cmc_assert(ms_insert(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // insert_many - set->flag = cmc_flags.ERROR; - cmc_assert(ms_insert_many(set, 1, 0)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - set->flag = cmc_flags.ERROR; - cmc_assert(ms_insert_many(set, 1, 2)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // update - set->flag = cmc_flags.ERROR; - cmc_assert(ms_update(set, 1, 1)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - set->flag = cmc_flags.ERROR; - cmc_assert(ms_update(set, 10, 0)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // remove - cmc_assert(!ms_remove(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, ms_flag(set)); - - cmc_assert(ms_remove(set, 1)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // remove_all - cmc_assert_equals(size_t, 0, ms_remove_all(set, 1)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); - - cmc_assert(ms_insert_many(set, 1, 10)); - cmc_assert_equals(size_t, 0, ms_remove_all(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.NOT_FOUND, ms_flag(set)); - - cmc_assert_equals(size_t, 10, ms_remove_all(set, 1)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // max min - cmc_assert(!ms_max(set, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); - set->flag = cmc_flags.ERROR; - cmc_assert(!ms_min(set, NULL)); - cmc_assert_equals(int32_t, cmc_flags.EMPTY, ms_flag(set)); - - cmc_assert(ms_insert(set, 1)); - set->flag = cmc_flags.ERROR; - cmc_assert(ms_max(set, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - set->flag = cmc_flags.ERROR; - cmc_assert(ms_min(set, NULL)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // multiplicity_of - set->flag = cmc_flags.ERROR; - cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // contains - set->flag = cmc_flags.ERROR; - cmc_assert(!ms_contains(set, 10)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - - // copy_of - set->flag = cmc_flags.ERROR; - struct multiset *set2 = ms_copy_of(set); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set2)); - - // equals - set->flag = cmc_flags.ERROR; - set2->flag = cmc_flags.ERROR; - cmc_assert(ms_equals(set, set2)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set)); - cmc_assert_equals(int32_t, cmc_flags.OK, ms_flag(set2)); - - ms_free(set); - ms_free(set2); - }); - - CMC_CREATE_TEST(callbacks, { - struct multiset *set = - ms_new_custom(100, 0.8, ms_fval, NULL, callbacks); - - cmc_assert_not_equals(ptr, NULL, set); - - total_create = 0; - total_read = 0; - total_update = 0; - total_delete = 0; - total_resize = 0; - - cmc_assert(ms_insert(set, 1)); - cmc_assert_equals(int32_t, 1, total_create); - - cmc_assert(ms_insert_many(set, 1, 3)); - cmc_assert_equals(int32_t, 2, total_create); - - cmc_assert(ms_update(set, 1, 0)); - cmc_assert_equals(int32_t, 1, total_update); - - cmc_assert(ms_update(set, 1, 10)); - cmc_assert_equals(int32_t, 2, total_update); - - cmc_assert(ms_remove(set, 1)); - cmc_assert_equals(int32_t, 1, total_delete); - - cmc_assert(ms_remove_all(set, 1)); - cmc_assert_equals(int32_t, 2, total_delete); - - cmc_assert(ms_update(set, 1, 10)); - cmc_assert_equals(int32_t, 3, total_update); - - cmc_assert(ms_max(set, NULL)); - cmc_assert_equals(int32_t, 1, total_read); - - cmc_assert(ms_min(set, NULL)); - cmc_assert_equals(int32_t, 2, total_read); - - cmc_assert(ms_contains(set, 1)); - cmc_assert_equals(int32_t, 3, total_read); - - cmc_assert(ms_resize(set, 1000)); - cmc_assert_equals(int32_t, 1, total_resize); - - cmc_assert(ms_resize(set, 100)); - cmc_assert_equals(int32_t, 2, total_resize); - - cmc_assert_equals(int32_t, 2, total_create); - cmc_assert_equals(int32_t, 3, total_read); - cmc_assert_equals(int32_t, 3, total_update); - cmc_assert_equals(int32_t, 2, total_delete); - cmc_assert_equals(int32_t, 2, total_resize); - - ms_customize(set, NULL, NULL); - - cmc_assert_equals(ptr, NULL, set->callbacks); - - ms_clear(set); - cmc_assert(ms_insert(set, 1)); - cmc_assert(ms_insert_many(set, 1, 3)); - cmc_assert(ms_update(set, 1, 0)); - cmc_assert(ms_update(set, 1, 10)); - cmc_assert(ms_remove(set, 1)); - cmc_assert(ms_remove_all(set, 1)); - cmc_assert(ms_update(set, 1, 10)); - cmc_assert(ms_max(set, NULL)); - cmc_assert(ms_min(set, NULL)); - cmc_assert(ms_contains(set, 1)); - cmc_assert(ms_resize(set, 1000)); - cmc_assert(ms_resize(set, 100)); - - cmc_assert_equals(int32_t, 2, total_create); - cmc_assert_equals(int32_t, 3, total_read); - cmc_assert_equals(int32_t, 3, total_update); - cmc_assert_equals(int32_t, 2, total_delete); - cmc_assert_equals(int32_t, 2, total_resize); - - cmc_assert_equals(ptr, NULL, set->callbacks); - - ms_free(set); - - total_create = 0; - total_read = 0; - total_update = 0; - total_delete = 0; - total_resize = 0; - }); -});