From b0a2e42cfe1fc0fd33fbf906c2a49e69eb8be2db Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 13 Jun 2019 00:40:55 -0300 Subject: [PATCH] Minor fixes all around Changed some input parameter names Updated TODO Changed how hashtables initialization works. Now the given initial capacity will be guaranteed to be reached before the hashtable rehashes (load is now considered in the calculation). --- Documentation.md | 24 +- TODO | 15 +- src/deque.h | 12 +- src/hashmap.h | 1270 +++++++++++++++++++------------------- src/hashset.h | 1536 +++++++++++++++++++++++----------------------- src/heap.h | 198 +++--- src/queue.h | 12 +- src/stack.h | 10 +- 8 files changed, 1537 insertions(+), 1540 deletions(-) diff --git a/Documentation.md b/Documentation.md index 757de4e..52faf03 100644 --- a/Documentation.md +++ b/Documentation.md @@ -136,15 +136,15 @@ The iterator is a simple structure that is capable of going back and forwards. A ## [ \_new() ](#list_function_index) -Allocates and returns a new list with an internal capacity of `size`. If allocation fails, `NULL` is returned. +Allocates and returns a new list with an internal capacity of the specified value. If allocation fails, `NULL` is returned. #### Declaration -> `FMOD SNAME *PFX##_new(size_t size);` +> `FMOD SNAME *PFX##_new(size_t capacity);` #### Parameters -1. `size_t size` - The initial capacity for the list. +1. `size_t capacity` - The initial capacity for the list. #### Returns @@ -1028,15 +1028,15 @@ A Stack is used in algorithms like backtracking, depth-first search, expression ## [ \_new() ](#stack_function_index) -Allocates and returns a new stack with an internal capacity of `size`. If allocation fails, `NULL` is returned. +Allocates and returns a new stack with an internal capacity of the specified value. If allocation fails, `NULL` is returned. #### Declaration -> `FMOD SNAME *PFX##_new(size_t size);` +> `FMOD SNAME *PFX##_new(size_t capacity);` #### Parameters -1. `size_t size` - The initial capacity for the stack. +1. `size_t capacity` - The initial capacity for the stack. #### Returns @@ -1545,15 +1545,15 @@ The queue is used in many applications where a resource is shared among multiple ## [ \_new() ](#queue_function_index) -Allocates and returns a new queue with an internal capacity of `size`. If allocation fails, `NULL` is returned. +Allocates and returns a new queue with an internal capacity of the specified value. If allocation fails, `NULL` is returned. #### Declaration -> `FMOD SNAME *PFX##_new(size_t size);` +> `FMOD SNAME *PFX##_new(size_t capacity);` #### Parameters -1. `size_t size` - The initial capacity for the queue. +1. `size_t capacity` - The initial capacity for the queue. #### Returns @@ -2062,15 +2062,15 @@ A double-ended queue backed by a circular buffer. Elements can be added and remo ## [ \_new() ](#deque_function_index) -Allocates and returns a new deque with an internal capacity of `size`. If allocation fails, `NULL` is returned. +Allocates and returns a new deque with an internal capacity of the specified value. If allocation fails, `NULL` is returned. #### Declaration -> `FMOD SNAME *PFX##_new(size_t size);` +> `FMOD SNAME *PFX##_new(size_t capacity);` #### Parameters -1. `size_t size` - The initial capacity for the deque. +1. `size_t capacity` - The initial capacity for the deque. #### Returns diff --git a/TODO b/TODO index 224148c..43505a9 100644 --- a/TODO +++ b/TODO @@ -25,27 +25,24 @@ Before 2.0 OK - Allow for struct to be a possible data type (instead of just pointer to struct) OK - Set functions: is_subset, is_proper_subset, is_superset, is_proper_superset, is_disjointset Iterator move and move_to - from_array - Creates a collection with all the elements in a specified array - to_array - Creates an array with all the elements inside the collection 1.6 + from_array - Creates a collection with all the elements in a specified array + to_array - Creates an array with all the elements inside the collection LinkedList - Insert/Remove/Append/Prepend/Extract Resize buffer function Add dispose method to each collection in order to automatically free its data + Add copy functions (copy of a collection) 2.0 - Add multiset, multimap and new heap implementation + Add new heap collection implementation + Add stack based collections 2.1 - Adapt multiset, multimap and new heap implementation to the current standards + Add variadic macros (generate only the necessary functions) 2.2 Add serialization functions - Header: - %d - Type specifier (LIST = 0, DEQUE = 1, STACK = 2, etc) for quick check - %llu - How many elements there are - %d - If data varies in size - %llu - Data size 2.3 Iterator functions (functions that operate relative to iterators position) like add or remove ranges diff --git a/src/deque.h b/src/deque.h index 8bbc193..e4f78c7 100644 --- a/src/deque.h +++ b/src/deque.h @@ -80,7 +80,7 @@ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t size); \ + FMOD SNAME *PFX##_new(size_t capacity); \ FMOD void PFX##_clear(SNAME *_deque_); \ FMOD void PFX##_free(SNAME *_deque_); \ /* Collection Input and Output */ \ @@ -140,9 +140,9 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \ \ - FMOD SNAME *PFX##_new(size_t size) \ + FMOD SNAME *PFX##_new(size_t capacity) \ { \ - if (size < 1) \ + if (capacity < 1) \ return NULL; \ \ SNAME *_deque_ = malloc(sizeof(SNAME)); \ @@ -150,7 +150,7 @@ if (!_deque_) \ return NULL; \ \ - _deque_->buffer = malloc(sizeof(V) * size); \ + _deque_->buffer = malloc(sizeof(V) * capacity); \ \ if (!_deque_->buffer) \ { \ @@ -158,9 +158,9 @@ return NULL; \ } \ \ - memset(_deque_->buffer, 0, sizeof(V) * size); \ + memset(_deque_->buffer, 0, sizeof(V) * capacity); \ \ - _deque_->capacity = size; \ + _deque_->capacity = capacity; \ _deque_->count = 0; \ _deque_->front = 0; \ _deque_->back = 0; \ diff --git a/src/hashmap.h b/src/hashmap.h index 4eca9a5..6efde97 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -74,642 +74,642 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) /* HEADER ********************************************************************/ -#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Hashmap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Key hash function */ \ - size_t (*hash)(K); \ - \ - /* Function that returns an iterator to the start of the hashmap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashmap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Hashmap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* 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) */ \ - enum EntryState_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashmap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target hashmap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - 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_); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ - /* Element Access */ \ - 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 V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - FMOD size_t PFX##_capacity(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter); \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Key */ \ - static inline K PFX##_impl_default_key(void) \ - { \ - K _empty_key_; \ - \ - memset(&_empty_key_, 0, sizeof(K)); \ - \ - return _empty_key_; \ - } \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + /* Hashmap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Key hash function */ \ + size_t (*hash)(K); \ + \ + /* Function that returns an iterator to the start of the hashmap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashmap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Hashmap Entry */ \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* 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) */ \ + enum EntryState_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashmap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target hashmap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ + FMOD void PFX##_clear(SNAME *_map_); \ + FMOD void PFX##_free(SNAME *_map_); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ + /* Element Access */ \ + 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 V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + FMOD size_t PFX##_capacity(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD K PFX##_iter_key(SNAME##_iter *iter); \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Key */ \ + static inline K PFX##_impl_default_key(void) \ + { \ + K _empty_key_; \ + \ + memset(&_empty_key_, 0, sizeof(K)); \ + \ + return _empty_key_; \ + } \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_map_); \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - if (size == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - size_t real_size = PFX##_impl_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; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_) \ - { \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_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##_impl_grow(_map_)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - if (PFX##_impl_get_entry(_map_, key) != NULL) \ - return false; \ - \ - if (target->state == ES_EMPTY || target->state == ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = original_pos - pos; \ - target->state = ES_FILLED; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - \ - if (target->state == ES_EMPTY || target->state == ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - target->state = ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < original_pos - pos) \ - { \ - K tmp_k = target->key; \ - V tmp_v = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - \ - key = tmp_k; \ - value = tmp_v; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ - \ - if (result == NULL) \ - return false; \ - \ - *value = result->value; \ - \ - result->key = PFX##_impl_default_key(); \ - result->value = PFX##_impl_default_value(); \ - result->dist = 0; \ - result->state = ES_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - 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, V *value, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) > 0) \ - { \ - *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; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) < 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - PFX##_impl_default_value(); \ - \ - return entry->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ - 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].state == 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 == ES_FILLED) \ - { \ - 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_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return false; \ - } \ - \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == ES_FILLED) \ - break; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return false; \ - } \ - \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == ES_FILLED) \ - break; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - PFX##_impl_default_key(); \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_map_) \ - { \ - size_t new_size = PFX##_impl_calculate_size(_map_->capacity + _map_->capacity / 2); \ - \ - SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_map_, key, value); \ - } \ - \ - if (_map_->count != _new_map_->count) \ - { \ - PFX##_free(_new_map_); \ - return false; \ - } \ - \ - SNAME##_entry *tmp = _map_->buffer; \ - _map_->buffer = _new_map_->buffer; \ - _new_map_->buffer = tmp; \ - \ - _map_->capacity = _new_map_->capacity; \ - \ - PFX##_free(_new_map_); \ - \ - return true; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - while (target->state == ES_FILLED || target->state == ES_DELETED) \ - { \ - if (_map_->cmp(target->key, key) == 0) \ - return target; \ - \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_map_); \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + \ + if (!_map_->buffer) \ + { \ + free(_map_); \ + return NULL; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_map_) \ + { \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_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##_impl_grow(_map_)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + if (PFX##_impl_get_entry(_map_, key) != NULL) \ + return false; \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = original_pos - pos; \ + target->state = ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + target->state = ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < original_pos - pos) \ + { \ + K tmp_k = target->key; \ + V tmp_v = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + \ + key = tmp_k; \ + value = tmp_v; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ + { \ + SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ + \ + if (result == NULL) \ + return false; \ + \ + *value = result->value; \ + \ + result->key = PFX##_impl_default_key(); \ + result->value = PFX##_impl_default_value(); \ + result->dist = 0; \ + result->state = ES_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + 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, V *value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) > 0) \ + { \ + *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; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) < 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + PFX##_impl_default_value(); \ + \ + return entry->value; \ + } \ + \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->index = 0; \ + 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].state == 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 == ES_FILLED) \ + { \ + 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_to_start(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + \ + return false; \ + } \ + \ + iter->index++; \ + \ + while (1) \ + { \ + iter->cursor++; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return false; \ + } \ + \ + iter->index--; \ + \ + while (1) \ + { \ + iter->cursor--; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + PFX##_impl_default_key(); \ + \ + return iter->target->buffer[iter->cursor].key; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor].value); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_map_) \ + { \ + size_t new_size = PFX##_impl_calculate_size(_map_->capacity + _map_->capacity / 2); \ + \ + SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_); \ + return false; \ + } \ + \ + SNAME##_entry *tmp = _map_->buffer; \ + _map_->buffer = _new_map_->buffer; \ + _new_map_->buffer = tmp; \ + \ + _map_->capacity = _new_map_->capacity; \ + \ + PFX##_free(_new_map_); \ + \ + return true; \ + } \ + \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + while (target->state == ES_FILLED || target->state == ES_DELETED) \ + { \ + if (_map_->cmp(target->key, key) == 0) \ + return target; \ + \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HASHMAP_H */ diff --git a/src/hashset.h b/src/hashset.h index 7c17358..569a677 100644 --- a/src/hashset.h +++ b/src/hashset.h @@ -74,775 +74,775 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* HEADER ********************************************************************/ -#define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Hashset Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current Array Capcity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Element hash function */ \ - size_t (*hash)(V); \ - \ - /* Function that returns an iterator to the start of the hashset */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry element */ \ - V value; \ - \ - /* 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) */ \ - enum EntryState_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashset Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Hashset */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - FMOD void PFX##_clear(SNAME *_set_); \ - FMOD void PFX##_free(SNAME *_set_); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_set_, V element); \ - FMOD bool PFX##_remove(SNAME *_set_, V element); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_set_, V *value); \ - FMOD bool PFX##_min(SNAME *_set_, V *value); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_set_, V element); \ - FMOD bool PFX##_empty(SNAME *_set_); \ - FMOD size_t PFX##_count(SNAME *_set_); \ - FMOD size_t PFX##_capacity(SNAME *_set_); \ - \ - /* Set Operations */ \ - 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 bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + /* Hashset Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ + \ + /* Current Array Capcity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Element hash function */ \ + size_t (*hash)(V); \ + \ + /* Function that returns an iterator to the start of the hashset */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry element */ \ + V value; \ + \ + /* 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) */ \ + enum EntryState_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashset Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Hashset */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ + FMOD void PFX##_clear(SNAME *_set_); \ + FMOD void PFX##_free(SNAME *_set_); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_set_, V element); \ + FMOD bool PFX##_remove(SNAME *_set_, V element); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + /* Element Access */ \ + FMOD bool PFX##_max(SNAME *_set_, V *value); \ + FMOD bool PFX##_min(SNAME *_set_, V *value); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_set_, V element); \ + FMOD bool PFX##_empty(SNAME *_set_); \ + FMOD size_t PFX##_count(SNAME *_set_); \ + FMOD size_t PFX##_capacity(SNAME *_set_); \ + \ + /* Set Operations */ \ + 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 bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - 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_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ - \ - FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)) \ - { \ - if (size == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - size_t real_size = PFX##_impl_calculate_size(size); \ - \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = malloc(sizeof(SNAME##_entry) * real_size); \ - \ - if (!_set_->buffer) \ - { \ - free(_set_); \ - return NULL; \ - } \ - \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_size); \ - \ - _set_->count = 0; \ - _set_->capacity = real_size; \ - _set_->load = load; \ - _set_->cmp = compare; \ - _set_->hash = hash; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ - return _set_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_set_) \ - { \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ - \ - _set_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_set_) \ - { \ - free(_set_->buffer); \ - free(_set_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ - { \ - if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \ - { \ - if (!PFX##_impl_grow(_set_)) \ - return false; \ - } \ - \ - size_t hash = _set_->hash(element); \ - size_t original_pos = hash % _set_->capacity; \ - size_t pos = original_pos; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - if (PFX##_impl_get_entry(_set_, element) != NULL) \ - return false; \ - \ - if (target->state == ES_EMPTY || target->state == ES_DELETED) \ - { \ - target->value = element; \ - target->dist = pos - original_pos; \ - target->state = ES_FILLED; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - \ - if (target->state == ES_EMPTY || target->state == ES_DELETED) \ - { \ - target->value = element; \ - target->dist = pos - original_pos; \ - target->state = ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < pos - original_pos) \ - { \ - V tmp = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->value = element; \ - target->dist = pos - original_pos; \ - \ - element = tmp; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return false; \ - \ - result->value = PFX##_impl_default_value(); \ - result->dist = 0; \ - result->state = ES_DELETED; \ - \ - _set_->count--; \ - \ - 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 bool PFX##_max(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) > 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) < 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_set_, V element) \ - { \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_set_) \ - { \ - return _set_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return false; \ - \ - SNAME##_iter iter1, iter2; \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return false; \ - \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set_A_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set_B_, value) != NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter1, iter2; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return false; \ - \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - V value = PFX##_iter_value(&iter2); \ - \ - if (PFX##_impl_get_entry(_set1_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - /* Is _set1_ a subset of _set2_ ? */ \ - /* A set X is a subset of a set Y when: X <= Y */ \ - /* If X is a subset of Y, then Y is a superset of X */ \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ - /* say that _set1_ can't be a subset of _set2_ */ \ - if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ - return false; \ - \ - /* The empty set is a subset of all sets */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a superset of _set2_ ? */ \ - /* A set X is a superset of a set Y when: X >= Y */ \ - /* If X is a superset of Y, then Y is a subset of X */ \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a proper subset of _set2_ ? */ \ - /* A set X is a proper subset of a set Y when: X < Y */ \ - /* If X is a proper subset of Y, then Y is a proper superset of X */ \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ - /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ - if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_empty(_set1_)) \ - { \ - /* The empty set is a proper subset of all non-empty sets */ \ - if (!PFX##_empty(_set2_)) \ - return true; \ - /* The empty set is not a proper subset of itself (this is true for any set) */ \ - else \ - return false; \ - } \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a proper superset of _set2_ ? */ \ - /* A set X is a proper superset of a set Y when: X > Y */ \ - /* If X is a proper superset of Y, then Y is a proper subset of X */ \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_proper_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a disjointset of _set2_ ? */ \ - /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ - /* there are no elements in common between the two */ \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* The intersection of an empty set with any other set will result in an empty set */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ - 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].state == 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 == ES_FILLED) \ - { \ - 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_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->last) \ - iter->end = true; \ - else \ - { \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == ES_FILLED) \ - break; \ - } \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->first) \ - iter->start = true; \ - else \ - { \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == ES_FILLED) \ - break; \ - } \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - 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(_new_set_, PFX##_iter_value(&iter)); \ - } \ - \ - if (_set_->count != _new_set_->count) \ - { \ - PFX##_free(_new_set_); \ - \ - 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_); \ - \ - return true; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ - { \ - size_t hash = _set_->hash(element); \ - size_t pos = hash % _set_->capacity; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - while (target->state == ES_FILLED || target->state == ES_DELETED) \ - { \ - if (_set_->cmp(target->value, element) == 0) \ - return target; \ - \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + 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_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ + { \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + SNAME *_set_ = malloc(sizeof(SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + \ + if (!_set_->buffer) \ + { \ + free(_set_); \ + return NULL; \ + } \ + \ + memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ + \ + _set_->count = 0; \ + _set_->capacity = real_capacity; \ + _set_->load = load; \ + _set_->cmp = compare; \ + _set_->hash = hash; \ + \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ + return _set_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_set_) \ + { \ + memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ + \ + _set_->count = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_set_) \ + { \ + free(_set_->buffer); \ + free(_set_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_set_, V element) \ + { \ + if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \ + { \ + if (!PFX##_impl_grow(_set_)) \ + return false; \ + } \ + \ + size_t hash = _set_->hash(element); \ + size_t original_pos = hash % _set_->capacity; \ + size_t pos = original_pos; \ + \ + SNAME##_entry *target = &(_set_->buffer[pos]); \ + \ + if (PFX##_impl_get_entry(_set_, element) != NULL) \ + return false; \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->value = element; \ + target->dist = pos - original_pos; \ + target->state = ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_set_->buffer[pos % _set_->capacity]); \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->value = element; \ + target->dist = pos - original_pos; \ + target->state = ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < pos - original_pos) \ + { \ + V tmp = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->value = element; \ + target->dist = pos - original_pos; \ + \ + element = tmp; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _set_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_set_, V element) \ + { \ + SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + \ + if (result == NULL) \ + return false; \ + \ + result->value = PFX##_impl_default_value(); \ + result->dist = 0; \ + result->state = ES_DELETED; \ + \ + _set_->count--; \ + \ + 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 bool PFX##_max(SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + *value = result; \ + else if (_set_->cmp(result, *value) > 0) \ + *value = result; \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + *value = result; \ + else if (_set_->cmp(result, *value) < 0) \ + *value = result; \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_set_, V element) \ + { \ + return PFX##_impl_get_entry(_set_, element) != NULL; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_set_) \ + { \ + return _set_->capacity; \ + } \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return false; \ + \ + SNAME##_iter iter1, iter2; \ + PFX##_iter_init(&iter1, _set1_); \ + PFX##_iter_init(&iter2, _set2_); \ + \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ + { \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ + { \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return false; \ + \ + SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set_A_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_impl_get_entry(_set_B_, value) != NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_impl_get_entry(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_init(&iter1, _set1_); \ + PFX##_iter_init(&iter2, _set2_); \ + \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ + { \ + V value = PFX##_iter_value(&iter1); \ + \ + if (PFX##_impl_get_entry(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ + { \ + V value = PFX##_iter_value(&iter2); \ + \ + if (PFX##_impl_get_entry(_set1_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + /* Is _set1_ a subset of _set2_ ? */ \ + /* A set X is a subset of a set Y when: X <= Y */ \ + /* If X is a subset of Y, then Y is a superset of X */ \ + FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ + /* say that _set1_ can't be a subset of _set2_ */ \ + if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ + return false; \ + \ + /* The empty set is a subset of all sets */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a superset of _set2_ ? */ \ + /* A set X is a superset of a set Y when: X >= Y */ \ + /* If X is a superset of Y, then Y is a subset of X */ \ + FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a proper subset of _set2_ ? */ \ + /* A set X is a proper subset of a set Y when: X < Y */ \ + /* If X is a proper subset of Y, then Y is a proper superset of X */ \ + FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ + /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ + if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + { \ + /* The empty set is a proper subset of all non-empty sets */ \ + if (!PFX##_empty(_set2_)) \ + return true; \ + /* The empty set is not a proper subset of itself (this is true for any set) */ \ + else \ + return false; \ + } \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a proper superset of _set2_ ? */ \ + /* A set X is a proper superset of a set Y when: X > Y */ \ + /* If X is a proper superset of Y, then Y is a proper subset of X */ \ + FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_proper_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a disjointset of _set2_ ? */ \ + /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ + /* there are no elements in common between the two */ \ + FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result in an empty set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->index = 0; \ + 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].state == 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 == ES_FILLED) \ + { \ + 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_to_start(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (iter->cursor == iter->last) \ + iter->end = true; \ + else \ + { \ + iter->index++; \ + \ + while (1) \ + { \ + iter->cursor++; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (iter->cursor == iter->first) \ + iter->start = true; \ + else \ + { \ + iter->index--; \ + \ + while (1) \ + { \ + iter->cursor--; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + 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(_new_set_, PFX##_iter_value(&iter)); \ + } \ + \ + if (_set_->count != _new_set_->count) \ + { \ + PFX##_free(_new_set_); \ + \ + 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_); \ + \ + return true; \ + } \ + \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ + { \ + size_t hash = _set_->hash(element); \ + size_t pos = hash % _set_->capacity; \ + \ + SNAME##_entry *target = &(_set_->buffer[pos]); \ + \ + while (target->state == ES_FILLED || target->state == ES_DELETED) \ + { \ + if (_set_->cmp(target->value, element) == 0) \ + return target; \ + \ + pos++; \ + target = &(_set_->buffer[pos % _set_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HASHSET_H */ diff --git a/src/heap.h b/src/heap.h index 16c7bbf..bd995cf 100644 --- a/src/heap.h +++ b/src/heap.h @@ -36,100 +36,100 @@ typedef enum HeapOrder HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* HEADER ********************************************************************/ -#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Heap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Heap order (MaxHeap or MinHeap) */ \ - enum HeapOrder HO; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Heap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target heap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_heap_); \ - FMOD void PFX##_free(SNAME *_heap_); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_heap_, V element); \ - FMOD bool PFX##_remove(SNAME *_heap_, V *result); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_peek(SNAME *_heap_); \ - FMOD V *PFX##_peek_ref(SNAME *_heap_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_heap_, V element); \ - FMOD bool PFX##_empty(SNAME *_heap_); \ - FMOD bool PFX##_full(SNAME *_heap_); \ - FMOD size_t PFX##_count(SNAME *_heap_); \ - FMOD size_t PFX##_capacity(SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + /* Heap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements in the heap */ \ + size_t count; \ + \ + /* Heap order (MaxHeap or MinHeap) */ \ + enum HeapOrder HO; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Heap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target heap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity, HeapOrder HO, int (*compare)(V, V)); \ + FMOD void PFX##_clear(SNAME *_heap_); \ + FMOD void PFX##_free(SNAME *_heap_); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_heap_, V element); \ + FMOD bool PFX##_remove(SNAME *_heap_, V *result); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \ + /* Element Access */ \ + FMOD V PFX##_peek(SNAME *_heap_); \ + FMOD V *PFX##_peek_ref(SNAME *_heap_); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_heap_, V element); \ + FMOD bool PFX##_empty(SNAME *_heap_); \ + FMOD bool PFX##_full(SNAME *_heap_); \ + FMOD size_t PFX##_count(SNAME *_heap_); \ + FMOD size_t PFX##_capacity(SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ #define HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ \ @@ -143,9 +143,9 @@ typedef enum HeapOrder static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ \ - FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)) \ + FMOD SNAME *PFX##_new(size_t capacity, HeapOrder HO, int (*compare)(V, V)) \ { \ - if (size < 1) \ + if (capacity < 1) \ return NULL; \ \ if (HO != MinHeap && HO != MaxHeap) \ @@ -156,7 +156,7 @@ typedef enum HeapOrder if (!_heap_) \ return NULL; \ \ - _heap_->buffer = malloc(sizeof(V) * size); \ + _heap_->buffer = malloc(sizeof(V) * capacity); \ \ if (!_heap_->buffer) \ { \ @@ -164,9 +164,9 @@ typedef enum HeapOrder return NULL; \ } \ \ - memset(_heap_->buffer, 0, sizeof(V) * size); \ + memset(_heap_->buffer, 0, sizeof(V) * capacity); \ \ - _heap_->capacity = size; \ + _heap_->capacity = capacity; \ _heap_->count = 0; \ _heap_->HO = HO; \ _heap_->cmp = compare; \ diff --git a/src/queue.h b/src/queue.h index 0dc1dfb..a45980e 100644 --- a/src/queue.h +++ b/src/queue.h @@ -80,7 +80,7 @@ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t size); \ + FMOD SNAME *PFX##_new(size_t capacity); \ FMOD void PFX##_clear(SNAME *_queue_); \ FMOD void PFX##_free(SNAME *_queue_); \ /* Collection Input and Output */ \ @@ -135,9 +135,9 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \ \ - FMOD SNAME *PFX##_new(size_t size) \ + FMOD SNAME *PFX##_new(size_t capacity) \ { \ - if (size < 1) \ + if (capacity < 1) \ return NULL; \ \ SNAME *_queue_ = malloc(sizeof(SNAME)); \ @@ -145,7 +145,7 @@ if (!_queue_) \ return NULL; \ \ - _queue_->buffer = malloc(sizeof(V) * size); \ + _queue_->buffer = malloc(sizeof(V) * capacity); \ \ if (!_queue_->buffer) \ { \ @@ -153,9 +153,9 @@ return NULL; \ } \ \ - memset(_queue_->buffer, 0, sizeof(V) * size); \ + memset(_queue_->buffer, 0, sizeof(V) * capacity); \ \ - _queue_->capacity = size; \ + _queue_->capacity = capacity; \ _queue_->count = 0; \ _queue_->front = 0; \ _queue_->rear = 0; \ diff --git a/src/stack.h b/src/stack.h index f59933b..e3879d2 100644 --- a/src/stack.h +++ b/src/stack.h @@ -71,7 +71,7 @@ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t size); \ + FMOD SNAME *PFX##_new(size_t capacity); \ FMOD void PFX##_clear(SNAME *_stack_); \ FMOD void PFX##_free(SNAME *_stack_); \ /* Collection Input and Output */ \ @@ -126,9 +126,9 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ \ - FMOD SNAME *PFX##_new(size_t size) \ + FMOD SNAME *PFX##_new(size_t capacity) \ { \ - if (size < 1) \ + if (capacity < 1) \ return NULL; \ \ SNAME *_stack_ = malloc(sizeof(SNAME)); \ @@ -136,7 +136,7 @@ if (!_stack_) \ return NULL; \ \ - _stack_->buffer = malloc(sizeof(V) * size); \ + _stack_->buffer = malloc(sizeof(V) * capacity); \ \ if (!_stack_->buffer) \ { \ @@ -146,7 +146,7 @@ \ memset(_stack_->buffer, 0, sizeof(V) * size); \ \ - _stack_->capacity = size; \ + _stack_->capacity = capacity; \ _stack_->count = 0; \ \ _stack_->it_start = PFX##_impl_it_start; \