diff --git a/examples/multimap/README.md b/examples/multimap/README.md new file mode 100644 index 0000000..35dba30 --- /dev/null +++ b/examples/multimap/README.md @@ -0,0 +1,3 @@ +# Multimap examples + +* multimap.c - Basic examples of a multimap. diff --git a/examples/multimap/multimap.c b/examples/multimap/multimap.c new file mode 100644 index 0000000..7c5a851 --- /dev/null +++ b/examples/multimap/multimap.c @@ -0,0 +1,77 @@ +#include "multimap.h" +#include "foreach.h" +#include +#include +#include + +int intcmp(int a, int b) +{ + return (a > b) - (a < b); +} + +size_t inthash(int t) +{ + size_t a = t; + a += ~(a << 15); + a ^= (a >> 10); + a += (a << 3); + a ^= (a >> 6); + a += ~(a << 11); + a ^= (a >> 16); + return a; +} + +MULTIMAP_GENERATE(mm, multi_map, , int, int) + +int main(int argc, char const *argv[]) +{ + const int min = 1, max = 201; + multi_map *map = mm_new(50, 0.8, intcmp, inthash); + + printf("Multimap actual capacity: %" PRIu64 "\n", map->capacity); + printf("Adding items from %d to %d twice\n", min, max); + + for (int i = min; i < max; i++) + if (!mm_insert(map, i, i)) + printf("ERROR with %d:%d\n", i, i); + + for (int i = min; i < max; i++) + if (!mm_insert(map, i, i)) + printf("ERROR with %d:%d\n", i, i); + + printf("Multimap count : %" PRIu64 "\n", map->count); + printf("Multimap capacity : %" PRIu64 "\n", map->capacity); + printf("Multimap load : %lf\n", (double)map->count / (double)map->capacity); + + int64_t sum = 0; + + for (int i = min; i < max; i++) + sum += mm_get(map, i); + + printf("Sum (unique): %" PRId64 "\n", sum); + + FOR_EACH_MAP(mm, multi_map, int, int, map, { + printf("[%3" PRIu64 "] = { %3d : %3d }\n", index, key, value); + }) + + printf("Removing all items\n"); + + for (int i = min; i < max; i++) + if (!mm_remove_all(map, i)) + printf("ERROR with %d:%d\n", i, i); + + sum = 0; + + for (int i = min; i < max; i++) + sum += mm_get(map, i); + + printf("Sum: %" PRId64 "\n", sum); + + FOR_EACH_MAP(mm, multi_map, int, int, map, { + printf("[%2" PRIu64 "] = { %2d : %5d }\n", index, key, value); + }) + + mm_free(map); + + return 0; +} diff --git a/examples/multiset/README.md b/examples/multiset/README.md new file mode 100644 index 0000000..37f81a9 --- /dev/null +++ b/examples/multiset/README.md @@ -0,0 +1,3 @@ +# Multiset examples + +* prime_cof.c - Prime factorization of a number. diff --git a/examples/multiset/prime_cof.c b/examples/multiset/prime_cof.c new file mode 100644 index 0000000..16757a5 --- /dev/null +++ b/examples/multiset/prime_cof.c @@ -0,0 +1,67 @@ +#include +#include "multiset.h" + +MULTISET_GENERATE(ms, multi_set, /* FMOD */, size_t) + +int cmp(size_t a, size_t b) +{ + if (a > b) + return 1; + else if (a < b) + return -1; + return 0; +} + +void prime_cof(const size_t number) +{ + multi_set *mset = ms_new(cmp); + + size_t num = number; + + for (size_t i = 2; num != 1; i++) + { + while (num % i == 0) + { + ms_insert(mset, i); + num /= i; + } + } + + printf("The factorization of %llu is given by:\n", number); + + multi_set_iter iter; + size_t result, mul, index; + for (ms_iter_new(&iter, mset); !ms_iter_end(&iter);) + { + if (!ms_iter_next(&iter, &result, &mul, &index)) + { + printf("ERROR\n"); + break; + } + + if (ms_count(mset) == 1) + printf("(%llu^%llu)\n", result, mul); + else if (index == 0) + printf("(%llu^%llu ", result, mul); + else if (index == ms_count(mset) - 1) + printf("* %llu^%llu)\n", result, mul); + else + printf("* %llu^%llu ", result, mul); + } + + printf("Set Cardinality: %llu\n\n", ms_cardinality(mset)); + + ms_free(mset); +} + +int main(int argc, char const *argv[]) +{ + prime_cof(360); + prime_cof(55777680); + prime_cof(4294967296); + prime_cof(31415926535); + prime_cof(27182818284); + prime_cof(16180339887); + + return 0; +} diff --git a/src/multimap.h b/src/multimap.h new file mode 100644 index 0000000..165f185 --- /dev/null +++ b/src/multimap.h @@ -0,0 +1,706 @@ +/** + * multimap.h + * + * Creation Date: 26/04/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/******************************************************************* MULTIMAP */ +/*****************************************************************************/ + +#ifndef CMC_MULTIMAP_H +#define CMC_MULTIMAP_H + +#include +#include +#include + +#ifndef CMC_HASH_TABLE_SETUP +#define CMC_HASH_TABLE_SETUP + +static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, + 3067, 6143, 12289, 24571, 49157, + 98299, 196613, 393209, 786431, + 1572869, 3145721, 6291449, + 12582917, 25165813, 50331653, + 100663291, 201326611, 402653189, + 805306357, 1610612741, + 3221225473, 6442450939, + 12884901893, 25769803799, + 51539607551, 103079215111, + 206158430209, 412316860441, + 824633720831, 1649267441651, + 3298534883309, 6597069766657, + 13194139533299, 26388279066623, + 52776558133303, 105553116266489, + 211106232532969, 422212465066001, + 844424930131963, + 1688849860263953, + 3377699720527861, + 6755399441055731, + 13510798882111483, + 27021597764222939, + 54043195528445957, + 108086391056891903, + 216172782113783773, + 432345564227567621, + 864691128455135207, + 1729382256910270481, + 3458764513820540933, + 6917529027641081903, + 13835058055282163729llu}; + +#endif /* CMC_HASH_TABLE_SETUP */ + +#define MULTIMAP_GENERATE(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) + +/* PRIVATE *******************************************************************/ +#define MULTIMAP_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define MULTIMAP_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +/* PUBLIC ********************************************************************/ +#define MULTIMAP_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define MULTIMAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ + MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +/* STRUCT ********************************************************************/ +#define MULTIMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + \ + struct SNAME##_s \ + { \ + struct SNAME##_entry_s **buffer; \ + size_t capacity; \ + size_t count; \ + double load; \ + int (*cmp)(K, K); \ + size_t (*hash)(K); \ + }; \ + \ + struct SNAME##_entry_s \ + { \ + K key; \ + V value; \ + struct SNAME##_entry_s *next; \ + struct SNAME##_entry_s *prev; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + struct SNAME##_entry_s *curr_entry; \ + size_t cursor; \ + size_t first; \ + size_t last; \ + size_t index; \ + bool start; \ + bool end; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_entry_s SNAME##_entry; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)); \ + FMOD void PFX##_clear(SNAME *_map_); \ + FMOD void PFX##_free(SNAME *_map_); \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_remove(SNAME *_map_, K key); \ + FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, bool condition); \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ + FMOD V PFX##_get(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index); \ + \ +/* SOURCE ********************************************************************/ +#define MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + FMOD bool PFX##_grow(SNAME *_map_); \ + FMOD SNAME##_entry *PFX##_new_entry(K key, V value); \ + FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key); \ + FMOD size_t PFX##_calculate_size(size_t required); \ + \ + FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + if (size == 0 || load <= 0) \ + return NULL; \ + \ + size_t real_size = PFX##_calculate_size(size); \ + \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = malloc(sizeof(SNAME##_entry *) * real_size); \ + \ + if (!_map_->buffer) \ + { \ + free(_map_); \ + return NULL; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry *) * real_size); \ + \ + _map_->count = 0; \ + _map_->capacity = real_size; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_map_) \ + { \ + size_t index = 0; \ + SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + free(scan); \ + else \ + { \ + while (scan != NULL) \ + { \ + SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry *) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_map_) \ + { \ + PFX##_clear(_map_); \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ + { \ + if (!PFX##_grow(_map_)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + SNAME##_entry **target = &(_map_->buffer[pos]); \ + \ + SNAME##_entry *entry = PFX##_new_entry(key, value); \ + \ + if (*target == NULL) \ + { \ + *target = entry; \ + } \ + else \ + { \ + entry->next = *target; \ + (*target)->prev = entry; \ + \ + *target = entry; \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry **target = &(_map_->buffer[hash % _map_->capacity]); \ + \ + if (*target == NULL) \ + return false; \ + \ + SNAME##_entry *entry = *target; \ + \ + if (entry->next == NULL && entry->prev == NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + *target = NULL; \ + else \ + return false; \ + } \ + else \ + { \ + bool found = false; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*target == entry) \ + { \ + if (entry->prev != NULL) \ + *target = entry->prev; \ + else \ + *target = entry->next; \ + } \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + found = true; \ + \ + break; \ + } \ + else \ + entry = entry->next; \ + } \ + \ + if (!found) \ + return false; \ + } \ + \ + free(entry); \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + FMOD size_t PFX##_remove_all(SNAME *_map_, K key) \ + { \ + size_t total = 0; \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry **target = &(_map_->buffer[hash % _map_->capacity]); \ + \ + if (*target == NULL) \ + return total; \ + \ + SNAME##_entry *entry = *target; \ + \ + if (entry->next == NULL) \ + { \ + *target = NULL; \ + \ + free(entry); \ + \ + total++; \ + } \ + else \ + { \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*target == entry) \ + { \ + if (entry->prev != NULL) \ + *target = entry->prev; \ + else \ + *target = entry->next; \ + } \ + \ + SNAME##_entry *tmp = entry->next; \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + if (entry->next == NULL && entry->prev == NULL) \ + *target = NULL; \ + \ + free(entry); \ + entry = tmp; \ + \ + total++; \ + } \ + else \ + entry = entry->next; \ + } \ + } \ + \ + _map_->count -= total; \ + \ + return total; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + K result_key; \ + K max_key; \ + V result_value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &result_key, &result_value, &index); \ + \ + if (index == 0) \ + { \ + max_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, max_key) > 0) \ + { \ + max_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + K result_key; \ + K min_key; \ + V result_value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &result_key, &result_value, &index); \ + \ + if (index == 0) \ + { \ + min_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, min_key) < 0) \ + { \ + min_key = result_key; \ + *key = min_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_get_entry(_map_, key); \ + \ + if (!entry) \ + return 0; \ + \ + return entry->value; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \ + { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!PFX##_empty(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + if (target->buffer[i] != NULL) \ + { \ + iter->curr_entry = target->buffer[i]; \ + iter->cursor = i; \ + iter->first = i; \ + \ + break; \ + } \ + } \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1] != NULL) \ + { \ + iter->last = i - 1; \ + \ + break; \ + } \ + } \ + } \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor]; \ + } \ + \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->curr_entry = iter->target->buffer[iter->cursor]; \ + \ + if (iter->curr_entry != NULL) \ + { \ + while (iter->curr_entry->next != NULL) \ + iter->curr_entry = iter->curr_entry->next; \ + } \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index) \ + { \ + if (iter->end) \ + return false; \ + \ + *key = iter->curr_entry->key; \ + *value = iter->curr_entry->value; \ + *index = iter->index; \ + \ + if (iter->curr_entry->next != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->next; \ + iter->index++; \ + } \ + else \ + { \ + if (iter->cursor == iter->last) \ + iter->end = true; \ + else \ + { \ + iter->cursor++; \ + \ + while (iter->target->buffer[iter->cursor] == NULL) \ + iter->cursor++; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor]; \ + \ + iter->index++; \ + } \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index) \ + { \ + if (iter->start) \ + return false; \ + \ + *key = iter->curr_entry->key; \ + *value = iter->curr_entry->value; \ + *index = iter->index; \ + \ + if (iter->curr_entry->prev != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->prev; \ + iter->index--; \ + } \ + else \ + { \ + if (iter->cursor == iter->first) \ + iter->start = true; \ + else \ + { \ + iter->cursor--; \ + \ + while (iter->target->buffer[iter->cursor] == NULL) \ + iter->cursor--; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor]; \ + \ + while (iter->curr_entry->next != NULL) \ + iter->curr_entry = iter->curr_entry->next; \ + \ + iter->index--; \ + } \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_grow(SNAME *_map_) \ + { \ + size_t new_size = PFX##_calculate_size((size_t)((double)_map_->capacity * 1.5)); \ + \ + SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + SNAME##_iter iter; \ + K key; \ + V value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &key, &value, &index); \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_); \ + return false; \ + } \ + \ + SNAME##_entry **tmp_b = _map_->buffer; \ + _map_->buffer = _new_map_->buffer; \ + _new_map_->buffer = tmp_b; \ + \ + size_t tmp_c = _map_->capacity; \ + _map_->capacity = _new_map_->capacity; \ + _new_map_->capacity = tmp_c; \ + \ + PFX##_free(_new_map_); \ + \ + return true; \ + } \ + \ + FMOD SNAME##_entry *PFX##_new_entry(K key, V value) \ + { \ + SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ + \ + if (!entry) \ + return NULL; \ + \ + entry->key = key; \ + entry->value = value; \ + entry->next = NULL; \ + entry->prev = NULL; \ + \ + return entry; \ + } \ + \ + FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity]; \ + \ + if (entry == NULL) \ + return NULL; \ + \ + if (entry->next == NULL && entry->prev == NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + return entry; \ + else \ + return NULL; \ + } \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + return entry; \ + \ + entry = entry->next; \ + } \ + \ + return NULL; \ + } \ + \ + FMOD size_t PFX##_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]; \ + } + +#endif /* CMC_MULTIMAP_H */ diff --git a/src/multiset.h b/src/multiset.h new file mode 100644 index 0000000..eeacdbf --- /dev/null +++ b/src/multiset.h @@ -0,0 +1,836 @@ +/** + * multiset.h + * + * Creation Date: 10/04/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/****************************************************************** MULTISET */ +/*****************************************************************************/ + +#ifndef CMC_MULTISET_H +#define CMC_MULTISET_H + +#include +#include + +#define MULTISET_GENERATE(PFX, SNAME, FMOD, V) \ + MULTISET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ + MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) + +/* PRIVATE *******************************************************************/ +#define MULTISET_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \ + MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define MULTISET_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \ + MULTISET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ + MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +/* PUBLIC ********************************************************************/ +#define MULTISET_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \ + MULTISET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ + MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define MULTISET_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ + MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +/* STRUCT ********************************************************************/ +#define MULTISET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \ + \ + struct SNAME##_s \ + { \ + struct SNAME##_node_s *root; \ + size_t count; \ + size_t cardinality; \ + int (*cmp)(V, V); \ + }; \ + \ + struct SNAME##_node_s \ + { \ + V key; \ + size_t multiplicity; \ + unsigned char height; \ + struct SNAME##_node_s *right; \ + struct SNAME##_node_s *left; \ + struct SNAME##_node_s *parent; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + struct SNAME##_node_s *cursor; \ + struct SNAME##_node_s *first; \ + struct SNAME##_node_s *last; \ + size_t index; \ + bool start; \ + bool end; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_node_s SNAME##_node; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(int (*compare)(V, V)); \ + FMOD void PFX##_clear(SNAME *_set_); \ + FMOD void PFX##_free(SNAME *_set_); \ + FMOD bool PFX##_insert(SNAME *_set_, V element); \ + FMOD bool PFX##_remove(SNAME *_set_, V element); \ + FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + FMOD V PFX##_max(SNAME *_set_); \ + FMOD V PFX##_min(SNAME *_set_); \ + FMOD bool PFX##_empty(SNAME *_set_); \ + FMOD size_t PFX##_count(SNAME *_set_); \ + FMOD size_t PFX##_cardinality(SNAME *_set_); \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *multiplicity, size_t *index); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *multiplicity, size_t *index); \ + \ +/* SOURCE ********************************************************************/ +#define MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + FMOD SNAME##_node *PFX##_new_node(V element); \ + FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element); \ + FMOD unsigned char PFX##_h(SNAME##_node *node); \ + FMOD unsigned char PFX##_hupdate(SNAME##_node *node); \ + FMOD void PFX##_rotate_right(SNAME##_node **Z); \ + FMOD void PFX##_rotate_left(SNAME##_node **Z); \ + FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ + { \ + SNAME *_set_ = malloc(sizeof(SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->count = 0; \ + _set_->cardinality = 0; \ + _set_->root = NULL; \ + _set_->cmp = compare; \ + \ + return _set_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_set_) \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _set_->count = 0; \ + _set_->cardinality = 0; \ + _set_->root = NULL; \ + } \ + \ + FMOD void PFX##_free(SNAME *_set_) \ + { \ + PFX##_clear(_set_); \ + \ + free(_set_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->root = PFX##_new_node(element); \ + \ + if (!_set_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_set_->cmp(scan->key, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->key, element) < 0) \ + scan = scan->right; \ + else \ + { \ + scan->multiplicity++; \ + _set_->cardinality++; \ + \ + return true; \ + } \ + } \ + \ + SNAME##_node *node; \ + \ + if (_set_->cmp(parent->key, element) > 0) \ + { \ + parent->left = PFX##_new_node(element); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_new_node(element); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_rebalance(_set_, node); \ + } \ + \ + _set_->count++; \ + _set_->cardinality++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_set_, V element) \ + { \ + SNAME##_node *node = PFX##_get_node(_set_, element); \ + \ + if (!node) \ + return false; \ + \ + if (node->multiplicity > 0) \ + { \ + node->multiplicity--; \ + _set_->cardinality--; \ + \ + return true; \ + } \ + \ + SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _set_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->right; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->left; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + V temp_key = temp->key; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->key = temp_key; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_rebalance(_set_, unbalanced); \ + \ + _set_->count--; \ + _set_->cardinality--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_set_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_set_, element); \ + \ + return false; \ + } \ + \ + FMOD V PFX##_max(SNAME *_set_) \ + { \ + if (PFX##_empty(_set_)) \ + return 0; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + return scan->key; \ + } \ + \ + FMOD V PFX##_min(SNAME *_set_) \ + { \ + if (PFX##_empty(_set_)) \ + return 0; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + return scan->key; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + FMOD size_t PFX##_cardinality(SNAME *_set_) \ + { \ + return _set_->cardinality; \ + } \ + \ + FMOD SNAME##_node *PFX##_new_node(V element) \ + { \ + SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = element; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + node->multiplicity = 1; \ + \ + return node; \ + } \ + \ + FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + return NULL; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->key, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->key, element) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + FMOD unsigned char PFX##_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + FMOD unsigned char PFX##_hupdate(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_h(node->left); \ + unsigned char h_r = PFX##_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + FMOD void PFX##_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_hupdate(root); \ + new_root->height = PFX##_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + FMOD void PFX##_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_hupdate(root); \ + new_root->height = PFX##_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node) \ + { \ + SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_hupdate(scan); \ + balance = PFX##_h(scan->right) - PFX##_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_h(child->right) < PFX##_h(child->left)) \ + PFX##_rotate_right(&(scan->right)); \ + \ + PFX##_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_h(child->left) < PFX##_h(child->right)) \ + PFX##_rotate_left(&(scan->left)); \ + \ + PFX##_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _set_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + size_t index, mul; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter1, _set1_); \ + PFX##_iter_new(&iter2, _set2_); \ + \ + for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + { \ + PFX##_iter_next(&iter1, &value, &mul, &index); \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + { \ + PFX##_iter_next(&iter2, &value, &mul, &index); \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter; \ + size_t index, mul; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + PFX##_iter_new(&iter, _set_A_); \ + \ + for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &value, &mul, &index); \ + if (PFX##_get_node(_set_B_, value) != NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter; \ + size_t index, mul; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter, _set1_); \ + \ + for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &value, &mul, &index); \ + if (PFX##_get_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + size_t index, mul; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter1, _set1_); \ + PFX##_iter_new(&iter2, _set2_); \ + \ + for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + { \ + PFX##_iter_next(&iter1, &value, &mul, &index); \ + if (PFX##_get_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + { \ + PFX##_iter_next(&iter2, &value, &mul, &index); \ + if (PFX##_get_node(_set1_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return iter->start && iter->cursor == iter->first; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return iter->end && iter->cursor == iter->last; \ + } \ + \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *multiplicity, size_t *index) \ + { \ + if (iter->end) \ + return false; \ + \ + *value = iter->cursor->key; \ + *multiplicity = iter->cursor->multiplicity; \ + *index = iter->index; \ + iter->start = false; \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *multiplicity, size_t *index) \ + { \ + if (iter->start) \ + return false; \ + \ + *value = iter->cursor->key; \ + *multiplicity = iter->cursor->multiplicity; \ + *index = iter->index; \ + iter->end = false; \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } + +#endif /* CMC_MULTISET_H */