LCOV - code coverage report
Current view: top level - lib - heap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 87 90.8 %
Date: 2016-09-14 01:02:56 Functions: 13 15 86.7 %
Branches: 27 28 96.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2012 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "heap.h"
      19                 :            : #include <stdlib.h>
      20                 :            : #include "util.h"
      21                 :            : 
      22                 :            : static void put_node(struct heap *, struct heap_node *, size_t i);
      23                 :            : static void swap_nodes(struct heap *, size_t i, size_t j);
      24                 :            : static bool float_up(struct heap *, size_t i);
      25                 :            : static void float_down(struct heap *, size_t i);
      26                 :            : static void float_up_or_down(struct heap *, size_t i);
      27                 :            : 
      28                 :            : /* Initializes 'heap' as an empty heap. */
      29                 :            : void
      30                 :     269580 : heap_init(struct heap *heap)
      31                 :            : {
      32                 :     269580 :     heap->array = NULL;
      33                 :     269580 :     heap->n = 0;
      34                 :     269580 :     heap->allocated = 0;
      35                 :     269580 : }
      36                 :            : 
      37                 :            : /* Frees memory owned internally by 'heap'.  The caller is responsible for
      38                 :            :  * freeing 'heap' itself, if necessary. */
      39                 :            : void
      40                 :     109950 : heap_destroy(struct heap *heap)
      41                 :            : {
      42         [ +  - ]:     109950 :     if (heap) {
      43                 :     109950 :         free(heap->array);
      44                 :            :     }
      45                 :     109950 : }
      46                 :            : 
      47                 :            : /* Removes all of the elements from 'heap', without freeing any allocated
      48                 :            :  * memory. */
      49                 :            : void
      50                 :          0 : heap_clear(struct heap *heap)
      51                 :            : {
      52                 :          0 :     heap->n = 0;
      53                 :          0 : }
      54                 :            : 
      55                 :            : /* Exchanges the contents of 'a' and 'b'. */
      56                 :            : void
      57                 :          0 : heap_swap(struct heap *a, struct heap *b)
      58                 :            : {
      59                 :          0 :     struct heap tmp = *a;
      60                 :          0 :     *a = *b;
      61                 :          0 :     *b = tmp;
      62                 :          0 : }
      63                 :            : 
      64                 :            : /* Inserts 'node' into 'heap' with the specified 'priority'.
      65                 :            :  *
      66                 :            :  * This takes time O(lg n). */
      67                 :            : void
      68                 :     474284 : heap_insert(struct heap *heap, struct heap_node *node, uint64_t priority)
      69                 :            : {
      70                 :     474284 :     heap_raw_insert(heap, node, priority);
      71                 :     474284 :     float_up(heap, node->idx);
      72                 :     474284 : }
      73                 :            : 
      74                 :            : /* Removes 'node' from 'heap'.
      75                 :            :  *
      76                 :            :  * This takes time O(lg n). */
      77                 :            : void
      78                 :     474274 : heap_remove(struct heap *heap, struct heap_node *node)
      79                 :            : {
      80                 :     474274 :     size_t i = node->idx;
      81                 :            : 
      82                 :     474274 :     heap_raw_remove(heap, node);
      83         [ +  + ]:     474274 :     if (i <= heap->n) {
      84                 :     296030 :         float_up_or_down(heap, i);
      85                 :            :     }
      86                 :     474274 : }
      87                 :            : 
      88                 :            : /* Changes the priority of 'node' (which must be in 'heap') to 'priority'.
      89                 :            :  *
      90                 :            :  * This takes time O(lg n). */
      91                 :            : void
      92                 :      87683 : heap_change(struct heap *heap, struct heap_node *node, uint64_t priority)
      93                 :            : {
      94                 :      87683 :     heap_raw_change(node, priority);
      95                 :      87683 :     float_up_or_down(heap, node->idx);
      96                 :      87683 : }
      97                 :            : 
      98                 :            : /* Inserts 'node' into 'heap' with the specified 'priority', without
      99                 :            :  * maintaining the heap invariant.
     100                 :            :  *
     101                 :            :  * After this call, heap_max() will no longer necessarily return the maximum
     102                 :            :  * value in the heap, and HEAP_FOR_EACH will no longer necessarily iterate in
     103                 :            :  * heap level order, until the next call to heap_rebuild(heap).
     104                 :            :  *
     105                 :            :  * This takes time O(1). */
     106                 :            : void
     107                 :     525564 : heap_raw_insert(struct heap *heap, struct heap_node *node, uint64_t priority)
     108                 :            : {
     109         [ +  + ]:     525564 :     if (heap->n >= heap->allocated) {
     110         [ +  + ]:     312683 :         heap->allocated = heap->n == 0 ? 1 : 2 * heap->n;
     111                 :     312683 :         heap->array = xrealloc(heap->array,
     112                 :     312683 :                                (heap->allocated + 1) * sizeof *heap->array);
     113                 :            :     }
     114                 :            : 
     115                 :     525564 :     put_node(heap, node, ++heap->n);
     116                 :     525564 :     node->priority = priority;
     117                 :     525564 : }
     118                 :            : 
     119                 :            : /* Removes 'node' from 'heap', without maintaining the heap invariant.
     120                 :            :  *
     121                 :            :  * After this call, heap_max() will no longer necessarily return the maximum
     122                 :            :  * value in the heap, and HEAP_FOR_EACH will no longer necessarily iterate in
     123                 :            :  * heap level order, until the next call to heap_rebuild(heap).
     124                 :            :  *
     125                 :            :  * This takes time O(1). */
     126                 :            : void
     127                 :     525554 : heap_raw_remove(struct heap *heap, struct heap_node *node)
     128                 :            : {
     129                 :     525554 :     size_t i = node->idx;
     130         [ +  + ]:     525554 :     if (i < heap->n) {
     131                 :     331422 :         put_node(heap, heap->array[heap->n], i);
     132                 :            :     }
     133                 :     525554 :     heap->n--;
     134                 :     525554 : }
     135                 :            : 
     136                 :            : /* Rebuilds 'heap' to restore the heap invariant following a series of one or
     137                 :            :  * more calls to heap_raw_*() functions.  (Otherwise this function need not be
     138                 :            :  * called.)
     139                 :            :  *
     140                 :            :  * This takes time O(n) in the current size of the heap. */
     141                 :            : void
     142                 :      42327 : heap_rebuild(struct heap *heap)
     143                 :            : {
     144                 :            :     size_t i;
     145                 :            : 
     146         [ +  + ]:     105819 :     for (i = heap->n / 2; i >= 1; i--) {
     147                 :      63492 :         float_down(heap, i);
     148                 :            :     }
     149                 :      42327 : }
     150                 :            : 
     151                 :            : static void
     152                 :    1861962 : put_node(struct heap *heap, struct heap_node *node, size_t i)
     153                 :            : {
     154                 :    1861962 :     heap->array[i] = node;
     155                 :    1861962 :     node->idx = i;
     156                 :    1861962 : }
     157                 :            : 
     158                 :            : static void
     159                 :     502488 : swap_nodes(struct heap *heap, size_t i, size_t j)
     160                 :            : {
     161                 :     502488 :     struct heap_node *old_i = heap->array[i];
     162                 :     502488 :     struct heap_node *old_j = heap->array[j];
     163                 :            : 
     164                 :     502488 :     put_node(heap, old_j, i);
     165                 :     502488 :     put_node(heap, old_i, j);
     166                 :     502488 : }
     167                 :            : 
     168                 :            : static bool
     169                 :     857997 : float_up(struct heap *heap, size_t i)
     170                 :            : {
     171                 :     857997 :     bool moved = false;
     172                 :            :     size_t parent;
     173                 :            : 
     174         [ +  + ]:    1106601 :     for (; i > 1; i = parent) {
     175                 :     790367 :         parent = heap_parent__(i);
     176         [ +  + ]:     790367 :         if (heap->array[parent]->priority >= heap->array[i]->priority) {
     177                 :     541763 :             break;
     178                 :            :         }
     179                 :     248604 :         swap_nodes(heap, parent, i);
     180                 :     248604 :         moved = true;
     181                 :            :     }
     182                 :     857997 :     return moved;
     183                 :            : }
     184                 :            : 
     185                 :            : static void
     186                 :     432957 : float_down(struct heap *heap, size_t i)
     187                 :            : {
     188         [ +  + ]:     686841 :     while (!heap_is_leaf__(heap, i)) {
     189                 :     387406 :         size_t left = heap_left__(i);
     190                 :     387406 :         size_t right = heap_right__(i);
     191                 :     387406 :         size_t max = i;
     192                 :            : 
     193         [ +  + ]:     387406 :         if (heap->array[left]->priority > heap->array[max]->priority) {
     194                 :     229828 :             max = left;
     195                 :            :         }
     196         [ +  + ]:     387406 :         if (right <= heap->n
     197         [ +  + ]:     309394 :             && heap->array[right]->priority > heap->array[max]->priority) {
     198                 :     109525 :             max = right;
     199                 :            :         }
     200         [ +  + ]:     387406 :         if (max == i) {
     201                 :     133522 :             break;
     202                 :            :         }
     203                 :            : 
     204                 :     253884 :         swap_nodes(heap, max, i);
     205                 :     253884 :         i = max;
     206                 :            :     }
     207                 :     432957 : }
     208                 :            : 
     209                 :            : static void
     210                 :     383713 : float_up_or_down(struct heap *heap, size_t i)
     211                 :            : {
     212         [ +  + ]:     383713 :     if (!float_up(heap, i)) {
     213                 :     369465 :         float_down(heap, i);
     214                 :            :     }
     215                 :     383713 : }
     216                 :            : 

Generated by: LCOV version 1.12