About Docs Source
LCOV - code coverage report
Current view: top level - src/lib/crater - pheap.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 74 74 100.0 %
Date: 2024-02-13 04:57:17 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include <stdlib.h>
       2             : #include <string.h>
       3             : 
       4             : #include <crater/pheap.h>
       5             : 
       6       10001 : cr8r_pheap_node *cr8r_pheap_new(void *key, cr8r_pheap_ft *ft, cr8r_pheap_node *first_child, cr8r_pheap_node *sibling, cr8r_pheap_node *parent){
       7       10001 :     void *res = ft->alloc ? ft->alloc(&ft->base) : NULL;
       8       10001 :     if(res){
       9       10001 :         memcpy(res, key, ft->base.size);
      10       10001 :         memcpy(res + ft->base.size, &(cr8r_pheap_node){.first_child = first_child, .sibling = sibling, .parent = parent}, sizeof(cr8r_pheap_node));
      11             :     }
      12       10001 :     return res + ft->base.size;
      13             : }
      14             : 
      15      265055 : void *cr8r_pheap_top(cr8r_pheap_node *r, cr8r_pheap_ft *ft){
      16      265055 :     return r ? CR8R_OUTER_S(r, ft) : NULL;
      17             : }
      18             : 
      19         130 : cr8r_pheap_node *cr8r_pheap_root(cr8r_pheap_node *n){
      20         130 :     if(!n){
      21             :         return NULL;
      22             :     }
      23         357 :     while(n->parent){
      24         228 :         n = n->parent;
      25             :     }
      26             :     return n;
      27             : }
      28             : 
      29     2291404 : cr8r_pheap_node *cr8r_pheap_meld(cr8r_pheap_node *a, cr8r_pheap_node *b, cr8r_pheap_ft *ft){
      30     2291404 :     if(!a){
      31             :         return b;
      32     2291402 :     }else if(!b){
      33             :         return a;
      34     1964740 :     }else if(ft->cmp(&ft->base, CR8R_OUTER_S(a, ft), CR8R_OUTER_S(b, ft)) > 0){
      35      685320 :         a->sibling = b->first_child;
      36      685320 :         b->first_child = a;
      37      685320 :         a->parent = b;
      38      685320 :         return b;
      39             :     }
      40     1279420 :     b->sibling = a->first_child;
      41     1279420 :     a->first_child = b;
      42     1279420 :     b->parent = a;
      43     1279420 :     return a;
      44             : }
      45             : 
      46       10000 : cr8r_pheap_node *cr8r_pheap_push(cr8r_pheap_node *r, void *key, cr8r_pheap_ft *ft){
      47       10000 :     cr8r_pheap_node *n = cr8r_pheap_new(key, ft, NULL, NULL, NULL);
      48       10000 :     return n ? cr8r_pheap_meld(r, n, ft) : NULL;
      49             : }
      50             : 
      51             : /// helper function for cr8r_pheap_pop.  Uses mergesort to combine a cr8r_pheap_node's children
      52             : /// linked list into one pairing heap.  Since the length of the list of children is
      53             : /// not stored, this function accepts a recursion depth and is called by another helper
      54             : /// function (cr8r_pheap_merge_exponential) with depth 0, 0, 1, 2, 3, 4, 5, 6, ... until all
      55             : /// children are merged.  If the list is empty, nothing is done.  If the depth is 0,
      56             : /// the first child in the remaining part of the list is removed and returned (1 node is sorted).
      57     3466501 : static cr8r_pheap_node *cr8r_pheap_merge_binary(cr8r_pheap_node **n, size_t depth, cr8r_pheap_ft *ft){
      58     3466501 :     cr8r_pheap_node *a, *b;
      59     3466501 :     if(!*n){
      60             :         return NULL;
      61     3139836 :     }else if(!depth){
      62     1954610 :         a = *n;
      63     1954610 :         *n = (*n)->sibling;
      64     1954610 :         a->sibling = NULL;
      65     1954610 :         a->parent = NULL;
      66     1954610 :         return a;
      67             :     }
      68     1185226 :     a = cr8r_pheap_merge_binary(n, depth - 1, ft);
      69     1185226 :     b = cr8r_pheap_merge_binary(n, depth - 1, ft);
      70     1185226 :     return cr8r_pheap_meld(a, b, ft);
      71             : }
      72             : 
      73             : /// helper function for pheap_pop.  Uses mergesort to combine a pheap_node's children
      74             : /// linked list into one pairing heap.
      75      263744 : static cr8r_pheap_node *cr8r_pheap_merge_exponential(cr8r_pheap_node **n, cr8r_pheap_ft *ft){
      76      263744 :     cr8r_pheap_node *a = cr8r_pheap_merge_binary(n, 0, ft);
      77     1096049 :     for(size_t depth = 0; *n; ++depth){
      78      832305 :         a = cr8r_pheap_meld(a, cr8r_pheap_merge_binary(n, depth, ft), ft);
      79             :     }
      80      263744 :     return a;
      81             : }
      82             : 
      83      263745 : cr8r_pheap_node *cr8r_pheap_pop(cr8r_pheap_node **r, cr8r_pheap_ft *ft){
      84      263745 :     if(!*r){
      85             :         return NULL;
      86             :     }
      87      263744 :     cr8r_pheap_node *ret = *r;
      88      263744 :     *r = cr8r_pheap_merge_exponential(&(*r)->first_child, ft);
      89      263744 :     return ret;
      90             : }
      91             : 
      92         130 : cr8r_pheap_node *cr8r_pheap_decreased_key(cr8r_pheap_node *n, cr8r_pheap_ft *ft){
      93         130 :     if(!n){
      94             :         return NULL;
      95             :     }
      96         130 :     cr8r_pheap_node *p = n->parent;
      97         130 :     if(!p || ft->cmp(&ft->base, CR8R_OUTER_S(p, ft), CR8R_OUTER_S(n, ft)) <= 0){
      98          98 :         return cr8r_pheap_root(p);
      99          32 :     }else if(p->first_child == n){
     100          18 :         p->first_child = n->sibling;
     101          22 :     }else for(cr8r_pheap_node *s = p->first_child;; s = s->sibling){
     102          22 :         if(s->sibling == n){
     103          14 :             s->sibling = n->sibling;
     104          14 :             break;
     105             :         }
     106             :     }
     107          32 :     n->sibling = NULL;
     108          32 :     n->parent = NULL;
     109          32 :     return cr8r_pheap_meld(cr8r_pheap_root(p), n, ft);
     110             : }
     111             : 
     112        6739 : void cr8r_pheap_delete(cr8r_pheap_node *r, cr8r_pheap_ft *ft){
     113        6739 :     if(!ft->free){
     114             :         return;
     115             :     }
     116       10002 :     for(cr8r_pheap_node *t; r;){
     117       10001 :         while(r->sibling){
     118        6738 :             cr8r_pheap_delete(r->sibling->first_child, ft);
     119        6738 :             t = r->sibling;
     120        6738 :             r->sibling = t->sibling;
     121        6738 :             ft->free(&ft->base, t);
     122             :         }
     123        3263 :         t = r;
     124        3263 :         r = r->first_child;
     125        3263 :         ft->free(&ft->base, t);
     126             :     }
     127             : }
     128             : 

Generated by: LCOV version 1.14