Added resize to multimap, multiset and sortedlist

This commit is contained in:
Leonardo committed 2019-10-16 21:34:30 -03:00
1 parent 99cd01ba1e
commit 2d3b441d74
6 files changed
+1067 -937

No files matched your search

+893 -873
View File
File diff suppressed because it is too large. Load diff
+65 -37
View File
@@ -185,10 +185,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
/* Collection State */ \
bool PFX##_contains(SNAME *_set_, V element); \
bool PFX##_empty(SNAME *_set_); \
bool PFX##_full(SNAME *_set_); \
size_t PFX##_count(SNAME *_set_); \
size_t PFX##_cardinality(SNAME *_set_); \
size_t PFX##_capacity(SNAME *_set_); \
double PFX##_load(SNAME *_set_); \
/* Collection Utility */ \
bool PFX##_resize(SNAME *_set_, size_t capacity); \
SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity); \
cmc_string PFX##_to_string(SNAME *_set_); \
@@ -242,7 +245,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
\
/* Implementation Detail Functions */ \
static SNAME##_entry *PFX##_impl_insert_and_return(SNAME *_set_, V element, bool *new_node); \
static bool PFX##_impl_grow(SNAME *_set_); \
static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \
static size_t PFX##_impl_calculate_size(size_t required); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
@@ -493,6 +495,11 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
return _set_->count == 0; \
} \
\
bool PFX##_full(SNAME *_set_) \
{ \
return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= (double)PFX##_count(_set_); \
} \
\
size_t PFX##_count(SNAME *_set_) \
{ \
return _set_->count; \
@@ -508,6 +515,61 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
return _set_->capacity; \
} \
\
double PFX##_load(SNAME *_set_) \
{ \
return _set_->load; \
} \
\
bool PFX##_resize(SNAME *_set_, size_t capacity) \
{ \
if (PFX##_capacity(_set_) == capacity) \
return true; \
\
if (PFX##_capacity(_set_) > capacity / PFX##_load(_set_)) \
return true; \
\
/* Prevent integer overflow */ \
if (capacity >= UINTMAX_MAX * PFX##_load(_set_)) \
return false; \
\
/* Calculate required capacity based on the prime numbers */ \
size_t theoretical_size = PFX##_impl_calculate_size(capacity); \
\
/* Not possible to shrink with current available prime numbers */ \
if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \
return false; \
\
SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \
\
if (!_new_set_) \
return false; \
\
SNAME##_iter iter; \
\
for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_insert_many(_new_set_, PFX##_iter_value(&iter), PFX##_iter_multiplicity(&iter)); \
} \
\
if (PFX##_count(_set_) != PFX##_count(_new_set_)) \
{ \
PFX##_free(_new_set_, NULL); \
return false; \
} \
\
SNAME##_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; \
\
PFX##_free(_new_set_, NULL); \
\
return true; \
} \
\
SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \
@@ -1063,9 +1125,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
\
*new_node = true; \
\
if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \
if (PFX##_full(_set_)) \
{ \
if (!PFX##_impl_grow(_set_)) \
if (!PFX##_resize(_set_, PFX##_capacity(_set_) + 1)) \
return NULL; \
} \
\
@@ -1123,40 +1185,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
return target; \
} \
\
static bool PFX##_impl_grow(SNAME *_set_) \
{ \
size_t new_size = PFX##_impl_calculate_size(_set_->capacity + _set_->capacity / 2); \
\
SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \
\
if (!_new_set_) \
return false; \
\
SNAME##_iter iter; \
\
for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_insert_many(_new_set_, PFX##_iter_value(&iter), PFX##_iter_multiplicity(&iter)); \
} \
\
if (_set_->count != _new_set_->count) \
{ \
PFX##_free(_new_set_, NULL); \
\
return false; \
} \
\
SNAME##_entry *tmp = _set_->buffer; \
_set_->buffer = _new_set_->buffer; \
_new_set_->buffer = tmp; \
\
_set_->capacity = _new_set_->capacity; \
\
PFX##_free(_new_set_, NULL); \
\
return true; \
} \
\
static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \
{ \
size_t hash = _set_->hash(element); \
+21 -20
View File
@@ -109,6 +109,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%
size_t PFX##_count(SNAME *_list_); \
size_t PFX##_capacity(SNAME *_list_); \
/* Collection Utility */ \
bool PFX##_resize(SNAME *_list_, size_t capacity); \
void PFX##_sort(SNAME *_list_); \
SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_list1_, SNAME *_list2_); \
@@ -149,7 +150,6 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%
#define CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static bool PFX##_impl_grow(SNAME *_list_, size_t required); \
static size_t PFX##_impl_binary_search_first(SNAME *_list_, V value); \
static size_t PFX##_impl_binary_search_last(SNAME *_list_, V value); \
void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, size_t high); \
@@ -215,7 +215,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + 1)) \
if (!PFX##_resize(_list_, PFX##_capacity(_list_) * 2)) \
return false; \
} \
\
@@ -315,6 +315,25 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%
return _list_->capacity; \
} \
\
bool PFX##_resize(SNAME *_list_, size_t capacity) \
{ \
if (PFX##_capacity(_list_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_list_)) \
return false; \
\
V *new_buffer = realloc(_list_->buffer, sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
_list_->buffer = new_buffer; \
_list_->capacity = capacity; \
\
return true; \
} \
\
void PFX##_sort(SNAME *_list_) \
{ \
if (!_list_->is_sorted && _list_->count > 1) \
@@ -536,24 +555,6 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%
return iter->cursor; \
} \
\
static bool PFX##_impl_grow(SNAME *_list_, size_t required) \
{ \
size_t new_capacity = _list_->capacity * 2; \
\
if (new_capacity < required) \
new_capacity = required; \
\
V *new_buffer = realloc(_list_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_list_->buffer = new_buffer; \
_list_->capacity = new_capacity; \
\
return true; \
} \
\
static size_t PFX##_impl_binary_search_first(SNAME *_list_, V value) \
{ \
if (PFX##_empty(_list_)) \
+18 -2
View File
@@ -53,10 +53,10 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
for (size_t i = 0; i < 100; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 200, mm_count(map));
cmc_assert_equals(size_t, 100, mm_count(map));
mm_free(map, NULL);
});
@@ -119,4 +119,20 @@ CMC_CREATE_UNIT(multimap_test, true, {
mm_free(map, NULL);
});
CMC_CREATE_TEST(key_count, {
multimap *map = mm_new(50, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 1000; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 1000, mm_count(map));
for (size_t i = 0; i < 20; i++)
cmc_assert_equals(size_t, 50, mm_key_count(map, i));
mm_free(map, NULL);
});
});
+69 -4
View File
@@ -69,19 +69,84 @@ CMC_CREATE_UNIT(multiset_test, true, {
ms_free(set, NULL);
});
CMC_CREATE_TEST(multiplicity, {
CMC_CREATE_TEST(remove[count cardinality multiplicity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 100; i++)
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, NULL);
});
CMC_CREATE_TEST(remove_all[count cardinality multiplicity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
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, NULL);
});
CMC_CREATE_TEST(multiplicity, {
multiset *set = ms_new(50, 0.6, cmp, hash);
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, 100, ms_cardinality(set));
cmc_assert_equals(size_t, 1000, ms_cardinality(set));
for (size_t i = 0; i < 20; i++)
cmc_assert_equals(size_t, 5, ms_multiplicity_of(set, i));
cmc_assert_equals(size_t, 50, ms_multiplicity_of(set, i));
ms_free(set, NULL);
});
+1 -1
View File
@@ -51,7 +51,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, {
});
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
sortedlist *sl = sl_new(100, cmp);
sortedlist *sl = sl_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, sl);