LCOV - code coverage report
Current view: top level - util/tmpl - fd_redblack.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 437 520 84.0 %
Date: 2025-01-08 12:08:44 Functions: 84 455 18.5 %

          Line data    Source code
       1             : /* Declares a family of functions implementing a single-threaded
       2             :    fixed-capacity red-black tree designed for high performance
       3             :    contexts.
       4             : 
       5             :    A red-black tree is a type of self-balanced binary tree where the
       6             :    nodes are kept in sorted order. Queries, insertions, and deletions
       7             :    are O(log n) cost where n is the size of the tree. The implicit
       8             :    sorting makes in-order traversal very fast, something a hash table
       9             :    cannot do.
      10             : 
      11             :    Tree nodes are allocated from a pool before insertion. After
      12             :    removal, they are returned to the pool. The pool is the result of
      13             :    the join operation.
      14             : 
      15             :    Multiple trees can coexist in the same pool, provided the total
      16             :    size of all the trees does not exceed the pool size. This is
      17             :    convenient for removing nodes from one tree and inserting them into
      18             :    another without copying the key or value.
      19             : 
      20             :    Example usage:
      21             : 
      22             :      struct my_rb_node {
      23             :          ulong key;
      24             :          ulong val;
      25             :          ulong redblack_parent;
      26             :          ulong redblack_left;
      27             :          ulong redblack_right;
      28             :          int redblack_color;
      29             :      };
      30             :      typedef struct my_rb_node my_rb_node_t;
      31             :      #define REDBLK_T my_rb_node_t
      32             :      #define REDBLK_NAME my_rb
      33             :      #include "fd_redblack.c"
      34             : 
      35             :    Note the order of declarations and includes. REDBLK_T and REDBLK_NAME
      36             :    need to be defined before including this template. REDBLK_T is the
      37             :    node or element type. It must include the following fields:
      38             : 
      39             :      ulong redblack_parent;
      40             :      ulong redblack_left;
      41             :      ulong redblack_right;
      42             :      int redblack_color;
      43             : 
      44             :    which are used by the redblack tree. Everything else in the node
      45             :    type is up to the application.
      46             : 
      47             :    This example creates the following API for use in the local compilation unit:
      48             : 
      49             :      ulong my_rb_max_for_footprint( ulong footprint );
      50             :      ulong my_rb_align( void );
      51             :      ulong my_rb_footprint( ulong max );
      52             :      void * my_rb_new( void * shmem, ulong max );
      53             :      my_rb_node_t * my_rb_join( void * shpool );
      54             :      void * my_rb_leave( my_rb_node_t * pool );
      55             :      void * my_rb_delete( void * shpool );
      56             :      ulong my_rb_max( my_rb_node_t const * pool );
      57             :      ulong my_rb_free( my_rb_node_t const * pool );
      58             :      ulong my_rb_idx( my_rb_node_t const * pool, my_rb_node_t const * node );
      59             :      my_rb_node_t * my_rb_node( my_rb_node_t * pool, ulong idx );
      60             :      my_rb_node_t * my_rb_acquire( my_rb_node_t * pool );
      61             :      void my_rb_release( my_rb_node_t * pool, my_rb_node_t * node );
      62             :      void my_rb_release_tree( my_rb_node_t * pool, my_rb_node_t * root );
      63             :      my_rb_node_t * my_rb_minimum(my_rb_node_t * pool, my_rb_node_t * root);
      64             :      my_rb_node_t * my_rb_maximum(my_rb_node_t * pool, my_rb_node_t * root);
      65             :      my_rb_node_t * my_rb_successor(my_rb_node_t * pool, my_rb_node_t * node);
      66             :      my_rb_node_t * my_rb_predecessor(my_rb_node_t * pool, my_rb_node_t * node);
      67             :      my_rb_node_t * my_rb_insert(my_rb_node_t * pool, my_rb_node_t ** root, my_rb_node_t * x);
      68             :      my_rb_node_t * my_rb_remove(my_rb_node_t * pool, my_rb_node_t ** root, my_rb_node_t * z);
      69             :      my_rb_node_t * my_rb_find(my_rb_node_t * pool, my_rb_node_t * root, my_rb_node_t * key);
      70             :      my_rb_node_t * my_rb_nearby(my_rb_node_t * pool, my_rb_node_t * root, my_rb_node_t * key);
      71             :      ulong my_rb_size(my_rb_node_t * pool, my_rb_node_t * root);
      72             :      int my_rb_verify(my_rb_node_t * pool, my_rb_node_t * root);
      73             :      long my_rb_compare(my_rb_node_t * left, my_rb_node_t * right);
      74             : 
      75             :    The specific usage and semantics of these methods is given below.
      76             : 
      77             :    A sample application is as follows:
      78             : 
      79             :      my_node_t* pool = my_rb_join( my_rb_new( shmem, 20 ) );
      80             :      my_node_t* root = NULL;
      81             :      for (ulong i = 0; i < 10; ++i) {
      82             :        my_node_t * n = my_rb_acquire( pool );
      83             :        n->key = 123 + i;
      84             :        n->value = 456 + i;
      85             :        my_rb_insert( pool, &root, n );
      86             :      }
      87             :      for (ulong i = 0; i < 10; ++i) {
      88             :        my_node_t k;
      89             :        k.key = 123 + i;
      90             :        my_node_t * n = my_rb_find( pool, root, &k );
      91             :        printf("key=%lu value=%lu\n", n->key, n->value);
      92             :        n = my_rb_remove( pool, &root, n );
      93             :        my_rb_release( pool, n );
      94             :      }
      95             :      my_rb_delete( my_rb_leave( pool ) );
      96             : 
      97             :    The application must provided the compare implementation. It must
      98             :    return a negative number, zero, or positive depending on whether
      99             :    the left is less than, equal to, or greater than right. For
     100             :    example:
     101             : 
     102             :      long my_rb_compare(my_node_t* left, my_node_t* right) {
     103             :        return (long)(left->key - right->key);
     104             :      }
     105             : 
     106             : */
     107             : 
     108             : #ifndef REDBLK_NAME
     109             : #define "Define REDBLK_NAME"
     110             : #endif
     111             : 
     112             : #ifndef REDBLK_T
     113             : #define "Define REDBLK_T"
     114             : #endif
     115             : 
     116             : /* 0 - local use only
     117             :    1 - library header declaration
     118             :    2 - library implementation */
     119             : #ifndef REDBLK_IMPL_STYLE
     120             : #define REDBLK_IMPL_STYLE 0
     121             : #endif
     122             : 
     123             : /* Constructors and verification logs detail on failure (rest only needs
     124             :    fd_bits.h, consider making logging a compile time option). */
     125             : 
     126             : #include "../log/fd_log.h"
     127             : 
     128             : /* Namespace macro */
     129 17449261330 : #define REDBLK_(n) FD_EXPAND_THEN_CONCAT3(REDBLK_NAME,_,n)
     130             : 
     131             : #if REDBLK_IMPL_STYLE==1 /* need structures and inlines */
     132             : 
     133             : FD_PROTOTYPES_BEGIN
     134             : 
     135             : /*
     136             :   E.g. ulong my_rb_max_for_footprint( ulong footprint );
     137             : 
     138             :   Return the maximum number of nodes that will fit into a pool with
     139             :   the given footprint.
     140             : */
     141             : FD_FN_CONST ulong REDBLK_(max_for_footprint)( ulong footprint );
     142             : 
     143             : /*
     144             :   E.g. ulong my_rb_align( void );
     145             : 
     146             :   Return the pool alignment.
     147             : */
     148             : FD_FN_CONST ulong REDBLK_(align)( void );
     149             : 
     150             : /*
     151             :   E.g. ulong my_rb_footprint( ulong max );
     152             : 
     153             :   Return the minimum memory footprint needed for a pool with the given
     154             :   number of nodes.
     155             : */
     156             : FD_FN_CONST ulong REDBLK_(footprint)( ulong max );
     157             : 
     158             : /*
     159             :   E.g. void * my_rb_new( void * shmem, ulong max );
     160             : 
     161             :   Initialize an allocation pool.
     162             : */
     163             : void * REDBLK_(new)( void * shmem, ulong max );
     164             : 
     165             : /*
     166             :   E.g. my_rb_node_t * my_rb_join( void * shpool );
     167             : 
     168             :   Join an allocation pool.
     169             : */
     170             : REDBLK_T * REDBLK_(join)( void * shpool );
     171             : 
     172             : /*
     173             :   E.g. void * my_rb_leave( my_rb_node_t * pool );
     174             : 
     175             :   Leave an allocation pool.
     176             : */
     177             : void * REDBLK_(leave)( REDBLK_T * pool );
     178             : 
     179             : /*
     180             :   E.g. void * my_rb_delete( void * shpool );
     181             : 
     182             :   Delete an allocation pool.
     183             : */
     184             : void * REDBLK_(delete)( void * shpool );
     185             : 
     186             : /*
     187             :   E.g. ulong my_rb_max( my_rb_node_t const * pool );
     188             : 
     189             :   Return the max value given when new was called.
     190             : */
     191             : FD_FN_PURE ulong REDBLK_(max)( REDBLK_T const * pool );
     192             : 
     193             : /*
     194             :   E.g. ulong my_rb_free( my_rb_node_t const * pool );
     195             : 
     196             :   Return the number of available nodes in the free pool.
     197             : */
     198             : FD_FN_PURE ulong REDBLK_(free)( REDBLK_T const * pool );
     199             : 
     200             : /*
     201             :   E.g. ulong my_rb_idx( my_rb_node_t const * pool, my_rb_node_t const * node );
     202             : 
     203             :   Return the logical index of the node in a pool. Useful when
     204             :   relocating a pool in memory.
     205             :   */
     206             : FD_FN_CONST ulong REDBLK_(idx)( REDBLK_T const * pool, REDBLK_T const * node );
     207             : 
     208             : /*
     209             :   E.g. my_rb_node_t * my_rb_node( my_rb_node_t * pool, ulong idx );
     210             : 
     211             :   Return the node at a logical index in a pool. Useful when relocating
     212             :   a pool in memory.
     213             : */
     214             : FD_FN_CONST REDBLK_T * REDBLK_(node)( REDBLK_T * pool, ulong idx );
     215             : 
     216             : /*
     217             :   E.g. my_rb_node_t * my_rb_acquire( my_rb_node_t * pool );
     218             : 
     219             :   Acquire a node from the free pool. The result requires
     220             :   initialization before insertion. For example:
     221             : 
     222             :     my_node_t * n = my_rb_acquire( pool );
     223             :     n->key = 123 + i;
     224             :     n->value = 456 + i;
     225             :     my_rb_insert( pool, &root, n );
     226             : */
     227             : REDBLK_T * REDBLK_(acquire)( REDBLK_T * pool );
     228             : 
     229             : /*
     230             :   E.g. void my_rb_release( my_rb_node_t * pool, my_rb_node_t * node );
     231             : 
     232             :   Return a node to the free pool. It must be removed from the tree
     233             :   first. For example:
     234             : 
     235             :     my_node_t * n = my_rb_find( pool, root, &k );
     236             :     n = my_rb_remove( pool, &root, n );
     237             :     my_rb_release( pool, n );
     238             : 
     239             : */
     240             : void REDBLK_(release)( REDBLK_T * pool, REDBLK_T * node );
     241             : 
     242             : /*
     243             :   E.g. void my_rb_release_tree( my_node_t * pool, my_node_t * root );
     244             : 
     245             :   Recursively release all nodes in a tree to a pool. The root argument
     246             :   is invalid after this method is called.
     247             : */
     248             : void REDBLK_(release_tree)( REDBLK_T * pool, REDBLK_T * root );
     249             : 
     250             : /*
     251             :   E.g. my_node_t * my_rb_minimum(my_node_t * pool, my_node_t * root);
     252             : 
     253             :   Return the node in a tree that has the smallest key (leftmost).
     254             : */
     255             : REDBLK_T * REDBLK_(minimum)(REDBLK_T * pool, REDBLK_T * root);
     256             : REDBLK_T const * REDBLK_(minimum_const)(REDBLK_T const * pool, REDBLK_T const * root);
     257             : 
     258             : /*
     259             :   E.g. my_node_t * my_rb_maximum(my_node_t * pool, my_node_t * root);
     260             : 
     261             :   Return the node in a tree that has the largest key (rightmost).
     262             : */
     263             : REDBLK_T * REDBLK_(maximum)(REDBLK_T * pool, REDBLK_T * root);
     264             : REDBLK_T const * REDBLK_(maximum_const)(REDBLK_T const * pool, REDBLK_T const * root);
     265             : 
     266             : /*
     267             :   E.g. my_node_t * my_rb_successor(my_node_t * pool, my_node_t * node);
     268             : 
     269             :   Return the next node which is larger than the given node. To iterate
     270             :   across the entire tree, do the following:
     271             : 
     272             :     for ( my_node_t* n = my_rb_minimum(pool, root); n; n = my_rb_successor(pool, n) ) {
     273             :       printf("key=%lu value=%lu\n", n->key, n->value);
     274             :     }
     275             : 
     276             :   To iterate safely while also deleting, do:
     277             : 
     278             :     my_node_t* nn;
     279             :     for ( my_node_t* n = my_rb_minimum(pool, root); n; n = nn ) {
     280             :       nn = my_rb_successor(pool, n);
     281             :       // Possibly delete n
     282             :     }
     283             : */
     284             : REDBLK_T * REDBLK_(successor)(REDBLK_T * pool, REDBLK_T * node);
     285             : REDBLK_T const * REDBLK_(successor_const)(REDBLK_T const * pool, REDBLK_T const * node);
     286             : /*
     287             :   E.g. my_node_t * my_rb_predecessor(my_node_t * pool, my_node_t * node);
     288             : 
     289             :   Return the previous node which is smaller than the given node. To iterate
     290             :   across the entire tree backwards, do the following:
     291             : 
     292             :     for ( my_node_t* n = my_rb_maximum(pool, root); n; n = my_rb_predecessor(pool, n) ) {
     293             :       printf("key=%lu value=%lu\n", n->key, n->value);
     294             :     }
     295             : 
     296             :   To iterate safely while also deleting, do:
     297             : 
     298             :     my_node_t* nn;
     299             :     for ( my_node_t* n = my_rb_maximum(pool, root); n; n = nn ) {
     300             :       nn = my_rb_predecessor(pool, n);
     301             :       // Possibly delete n
     302             :     }
     303             : */
     304             : REDBLK_T * REDBLK_(predecessor)(REDBLK_T * pool, REDBLK_T * node);
     305             : /*
     306             :   E.g. my_node_t * my_rb_insert(my_node_t * pool, my_node_t ** root, my_node_t * x);
     307             : 
     308             :   Insert a node into a tree. Typically, the node must be allocated
     309             :   from a pool first. The application must initialize any values in the
     310             :   node after allocation but before insertion. For example:
     311             : 
     312             :     my_node_t * n = my_rb_acquire( pool );
     313             :     n->key = 123;
     314             :     n->value = 456;
     315             :     n = my_rb_insert( pool, &root, n );
     316             : 
     317             :   The inserted node is returned.
     318             : */
     319             : REDBLK_T * REDBLK_(insert)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x);
     320             : /*
     321             :   E.g. my_node_t * my_rb_remove(my_node_t * pool, my_node_t ** root, my_node_t * z);
     322             : 
     323             :   Remove a node from a tree. The node must be a member of the tree,
     324             :   usually the result of a find operation. The node is typically
     325             :   released to the pool afterwards. For example:
     326             : 
     327             :     my_node_t * n = my_rb_find( pool, root, &k );
     328             :     n = my_rb_remove( pool, &root, n );
     329             :     my_rb_pool_release( pool, n );
     330             : 
     331             :   Remove and release are separate steps to allow an application to
     332             :   perform final cleanup on the node in between. You can insert a node
     333             :   into a different tree after deletion if both trees share a pool. For
     334             :   example:
     335             : 
     336             :     n = my_rb_remove( pool, &root, n );
     337             :     my_rb_insert( pool, &root2, n );
     338             : */
     339             : REDBLK_T * REDBLK_(remove)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * z);
     340             : /*
     341             :   E.g. my_node_t * my_rb_find(my_node_t * pool, my_node_t * root, my_node_t * key);
     342             : 
     343             :   Search for a key in the tree. In this special case, the key can be a
     344             :   temporary instance of the node type rather than a properly
     345             :   allocated node. For example:
     346             : 
     347             :     my_node_t k;
     348             :     k.key = 123 + i;
     349             :     my_node_t * n = my_rb_find( pool, root, &k );
     350             :     printf("key=%lu value=%lu\n", n->key, n->value);
     351             : 
     352             :   A NULL is returned if the find fails.
     353             : */
     354             : REDBLK_T * REDBLK_(find)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key);
     355             : /*
     356             :   E.g. my_node_t * my_rb_nearby(my_node_t * pool, my_node_t * root, my_node_t * key);
     357             : 
     358             :   Search for a key in the tree. If the key can't be found, a nearby
     359             :   approximation is returned instead. This is either the greatest node
     360             :   less than the key, or the least node greater than the key. In this
     361             :   special case, the key can be a temporary instance of the node type
     362             :   rather than a properly allocated node. For example:
     363             : 
     364             :     my_node_t k;
     365             :     k.key = 123 + i;
     366             :     my_node_t * n = my_rb_nearby( pool, root, &k );
     367             :     printf("key=%lu value=%lu\n", n->key, n->value);
     368             : 
     369             :   A NULL is returned if the search fails.
     370             : */
     371             : REDBLK_T * REDBLK_(nearby)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key);
     372             : /*
     373             :   E.g. ulong my_rb_size(my_node_t * pool, my_node_t * root);
     374             : 
     375             :   Count the number of nodes in a tree.
     376             : */
     377             : ulong REDBLK_(size)(REDBLK_T * pool, REDBLK_T * root);
     378             : 
     379             : /*
     380             :   E.g. int my_rb_verify(my_node_t * pool, my_node_t * root);
     381             : 
     382             :   Verify the integrity of the tree data structure. Useful for
     383             :   debugging memory corruption. A non-zero result is returned if an error
     384             :   is detected.
     385             : */
     386             : int REDBLK_(verify)(REDBLK_T * pool, REDBLK_T * root);
     387             : 
     388             : /*
     389             :   E.g. long my_rb_compare(my_node_t * left, my_node_t * right);
     390             : 
     391             :   Defined by application to implement key comparison. Returns a
     392             :   negative number, zero, or positive depending on whether the left is
     393             :   less than, equal to, or greater than right. For example:
     394             : 
     395             :     long my_rb_compare(my_node_t* left, my_node_t* right) {
     396             :       return (long)(left->key - right->key);
     397             :     }
     398             : 
     399             :   Should be a pure function.  (FIXME: SHOULD TAKE CONST POINTERS?)
     400             : */
     401             : FD_FN_PURE long REDBLK_(compare)(REDBLK_T * left, REDBLK_T * right);
     402             : 
     403             : FD_PROTOTYPES_END
     404             : 
     405             : #endif /* REDBLK_IMPL_STYLE==0 || REDBLK_IMPL_STYLE==1 */
     406             : 
     407             : #if REDBLK_IMPL_STYLE==0 /* local only */
     408             : #define REDBLK_IMPL_STATIC FD_FN_UNUSED static
     409             : #else
     410             : #define REDBLK_IMPL_STATIC
     411             : #endif
     412             : 
     413             : #if REDBLK_IMPL_STYLE==0 || REDBLK_IMPL_STYLE==2 /* need implementations */
     414             : 
     415             : /* Tree node colors */
     416  7240485738 : #define REDBLK_FREE -1
     417   335659317 : #define REDBLK_NEW 0
     418  3519645278 : #define REDBLK_BLACK 1
     419  1057912084 : #define REDBLK_RED 2
     420             : 
     421             : #ifndef REDBLK_PARENT
     422   102213567 : #define REDBLK_PARENT redblack_parent
     423             : #endif
     424             : #ifndef REDBLK_LEFT
     425   255942429 : #define REDBLK_LEFT redblack_left
     426             : #endif
     427             : #ifndef REDBLK_RIGHT
     428   410253558 : #define REDBLK_RIGHT redblack_right
     429             : #endif
     430             : #ifndef REDBLK_COLOR
     431   315917442 : #define REDBLK_COLOR redblack_color
     432             : #endif
     433             : 
     434             : #define POOL_NAME FD_EXPAND_THEN_CONCAT2(REDBLK_NAME,_pool)
     435     3721764 : #define POOL_T REDBLK_T
     436             : #define POOL_SENTINEL 1
     437             : #ifdef REDBLK_NEXTFREE
     438   435485649 : #define POOL_NEXT REDBLK_NEXTFREE
     439             : #else
     440   173362530 : #define POOL_NEXT REDBLK_RIGHT
     441             : #endif
     442             : #include "fd_pool.c"
     443             : #undef MAP_POOL_NAME
     444             : #undef MAP_POOL_T
     445             : 
     446  7734985044 : #define REDBLK_POOL_(n) FD_EXPAND_THEN_CONCAT3(REDBLK_NAME,_pool_,n)
     447             : 
     448 17482294597 : #define REDBLK_NIL 0UL /* Must be same as pool sentinel */
     449             : 
     450           6 : REDBLK_IMPL_STATIC ulong REDBLK_(max_for_footprint)( ulong footprint ) {
     451           6 :   return REDBLK_POOL_(max_for_footprint)(footprint) - 1; /* Allow for sentinel */
     452           6 : }
     453             : 
     454     1644189 : REDBLK_IMPL_STATIC ulong REDBLK_(align)( void ) {
     455     1644189 :   return REDBLK_POOL_(align)();
     456     1644189 : }
     457             : 
     458     1644195 : REDBLK_IMPL_STATIC ulong REDBLK_(footprint)( ulong max ) {
     459     1644195 :   return REDBLK_POOL_(footprint)(max + 1); /* Allow for sentinel */
     460     1644195 : }
     461             : 
     462     1236336 : REDBLK_IMPL_STATIC void * REDBLK_(new)( void * shmem, ulong max ) {
     463     1236336 :   void * shmem2 = REDBLK_POOL_(new)(shmem, max + 1); /* Allow for sentinel */
     464     1236336 :   if ( FD_UNLIKELY( shmem2 == NULL ) )
     465           0 :     return NULL;
     466             :   /* Initialize sentinel */
     467     1236336 :   REDBLK_T * pool = REDBLK_POOL_(join)(shmem2);
     468     1236336 :   if ( FD_UNLIKELY( pool == NULL ) )
     469           0 :     return NULL;
     470     1236336 :   REDBLK_T * node = REDBLK_POOL_(ele_sentinel)(pool);
     471     1236336 :   node->REDBLK_LEFT = REDBLK_NIL;
     472     1236336 :   node->REDBLK_RIGHT = REDBLK_NIL;
     473     1236336 :   node->REDBLK_PARENT = REDBLK_NIL;
     474     1236336 :   node->REDBLK_COLOR = REDBLK_BLACK;
     475     1236336 :   return shmem2;
     476     1236336 : }
     477             : 
     478     1236345 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(join)( void * shpool ) {
     479     1236345 :   FD_COMPILER_MFENCE();
     480     1236345 :   return REDBLK_POOL_(join)(shpool);
     481     1236345 : }
     482             : 
     483     4078605 : REDBLK_IMPL_STATIC void * REDBLK_(leave)( REDBLK_T * pool ) {
     484     4078605 :   FD_COMPILER_MFENCE();
     485     4078605 :   return REDBLK_POOL_(leave)(pool);
     486     4078605 : }
     487             : 
     488     4078596 : REDBLK_IMPL_STATIC void * REDBLK_(delete)( void * shpool ) {
     489     4078596 :   FD_COMPILER_MFENCE();
     490     4078596 :   return REDBLK_POOL_(delete)(shpool);
     491     4078596 : }
     492             : 
     493          15 : REDBLK_IMPL_STATIC ulong REDBLK_(max)( REDBLK_T const * pool ) {
     494          15 :   return REDBLK_POOL_(max)(pool) - 1; /* Allow for sentinel */
     495          15 : }
     496             : 
     497          69 : REDBLK_IMPL_STATIC ulong REDBLK_(free)( REDBLK_T const * pool ) {
     498          69 :   return REDBLK_POOL_(free)(pool);
     499          69 : }
     500             : 
     501           9 : REDBLK_IMPL_STATIC ulong REDBLK_(idx)( REDBLK_T const * pool, REDBLK_T const * node ) {
     502           9 :   return REDBLK_POOL_(idx)(pool, node);
     503           9 : }
     504             : 
     505           9 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(node)( REDBLK_T * pool, ulong idx ) {
     506           9 :   return REDBLK_POOL_(ele)(pool, idx);
     507           9 : }
     508             : 
     509   222711678 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(acquire)( REDBLK_T * pool ) {
     510   222711678 :   if ( REDBLK_POOL_(free)( pool ) == 0 )
     511        3009 :     return NULL;
     512   222708669 :   REDBLK_T * node = REDBLK_POOL_(ele_acquire)(pool);
     513   222708669 :   node->REDBLK_COLOR = REDBLK_NEW;
     514   222708669 :   return node;
     515   222711678 : }
     516             : 
     517             : #ifndef REDBLK_UNSAFE
     518  7051331523 : REDBLK_IMPL_STATIC void REDBLK_(validate_element)( REDBLK_T * pool, REDBLK_T * node ) {
     519  7051331523 :   if ( !REDBLK_POOL_(ele_test)( pool, node ) )
     520           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     521  7051331523 :   if ( node && node->REDBLK_COLOR == REDBLK_FREE )
     522           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     523  7051331523 : }
     524           0 : REDBLK_IMPL_STATIC void REDBLK_(validate_element_const)( REDBLK_T const * pool, REDBLK_T const * node ) {
     525           0 :   if ( !REDBLK_POOL_(ele_test)( pool, node ) )
     526           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     527           0 :   if ( node && node->REDBLK_COLOR == REDBLK_FREE )
     528           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     529           0 : }
     530             : #endif
     531             : 
     532   221842128 : REDBLK_IMPL_STATIC void REDBLK_(release)( REDBLK_T * pool, REDBLK_T * node ) {
     533   221842128 : #ifndef REDBLK_UNSAFE
     534   221842128 :   REDBLK_(validate_element)(pool, node);
     535   221842128 : #endif
     536             : 
     537   221842128 :   node->REDBLK_COLOR = REDBLK_FREE;
     538   221842128 :   REDBLK_POOL_(ele_release)(pool, node);
     539   221842128 : }
     540             : 
     541             : /*
     542             :   Recursively release all nodes in a tree to a pool. The root argument
     543             :   is invalid after this method is called.
     544             : */
     545   239555949 : REDBLK_IMPL_STATIC void REDBLK_(release_tree)( REDBLK_T * pool, REDBLK_T * node ) {
     546   239555949 :   if (!node || node == &pool[REDBLK_NIL])
     547   130664469 :     return;
     548             : 
     549   108891480 : #ifndef REDBLK_UNSAFE
     550   108891480 :   REDBLK_(validate_element)(pool, node);
     551   108891480 : #endif
     552             : 
     553   108891480 :   REDBLK_T * left = &pool[node->REDBLK_LEFT];
     554   108891480 :   REDBLK_T * right = &pool[node->REDBLK_RIGHT];
     555             : 
     556   108891480 :   REDBLK_(release)(pool, node);
     557             : 
     558   108891480 :   REDBLK_(release_tree)(pool, left);
     559   108891480 :   REDBLK_(release_tree)(pool, right);
     560   108891480 : }
     561             : 
     562             : /*
     563             :   Return the node in a tree that has the smallest key (leftmost).
     564             : */
     565     6573861 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(minimum)(REDBLK_T * pool, REDBLK_T * node) {
     566     6573861 :   if (!node || node == &pool[REDBLK_NIL])
     567     4081290 :     return NULL;
     568     2492571 : #ifndef REDBLK_UNSAFE
     569     2492571 :   REDBLK_(validate_element)(pool, node);
     570     2492571 : #endif
     571     4966503 :   while (node->REDBLK_LEFT != REDBLK_NIL) {
     572     2473932 :     node = &pool[node->REDBLK_LEFT];
     573     2473932 :   }
     574     2492571 :   return node;
     575     6573861 : }
     576           0 : REDBLK_IMPL_STATIC REDBLK_T const * REDBLK_(minimum_const)(REDBLK_T const * pool, REDBLK_T const * node) {
     577           0 :   if (!node || node == &pool[REDBLK_NIL])
     578           0 :     return NULL;
     579           0 : #ifndef REDBLK_UNSAFE
     580           0 :   REDBLK_(validate_element_const)(pool, node);
     581           0 : #endif
     582           0 :   while (node->REDBLK_LEFT != REDBLK_NIL) {
     583           0 :     node = &pool[node->REDBLK_LEFT];
     584           0 :   }
     585           0 :   return node;
     586           0 : }
     587             : 
     588             : /*
     589             :   Return the node in a tree that has the largest key (rightmost).
     590             : */
     591     2041752 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(maximum)(REDBLK_T * pool, REDBLK_T * node) {
     592     2041752 :   if (!node || node == &pool[REDBLK_NIL])
     593           0 :     return NULL;
     594     2041752 : #ifndef REDBLK_UNSAFE
     595     2041752 :   REDBLK_(validate_element)(pool, node);
     596     2041752 : #endif
     597     4083000 :   while (node->REDBLK_RIGHT != REDBLK_NIL) {
     598     2041248 :     node = &pool[node->REDBLK_RIGHT];
     599     2041248 :   }
     600     2041752 :   return node;
     601     2041752 : }
     602           0 : REDBLK_IMPL_STATIC REDBLK_T const * REDBLK_(maximum_const)(REDBLK_T const * pool, REDBLK_T const * node) {
     603           0 :   if (!node || node == &pool[REDBLK_NIL])
     604           0 :     return NULL;
     605           0 : #ifndef REDBLK_UNSAFE
     606           0 :   REDBLK_(validate_element_const)(pool, node);
     607           0 : #endif
     608           0 :   while (node->REDBLK_RIGHT != REDBLK_NIL) {
     609           0 :     node = &pool[node->REDBLK_RIGHT];
     610           0 :   }
     611           0 :   return node;
     612           0 : }
     613             : 
     614             : /*
     615             :   Return the next node which is larger than the given node.
     616             : */
     617     4966488 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(successor)(REDBLK_T * pool, REDBLK_T * x) {
     618     4966488 : #ifndef REDBLK_UNSAFE
     619     4966488 :   REDBLK_(validate_element)(pool, x);
     620     4966488 : #endif
     621             : 
     622             :   // if the right subtree is not null,
     623             :   // the successor is the leftmost node in the
     624             :   // right subtree
     625     4966488 :   if (x->REDBLK_RIGHT != REDBLK_NIL) {
     626     2476779 :     return REDBLK_(minimum)(pool, &pool[x->REDBLK_RIGHT]);
     627     2476779 :   }
     628             : 
     629             :   // else it is the lowest ancestor of x whose
     630             :   // left child is also an ancestor of x.
     631     4966488 :   for (;;) {
     632     4966488 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     633       15780 :       return NULL;
     634     4950708 :     REDBLK_T * y = &pool[x->REDBLK_PARENT];
     635     4950708 :     if (x == &pool[y->REDBLK_LEFT])
     636     2473929 :       return y;
     637     2476779 :     x = y;
     638     2476779 :   }
     639     2489709 : }
     640           0 : REDBLK_IMPL_STATIC REDBLK_T const * REDBLK_(successor_const)(REDBLK_T const * pool, REDBLK_T const * x) {
     641           0 : #ifndef REDBLK_UNSAFE
     642           0 :   REDBLK_(validate_element_const)(pool, x);
     643           0 : #endif
     644             : 
     645             :   // if the right subtree is not null,
     646             :   // the successor is the leftmost node in the
     647             :   // right subtree
     648           0 :   if (x->REDBLK_RIGHT != REDBLK_NIL) {
     649           0 :     return REDBLK_(minimum_const)(pool, &pool[x->REDBLK_RIGHT]);
     650           0 :   }
     651             : 
     652             :   // else it is the lowest ancestor of x whose
     653             :   // left child is also an ancestor of x.
     654           0 :   for (;;) {
     655           0 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     656           0 :       return NULL;
     657           0 :     REDBLK_T const * y = &pool[x->REDBLK_PARENT];
     658           0 :     if (x == &pool[y->REDBLK_LEFT])
     659           0 :       return y;
     660           0 :     x = y;
     661           0 :   }
     662           0 : }
     663             : 
     664             : /*
     665             :   Return the previous node which is smaller than the given node.
     666             : */
     667     4083000 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(predecessor)(REDBLK_T * pool, REDBLK_T * x) {
     668     4083000 : #ifndef REDBLK_UNSAFE
     669     4083000 :   REDBLK_(validate_element)(pool, x);
     670     4083000 : #endif
     671             : 
     672             :   // if the left subtree is not null,
     673             :   // the predecessor is the rightmost node in the
     674             :   // left subtree
     675     4083000 :   if (x->REDBLK_LEFT != REDBLK_NIL) {
     676     2038752 :     return REDBLK_(maximum)(pool, &pool[x->REDBLK_LEFT]);
     677     2038752 :   }
     678             : 
     679             :   // else it is the lowest ancestor of x whose
     680             :   // right child is also an ancestor of x.
     681     4083000 :   for (;;) {
     682     4083000 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     683        3000 :       return NULL;
     684     4080000 :     REDBLK_T * y = &pool[x->REDBLK_PARENT];
     685     4080000 :     if (x == &pool[y->REDBLK_RIGHT])
     686     2041248 :       return y;
     687     2038752 :     x = y;
     688     2038752 :   }
     689     2044248 : }
     690           0 : REDBLK_IMPL_STATIC REDBLK_T const * REDBLK_(predecessor_const)(REDBLK_T const * pool, REDBLK_T const * x) {
     691           0 : #ifndef REDBLK_UNSAFE
     692           0 :   REDBLK_(validate_element_const)(pool, x);
     693           0 : #endif
     694             : 
     695             :   // if the left subtree is not null,
     696             :   // the predecessor is the rightmost node in the
     697             :   // left subtree
     698           0 :   if (x->REDBLK_LEFT != REDBLK_NIL) {
     699           0 :     return REDBLK_(maximum_const)(pool, &pool[x->REDBLK_LEFT]);
     700           0 :   }
     701             : 
     702             :   // else it is the lowest ancestor of x whose
     703             :   // right child is also an ancestor of x.
     704           0 :   for (;;) {
     705           0 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     706           0 :       return NULL;
     707           0 :     REDBLK_T const * y = &pool[x->REDBLK_PARENT];
     708           0 :     if (x == &pool[y->REDBLK_RIGHT])
     709           0 :       return y;
     710           0 :     x = y;
     711           0 :   }
     712           0 : }
     713             : 
     714             : /*
     715             :   Perform a left rotation around a node
     716             : */
     717    98537289 : static void REDBLK_(rotateLeft)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     718    98537289 :   REDBLK_T * y = &pool[x->REDBLK_RIGHT];
     719             : 
     720             :   /* establish x->REDBLK_RIGHT link */
     721    98537289 :   x->REDBLK_RIGHT = y->REDBLK_LEFT;
     722    98537289 :   if (y->REDBLK_LEFT != REDBLK_NIL)
     723    24209578 :     pool[y->REDBLK_LEFT].REDBLK_PARENT = (uint)(x - pool);
     724             : 
     725             :   /* establish y->REDBLK_PARENT link */
     726    98537289 :   if (y != &pool[REDBLK_NIL])
     727    98537289 :     y->REDBLK_PARENT = x->REDBLK_PARENT;
     728    98537289 :   if (x->REDBLK_PARENT) {
     729    63718654 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     730    63718654 :     if (x == &pool[p->REDBLK_LEFT])
     731    17128997 :       p->REDBLK_LEFT = (uint)(y - pool);
     732    46589657 :     else
     733    46589657 :       p->REDBLK_RIGHT = (uint)(y - pool);
     734    63718654 :   } else {
     735    34818635 :     *root = y;
     736    34818635 :   }
     737             : 
     738             :   /* link x and y */
     739    98537289 :   y->REDBLK_LEFT = (uint)(x - pool);
     740    98537289 :   if (x != &pool[REDBLK_NIL])
     741    98537289 :     x->REDBLK_PARENT = (uint)(y - pool);
     742    98537289 : }
     743             : 
     744             : /*
     745             :   Perform a right rotation around a node
     746             : */
     747    34662819 : static void REDBLK_(rotateRight)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     748    34662819 :   REDBLK_T * y = &pool[x->REDBLK_LEFT];
     749             : 
     750             :   /* establish x->REDBLK_LEFT link */
     751    34662819 :   x->REDBLK_LEFT = y->REDBLK_RIGHT;
     752    34662819 :   if (y->REDBLK_RIGHT != REDBLK_NIL)
     753     5561997 :     pool[y->REDBLK_RIGHT].REDBLK_PARENT = (uint)(x - pool);
     754             : 
     755             :   /* establish y->REDBLK_PARENT link */
     756    34662819 :   if (y != &pool[REDBLK_NIL])
     757    34662819 :     y->REDBLK_PARENT = x->REDBLK_PARENT;
     758    34662819 :   if (x->REDBLK_PARENT) {
     759    24535729 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     760    24535729 :     if (x == &pool[p->REDBLK_RIGHT])
     761    16422924 :       p->REDBLK_RIGHT = (uint)(y - pool);
     762     8112805 :     else
     763     8112805 :       p->REDBLK_LEFT = (uint)(y - pool);
     764    24535729 :   } else {
     765    10127090 :     *root = y;
     766    10127090 :   }
     767             : 
     768             :   /* link x and y */
     769    34662819 :   y->REDBLK_RIGHT = (uint)(x - pool);
     770    34662819 :   if (x != &pool[REDBLK_NIL])
     771    34662819 :     x->REDBLK_PARENT = (uint)(y - pool);
     772    34662819 : }
     773             : 
     774             : /*
     775             :   Restore tree invariants after an insert.
     776             : */
     777   222708669 : static void REDBLK_(insertFixup)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     778             :   /* check Red-Black properties */
     779   222708669 :   REDBLK_T * p;
     780   397906283 :   while (x != *root && (p = &pool[x->REDBLK_PARENT])->REDBLK_COLOR == REDBLK_RED) {
     781             :     /* we have a violation */
     782   175197614 :     REDBLK_T * gp = &pool[p->REDBLK_PARENT];
     783   175197614 :     if (x->REDBLK_PARENT == gp->REDBLK_LEFT) {
     784    33164562 :       REDBLK_T * y = &pool[gp->REDBLK_RIGHT];
     785    33164562 :       if (y->REDBLK_COLOR == REDBLK_RED) {
     786             : 
     787             :         /* uncle is REDBLK_RED */
     788    16404519 :         p->REDBLK_COLOR = REDBLK_BLACK;
     789    16404519 :         y->REDBLK_COLOR = REDBLK_BLACK;
     790    16404519 :         gp->REDBLK_COLOR = REDBLK_RED;
     791    16404519 :         x = gp;
     792    16760043 :       } else {
     793             : 
     794             :         /* uncle is REDBLK_BLACK */
     795    16760043 :         if (x == &pool[p->REDBLK_RIGHT]) {
     796             :           /* make x a left child */
     797     8376788 :           x = p;
     798     8376788 :           REDBLK_(rotateLeft)(pool, root, x);
     799     8376788 :           p = &pool[x->REDBLK_PARENT];
     800     8376788 :           gp = &pool[p->REDBLK_PARENT];
     801     8376788 :         }
     802             : 
     803             :         /* recolor and rotate */
     804    16760043 :         p->REDBLK_COLOR = REDBLK_BLACK;
     805    16760043 :         gp->REDBLK_COLOR = REDBLK_RED;
     806    16760043 :         REDBLK_(rotateRight)(pool, root, gp);
     807    16760043 :       }
     808             : 
     809   142033052 :     } else {
     810             :       /* mirror image of above code */
     811   142033052 :       REDBLK_T * y = &pool[gp->REDBLK_LEFT];
     812   142033052 :       if (y->REDBLK_COLOR == REDBLK_RED) {
     813             : 
     814             :         /* uncle is REDBLK_RED */
     815    70837021 :         p->REDBLK_COLOR = REDBLK_BLACK;
     816    70837021 :         y->REDBLK_COLOR = REDBLK_BLACK;
     817    70837021 :         gp->REDBLK_COLOR = REDBLK_RED;
     818    70837021 :         x = gp;
     819    71196031 :       } else {
     820             : 
     821             :         /* uncle is REDBLK_BLACK */
     822    71196031 :         if (x == &pool[p->REDBLK_LEFT]) {
     823     8376374 :           x = p;
     824     8376374 :           REDBLK_(rotateRight)(pool, root, x);
     825     8376374 :           p = &pool[x->REDBLK_PARENT];
     826     8376374 :           gp = &pool[p->REDBLK_PARENT];
     827     8376374 :         }
     828    71196031 :         p->REDBLK_COLOR = REDBLK_BLACK;
     829    71196031 :         gp->REDBLK_COLOR = REDBLK_RED;
     830    71196031 :         REDBLK_(rotateLeft)(pool, root, gp);
     831    71196031 :       }
     832   142033052 :     }
     833   175197614 :   }
     834             : 
     835   222708669 :   (*root)->REDBLK_COLOR = REDBLK_BLACK;
     836   222708669 : }
     837             : 
     838             : /*
     839             :   Insert a node into a tree. Typically, the node must be allocated
     840             :   from a pool first.
     841             : */
     842   222708669 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(insert)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     843   222708669 : #ifndef REDBLK_UNSAFE
     844   222708669 :   REDBLK_(validate_element)(pool, *root);
     845   222708669 :   REDBLK_(validate_element)(pool, x);
     846   222708669 : #endif
     847             : 
     848   222708669 :   REDBLK_T * current;
     849   222708669 :   REDBLK_T * parent;
     850             : 
     851             :   /* find where node belongs */
     852   222708669 :   current = *root;
     853   222708669 :   if (current == NULL)
     854    21788718 :     current = &pool[REDBLK_NIL];
     855   222708669 :   parent = &pool[REDBLK_NIL];
     856   804867294 :   while (current != &pool[REDBLK_NIL]) {
     857   582158625 :     long c = REDBLK_(compare)(x, current);
     858   582158625 :     parent = current;
     859   582158625 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
     860   582158625 :   }
     861             : 
     862             :   /* setup new node */
     863   222708669 :   x->REDBLK_PARENT = (uint)(parent - pool);
     864   222708669 :   x->REDBLK_LEFT = REDBLK_NIL;
     865   222708669 :   x->REDBLK_RIGHT = REDBLK_NIL;
     866   222708669 :   x->REDBLK_COLOR = REDBLK_RED;
     867             : 
     868             :   /* insert node in tree */
     869   222708669 :   if (parent != &pool[REDBLK_NIL]) {
     870   200919951 :     long c = REDBLK_(compare)(x, parent);
     871   200919951 :     if (c < 0)
     872    51466511 :       parent->REDBLK_LEFT = (uint)(x - pool);
     873   149453440 :     else
     874   149453440 :       parent->REDBLK_RIGHT = (uint)(x - pool);
     875   200919951 :   } else {
     876    21788718 :     *root = x;
     877    21788718 :   }
     878             : 
     879   222708669 :   REDBLK_(insertFixup)(pool, root, x);
     880   222708669 :   return x;
     881   222708669 : }
     882             : 
     883             : /*
     884             :   Restore tree invariants after a delete
     885             : */
     886    92124657 : static void REDBLK_(deleteFixup)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     887   166922274 :   while (x != *root && x->REDBLK_COLOR == REDBLK_BLACK) {
     888    74797617 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     889    74797617 :     if (x == &pool[p->REDBLK_LEFT]) {
     890    37308685 :       REDBLK_T * w = &pool[p->REDBLK_RIGHT];
     891    37308685 :       if (w->REDBLK_COLOR == REDBLK_RED) {
     892     4179985 :         w->REDBLK_COLOR = REDBLK_BLACK;
     893     4179985 :         p->REDBLK_COLOR = REDBLK_RED;
     894     4179985 :         REDBLK_(rotateLeft)(pool, root, p);
     895     4179985 :         p = &pool[x->REDBLK_PARENT];
     896     4179985 :         w = &pool[p->REDBLK_RIGHT];
     897     4179985 :       }
     898    37308685 :       if (pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK &&
     899    37308685 :          pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK) {
     900    25543674 :         w->REDBLK_COLOR = REDBLK_RED;
     901    25543674 :         x = p;
     902    25543674 :       } else {
     903    11765011 :         if (pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK) {
     904     1505681 :           pool[w->REDBLK_LEFT].REDBLK_COLOR = REDBLK_BLACK;
     905     1505681 :           w->REDBLK_COLOR = REDBLK_RED;
     906     1505681 :           REDBLK_(rotateRight)(pool, root, w);
     907     1505681 :           p = &pool[x->REDBLK_PARENT];
     908     1505681 :           w = &pool[p->REDBLK_RIGHT];
     909     1505681 :         }
     910    11765011 :         w->REDBLK_COLOR = p->REDBLK_COLOR;
     911    11765011 :         p->REDBLK_COLOR = REDBLK_BLACK;
     912    11765011 :         pool[w->REDBLK_RIGHT].REDBLK_COLOR = REDBLK_BLACK;
     913    11765011 :         REDBLK_(rotateLeft)(pool, root, p);
     914    11765011 :         x = *root;
     915    11765011 :       }
     916             : 
     917    37488932 :     } else {
     918    37488932 :       REDBLK_T * w = &pool[p->REDBLK_LEFT];
     919    37488932 :       if (w->REDBLK_COLOR == REDBLK_RED) {
     920     1499667 :         w->REDBLK_COLOR = REDBLK_BLACK;
     921     1499667 :         p->REDBLK_COLOR = REDBLK_RED;
     922     1499667 :         REDBLK_(rotateRight)(pool, root, p);
     923     1499667 :         p = &pool[x->REDBLK_PARENT];
     924     1499667 :         w = &pool[p->REDBLK_LEFT];
     925     1499667 :       }
     926    37488932 :       if (pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK &&
     927    37488932 :           pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK) {
     928    30967878 :         w->REDBLK_COLOR = REDBLK_RED;
     929    30967878 :         x = p;
     930    30967878 :       } else {
     931     6521054 :         if (pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK) {
     932     3019474 :           pool[w->REDBLK_RIGHT].REDBLK_COLOR = REDBLK_BLACK;
     933     3019474 :           w->REDBLK_COLOR = REDBLK_RED;
     934     3019474 :           REDBLK_(rotateLeft)(pool, root, w);
     935     3019474 :           p = &pool[x->REDBLK_PARENT];
     936     3019474 :           w = &pool[p->REDBLK_LEFT];
     937     3019474 :         }
     938     6521054 :         w->REDBLK_COLOR = p->REDBLK_COLOR;
     939     6521054 :         p->REDBLK_COLOR = REDBLK_BLACK;
     940     6521054 :         pool[w->REDBLK_LEFT].REDBLK_COLOR = REDBLK_BLACK;
     941     6521054 :         REDBLK_(rotateRight)(pool, root, p);
     942     6521054 :         x = *root;
     943     6521054 :       }
     944    37488932 :     }
     945    74797617 :   }
     946             : 
     947    92124657 :   x->REDBLK_COLOR = REDBLK_BLACK;
     948    92124657 : }
     949             : 
     950             : /*
     951             :   Remove a node from a tree. The node must be a member of the tree,
     952             :   usually the result of a find operation. The node is typically
     953             :   released to the pool afterwards.
     954             : */
     955   112950648 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(remove)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * z) {
     956   112950648 : #ifndef REDBLK_UNSAFE
     957   112950648 :   REDBLK_(validate_element)(pool, *root);
     958   112950648 :   REDBLK_(validate_element)(pool, z);
     959   112950648 : #endif
     960             : 
     961   112950648 :   REDBLK_T * x;
     962   112950648 :   REDBLK_T * y;
     963             : 
     964   112950648 :   if (!z || z == &pool[REDBLK_NIL])
     965           0 :     return NULL;
     966             : 
     967   112950648 :   if (z->REDBLK_LEFT == REDBLK_NIL || z->REDBLK_RIGHT == REDBLK_NIL) {
     968             :     /* y has a REDBLK_NIL node as a child */
     969    81489266 :     y = z;
     970    81489266 :   } else {
     971             :     /* find tree successor with a REDBLK_NIL node as a child */
     972    31461382 :     y = &pool[z->REDBLK_RIGHT];
     973    43608918 :     while (y->REDBLK_LEFT != REDBLK_NIL)
     974    12147536 :       y = &pool[y->REDBLK_LEFT];
     975    31461382 :   }
     976             : 
     977             :   /* x is y's only child */
     978   112950648 :   if (y->REDBLK_LEFT != REDBLK_NIL)
     979     9310926 :     x = &pool[y->REDBLK_LEFT];
     980   103639722 :   else
     981   103639722 :     x = &pool[y->REDBLK_RIGHT];
     982             : 
     983             :   /* remove y from the parent chain */
     984   112950648 :   x->REDBLK_PARENT = y->REDBLK_PARENT;
     985   112950648 :   if (y->REDBLK_PARENT)
     986    96616488 :     if (y == &pool[pool[y->REDBLK_PARENT].REDBLK_LEFT])
     987    45041392 :       pool[y->REDBLK_PARENT].REDBLK_LEFT = (uint)(x - pool);
     988    51575096 :     else
     989    51575096 :       pool[y->REDBLK_PARENT].REDBLK_RIGHT = (uint)(x - pool);
     990    16334160 :   else
     991    16334160 :     *root = x;
     992             : 
     993   112950648 :   if (y->REDBLK_COLOR == REDBLK_BLACK)
     994    92124657 :     REDBLK_(deleteFixup)(pool, root, x);
     995             : 
     996   112950648 :   if (y != z) {
     997             :     /* we got rid of y instead of z. Oops! Replace z with y in the
     998             :      * tree so we don't lose y's key/value. */
     999    31461382 :     y->REDBLK_PARENT = z->REDBLK_PARENT;
    1000    31461382 :     y->REDBLK_LEFT = z->REDBLK_LEFT;
    1001    31461382 :     y->REDBLK_RIGHT = z->REDBLK_RIGHT;
    1002    31461382 :     y->REDBLK_COLOR = z->REDBLK_COLOR;
    1003    31461382 :     if (z == *root)
    1004    13492890 :       *root = y;
    1005    17968492 :     else if (&pool[pool[y->REDBLK_PARENT].REDBLK_LEFT] == z)
    1006     5629778 :       pool[y->REDBLK_PARENT].REDBLK_LEFT = (uint)(y - pool);
    1007    12338714 :     else
    1008    12338714 :       pool[y->REDBLK_PARENT].REDBLK_RIGHT = (uint)(y - pool);
    1009    31461382 :     pool[y->REDBLK_LEFT].REDBLK_PARENT = (uint)(y - pool);
    1010    31461382 :     pool[y->REDBLK_RIGHT].REDBLK_PARENT = (uint)(y - pool);
    1011    31461382 :   }
    1012             : 
    1013   112950648 :   if (*root == &pool[REDBLK_NIL])
    1014    10889451 :     *root = NULL;
    1015   112950648 :   z->REDBLK_COLOR = REDBLK_NEW;
    1016   112950648 :   return z;
    1017   112950648 : }
    1018             : 
    1019             : /*
    1020             :   Search for a key in the tree. In this special case, the key can be a
    1021             :   temporary instance of the node type rather than a properly
    1022             :   allocated node.
    1023             : */
    1024   447793125 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(find)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key) {
    1025   447793125 : #ifndef REDBLK_UNSAFE
    1026   447793125 :   REDBLK_(validate_element)(pool, root);
    1027   447793125 : #endif
    1028             : 
    1029   447793125 :   REDBLK_T * current = root;
    1030   447793125 :   if (current == NULL || current == &pool[REDBLK_NIL])
    1031    10886454 :     return NULL;
    1032  1330290858 :   while (current != &pool[REDBLK_NIL]) {
    1033  1232269122 :     long c = REDBLK_(compare)(key, current);
    1034  1232269122 :     if (c == 0)
    1035   338884935 :       return current;
    1036   893384187 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
    1037   893384187 :   }
    1038    98021736 :   return NULL;
    1039   436906671 : }
    1040             : 
    1041             : /*
    1042             :   Search for a key in the tree. If the key can't be found, a nearby
    1043             :   approximation is returned instead. This is either the greatest node
    1044             :   less than the key, or the least node greater than the key. In this
    1045             :   special case, the key can be a temporary instance of the node type
    1046             :   rather than a properly allocated node.
    1047             : */
    1048           0 : REDBLK_IMPL_STATIC REDBLK_T * REDBLK_(nearby)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key) {
    1049           0 : #ifndef REDBLK_UNSAFE
    1050           0 :   REDBLK_(validate_element)(pool, root);
    1051           0 : #endif
    1052             : 
    1053           0 :   REDBLK_T * current = root;
    1054           0 :   if (current == NULL || current == &pool[REDBLK_NIL])
    1055           0 :     return NULL;
    1056           0 :   REDBLK_T * result = current;
    1057           0 :   while (current != &pool[REDBLK_NIL]) {
    1058           0 :     result = current; /* Return the last non-NIL node that was touched */
    1059           0 :     long c = REDBLK_(compare)(key, current);
    1060           0 :     if (c == 0)
    1061           0 :       return current;
    1062           0 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
    1063           0 :   }
    1064           0 :   return result;
    1065           0 : }
    1066             : 
    1067             : /*
    1068             :   Count the number of nodes in a tree.
    1069             : */
    1070  3887292116 : REDBLK_IMPL_STATIC ulong REDBLK_(size)(REDBLK_T * pool, REDBLK_T * root) {
    1071  3887292116 : #ifndef REDBLK_UNSAFE
    1072  3887292116 :   REDBLK_(validate_element)(pool, root);
    1073  3887292116 : #endif
    1074  3887292116 :  if (!root || root == &pool[REDBLK_NIL])
    1075  2101941784 :    return 0;
    1076  1785350332 :  return 1 +
    1077  1785350332 :         REDBLK_(size)(pool, &pool[root->REDBLK_LEFT]) +
    1078  1785350332 :         REDBLK_(size)(pool, &pool[root->REDBLK_RIGHT]);
    1079  3887292116 : }
    1080             : 
    1081             : /*
    1082             :   Recursive implementation of the verify function
    1083             : */
    1084  3716939249 : static int REDBLK_(verify_private)(REDBLK_T * pool, REDBLK_T * node, REDBLK_T * parent, ulong curblkcnt, ulong correctblkcnt) {
    1085  7272429818 : # define REDBLK_TEST(c) do {                                                        \
    1086  7272429818 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return -1; } \
    1087  7272429818 :   } while(0)
    1088             : 
    1089  3716939249 :   if (!node || node == &pool[REDBLK_NIL]) {
    1090  2016329020 :     REDBLK_TEST(curblkcnt == correctblkcnt);
    1091  2016329020 :     return 0;
    1092  2016329020 :   }
    1093             : 
    1094  1700610229 : #ifndef REDBLK_UNSAFE
    1095  1700610229 :   REDBLK_(validate_element)(pool, node);
    1096  1700610229 : #endif
    1097             : 
    1098  1700610229 :   REDBLK_TEST(&pool[node->REDBLK_PARENT] == parent);
    1099             : 
    1100  1700610229 :   if (node->REDBLK_COLOR == REDBLK_BLACK)
    1101  1094333574 :     ++curblkcnt;
    1102   606276655 :   else {
    1103   606276655 :     REDBLK_TEST(node->REDBLK_COLOR == REDBLK_RED);
    1104   606276655 :     REDBLK_TEST(parent->REDBLK_COLOR == REDBLK_BLACK);
    1105   606276655 :   }
    1106             : 
    1107  1700610229 :   if (node->REDBLK_LEFT != REDBLK_NIL)
    1108   663935574 :     REDBLK_TEST(REDBLK_(compare)(&pool[node->REDBLK_LEFT], node) <= 0);
    1109  1700610229 :   if (node->REDBLK_RIGHT != REDBLK_NIL)
    1110   720955864 :     REDBLK_TEST(REDBLK_(compare)(node, &pool[node->REDBLK_RIGHT]) <= 0);
    1111             : 
    1112  1700610229 :   int err = REDBLK_(verify_private)(pool, &pool[node->REDBLK_LEFT], node, curblkcnt, correctblkcnt);
    1113  1700610229 :   if (err) return err;
    1114  1700610229 :   return REDBLK_(verify_private)(pool, &pool[node->REDBLK_RIGHT], node, curblkcnt, correctblkcnt);
    1115  1700610229 : }
    1116             : 
    1117             : /*
    1118             :   Verify the integrity of the tree data structure. Useful for
    1119             :   debugging memory corruption. A non-zero result is returned if an error
    1120             :   is detected.
    1121             : */
    1122   326608239 : REDBLK_IMPL_STATIC int REDBLK_(verify)(REDBLK_T * pool, REDBLK_T * root) {
    1123   326608239 :   REDBLK_TEST(pool[REDBLK_NIL].REDBLK_LEFT == REDBLK_NIL &&
    1124   326608239 :        pool[REDBLK_NIL].REDBLK_RIGHT == REDBLK_NIL &&
    1125   326608239 :        pool[REDBLK_NIL].REDBLK_COLOR == REDBLK_BLACK);
    1126             : 
    1127   326608239 :   if (!root || root == &pool[REDBLK_NIL])
    1128    10889448 :     return 0; // Trivially correct
    1129   315718791 :   REDBLK_TEST(root->REDBLK_COLOR == REDBLK_BLACK);
    1130             : 
    1131   315718791 :   ulong sz = REDBLK_(size)(pool, root);
    1132   315718791 :   REDBLK_TEST(sz + 1 == REDBLK_POOL_(used)(pool));
    1133             : 
    1134             :   // Compute the correct number of black nodes on a path
    1135   315718791 :   ulong blkcnt = 0;
    1136   315718791 :   REDBLK_T * node = root;
    1137  1047933621 :   while (node != &pool[REDBLK_NIL]) {
    1138   732214830 :     if (node->REDBLK_COLOR == REDBLK_BLACK)
    1139   582354819 :       ++blkcnt;
    1140   732214830 :     node = &pool[node->REDBLK_LEFT];
    1141   732214830 :   }
    1142             :   // Recursive check
    1143   315718791 :   return REDBLK_(verify_private)(pool, root, &pool[REDBLK_NIL], 0, blkcnt);
    1144             : 
    1145   315718791 : #undef REDBLK_TEST
    1146   315718791 : }
    1147             : 
    1148             : #undef REDBLK_FREE
    1149             : #undef REDBLK_NEW
    1150             : #undef REDBLK_BLACK
    1151             : #undef REDBLK_RED
    1152             : #undef REDBLK_POOL_
    1153             : #undef REDBLK_PARENT
    1154             : #undef REDBLK_LEFT
    1155             : #undef REDBLK_RIGHT
    1156             : #undef REDBLK_COLOR
    1157             : 
    1158             : #endif /* REDBLK_IMPL_STYLE==0 || REDBLK_IMPL_STYLE==2 */
    1159             : 
    1160             : #undef REDBLK_IMPL_STATIC
    1161             : #undef REDBLK_
    1162             : #undef REDBLK_T
    1163             : #undef REDBLK_IMPL_STYLE
    1164             : #undef REDBLK_NAME

Generated by: LCOV version 1.14