diff --git a/src/cmc/deque.h b/src/cmc/deque.h index cb3bb65..4a7e6c6 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -121,6 +121,7 @@ FMOD size_t PFX##_count(SNAME *_deque_); \ FMOD size_t PFX##_capacity(SNAME *_deque_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_deque_); \ \ /* Iterator Functions */ \ @@ -363,6 +364,33 @@ return _deque_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_deque_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ + { \ + result->buffer[j] = copy_func(_deque_->buffer[i]); \ + } \ + } \ + else \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ + { \ + result->buffer[j] = _deque_->buffer[i]; \ + } \ + } \ + \ + result->count = _deque_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_deque_) \ { \ cmc_string str; \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index b168375..45b5ee7 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -178,6 +178,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_count(SNAME *_map_); \ FMOD size_t PFX##_capacity(SNAME *_map_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -525,6 +526,51 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _map_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + if (key_copy_func || value_copy_func) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *scan = &(_map_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + SNAME##_entry *target = &(result->buffer[i]); \ + \ + if (scan->state == CMC_ES_DELETED) \ + target->state = CMC_ES_DELETED; \ + else \ + { \ + target->state = scan->state; \ + target->dist = scan->dist; \ + \ + if (key_copy_func) \ + target->key = key_copy_func(scan->key); \ + else \ + target->key = scan->key; \ + \ + if (value_copy_func) \ + target->value = value_copy_func(scan->value); \ + else \ + target->value = scan->value; \ + } \ + } \ + } \ + } \ + else \ + memcpy(result->buffer, _map_->buffer, sizeof(SNAME##_entry) * _map_->capacity); \ + \ + result->count = _map_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 8dd076b..264b259 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -169,6 +169,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_count(SNAME *_set_); \ FMOD size_t PFX##_capacity(SNAME *_set_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -448,6 +449,43 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *scan = &(_set_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + SNAME##_entry *target = &(result->buffer[i]); \ + \ + if (scan->state == CMC_ES_DELETED) \ + target->state = CMC_ES_DELETED; \ + else \ + { \ + target->state = scan->state; \ + target->dist = scan->dist; \ + \ + target->value = copy_func(scan->value); \ + } \ + } \ + } \ + } \ + else \ + memcpy(result->buffer, _set_->buffer, sizeof(SNAME##_entry) * _set_->capacity); \ + \ + result->count = _set_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 83da512..c1602b0 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -119,6 +119,7 @@ typedef enum cmc_heap_order_e FMOD size_t PFX##_count(SNAME *_heap_); \ FMOD size_t PFX##_capacity(SNAME *_heap_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ \ /* Iterator Functions */ \ @@ -324,6 +325,26 @@ typedef enum cmc_heap_order_e return _heap_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_heap_->capacity, _heap_->HO, _heap_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + result->buffer[i] = copy_func(_heap_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \ + \ + result->count = _heap_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ { \ cmc_string str; \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index 001b321..a5d2b5e 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -126,6 +126,7 @@ FMOD bool PFX##_empty(SNAME *_list_); \ FMOD size_t PFX##_count(SNAME *_list_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_list_); \ \ /* Node Related Functions */ \ @@ -467,6 +468,46 @@ return _list_->count; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_node *scan = _list_->head; \ + \ + while (scan != NULL) \ + { \ + /* This allocation should never fail since it might not be */ \ + /* possible to recover from it. That is why it isn't checked */ \ + SNAME##_node *new_node; \ + \ + if (copy_func) \ + new_node = PFX##_new_node(copy_func(scan->data)); \ + else \ + new_node = PFX##_new_node(scan->data); \ + \ + if (!result->head) \ + { \ + result->head = new_node; \ + result->tail = new_node; \ + } \ + else \ + { \ + new_node->prev = result->tail; \ + result->tail->next = new_node; \ + result->tail = new_node; \ + } \ + \ + scan = scan->next; \ + } \ + \ + result->count = _list_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_list_) \ { \ cmc_string str; \ diff --git a/src/cmc/list.h b/src/cmc/list.h index 0fd6b6c..6bc72ea 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -135,6 +135,7 @@ FMOD bool PFX##_fits(SNAME *_list_, size_t size); \ FMOD size_t PFX##_capacity(SNAME *_list_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_list_); \ \ /* Iterator Functions */ \ @@ -564,6 +565,26 @@ return _list_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_list_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + result->buffer[i] = copy_func(_list_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \ + \ + result->count = _list_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_list_) \ { \ cmc_string str; \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index eae6b7b..97a495f 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -128,6 +128,7 @@ FMOD size_t PFX##_count(SNAME *_queue_); \ FMOD size_t PFX##_capacity(SNAME *_queue_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_queue_); \ \ /* Iterator Functions */ \ @@ -313,6 +314,33 @@ return _queue_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_queue_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ + { \ + result->buffer[j] = copy_func(_queue_->buffer[i]); \ + } \ + } \ + else \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ + { \ + result->buffer[j] = _queue_->buffer[i]; \ + } \ + } \ + \ + result->count = _queue_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_queue_) \ { \ cmc_string str; \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 8871fc1..46bc5ad 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -104,6 +104,7 @@ FMOD size_t PFX##_count(SNAME *_stack_); \ FMOD size_t PFX##_capacity(SNAME *_stack_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_stack_); \ \ /* Iterator Functions */ \ @@ -275,6 +276,26 @@ return _stack_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_stack_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + result->buffer[i] = copy_func(_stack_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _stack_->buffer, sizeof(V) * _stack_->count); \ + \ + result->count = _stack_->count; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_stack_) \ { \ cmc_string str; \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index aa5c083..952b908 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -36,901 +36,931 @@ TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) /* HEADER ********************************************************************/ -#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Treemap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Root node */ \ - struct SNAME##_node_s *root; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Function that returns an iterator to the start of the treemap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Treemap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node Key */ \ - K key; \ - \ - /* Node Value */ \ - V value; \ - \ - /* Node height used by the AVL tree to keep it strictly balanced */ \ - unsigned char height; \ - \ - /* Right child node or subtree */ \ - struct SNAME##_node_s *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node_s *left; \ - \ - /* Parent node */ \ - struct SNAME##_node_s *parent; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Treemap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target treemap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node_s *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node_s *last; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* 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(int (*compare)(K, K)); \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_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); \ - FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - /* Collection Utility */ \ - FMOD cmc_string PFX##_to_string(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 TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + /* Treemap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Root node */ \ + struct SNAME##_node_s *root; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Function that returns an iterator to the start of the treemap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the treemap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Treemap Node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node Key */ \ + K key; \ + \ + /* Node Value */ \ + V value; \ + \ + /* Node height used by the AVL tree to keep it strictly balanced */ \ + unsigned char height; \ + \ + /* Right child node or subtree */ \ + struct SNAME##_node_s *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node_s *left; \ + \ + /* Parent node */ \ + struct SNAME##_node_s *parent; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Treemap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target treemap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node_s *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node_s *last; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* 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(int (*compare)(K, K)); \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_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); \ + FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + FMOD cmc_string PFX##_to_string(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 TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - /* Implementation Detail Functions */ \ - static SNAME##_node *PFX##_impl_new_node(K key, V value); \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ - static unsigned char PFX##_impl_h(SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ - static void PFX##_impl_rotate_right(SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(SNAME##_node **Z); \ - static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ - { \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - } \ - \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - free(_map_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_impl_new_node(key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - SNAME##_node *node; \ - \ - if (_map_->cmp(parent->key, key) > 0) \ - { \ - parent->left = PFX##_impl_new_node(key, value); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(key, value); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_map_, node); \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - *old_value = node->value; \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - *value = node->value; \ - \ - SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _map_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->right; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->left; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - K temp_key = temp->key; \ - V temp_val = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - free(temp); \ - \ - node->key = temp_key; \ - node->value = temp_val; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_map_, unbalanced); \ - \ - _map_->count--; \ - \ - if (_map_->count == 0) \ - _map_->root = NULL; \ - \ - 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##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return PFX##_impl_default_value(); \ - \ - return node->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ - name, m_, m_->root, m_->count, m_->cmp); \ - \ - return str; \ - } \ - \ - 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->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return 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->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = false; \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = false; \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_key(); \ - \ - return iter->cursor->key; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->cursor->value; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->value); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_node *PFX##_impl_new_node(K key, V value) \ - { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->key = key; \ - node->value = value; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \ - { \ - SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _map_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - 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 TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + /* Implementation Detail Functions */ \ + static SNAME##_node *PFX##_impl_new_node(K key, V value); \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ + static unsigned char PFX##_impl_h(SNAME##_node *node); \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ + static void PFX##_impl_rotate_right(SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(SNAME##_node **Z); \ + static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ + { \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _map_->cmp = compare; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + SNAME##_node *scan = _map_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + } \ + \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + PFX##_clear(_map_, deallocator); \ + \ + free(_map_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->root = PFX##_impl_new_node(key, value); \ + \ + if (!_map_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _map_->root; \ + SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + SNAME##_node *node; \ + \ + if (_map_->cmp(parent->key, key) > 0) \ + { \ + parent->left = PFX##_impl_new_node(key, value); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(key, value); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_map_, node); \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + *old_value = node->value; \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + *value = node->value; \ + \ + SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _map_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->right; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->left; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + K temp_key = temp->key; \ + V temp_val = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->key = temp_key; \ + node->value = temp_val; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_map_, unbalanced); \ + \ + _map_->count--; \ + \ + if (_map_->count == 0) \ + _map_->root = NULL; \ + \ + 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##_node *scan = _map_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return PFX##_impl_default_value(); \ + \ + return node->value; \ + } \ + \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return NULL; \ + \ + return &(node->value); \ + } \ + \ + FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_map_, K key) \ + { \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_map_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + if (!PFX##_empty(_map_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + if (key_copy_func) \ + key = key_copy_func(key); \ + if (value_copy_func) \ + value = value_copy_func(value); \ + \ + PFX##_insert(result, key, value); \ + } \ + } \ + \ + return result; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_map_) \ + { \ + cmc_string str; \ + SNAME *m_ = _map_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ + name, m_, m_->root, m_->count, m_->cmp); \ + \ + return str; \ + } \ + \ + 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->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return 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->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = false; \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = false; \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_key(); \ + \ + return iter->cursor->key; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->cursor->value; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->value); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static SNAME##_node *PFX##_impl_new_node(K key, V value) \ + { \ + SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = key; \ + node->value = value; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ + { \ + if (PFX##_empty(_map_)) \ + return NULL; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \ + { \ + SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _map_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + 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_TREEMAP_H */ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index a9c2055..37d52ad 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -123,6 +123,7 @@ FMOD bool PFX##_empty(SNAME *_set_); \ FMOD size_t PFX##_count(SNAME *_set_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -165,899 +166,923 @@ } \ \ /* SOURCE ********************************************************************/ -#define TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static SNAME##_node *PFX##_impl_new_node(V element); \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element); \ - static unsigned char PFX##_impl_h(SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ - static void PFX##_impl_rotate_right(SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(SNAME##_node **Z); \ - static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ - \ - FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ - { \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ - return _set_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ - { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->value); \ - \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - if (deallocator) \ - deallocator(scan->value); \ - \ - free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - } \ - \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ - { \ - PFX##_clear(_set_, deallocator); \ - \ - free(_set_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - { \ - _set_->root = PFX##_impl_new_node(element); \ - \ - if (!_set_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - SNAME##_node *node; \ - \ - if (_set_->cmp(parent->value, element) > 0) \ - { \ - parent->left = PFX##_impl_new_node(element); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(element); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_set_, node); \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ - \ - if (!node) \ - return false; \ - \ - SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _set_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _set_->root = node->right; \ - _set_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _set_->root = node->left; \ - _set_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - V temp_value = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - free(temp); \ - \ - node->value = temp_value; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_set_, unbalanced); \ - \ - _set_->count--; \ - \ - if (_set_->count == 0) \ - _set_->root = NULL; \ - \ - 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##_node *scan = _set_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_set_, V element) \ - { \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan != NULL) \ - { \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_set_) \ - { \ - cmc_string str; \ - SNAME *s_ = _set_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ - name, s_, s_->root, s_->count, s_->cmp); \ - \ - return str; \ - } \ - \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - 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_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - 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_node(_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_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - 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_node(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - 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)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - if (PFX##_impl_get_node(_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_node(_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->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return 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->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->cursor->value; \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_node *PFX##_impl_new_node(V element) \ - { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->value = element; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - return NULL; \ - \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan != NULL) \ - { \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node) \ - { \ - SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _set_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - 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 TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + static SNAME##_node *PFX##_impl_new_node(V element); \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element); \ + static unsigned char PFX##_impl_h(SNAME##_node *node); \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ + static void PFX##_impl_rotate_right(SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(SNAME##_node **Z); \ + static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ + { \ + SNAME *_set_ = malloc(sizeof(SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + _set_->cmp = compare; \ + \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ + return _set_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->value); \ + \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (deallocator) \ + deallocator(scan->value); \ + \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + } \ + \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + { \ + PFX##_clear(_set_, deallocator); \ + \ + free(_set_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->root = PFX##_impl_new_node(element); \ + \ + if (!_set_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + SNAME##_node *node; \ + \ + if (_set_->cmp(parent->value, element) > 0) \ + { \ + parent->left = PFX##_impl_new_node(element); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(element); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_set_, node); \ + } \ + \ + _set_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_set_, V element) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ + \ + if (!node) \ + return false; \ + \ + SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _set_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->right; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->left; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + V temp_value = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->value = temp_value; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_set_, unbalanced); \ + \ + _set_->count--; \ + \ + if (_set_->count == 0) \ + _set_->root = NULL; \ + \ + 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##_node *scan = _set_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_set_, V element) \ + { \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_set_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set_); \ + \ + if (!PFX##_empty(_set_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (copy_func) \ + PFX##_insert(result, copy_func(PFX##_iter_value(&iter))); \ + else \ + PFX##_insert(result, PFX##_iter_value(&iter)); \ + } \ + } \ + \ + return result; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_set_) \ + { \ + cmc_string str; \ + SNAME *s_ = _set_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ + name, s_, s_->root, s_->count, s_->cmp); \ + \ + return str; \ + } \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + 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_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + 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_node(_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_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + 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_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + 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)) \ + { \ + V value = PFX##_iter_value(&iter1); \ + \ + if (PFX##_impl_get_node(_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_node(_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->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return 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->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->cursor->value; \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static SNAME##_node *PFX##_impl_new_node(V element) \ + { \ + SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->value = element; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + return NULL; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node) \ + { \ + SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _set_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + 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_TREESET_H */ diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index 80cda2d..323d885 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -118,6 +118,7 @@ FMOD size_t PFX##_count(SNAME *_heap_); \ FMOD size_t PFX##_capacity(SNAME *_heap_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ \ /* Iterator Functions */ \ @@ -149,709 +150,737 @@ } \ \ /* SOURCE ********************************************************************/ -#define INTERVALHEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_heap_); \ - static void PFX##_impl_float_up_max(SNAME *_heap_); \ - static void PFX##_impl_float_up_min(SNAME *_heap_); \ - static void PFX##_impl_float_down_max(SNAME *_heap_); \ - static void PFX##_impl_float_down_min(SNAME *_heap_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ - { \ - SNAME *_heap_ = malloc(sizeof(SNAME)); \ - \ - if (!_heap_) \ - return NULL; \ - \ - /* Since each node can store two elements, divide the actual capacity by 2 */ \ - /* Round the capacity of nodes up */ \ - capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ - \ - _heap_->buffer = malloc(sizeof(SNAME##_node) * capacity); \ - \ - if (!_heap_->buffer) \ - { \ - free(_heap_); \ - return NULL; \ - } \ - \ - memset(_heap_->buffer, 0, sizeof(SNAME##_node) * capacity); \ - \ - _heap_->capacity = capacity; \ - _heap_->size = 0; \ - _heap_->count = 0; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ - return _heap_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - } \ - \ - memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ - \ - _heap_->size = 0; \ - _heap_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - } \ - \ - free(_heap_->buffer); \ - \ - free(_heap_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_heap_, V element) \ - { \ - if (PFX##_full(_heap_)) \ - { \ - if (!PFX##_impl_grow(_heap_)) \ - return false; \ - } \ - \ - if (PFX##_count(_heap_) % 2 == 0) \ - { \ - /* Occupying a new node */ \ - _heap_->buffer[_heap_->size].data[0] = element; \ - _heap_->buffer[_heap_->size].data[1] = PFX##_impl_default_value(); \ - \ - _heap_->size++; \ - } \ - else \ - { \ - SNAME##_node *curr_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - /* Decide if the new element goes into the MinHeap or MaxHeap */ \ - if (_heap_->cmp(curr_node->data[0], element) > 0) \ - { \ - /* Swap current value and add new element to the MinHeap */ \ - curr_node->data[1] = curr_node->data[0]; \ - curr_node->data[0] = element; \ - } \ - else \ - { \ - /* No need to swap and add the new element to the MaxHeap */ \ - curr_node->data[1] = element; \ - } \ - } \ - \ - _heap_->count++; \ - \ - if (PFX##_count(_heap_) <= 2) \ - return true; \ - \ - /* Determine wheather to do a MaxHeap insert or a MinHeap insert */ \ - SNAME##_node *parent = &(_heap_->buffer[(_heap_->size - 1) / 2]); \ - \ - if (_heap_->cmp(parent->data[0], element) > 0) \ - PFX##_impl_float_up_min(_heap_); \ - else if (_heap_->cmp(parent->data[1], element) < 0) \ - PFX##_impl_float_up_max(_heap_); \ - /* else no float up required */ \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove_max(SNAME *_heap_, V *result) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - *result = _heap_->buffer[0].data[0]; \ - \ - _heap_->buffer[0].data[0] = PFX##_impl_default_value(); \ - \ - _heap_->count--; \ - \ - return true; \ - } \ - else \ - *result = _heap_->buffer[0].data[1]; \ - \ - /* Swap the result with the last element in the MaxHeap and float it down */ \ - SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - if (PFX##_count(_heap_) % 2 == 1) \ - { \ - /* Grab from MinHeap and discard last node */ \ - _heap_->buffer[0].data[1] = last_node->data[0]; \ - \ - last_node->data[0] = PFX##_impl_default_value(); \ - \ - _heap_->size--; \ - } \ - else \ - { \ - _heap_->buffer[0].data[1] = last_node->data[1]; \ - \ - last_node->data[1] = PFX##_impl_default_value(); \ - } \ - \ - _heap_->count--; \ - \ - /* FLoat Down on the MaxHeap */ \ - PFX##_impl_float_down_max(_heap_); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove_min(SNAME *_heap_, V *result) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *result = _heap_->buffer[0].data[0]; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = PFX##_impl_default_value(); \ - \ - _heap_->count--; \ - \ - return true; \ - } \ - \ - /* Swap the result with the last element in the MinHeap and float it down */ \ - SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - _heap_->buffer[0].data[0] = last_node->data[0]; \ - \ - if (PFX##_count(_heap_) % 2 == 1) \ - { \ - /* Discard last node */ \ - last_node->data[0] = PFX##_impl_default_value(); \ - \ - _heap_->size--; \ - } \ - else \ - { \ - /* Place the MaxHeap value in the MinHeap value spot */ \ - last_node->data[0] = last_node->data[1]; \ - last_node->data[1] = PFX##_impl_default_value(); \ - } \ - \ - _heap_->count--; \ - \ - /* FLoat Down on the MinHeap */ \ - PFX##_impl_float_down_min(_heap_); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_heap_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition) \ - { \ - if (condition) \ - return PFX##_remove_max(_heap_, result); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition) \ - { \ - if (condition) \ - return PFX##_remove_min(_heap_, result); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_update_max(SNAME *_heap_, V element) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = element; \ - } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \ - { \ - /* Corner case: we are updating the Max value but it is less than */ \ - /* the Min value */ \ - _heap_->buffer[0].data[1] = _heap_->buffer[0].data[0]; \ - _heap_->buffer[0].data[0] = element; \ - \ - PFX##_impl_float_down_max(_heap_); \ - } \ - else \ - { \ - /* Update Max element and float it down */ \ - _heap_->buffer[0].data[1] = element; \ - \ - PFX##_impl_float_down_max(_heap_); \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_update_min(SNAME *_heap_, V element) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = element; \ - } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \ - { \ - /* Corner case: we are updating the Min value but it is greater */ \ - /* than the Max value. */ \ - _heap_->buffer[0].data[0] = _heap_->buffer[0].data[1]; \ - _heap_->buffer[0].data[1] = element; \ - \ - PFX##_impl_float_down_min(_heap_); \ - } \ - else \ - { \ - /* Update Min element and float it down */ \ - _heap_->buffer[0].data[0] = element; \ - \ - PFX##_impl_float_down_min(_heap_); \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_heap_, V *value) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - /* If there is only one element, then the maximum element is the same */ \ - /* as the one in the MinHeap */ \ - if (PFX##_count(_heap_) == 1) \ - *value = _heap_->buffer[0].data[0]; \ - else \ - *value = _heap_->buffer[0].data[1]; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_heap_, V *value) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *value = _heap_->buffer[0].data[0]; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_heap_, V element) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_heap_) \ - { \ - return _heap_->count == 0; \ - } \ - \ - FMOD bool PFX##_full(SNAME *_heap_) \ - { \ - /* The heap is full if all nodes are completely filled */ \ - return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_heap_) \ - { \ - return _heap_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_heap_) \ - { \ - return _heap_->capacity; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ - { \ - cmc_string str; \ - SNAME *h_ = _heap_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ - name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); \ - \ - return str; \ - } \ - \ - 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->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - 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 = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->cursor = 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; \ - \ - iter->start = false; \ - \ - if (iter->cursor == iter->target->count - 1) \ - iter->end = true; \ - else \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = false; \ - \ - if (iter->cursor == 0) \ - iter->start = true; \ - else \ - iter->cursor--; \ - \ - 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 / 2].data[iter->cursor % 2]; \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_heap_) \ - { \ - size_t new_cap = _heap_->capacity * 2; \ - \ - SNAME##_node *new_buffer = realloc(_heap_->buffer, sizeof(SNAME##_node) * new_cap); \ - \ - if (!new_buffer) \ - return false; \ - \ - memset(new_buffer + _heap_->capacity, 0, sizeof(SNAME##_node) * _heap_->capacity); \ - \ - _heap_->buffer = new_buffer; \ - _heap_->capacity = new_cap; \ - \ - return true; \ - } \ - \ - static void PFX##_impl_float_up_max(SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MaxHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - SNAME##_node *parent = &(_heap_->buffer[P_index]); \ - \ - if (index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - { \ - /* In this case, the current node has no MaxHeap value so we */ \ - /* instead compare with the MinHeap value */ \ - if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \ - break; \ - \ - /* Since the comparison above passed now we need to swap the */ \ - /* current node with the parent but it will have to be done */ \ - /* with the node's MinHeap value since the MaxHeap value */ \ - /* doesn't exist */ \ - V tmp = curr_node->data[0]; \ - curr_node->data[0] = parent->data[1]; \ - parent->data[1] = tmp; \ - } \ - else \ - { \ - /* Usual case, just compare both MaxHeap values */ \ - if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \ - break; \ - \ - /* Swap with parent and repeat */ \ - V tmp = curr_node->data[1]; \ - curr_node->data[1] = parent->data[1]; \ - parent->data[1] = tmp; \ - } \ - \ - /* Update indexe and node */ \ - index = P_index; \ - curr_node = parent; \ - } \ - } \ - \ - static void PFX##_impl_float_up_min(SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MinHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - SNAME##_node *parent = &(_heap_->buffer[P_index]); \ - \ - if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \ - break; \ - \ - /* Swap with parent and repeat */ \ - V tmp = curr_node->data[0]; \ - curr_node->data[0] = parent->data[0]; \ - parent->data[0] = tmp; \ - \ - /* Update indexe and node */ \ - index = P_index; \ - curr_node = parent; \ - } \ - } \ - \ - static void PFX##_impl_float_down_max(SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - while (true) \ - { \ - /* If there are no children it is done */ \ - if (2 * index + 1 >= _heap_->size) \ - break; \ - \ - /* Child index to be compared with current value */ \ - size_t child; \ - size_t L_index = index * 2 + 1; \ - size_t R_index = index * 2 + 2; \ - \ - /* If there are two children, pick the smallest one */ \ - if (R_index < _heap_->size) \ - { \ - SNAME##_node *L = &(_heap_->buffer[L_index]); \ - SNAME##_node *R = &(_heap_->buffer[R_index]); \ - \ - /* If the right child is the last node and there is no MaxHeap value */ \ - /* then do the comparison with the MinHeap value */ \ - if (R_index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index : R_index; \ - else \ - child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index : R_index; \ - } \ - /* Pick the only one available */ \ - else \ - child = L_index; \ - \ - SNAME##_node *child_node = &(_heap_->buffer[child]); \ - \ - /* Again, check if the child node is the last one and has no MaxHeap value */ \ - if (child == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - { \ - /* Odd case, compare with MinHeap value */ \ - /* If current value is not less than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[0]; \ - child_node->data[0] = curr_node->data[1]; \ - curr_node->data[1] = tmp; \ - } \ - else \ - { \ - /* If current value is not less than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[1]; \ - child_node->data[1] = curr_node->data[1]; \ - curr_node->data[1] = tmp; \ - \ - /* Check if the MinHeap and MaxHeap values need to be swapped */ \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ - { \ - /* Swap because the MinHeap value is greater than the MaxHeap value */ \ - tmp = child_node->data[0]; \ - child_node->data[0] = child_node->data[1]; \ - child_node->data[1] = tmp; \ - } \ - } \ - \ - /* Update index and node */ \ - index = child; \ - curr_node = child_node; \ - } \ - } \ - \ - static void PFX##_impl_float_down_min(SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - while (true) \ - { \ - /* If there are no children it is done */ \ - if (2 * index + 1 >= _heap_->size) \ - break; \ - \ - /* Child index to be compared with current value */ \ - size_t child; \ - size_t L_index = index * 2 + 1; \ - size_t R_index = index * 2 + 2; \ - \ - /* If there are two children, pick the smallest one */ \ - if (R_index < _heap_->size) \ - { \ - SNAME##_node *L = &(_heap_->buffer[L_index]); \ - SNAME##_node *R = &(_heap_->buffer[R_index]); \ - \ - child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index : R_index; \ - } \ - /* Pick the only one available */ \ - else \ - child = L_index; \ - \ - SNAME##_node *child_node = &(_heap_->buffer[child]); \ - \ - /* If current value is smaller than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[0]; \ - child_node->data[0] = curr_node->data[0]; \ - curr_node->data[0] = tmp; \ - \ - /* If the child node is the last node check if the MinHeap and */ \ - /* MaxHeap values need to be swapped */ \ - if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \ - { \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ - { \ - /* Swap because the MinHeap value is greater than the MaxHeap value */ \ - tmp = child_node->data[0]; \ - child_node->data[0] = child_node->data[1]; \ - child_node->data[1] = tmp; \ - } \ - } \ - \ - /* Update index and node */ \ - index = child; \ - curr_node = child_node; \ - } \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define INTERVALHEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_heap_); \ + static void PFX##_impl_float_up_max(SNAME *_heap_); \ + static void PFX##_impl_float_up_min(SNAME *_heap_); \ + static void PFX##_impl_float_down_max(SNAME *_heap_); \ + static void PFX##_impl_float_down_min(SNAME *_heap_); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + { \ + SNAME *_heap_ = malloc(sizeof(SNAME)); \ + \ + if (!_heap_) \ + return NULL; \ + \ + /* Since each node can store two elements, divide the actual capacity by 2 */ \ + /* Round the capacity of nodes up */ \ + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ + \ + _heap_->buffer = malloc(sizeof(SNAME##_node) * capacity); \ + \ + if (!_heap_->buffer) \ + { \ + free(_heap_); \ + return NULL; \ + } \ + \ + memset(_heap_->buffer, 0, sizeof(SNAME##_node) * capacity); \ + \ + _heap_->capacity = capacity; \ + _heap_->size = 0; \ + _heap_->count = 0; \ + _heap_->cmp = compare; \ + \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ + \ + return _heap_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ + memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ + \ + _heap_->size = 0; \ + _heap_->count = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ + free(_heap_->buffer); \ + \ + free(_heap_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_heap_, V element) \ + { \ + if (PFX##_full(_heap_)) \ + { \ + if (!PFX##_impl_grow(_heap_)) \ + return false; \ + } \ + \ + if (PFX##_count(_heap_) % 2 == 0) \ + { \ + /* Occupying a new node */ \ + _heap_->buffer[_heap_->size].data[0] = element; \ + _heap_->buffer[_heap_->size].data[1] = PFX##_impl_default_value(); \ + \ + _heap_->size++; \ + } \ + else \ + { \ + SNAME##_node *curr_node = &(_heap_->buffer[_heap_->size - 1]); \ + \ + /* Decide if the new element goes into the MinHeap or MaxHeap */ \ + if (_heap_->cmp(curr_node->data[0], element) > 0) \ + { \ + /* Swap current value and add new element to the MinHeap */ \ + curr_node->data[1] = curr_node->data[0]; \ + curr_node->data[0] = element; \ + } \ + else \ + { \ + /* No need to swap and add the new element to the MaxHeap */ \ + curr_node->data[1] = element; \ + } \ + } \ + \ + _heap_->count++; \ + \ + if (PFX##_count(_heap_) <= 2) \ + return true; \ + \ + /* Determine wheather to do a MaxHeap insert or a MinHeap insert */ \ + SNAME##_node *parent = &(_heap_->buffer[(_heap_->size - 1) / 2]); \ + \ + if (_heap_->cmp(parent->data[0], element) > 0) \ + PFX##_impl_float_up_min(_heap_); \ + else if (_heap_->cmp(parent->data[1], element) < 0) \ + PFX##_impl_float_up_max(_heap_); \ + /* else no float up required */ \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove_max(SNAME *_heap_, V *result) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + *result = _heap_->buffer[0].data[0]; \ + \ + _heap_->buffer[0].data[0] = PFX##_impl_default_value(); \ + \ + _heap_->count--; \ + \ + return true; \ + } \ + else \ + *result = _heap_->buffer[0].data[1]; \ + \ + /* Swap the result with the last element in the MaxHeap and float it down */ \ + SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ + \ + if (PFX##_count(_heap_) % 2 == 1) \ + { \ + /* Grab from MinHeap and discard last node */ \ + _heap_->buffer[0].data[1] = last_node->data[0]; \ + \ + last_node->data[0] = PFX##_impl_default_value(); \ + \ + _heap_->size--; \ + } \ + else \ + { \ + _heap_->buffer[0].data[1] = last_node->data[1]; \ + \ + last_node->data[1] = PFX##_impl_default_value(); \ + } \ + \ + _heap_->count--; \ + \ + /* FLoat Down on the MaxHeap */ \ + PFX##_impl_float_down_max(_heap_); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove_min(SNAME *_heap_, V *result) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + *result = _heap_->buffer[0].data[0]; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = PFX##_impl_default_value(); \ + \ + _heap_->count--; \ + \ + return true; \ + } \ + \ + /* Swap the result with the last element in the MinHeap and float it down */ \ + SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ + \ + _heap_->buffer[0].data[0] = last_node->data[0]; \ + \ + if (PFX##_count(_heap_) % 2 == 1) \ + { \ + /* Discard last node */ \ + last_node->data[0] = PFX##_impl_default_value(); \ + \ + _heap_->size--; \ + } \ + else \ + { \ + /* Place the MaxHeap value in the MinHeap value spot */ \ + last_node->data[0] = last_node->data[1]; \ + last_node->data[1] = PFX##_impl_default_value(); \ + } \ + \ + _heap_->count--; \ + \ + /* FLoat Down on the MinHeap */ \ + PFX##_impl_float_down_min(_heap_); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_heap_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition) \ + { \ + if (condition) \ + return PFX##_remove_max(_heap_, result); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition) \ + { \ + if (condition) \ + return PFX##_remove_min(_heap_, result); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_update_max(SNAME *_heap_, V element) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = element; \ + } \ + else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \ + { \ + /* Corner case: we are updating the Max value but it is less than */ \ + /* the Min value */ \ + _heap_->buffer[0].data[1] = _heap_->buffer[0].data[0]; \ + _heap_->buffer[0].data[0] = element; \ + \ + PFX##_impl_float_down_max(_heap_); \ + } \ + else \ + { \ + /* Update Max element and float it down */ \ + _heap_->buffer[0].data[1] = element; \ + \ + PFX##_impl_float_down_max(_heap_); \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_update_min(SNAME *_heap_, V element) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = element; \ + } \ + else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \ + { \ + /* Corner case: we are updating the Min value but it is greater */ \ + /* than the Max value. */ \ + _heap_->buffer[0].data[0] = _heap_->buffer[0].data[1]; \ + _heap_->buffer[0].data[1] = element; \ + \ + PFX##_impl_float_down_min(_heap_); \ + } \ + else \ + { \ + /* Update Min element and float it down */ \ + _heap_->buffer[0].data[0] = element; \ + \ + PFX##_impl_float_down_min(_heap_); \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_heap_, V *value) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + /* If there is only one element, then the maximum element is the same */ \ + /* as the one in the MinHeap */ \ + if (PFX##_count(_heap_) == 1) \ + *value = _heap_->buffer[0].data[0]; \ + else \ + *value = _heap_->buffer[0].data[1]; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_heap_, V *value) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + *value = _heap_->buffer[0].data[0]; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_heap_, V element) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_heap_) \ + { \ + return _heap_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_heap_) \ + { \ + /* The heap is full if all nodes are completely filled */ \ + return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_heap_) \ + { \ + return _heap_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_heap_) \ + { \ + return _heap_->capacity; \ + } \ + \ + FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ + { \ + SNAME *result = malloc(sizeof(SNAME)); \ + \ + if (!result) \ + return NULL; \ + \ + memcpy(result, _heap_, sizeof(SNAME)); \ + \ + result->buffer = malloc(sizeof(SNAME##_node) * _heap_->capacity); \ + \ + if (!result->buffer) \ + { \ + free(result); \ + return NULL; \ + } \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + result->buffer[i / 2].data[i % 2] = copy_func(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + else \ + memcpy(result->buffer, _heap_->buffer, sizeof(SNAME##_node) * _heap_->capacity); \ + \ + return result; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ + { \ + cmc_string str; \ + SNAME *h_ = _heap_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ + name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); \ + \ + return str; \ + } \ + \ + 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->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + 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 = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->cursor = 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; \ + \ + iter->start = false; \ + \ + if (iter->cursor == iter->target->count - 1) \ + iter->end = true; \ + else \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = false; \ + \ + if (iter->cursor == 0) \ + iter->start = true; \ + else \ + iter->cursor--; \ + \ + 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 / 2].data[iter->cursor % 2]; \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_heap_) \ + { \ + size_t new_cap = _heap_->capacity * 2; \ + \ + SNAME##_node *new_buffer = realloc(_heap_->buffer, sizeof(SNAME##_node) * new_cap); \ + \ + if (!new_buffer) \ + return false; \ + \ + memset(new_buffer + _heap_->capacity, 0, sizeof(SNAME##_node) * _heap_->capacity); \ + \ + _heap_->buffer = new_buffer; \ + _heap_->capacity = new_cap; \ + \ + return true; \ + } \ + \ + static void PFX##_impl_float_up_max(SNAME *_heap_) \ + { \ + size_t index = _heap_->size - 1; \ + \ + SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + /* FLoat Up on the MaxHeap */ \ + while (index > 0) \ + { \ + /* Parent index */ \ + size_t P_index = (index - 1) / 2; \ + \ + SNAME##_node *parent = &(_heap_->buffer[P_index]); \ + \ + if (index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + { \ + /* In this case, the current node has no MaxHeap value so we */ \ + /* instead compare with the MinHeap value */ \ + if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \ + break; \ + \ + /* Since the comparison above passed now we need to swap the */ \ + /* current node with the parent but it will have to be done */ \ + /* with the node's MinHeap value since the MaxHeap value */ \ + /* doesn't exist */ \ + V tmp = curr_node->data[0]; \ + curr_node->data[0] = parent->data[1]; \ + parent->data[1] = tmp; \ + } \ + else \ + { \ + /* Usual case, just compare both MaxHeap values */ \ + if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \ + break; \ + \ + /* Swap with parent and repeat */ \ + V tmp = curr_node->data[1]; \ + curr_node->data[1] = parent->data[1]; \ + parent->data[1] = tmp; \ + } \ + \ + /* Update indexe and node */ \ + index = P_index; \ + curr_node = parent; \ + } \ + } \ + \ + static void PFX##_impl_float_up_min(SNAME *_heap_) \ + { \ + size_t index = _heap_->size - 1; \ + \ + SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + /* FLoat Up on the MinHeap */ \ + while (index > 0) \ + { \ + /* Parent index */ \ + size_t P_index = (index - 1) / 2; \ + \ + SNAME##_node *parent = &(_heap_->buffer[P_index]); \ + \ + if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \ + break; \ + \ + /* Swap with parent and repeat */ \ + V tmp = curr_node->data[0]; \ + curr_node->data[0] = parent->data[0]; \ + parent->data[0] = tmp; \ + \ + /* Update indexe and node */ \ + index = P_index; \ + curr_node = parent; \ + } \ + } \ + \ + static void PFX##_impl_float_down_max(SNAME *_heap_) \ + { \ + /* Floats Down from the MinHeap */ \ + size_t index = 0; \ + \ + SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + while (true) \ + { \ + /* If there are no children it is done */ \ + if (2 * index + 1 >= _heap_->size) \ + break; \ + \ + /* Child index to be compared with current value */ \ + size_t child; \ + size_t L_index = index * 2 + 1; \ + size_t R_index = index * 2 + 2; \ + \ + /* If there are two children, pick the smallest one */ \ + if (R_index < _heap_->size) \ + { \ + SNAME##_node *L = &(_heap_->buffer[L_index]); \ + SNAME##_node *R = &(_heap_->buffer[R_index]); \ + \ + /* If the right child is the last node and there is no MaxHeap value */ \ + /* then do the comparison with the MinHeap value */ \ + if (R_index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index : R_index; \ + else \ + child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index : R_index; \ + } \ + /* Pick the only one available */ \ + else \ + child = L_index; \ + \ + SNAME##_node *child_node = &(_heap_->buffer[child]); \ + \ + /* Again, check if the child node is the last one and has no MaxHeap value */ \ + if (child == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + { \ + /* Odd case, compare with MinHeap value */ \ + /* If current value is not less than the child node's value, it is done */ \ + if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[0]; \ + child_node->data[0] = curr_node->data[1]; \ + curr_node->data[1] = tmp; \ + } \ + else \ + { \ + /* If current value is not less than the child node's value, it is done */ \ + if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[1]; \ + child_node->data[1] = curr_node->data[1]; \ + curr_node->data[1] = tmp; \ + \ + /* Check if the MinHeap and MaxHeap values need to be swapped */ \ + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + { \ + /* Swap because the MinHeap value is greater than the MaxHeap value */ \ + tmp = child_node->data[0]; \ + child_node->data[0] = child_node->data[1]; \ + child_node->data[1] = tmp; \ + } \ + } \ + \ + /* Update index and node */ \ + index = child; \ + curr_node = child_node; \ + } \ + } \ + \ + static void PFX##_impl_float_down_min(SNAME *_heap_) \ + { \ + /* Floats Down from the MinHeap */ \ + size_t index = 0; \ + \ + SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + while (true) \ + { \ + /* If there are no children it is done */ \ + if (2 * index + 1 >= _heap_->size) \ + break; \ + \ + /* Child index to be compared with current value */ \ + size_t child; \ + size_t L_index = index * 2 + 1; \ + size_t R_index = index * 2 + 2; \ + \ + /* If there are two children, pick the smallest one */ \ + if (R_index < _heap_->size) \ + { \ + SNAME##_node *L = &(_heap_->buffer[L_index]); \ + SNAME##_node *R = &(_heap_->buffer[R_index]); \ + \ + child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index : R_index; \ + } \ + /* Pick the only one available */ \ + else \ + child = L_index; \ + \ + SNAME##_node *child_node = &(_heap_->buffer[child]); \ + \ + /* If current value is smaller than the child node's value, it is done */ \ + if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[0]; \ + child_node->data[0] = curr_node->data[0]; \ + curr_node->data[0] = tmp; \ + \ + /* If the child node is the last node check if the MinHeap and */ \ + /* MaxHeap values need to be swapped */ \ + if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \ + { \ + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + { \ + /* Swap because the MinHeap value is greater than the MaxHeap value */ \ + tmp = child_node->data[0]; \ + child_node->data[0] = child_node->data[1]; \ + child_node->data[1] = tmp; \ + } \ + } \ + \ + /* Update index and node */ \ + index = child; \ + curr_node = child_node; \ + } \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_INTERVALHEAP_H */ diff --git a/src/ext/multimap.h b/src/ext/multimap.h index 6fc148c..6b6f02f 100644 --- a/src/ext/multimap.h +++ b/src/ext/multimap.h @@ -200,6 +200,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_count(SNAME *_map_); \ FMOD size_t PFX##_capacity(SNAME *_map_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -709,6 +710,35 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _map_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + if (!PFX##_empty(_map_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + if (key_copy_func) \ + key = key_copy_func(key); \ + if (value_copy_func) \ + value = value_copy_func(value); \ + \ + PFX##_insert(result, key, value); \ + } \ + } \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ diff --git a/src/ext/multiset.h b/src/ext/multiset.h index 7aa8cc9..6578c42 100644 --- a/src/ext/multiset.h +++ b/src/ext/multiset.h @@ -183,6 +183,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_cardinality(SNAME *_set_); \ FMOD size_t PFX##_capacity(SNAME *_set_); \ /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -513,6 +514,45 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_->capacity; \ } \ \ + FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *scan = &(_set_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + SNAME##_entry *target = &(result->buffer[i]); \ + \ + if (scan->state == CMC_ES_DELETED) \ + target->state = CMC_ES_DELETED; \ + else \ + { \ + target->state = scan->state; \ + target->dist = scan->dist; \ + target->multiplicity = scan->multiplicity; \ + \ + target->value = copy_func(scan->value); \ + } \ + } \ + } \ + } \ + else \ + memcpy(result->buffer, _set_->buffer, sizeof(SNAME##_entry) * _set_->capacity); \ + \ + result->count = _set_->count; \ + result->cardinality = _set_->cardinality; \ + \ + return result; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \