From 8bd297f4a3667ef326016d9da464144f31cd3895 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 4 Mar 2020 14:25:44 -0300 Subject: [PATCH] Added flags to intervalheap --- src/cmc/intervalheap.h | 141 ++++++++++++++++++++++++-------- tests/main/unt/intervalheap.c | 150 +++++++++++++++++++++++++++++++--- 2 files changed, 247 insertions(+), 44 deletions(-) diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 5c9a5cc..d27127b 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -218,8 +218,8 @@ struct cmc_callbacks_intervalheap struct cmc_callbacks_intervalheap *callbacks); \ /* Collection Input and Output */ \ bool PFX##_insert(struct SNAME *_heap_, V element); \ - bool PFX##_remove_max(struct SNAME *_heap_, V *result); \ - bool PFX##_remove_min(struct SNAME *_heap_, V *result); \ + bool PFX##_remove_max(struct SNAME *_heap_); \ + bool PFX##_remove_min(struct SNAME *_heap_); \ /* Collection Update */ \ bool PFX##_update_max(struct SNAME *_heap_, V element); \ bool PFX##_update_min(struct SNAME *_heap_, V element); \ @@ -232,11 +232,13 @@ struct cmc_callbacks_intervalheap bool PFX##_full(struct SNAME *_heap_); \ size_t PFX##_count(struct SNAME *_heap_); \ size_t PFX##_capacity(struct SNAME *_heap_); \ + int PFX##_flag(struct SNAME *_heap_); \ /* Collection Utility */ \ bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ struct SNAME *PFX##_copy_of(struct SNAME *_set_); \ bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ + bool PFX##_print(struct SNAME *_heap_, FILE *fptr); \ \ /* Iterator Functions */ \ /* Iterator Allocation and Deallocation */ \ @@ -276,7 +278,7 @@ struct cmc_callbacks_intervalheap { \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ - if (capacity == 0 || capacity == UINT64_MAX) \ + if (capacity == 0 || capacity == UINTMAX_MAX) \ return NULL; \ \ if (!f_val) \ @@ -372,6 +374,7 @@ struct cmc_callbacks_intervalheap \ _heap_->size = 0; \ _heap_->count = 0; \ + _heap_->flag = cmc_flags.OK; \ } \ \ void PFX##_free(struct SNAME *_heap_) \ @@ -397,17 +400,19 @@ struct cmc_callbacks_intervalheap \ if (callbacks) \ _heap_->callbacks = callbacks; \ + \ + _heap_->flag = cmc_flags.OK; \ } \ \ bool PFX##_insert(struct SNAME *_heap_, V element) \ { \ if (PFX##_full(_heap_)) \ { \ - if (!PFX##_resize(_heap_, PFX##_capacity(_heap_) * 4)) \ + if (!PFX##_resize(_heap_, _heap_->capacity * 4)) \ return false; \ } \ \ - if (PFX##_count(_heap_) % 2 == 0) \ + if (_heap_->count % 2 == 0) \ { \ /* Occupying a new node */ \ _heap_->buffer[_heap_->size].data[0] = element; \ @@ -434,8 +439,9 @@ struct cmc_callbacks_intervalheap } \ \ _heap_->count++; \ + _heap_->flag = cmc_flags.OK; \ \ - if (PFX##_count(_heap_) <= 2) \ + if (_heap_->count <= 2) \ return true; \ \ /* Determine wheather to do a MaxHeap insert or a MinHeap insert */ \ @@ -451,29 +457,31 @@ struct cmc_callbacks_intervalheap return true; \ } \ \ - bool PFX##_remove_max(struct SNAME *_heap_, V *result) \ + bool PFX##_remove_max(struct SNAME *_heap_) \ { \ if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ { \ - *result = _heap_->buffer[0].data[0]; \ + _heap_->flag = cmc_flags.EMPTY; \ + return false; \ + } \ \ + if (_heap_->count == 1) \ + { \ _heap_->buffer[0].data[0] = (V){ 0 }; \ \ _heap_->count--; \ + _heap_->size--; \ + \ + _heap_->flag = cmc_flags.OK; \ \ return true; \ } \ - else \ - *result = _heap_->buffer[0].data[1]; \ \ /* Swap the result with the last element in the MaxHeap and float */ \ /* it down */ \ struct SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ \ - if (PFX##_count(_heap_) % 2 == 1) \ + if (_heap_->count % 2 == 1) \ { \ /* Grab from MinHeap and discard last node */ \ _heap_->buffer[0].data[1] = last_node->data[0]; \ @@ -490,6 +498,7 @@ struct cmc_callbacks_intervalheap } \ \ _heap_->count--; \ + _heap_->flag = cmc_flags.OK; \ \ /* FLoat Down on the MaxHeap */ \ PFX##_impl_float_down_max(_heap_); \ @@ -497,18 +506,22 @@ struct cmc_callbacks_intervalheap return true; \ } \ \ - bool PFX##_remove_min(struct SNAME *_heap_, V *result) \ + bool PFX##_remove_min(struct SNAME *_heap_) \ { \ if (PFX##_empty(_heap_)) \ + { \ + _heap_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ - *result = _heap_->buffer[0].data[0]; \ - \ - if (PFX##_count(_heap_) == 1) \ + if (_heap_->count == 1) \ { \ _heap_->buffer[0].data[0] = (V){ 0 }; \ \ _heap_->count--; \ + _heap_->size--; \ + \ + _heap_->flag = cmc_flags.OK; \ \ return true; \ } \ @@ -519,7 +532,7 @@ struct cmc_callbacks_intervalheap \ _heap_->buffer[0].data[0] = last_node->data[0]; \ \ - if (PFX##_count(_heap_) % 2 == 1) \ + if (_heap_->count % 2 == 1) \ { \ /* Discard last node */ \ last_node->data[0] = (V){ 0 }; \ @@ -534,6 +547,7 @@ struct cmc_callbacks_intervalheap } \ \ _heap_->count--; \ + _heap_->flag = cmc_flags.OK; \ \ /* FLoat Down on the MinHeap */ \ PFX##_impl_float_down_min(_heap_); \ @@ -544,9 +558,12 @@ struct cmc_callbacks_intervalheap bool PFX##_update_max(struct SNAME *_heap_, V element) \ { \ if (PFX##_empty(_heap_)) \ + { \ + _heap_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ - if (PFX##_count(_heap_) == 1) \ + if (_heap_->count == 1) \ { \ _heap_->buffer[0].data[0] = element; \ } \ @@ -567,15 +584,20 @@ struct cmc_callbacks_intervalheap PFX##_impl_float_down_max(_heap_); \ } \ \ + _heap_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_update_min(struct SNAME *_heap_, V element) \ { \ if (PFX##_empty(_heap_)) \ + { \ + _heap_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ - if (PFX##_count(_heap_) == 1) \ + if (_heap_->count == 1) \ { \ _heap_->buffer[0].data[0] = element; \ } \ @@ -596,36 +618,50 @@ struct cmc_callbacks_intervalheap PFX##_impl_float_down_min(_heap_); \ } \ \ + _heap_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_max(struct SNAME *_heap_, V *value) \ { \ if (PFX##_empty(_heap_)) \ + { \ + _heap_->flag = cmc_flags.EMPTY; \ 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) \ + if (_heap_->count == 1) \ *value = _heap_->buffer[0].data[0]; \ else \ *value = _heap_->buffer[0].data[1]; \ \ + _heap_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_min(struct SNAME *_heap_, V *value) \ { \ if (PFX##_empty(_heap_)) \ + { \ + _heap_->flag = cmc_flags.EMPTY; \ return false; \ + } \ \ *value = _heap_->buffer[0].data[0]; \ \ + _heap_->flag = cmc_flags.OK; \ + \ return true; \ } \ \ bool PFX##_contains(struct SNAME *_heap_, V element) \ { \ + _heap_->flag = cmc_flags.OK; \ + \ for (size_t i = 0; i < _heap_->count; i++) \ { \ if (_heap_->f_val->cmp(_heap_->buffer[i / 2].data[i % 2], \ @@ -657,13 +693,23 @@ struct cmc_callbacks_intervalheap return _heap_->capacity; \ } \ \ + int PFX##_flag(struct SNAME *_heap_) \ + { \ + return _heap_->flag; \ + } \ + \ bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ { \ - if (PFX##_capacity(_heap_) == capacity) \ + _heap_->flag = cmc_flags.OK; \ + \ + if (_heap_->capacity == capacity) \ return true; \ \ - if (capacity < PFX##_count(_heap_)) \ + if (capacity < _heap_->count) \ + { \ + _heap_->flag = cmc_flags.ERROR; \ return false; \ + } \ \ capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ \ @@ -671,7 +717,10 @@ struct cmc_callbacks_intervalheap _heap_->buffer, sizeof(struct SNAME##_node) * capacity); \ \ if (!new_buffer) \ + { \ + _heap_->flag = cmc_flags.ALLOC; \ return false; \ + } \ \ memset(new_buffer + _heap_->capacity, 0, \ sizeof(struct SNAME##_node) * _heap_->capacity); \ @@ -687,7 +736,10 @@ struct cmc_callbacks_intervalheap struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME)); \ \ if (!result) \ + { \ + _heap_->flag = cmc_flags.ALLOC; \ return NULL; \ + } \ \ memcpy(result, _heap_, sizeof(struct SNAME)); \ \ @@ -697,6 +749,7 @@ struct cmc_callbacks_intervalheap if (!result->buffer) \ { \ _heap_->alloc->free(result); \ + _heap_->flag = cmc_flags.ALLOC; \ return NULL; \ } \ \ @@ -710,15 +763,27 @@ struct cmc_callbacks_intervalheap memcpy(result->buffer, _heap_->buffer, \ sizeof(struct SNAME##_node) * _heap_->capacity); \ \ + result->capacity = _heap_->capacity; \ + result->size = _heap_->size; \ + result->count = _heap_->count; \ + result->flag = cmc_flags.OK; \ + result->f_val = _heap_->f_val; \ result->alloc = _heap_->alloc; \ result->callbacks = _heap_->callbacks; \ + result->it_start = PFX##_impl_it_start; \ + result->it_end = PFX##_impl_it_end; \ + \ + _heap_->flag = cmc_flags.OK; \ \ return result; \ } \ \ bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ { \ - if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ + _heap1_->flag = cmc_flags.OK; \ + _heap2_->flag = cmc_flags.OK; \ + \ + if (_heap1_->count != _heap2_->count) \ return false; \ \ for (size_t i = 0; i < _heap1_->count; i++) \ @@ -746,6 +811,17 @@ struct cmc_callbacks_intervalheap return n >= 0 ? str : (struct cmc_string){ 0 }; \ } \ \ + bool PFX##_print(struct SNAME *_heap_, FILE *fptr) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + if (!_heap_->f_val->str(fptr, _heap_->buffer[i / 2].data[i % 2])) \ + return false; \ + } \ + \ + return true; \ + } \ + \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ struct SNAME##_iter *iter = \ @@ -807,7 +883,7 @@ struct cmc_callbacks_intervalheap if (iter->end) \ return false; \ \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ + if (iter->cursor + 1 == iter->target->count) \ { \ iter->end = true; \ return false; \ @@ -850,7 +926,7 @@ struct cmc_callbacks_intervalheap return false; \ } \ \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + if (steps == 0 || iter->cursor + steps >= iter->target->count) \ return false; \ \ iter->start = PFX##_empty(iter->target); \ @@ -886,7 +962,7 @@ struct cmc_callbacks_intervalheap /* given index */ \ bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ - if (index >= PFX##_count(iter->target)) \ + if (index >= iter->target->count) \ return false; \ \ if (iter->cursor > index) \ @@ -924,7 +1000,7 @@ struct cmc_callbacks_intervalheap \ struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ \ - if (index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + if (index == _heap_->size - 1 && _heap_->count % 2 != 0) \ { \ /* In this case, the current node has no MaxHeap value so */ \ /* we instead compare with the MinHeap value */ \ @@ -1014,8 +1090,7 @@ struct cmc_callbacks_intervalheap /* 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) \ + if (R_index == _heap_->size - 1 && _heap_->count % 2 != 0) \ child = _heap_->f_val->cmp(L->data[1], R->data[0]) > 0 \ ? L_index \ : R_index; \ @@ -1032,7 +1107,7 @@ struct cmc_callbacks_intervalheap \ /* 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) \ + if (child == _heap_->size - 1 && _heap_->count % 2 != 0) \ { \ /* Odd case, compare with MinHeap value */ \ /* If current value is not less than the child node's */ \ @@ -1125,7 +1200,7 @@ struct cmc_callbacks_intervalheap \ /* 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 (child != _heap_->size - 1 || _heap_->count % 2 == 0) \ { \ if (_heap_->f_val->cmp(child_node->data[0], \ child_node->data[1]) > 0) \ diff --git a/tests/main/unt/intervalheap.c b/tests/main/unt/intervalheap.c index 8fbbc23..6ba1422 100644 --- a/tests/main/unt/intervalheap.c +++ b/tests/main/unt/intervalheap.c @@ -120,23 +120,151 @@ CMC_CREATE_UNIT(intervalheap_test, true, { ih_free(ih); }); - CMC_CREATE_TEST(insert[max min], { + CMC_CREATE_TEST(insert[max], { struct intervalheap *ih = ih_new(1, ih_ftab_val); - cmc_assert_not_equals(ptr, NULL, ih); - - cmc_assert(ih_insert(ih, 1)); cmc_assert(ih_insert(ih, 0)); + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 2)); - size_t min; - size_t max; + size_t r; + cmc_assert(ih_max(ih, &r)); - cmc_assert(ih_min(ih, &min)); - cmc_assert(ih_max(ih, &max)); - - cmc_assert_equals(size_t, 0, min); - cmc_assert_equals(size_t, 1, max); + cmc_assert_equals(size_t, 2, r); ih_free(ih); }); + + CMC_CREATE_TEST(insert[min], { + struct intervalheap *ih = ih_new(1, ih_ftab_val); + + cmc_assert(ih_insert(ih, 0)); + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 2)); + + size_t r; + cmc_assert(ih_min(ih, &r)); + + cmc_assert_equals(size_t, 0, r); + + ih_free(ih); + }); + + CMC_CREATE_TEST(insert[remove_max remove_min], { + struct intervalheap *ih = ih_new(100, ih_ftab_val); + + cmc_assert_not_equals(ptr, NULL, ih); + + cmc_assert(ih_insert(ih, 2)); + cmc_assert_equals(size_t, 2, ih->buffer[0].data[0]); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert_equals(size_t, 1, ih->buffer[0].data[0]); + cmc_assert_equals(size_t, 2, ih->buffer[0].data[1]); + + cmc_assert(ih_remove_min(ih)); + cmc_assert_equals(size_t, 2, ih->buffer[0].data[0]); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert_equals(size_t, 1, ih->buffer[0].data[0]); + cmc_assert_equals(size_t, 2, ih->buffer[0].data[1]); + + cmc_assert(ih_remove_max(ih)); + cmc_assert_equals(size_t, 1, ih->buffer[0].data[0]); + + ih_free(ih); + }); + + CMC_CREATE_TEST(flags, { + struct intervalheap *ih = ih_new(100, ih_ftab_val); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + ih->flag = cmc_flags.ERROR; + + // clear + ih_clear(ih); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // customize + ih->flag = cmc_flags.ERROR; + ih_customize(ih, NULL, NULL); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // insert + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_insert(ih, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // remove_max + cmc_assert(ih_remove_max(ih)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + cmc_assert(!ih_remove_max(ih)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + + // remove min + cmc_assert(ih_insert(ih, 10)); + cmc_assert(ih_remove_min(ih)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + cmc_assert(!ih_remove_min(ih)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + + // update_max + cmc_assert(!ih_update_max(ih, 20)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + cmc_assert(ih_insert(ih, 10)); + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_update_max(ih, 20)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // update_min + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_update_min(ih, 20)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + cmc_assert(ih_remove_min(ih)); + ih->flag = cmc_flags.ERROR; + cmc_assert(!ih_update_max(ih, 20)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + + // max min + size_t r; + ih->flag = cmc_flags.ERROR; + cmc_assert(!ih_max(ih, &r)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + + ih->flag = cmc_flags.ERROR; + cmc_assert(!ih_min(ih, &r)); + cmc_assert_equals(int32_t, cmc_flags.EMPTY, ih_flag(ih)); + + cmc_assert(ih_insert(ih, 10)); + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_max(ih, &r)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_max(ih, &r)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // contains + ih->flag = cmc_flags.ERROR; + cmc_assert(ih_contains(ih, 10)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + + // copy_of + ih->flag = cmc_flags.ERROR; + struct intervalheap *ih2 = ih_copy_of(ih); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih2)); + + // equals + ih->flag = cmc_flags.ERROR; + ih2->flag = cmc_flags.ERROR; + cmc_assert(ih_equals(ih, ih2)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih)); + cmc_assert_equals(int32_t, cmc_flags.OK, ih_flag(ih2)); + + ih_free(ih); + ih_free(ih2); + }); });