rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 7b24c1b44e2ee18ac15d2d698e66cfee0b6bdaf4
parent 56f8c7a245561abeaee4f5914c733a052aa51e21
Author: vaplv <vaplv@free.fr>
Date:   Sun, 30 Mar 2014 00:05:53 +0100

Major changes of the binary heap API

Push further the binary heap tests

Diffstat:
Msrc/binary_heap.h | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/test_binary_heap.c | 177++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/test_dynamic_array.c | 1-
3 files changed, 204 insertions(+), 60 deletions(-)

diff --git a/src/binary_heap.h b/src/binary_heap.h @@ -78,6 +78,16 @@ BHEAP_FUNC__(functor_cmp__)(const BHEAP_DATA* a, const BHEAP_DATA* b) #define BHEAP_FUNCTOR_COMPARE BHEAP_FUNC__(functor_cmp__) #endif +#ifndef BHEAP_FUNCTOR_COPY + #define BHEAP_FUNCTOR_COPY BHEAP_NODES_FUNC__(functor_cp__) +#endif +#ifndef BHEAP_FUNCTOR_INIT + #define BHEAP_FUNCTOR_INIT BHEAP_NODES_FUNC__(functor_init__) +#endif +#ifndef BHEAP_FUNCTOR_RELEASE + #define BHEAP_FUNCTOR_RELEASE BHEAP_NODES_FUNC__(functor_release__) +#endif + /******************************************************************************* * Binary heap API ******************************************************************************/ @@ -112,70 +122,94 @@ BHEAP_FUNC__(is_empty)(struct BHEAP_TYPE__* heap) } static INLINE int -BHEAP_FUNC__(insert)(struct BHEAP_TYPE__* heap, const uint64_t value) +BHEAP_FUNC__(insert)(struct BHEAP_TYPE__* heap, const BHEAP_DATA* value) { - uint64_t* nodes = NULL; - uint64_t node; + BHEAP_DATA* nodes = NULL; + BHEAP_DATA tmp; size_t inode = 0; ASSERT(heap); inode = BHEAP_NODES_FUNC__(size_get)(&heap->nodes); - node = value; - if(BHEAP_NODES_FUNC__(push_back)(&heap->nodes, &node)) + if(BHEAP_NODES_FUNC__(push_back)(&heap->nodes, value)) return -1; nodes = BHEAP_NODES_FUNC__(data_get)(&heap->nodes); + BHEAP_FUNCTOR_INIT(heap->nodes.allocator, &tmp); while(inode) { const size_t iparent = (inode - 1) / 2; - if(BHEAP_FUNC__(functor_cmp__)(&nodes[iparent], &nodes[inode]) <= 0) + if(BHEAP_FUNCTOR_COMPARE(&nodes[iparent], &nodes[inode]) <= 0) break; - SWAP(uint64_t, nodes[iparent], nodes[inode]); + + BHEAP_FUNCTOR_COPY(&tmp, &nodes[iparent]); + BHEAP_FUNCTOR_COPY(&nodes[iparent], &nodes[inode]); + BHEAP_FUNCTOR_COPY(&nodes[inode], &tmp); inode = iparent; } + BHEAP_FUNCTOR_RELEASE(&tmp); return 0; } -static INLINE uint64_t -BHEAP_FUNC__(top)(struct BHEAP_TYPE__* heap) +static INLINE char +BHEAP_FUNC__(top)(struct BHEAP_TYPE__* heap, BHEAP_DATA* top) { - ASSERT(heap && !BHEAP_FUNC__(is_empty)(&heap->nodes)); - return BHEAP_NODES_FUNC__(data_get)(&heap->nodes)[0]; + ASSERT(heap); + + if(BHEAP_FUNC__(is_empty)(heap)) + return 0; + + BHEAP_FUNCTOR_COPY(top, &BHEAP_NODES_FUNC__(data_get)(&heap->nodes)[0]); + return 1; } -static INLINE uint64_t -BHEAP_FUNC__(pop)(struct BHEAP_TYPE__* heap) +static INLINE char +BHEAP_FUNC__(pop)(struct BHEAP_TYPE__* heap, BHEAP_DATA* top) { - uint64_t* nodes = NULL; - uint64_t head = 0; - uint64_t last = 0; + BHEAP_DATA* nodes = NULL; + BHEAP_DATA tmp; size_t size = 0; size_t inode = 0; size_t ichild = 0; - ASSERT(heap && !BHEAP_FUNC__(is_empty)(&heap->nodes)); + char res = 1; + ASSERT(heap); + + BHEAP_FUNCTOR_INIT(heap->nodes.allocator, &tmp); + + if(BHEAP_FUNC__(is_empty)(heap)) { + res = 0; + goto exit; + } nodes = BHEAP_NODES_FUNC__(data_get)(&heap->nodes); - head = nodes[0]; + BHEAP_FUNCTOR_COPY(top, &nodes[0]); inode = BHEAP_NODES_FUNC__(size_get)(&heap->nodes) - 1; - last = nodes[inode]; + BHEAP_FUNCTOR_COPY(&tmp, &nodes[inode]); BHEAP_NODES_FUNC__(pop_back)(&heap->nodes); - if(!inode) - return head; + if(!inode) { + res = 1; + goto exit; + } nodes = BHEAP_NODES_FUNC__(data_get)(&heap->nodes); - nodes[0] = last; + BHEAP_FUNCTOR_COPY(&nodes[0], &tmp); size = inode; for(inode=0, ichild=1; ichild < size; inode = ichild, ichild = 2*inode + 1) { - if(ichild + 1 < size && nodes[ichild] > nodes[ichild+1]) + + if(ichild + 1 < size + && BHEAP_FUNCTOR_COMPARE(&nodes[ichild], &nodes[ichild+1]) > 0) ++ichild; - if(nodes[inode] < nodes[ichild]) + if(BHEAP_FUNCTOR_COMPARE(&nodes[inode], &nodes[ichild]) <= 0) break; - SWAP(uint64_t, nodes[inode], nodes[ichild]); + BHEAP_FUNCTOR_COPY(&tmp, &nodes[inode]); + BHEAP_FUNCTOR_COPY(&nodes[inode], &nodes[ichild]); + BHEAP_FUNCTOR_COPY(&nodes[ichild], &tmp); inode = ichild; } - return head; +exit: + BHEAP_FUNCTOR_RELEASE(&tmp); + return res; } #undef BHEAP_NAME diff --git a/src/test_binary_heap.c b/src/test_binary_heap.c @@ -1,17 +1,17 @@ #include "binary_heap.h" #include "mem_allocator.h" +#include "str.h" #define BHEAP_NAME u64 #define BHEAP_DATA uint64_t #include "binary_heap.h" -int -main(int argc, char** argv) +static void +test_primitive_type(void) { struct mem_allocator allocator_proxy; struct bheap_u64 heap; uint64_t i; - (void)argc, (void)argv; mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator); @@ -21,44 +21,63 @@ main(int argc, char** argv) CHECK(bheap_u64_is_empty(&heap), 1); CHECK(bheap_u64_is_empty(&heap), 1); - CHECK(bheap_u64_insert(&heap, 48), 0); - CHECK(bheap_u64_insert(&heap, 51), 0); - CHECK(bheap_u64_insert(&heap, 1), 0); - CHECK(bheap_u64_insert(&heap, 7), 0); - CHECK(bheap_u64_insert(&heap, 78), 0); - CHECK(bheap_u64_insert(&heap, 4), 0); - CHECK(bheap_u64_insert(&heap, 61), 0); - CHECK(bheap_u64_insert(&heap, 72), 0); + CHECK(bheap_u64_top(&heap, &i), 0); + CHECK(bheap_u64_pop(&heap, &i), 0); + i = 48; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 51; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 1; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 7; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 78; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 4; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 61; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 72; CHECK(bheap_u64_insert(&heap, &i), 0); CHECK(bheap_u64_is_empty(&heap), 0); - CHECK(bheap_u64_top(&heap), 1); - CHECK(bheap_u64_top(&heap), 1); - CHECK(bheap_u64_pop(&heap), 1); - CHECK(bheap_u64_pop(&heap), 4); - CHECK(bheap_u64_pop(&heap), 7); - CHECK(bheap_u64_pop(&heap), 48); - - CHECK(bheap_u64_insert(&heap, 5), 0); - CHECK(bheap_u64_insert(&heap, 50), 0); - CHECK(bheap_u64_insert(&heap, 51), 0); - CHECK(bheap_u64_top(&heap), 5); - CHECK(bheap_u64_pop(&heap), 5); - CHECK(bheap_u64_pop(&heap), 50); - CHECK(bheap_u64_pop(&heap), 51); - CHECK(bheap_u64_pop(&heap), 51); - CHECK(bheap_u64_pop(&heap), 61); - CHECK(bheap_u64_pop(&heap), 72); - CHECK(bheap_u64_pop(&heap), 78);; + NCHECK(bheap_u64_top(&heap, &i), 0); + CHECK(i, 1); + NCHECK(bheap_u64_top(&heap, &i), 0); + CHECK(i, 1); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 1); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 4); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 7); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 48); + + i = 5; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 50; CHECK(bheap_u64_insert(&heap, &i), 0); + i = 51; CHECK(bheap_u64_insert(&heap, &i), 0); + NCHECK(bheap_u64_top(&heap, &i), 0); + CHECK(i, 5); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 5); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 50); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 51); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 51); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 61); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 72); + NCHECK(bheap_u64_pop(&heap, &i), 0); + CHECK(i, 78); + CHECK(bheap_u64_pop(&heap, &i), 0); CHECK(bheap_u64_is_empty(&heap), 1); FOR_EACH(i, 0, 17689) { - CHECK(bheap_u64_insert(&heap, (uint64_t)rand()), 0); + const uint64_t j = (uint64_t)rand(); + CHECK(bheap_u64_insert(&heap, &j), 0); } CHECK(bheap_u64_is_empty(&heap), 0); - i = bheap_u64_pop(&heap); - while(!bheap_u64_is_empty(&heap)) { - uint64_t j = bheap_u64_pop(&heap); + NCHECK(bheap_u64_pop(&heap, &i), 0); + while(bheap_u64_is_empty(&heap)) { + uint64_t j = 0; + NCHECK(bheap_u64_pop(&heap, &j), 0); CHECK(j >= i, 1); i = j; } @@ -72,6 +91,98 @@ main(int argc, char** argv) FATAL("Memory leaks\n"); } mem_shutdown_proxy_allocator(&allocator_proxy); +} + +static int +str_cmp(const struct str* a, const struct str* b) +{ + ASSERT(a && b); + return strcmp(str_cget(a), str_cget(b)); +} + +#define BHEAP_NAME str +#define BHEAP_DATA struct str +#define BHEAP_FUNCTOR_INIT str_init +#define BHEAP_FUNCTOR_COPY str_copy +#define BHEAP_FUNCTOR_RELEASE str_release +#define BHEAP_FUNCTOR_COPY_AND_RELEASE str_copy_and_release +#define BHEAP_FUNCTOR_COMPARE str_cmp +#include "binary_heap.h" + +static void +test_struct(void) +{ + struct mem_allocator allocator_proxy; + struct bheap_str heap; + struct str str; + size_t i; + const char* strs[] = { + "Rcvfbqr", "1,", "XARR-QRRC", "VA", "GUR", "QRNQ:\n", + "---------------------------------", "BAPR", "LBH", "ORNG", "GUR", "OVT", + "ONQNFFRF", "NAQ", "PYRNA", "BHG", "GUR", "ZBBA", "ONFR", "LBH'ER", + "FHCCBFRQ", "GB\n", "JVA", "NERA'G", "LBH?", "NERA'G", "LBH?", "JURER'F", + "LBHE", "SNG", "ERJNEQ", "NAQ", "GVPXRG", "UBZR?", "JUNG\n", "GUR", "URYY", + "VF", "GUVF?", "VG'F", "ABG", "FHCCBFRQ", "GB", "RAQ", "GUVF", "JNL!", "VG", + "FGVAXF", "YVXR", "EBGGRA", "ZRNG,", "OHG", "YBBXF", "YVXR", "GUR", "YBFG", + "QRVZBF", "ONFR.", "YBBXF", "YVXR\n", "LBH'ER", "FGHPX", "BA", "GUR", + "FUBERF", "BS", "URYY.", "GUR", "BAYL", "JNL", "BHG", "VF", "GUEBHTU.", "GB", + "PBAGVAHR", "GUR", "QBBZ", "RKCREVRAPR,", "CYNL", "GUR", "FUBERF", "BS", + "URYY", "NAQ", "VGF", "NZNMVAT\n", "FRDHRY,", "VASREAB!", + + "Rcvfbqr 2, GUR FUBERF BS URYY:\n\ + ------------------------------\n\ + \n\ + LBH'IR QBAR VG! GUR UVQRBHF PLORE- QRZBA YBEQ GUNG EHYRQ GUR YBFG QRVZBF ZBBA\n\ + ONFR UNF ORRA FYNVA NAQ LBH NER GEVHZCUNAG! OHG ... JURER NER LBH? LBH\n\ + PYNZORE GB GUR RQTR BS GUR ZBBA NAQ YBBX QBJA GB FRR GUR NJSHY GEHGU.\n\ + \n", + + "QRVZBF SYBNGF NOBIR URYY VGFRYS! LBH'IR ARIRE URNEQ BS NALBAR RFPNCVAT SEBZ\n\ + URYY, OHG LBH'YY ZNXR GUR ONFGNEQF FBEEL GURL RIRE URNEQ BS LBH! DHVPXYL, LBH\n\ + ENCCRY QBJA GB GUR FHESNPR BS URYY.\n\ + \n\ + ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB." + }; + const size_t nstrs = sizeof(strs)/sizeof(const char*); + + mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator); + str_init(&allocator_proxy, &str); + + bheap_str_init(&allocator_proxy, &heap); + FOR_EACH(i, 0, nstrs) { + str_set(&str, strs[i]); + bheap_str_insert(&heap, &str); + } + + NCHECK(bheap_str_pop(&heap, &str), 0); + while(bheap_str_is_empty(&heap)) { + struct str str2; + str_init(&allocator_proxy, &str2); + NCHECK(bheap_str_pop(&heap, &str2), 0); + CHECK(strcmp(str_cget(&str), str_cget(&str2)), -1); + str_set(&str, str_cget(&str2)); + str_release(&str2); + } + + str_release(&str); + bheap_str_release(&heap); + + if(MEM_ALLOCATED_SIZE(&allocator_proxy)) { + char dump[512]; + MEM_DUMP(&allocator_proxy, dump, sizeof(dump)/sizeof(char)); + fprintf(stderr, "%s\n", dump); + FATAL("Memory leaks\n"); + } + mem_shutdown_proxy_allocator(&allocator_proxy); +} + +int +main(int argc, char** argv) +{ + (void)argc, (void)argv; + test_primitive_type(); + test_struct(); CHECK(mem_allocated_size(), 0); return 0; } + diff --git a/src/test_dynamic_array.c b/src/test_dynamic_array.c @@ -30,7 +30,6 @@ const char* strs[] = { ENCCRY QBJA GB GUR FHESNPR BS URYY.\n\ \n\ ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB." - }; const size_t nstrs = sizeof(strs)/sizeof(const char*);