diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index d112a03..4493428 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -118,6 +118,7 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity size_t PFX##_count(SNAME *_heap_); \ size_t PFX##_capacity(SNAME *_heap_); \ /* Collection Utility */ \ + bool PFX##_resize(SNAME *_heap_, size_t capacity); \ SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ cmc_string PFX##_to_string(SNAME *_heap_); \ @@ -157,7 +158,6 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity #define CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, 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_); \ @@ -235,7 +235,7 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity { \ if (PFX##_full(_heap_)) \ { \ - if (!PFX##_impl_grow(_heap_)) \ + if (!PFX##_resize(_heap_, PFX##_capacity(_heap_) * 4)) \ return false; \ } \ \ @@ -485,6 +485,29 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity return _heap_->capacity; \ } \ \ + bool PFX##_resize(SNAME *_heap_, size_t capacity) \ + { \ + if (PFX##_capacity(_heap_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_heap_)) \ + return false; \ + \ + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ + \ + SNAME##_node *new_buffer = realloc(_heap_->buffer, sizeof(SNAME##_node) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + memset(new_buffer + _heap_->capacity, 0, sizeof(SNAME##_node) * _heap_->capacity); \ + \ + _heap_->buffer = new_buffer; \ + _heap_->capacity = capacity; \ + \ + return true; \ + } \ + \ SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ { \ SNAME *result = malloc(sizeof(SNAME)); \ @@ -704,23 +727,6 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity 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; \ diff --git a/tests/main/unt/intervalheap.c b/tests/main/unt/intervalheap.c index 4fefced..3ee4dd2 100644 --- a/tests/main/unt/intervalheap.c +++ b/tests/main/unt/intervalheap.c @@ -28,6 +28,36 @@ CMC_CREATE_UNIT(intervalheap_test, true, { ih_free(ih, NULL); }); + CMC_CREATE_TEST(new[capacity], { + intervalheap *ih = ih_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 1, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(2, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 1, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(3, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 2, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(4, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 2, ih_capacity(ih)); + + ih_free(ih, NULL); + }); + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { intervalheap *ih = ih_new(UINT64_MAX, cmp); @@ -43,7 +73,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_not_equals(ptr, NULL, ih); for (size_t i = 0; i < 50; i++) - ih_insert(ih, i); + cmc_assert(ih_insert(ih, i)); cmc_assert_equals(size_t, 50, ih_count(ih)); @@ -61,9 +91,43 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_not_equals(ptr, NULL, ih); for (size_t i = 0; i < 50; i++) - ih_insert(ih, i); + cmc_assert(ih_insert(ih, i)); cmc_assert_equals(size_t, 50, ih_count(ih)); + cmc_assert_greater(size_t, 50, ih_capacity(ih) * 2); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(insert[count], { + intervalheap *ih = ih_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 0)); + + cmc_assert_equals(size_t, 2, ih_count(ih)); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(insert[max min], { + intervalheap *ih = ih_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 0)); + + size_t min; + size_t max; + + 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); ih_free(ih, NULL); });