LCOV - code coverage report
Current view: top level - src/foreign/RoutingKit/include/routingkit - id_set_queue.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.1 % 35 34
Test Date: 2026-09-23 15:43:02 Functions: 100.0 % 3 3

            Line data    Source code
       1              : #ifndef ROUTING_KIT_ID_SET_QUEUE_H
       2              : #define ROUTING_KIT_ID_SET_QUEUE_H
       3              : 
       4              : #include <routingkit/constants.h>
       5              : #include <routingkit/min_max.h>
       6              : #include <vector>
       7              : #include <assert.h>
       8              : 
       9              : namespace RoutingKit{
      10              : 
      11              : //! This is min queue that can only contain IDs from a given range.
      12              : //! IDs are compared by their value. Ids in the queue cannot be
      13              : //! duplicated.
      14              : class IDSetMinQueue{
      15              : 
      16              : private:
      17              :         // Internally, the queue is represented using an implicit binary tree
      18              :         // For every node in the tree, a bit is stored in data.
      19              :         //
      20              :         // Suppose that id_count() is 6, then the tree nodes are organized as
      21              :         // follows:
      22              :         //           1
      23              :         //          / |
      24              :         //         /   |
      25              :         //        /     |
      26              :         //       /       |
      27              :         //      2         3
      28              :         //     / |       / |
      29              :         //    /   |     /   |
      30              :         //   4     5   6     7
      31              :         //  /|    /|  / |
      32              :         // 8 9  10 11 12 13
      33              :         //
      34              :         // Node ids are counted starting from 1 and not from 0. IDs are counted 
      35              :         // starting from 0.
      36              :         //
      37              :         // The lowest level contains 6 bits because we have at most 6 IDs. Each of 
      38              :         // these lowest level bits encodes whether an ID is in the queue or not.
      39              :         //
      40              :         // If the number of IDs is uneven, for example 5, then we add another node
      41              :         // to the lowest level to make sure that every node has a sibling. This
      42              :         // padding bit will always remain false.
      43              :         //
      44              :         // The bit of upper level nodes is set, iff, there is a child whose bit is
      45              :         // set. If the queue would contain the IDs 1 and 2, then the nodes
      46              :         // 9, 10, 4, 5, 2, and 1 would have their bits sets. 
      47              :         //
      48              :         // Whether a bit is set is stored in data. data[0] is not used. The first
      49              :         // meaningful bit is data[1].
      50              :         //
      51              :         // offset stores the node number of the first node of the lowest level.
      52              :         // Because of the way that the tree is constructed, this is always
      53              :         // a power of two and it is never smaller than id_count().
      54              :         //
      55              :         // min_id stores the smallest id in the queue or invalid_id.
      56              :         //
      57              :         //
      58              :         // parent maps a node onto its parent.
      59              :         //      
      60              :         // other_child turns a node into its sibling.
      61              :         // is_larger_child checks whether a node is a right child in the 
      62              :         // above diagram.
      63              :         // is_smaller_child 
      64              : 
      65              : 
      66              :         static const unsigned root = 1;
      67              : 
      68              :         //! Maps a node onto its parent. Only works if x != root.
      69              :         static unsigned parent(unsigned x){
      70    159289949 :                 return x>>1;
      71              :         }
      72              :         
      73              :         //! Maps a node onto its sibling. Only works if x != root.
      74              :         static unsigned other_child(unsigned x){
      75     94979704 :                 return x^1;
      76              :         }
      77              : 
      78              :         //! True if other_child(x) < x. Only works if x != root.
      79              :         static unsigned is_larger_child(unsigned x){
      80              :                 return x&1;
      81              :         }
      82              : 
      83              :         //! True if other_child(x) > x. Only works if x != root.
      84              :         static unsigned is_smaller_child(unsigned x){
      85              :                 return !is_larger_child(x);
      86              :         }
      87              : 
      88              :         //! Returns the node y such that parent(y) == x and y < other_child(y).
      89              :         static unsigned smaller_child(unsigned x){
      90     90917448 :                 return x<<1;
      91              :         }
      92              : 
      93              :         //! Returns the node y such that parent(y) == x and y > other_child(y).
      94              :         static unsigned larger_child(unsigned x){
      95              :                 return (x<<1)|1;
      96              :         }
      97              : 
      98              :         static unsigned smallest_two_power_no_smaller_than(unsigned x){
      99              :                 unsigned y = 1;
     100         9336 :                 while(y < x){
     101         7887 :                         y <<= 1;
     102              :                         assert(y != 0);
     103              :                 }
     104              :                 return y;
     105              :         }
     106              : 
     107              : public:
     108              :         IDSetMinQueue(){}
     109              : 
     110              :         //! The queue may contain IDs from 0 to n-1.
     111         1449 :         explicit IDSetMinQueue(unsigned n):
     112         1449 :                 max_number_of_ids(n),
     113         1449 :                 min_id(invalid_id),
     114         1449 :                 offset(smallest_two_power_no_smaller_than(n)),
     115         1449 :                 data(n+offset+(n&1), false)// +(n&1) add an element if n is odd
     116         1449 :         {}
     117              : 
     118              :         unsigned id_count() const {
     119      1350287 :                 return max_number_of_ids;
     120              :         }
     121              : 
     122              :         //! Adds an ID to the queue. If the ID is already in the queue, then
     123              :         //! nothing happens.
     124     88492287 :         void push(unsigned id){
     125              :                 assert(id < id_count() && "id out of bounds");
     126              : 
     127     88492287 :                 if(min_id == invalid_id)
     128      1315296 :                         min_id = id;
     129              :                 else            
     130              :                         min_to(min_id, id);
     131              : 
     132     88492287 :                 unsigned x = id + offset;
     133              : 
     134     88492287 :                 if(data[x])
     135              :                         return;
     136              : 
     137              :                 for(;;)
     138              :                 {
     139              :                         assert(!data[x]);
     140              :                         data[x] = true;
     141              : 
     142    160605245 :                         if(x == root)
     143              :                                 break;
     144              : 
     145              :                         x = parent(x);
     146              : 
     147    159289949 :                         if(data[x])
     148              :                                 break;
     149              :                 }
     150              :         }
     151              : 
     152              :         //! Checks whether an ID is in the queue.
     153              :         bool contains(unsigned id) const {
     154              :                 assert(id < id_count() && "id out of bounds");
     155              :                 return data[offset + id];
     156              :         }
     157              : 
     158              :         //! Checks whether the queue contains any element.
     159              :         bool empty() const {
     160     64687480 :                 return min_id == invalid_id;
     161              :         }
     162              : 
     163              :         //! Returns the smallest ID in the queue without removing it.
     164              :         //! Returns invalid_id if the queue is empty.
     165              :         unsigned peek() const {
     166              :                 return min_id;
     167              :         }
     168              : 
     169              :         //! Returns the smallest ID in the queue and removes it.
     170              :         //! Returns invalid_id if the queue is empty.
     171     64075578 :         unsigned pop() {
     172              :                 assert(!empty());
     173              : 
     174     64075578 :                 unsigned ret = min_id;
     175              : 
     176     64075578 :                 unsigned x = min_id + offset;
     177              : 
     178              :                 for(;;)
     179              :                 {
     180              :                         assert(data[x]);
     181              :                         data[x] = false;
     182              : 
     183    160605245 :                         if(x == root){
     184      1315296 :                                 min_id = invalid_id;
     185      1315296 :                                 return ret;
     186              :                         }
     187              : 
     188    159289949 :                         if(is_smaller_child(x)){
     189              :                                 unsigned y = other_child(x);
     190              :                                 assert(y < data.size());
     191     80679188 :                                 if(data[y])
     192              :                                         break;
     193              :                         } else {
     194              :                                 assert(!data[other_child(x)]);
     195              :                         }
     196              : 
     197              :                         x = parent(x);
     198     96529667 :                 }
     199              : 
     200              :                 assert(is_smaller_child(x));
     201              :                 x = other_child(x);
     202              :                 assert(data[x]);
     203              :                 for(;;){
     204    153677730 :                         if(x >= offset)
     205              :                                 break;
     206              : 
     207              :                         x = smaller_child(x);
     208     90917448 :                         if(!data[x])
     209              :                                 x = other_child(x);
     210              :                         assert(data[x]);
     211              :                 }
     212     62760282 :                 min_id = x - offset;
     213              :                 
     214     62760282 :                 return ret;
     215              :         }
     216              : 
     217              :         //! Removes all elements from the queue.
     218              :         void clear(){
     219      1350287 :                 while(!empty())
     220            0 :                         pop();
     221              :         }
     222              : 
     223              : private:
     224              : 
     225              :         unsigned max_number_of_ids;
     226              :         unsigned min_id;
     227              :         unsigned offset;
     228              :         std::vector<bool>data;
     229              : };
     230              : 
     231              : } // RoutingKit
     232              : 
     233              : #endif
     234              : 
        

Generated by: LCOV version 2.0-1