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; \