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: 2024-11-13 11:58:15 Functions: 84 420 20.0 %

          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 17433296150 : #define REDBLK_(n) FD_EXPAND_THEN_CONCAT3(REDBLK_NAME,_,n)
     130             : 
     131             : #if REDBLK_IMPL_STYLE==0 || 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 || REDBLK_IMPL_STYLE==2 /* need implementations */
     408             : 
     409             : /* Tree node colors */
     410  7232570973 : #define REDBLK_FREE -1
     411   335617278 : #define REDBLK_NEW 0
     412  3518699120 : #define REDBLK_BLACK 1
     413  1057723740 : #define REDBLK_RED 2
     414             : 
     415             : #ifndef REDBLK_PARENT
     416   100903023 : #define REDBLK_PARENT redblack_parent
     417             : #endif
     418             : #ifndef REDBLK_LEFT
     419   250650966 : #define REDBLK_LEFT redblack_left
     420             : #endif
     421             : #ifndef REDBLK_RIGHT
     422   287807877 : #define REDBLK_RIGHT redblack_right
     423             : #endif
     424             : #ifndef REDBLK_COLOR
     425   306600477 : #define REDBLK_COLOR redblack_color
     426             : #endif
     427             : 
     428             : #define POOL_NAME FD_EXPAND_THEN_CONCAT2(REDBLK_NAME,_pool)
     429     1024623 : #define POOL_T REDBLK_T
     430             : #define POOL_SENTINEL 1
     431             : #ifdef REDBLK_NEXTFREE
     432   435485685 : #define POOL_NEXT REDBLK_NEXTFREE
     433             : #else
     434    56130852 : #define POOL_NEXT REDBLK_RIGHT
     435             : #endif
     436             : #include "fd_pool.c"
     437             : #undef MAP_POOL_NAME
     438             : #undef MAP_POOL_T
     439             : 
     440  7715012292 : #define REDBLK_POOL_(n) FD_EXPAND_THEN_CONCAT3(REDBLK_NAME,_pool_,n)
     441             : 
     442 17471312076 : #define REDBLK_NIL 0UL /* Must be same as pool sentinel */
     443             : 
     444           6 : ulong REDBLK_(max_for_footprint)( ulong footprint ) {
     445           6 :   return REDBLK_POOL_(max_for_footprint)(footprint) - 1; /* Allow for sentinel */
     446           6 : }
     447             : 
     448      446526 : ulong REDBLK_(align)( void ) {
     449      446526 :   return REDBLK_POOL_(align)();
     450      446526 : }
     451             : 
     452      446532 : ulong REDBLK_(footprint)( ulong max ) {
     453      446532 :   return REDBLK_POOL_(footprint)(max + 1); /* Allow for sentinel */
     454      446532 : }
     455             : 
     456      337746 : void * REDBLK_(new)( void * shmem, ulong max ) {
     457      337746 :   void * shmem2 = REDBLK_POOL_(new)(shmem, max + 1); /* Allow for sentinel */
     458      337746 :   if ( FD_UNLIKELY( shmem2 == NULL ) )
     459           0 :     return NULL;
     460             :   /* Initialize sentinel */
     461      337746 :   REDBLK_T * pool = REDBLK_POOL_(join)(shmem2);
     462      337746 :   if ( FD_UNLIKELY( pool == NULL ) )
     463           0 :     return NULL;
     464      337746 :   REDBLK_T * node = REDBLK_POOL_(ele_sentinel)(pool);
     465      337746 :   node->REDBLK_LEFT = REDBLK_NIL;
     466      337746 :   node->REDBLK_RIGHT = REDBLK_NIL;
     467      337746 :   node->REDBLK_PARENT = REDBLK_NIL;
     468      337746 :   node->REDBLK_COLOR = REDBLK_BLACK;
     469      337746 :   return shmem2;
     470      337746 : }
     471             : 
     472      337755 : REDBLK_T * REDBLK_(join)( void * shpool ) {
     473      337755 :   FD_COMPILER_MFENCE();
     474      337755 :   return REDBLK_POOL_(join)(shpool);
     475      337755 : }
     476             : 
     477     1087875 : void * REDBLK_(leave)( REDBLK_T * pool ) {
     478     1087875 :   FD_COMPILER_MFENCE();
     479     1087875 :   return REDBLK_POOL_(leave)(pool);
     480     1087875 : }
     481             : 
     482     1087866 : void * REDBLK_(delete)( void * shpool ) {
     483     1087866 :   FD_COMPILER_MFENCE();
     484     1087866 :   return REDBLK_POOL_(delete)(shpool);
     485     1087866 : }
     486             : 
     487          15 : ulong REDBLK_(max)( REDBLK_T const * pool ) {
     488          15 :   return REDBLK_POOL_(max)(pool) - 1; /* Allow for sentinel */
     489          15 : }
     490             : 
     491          66 : ulong REDBLK_(free)( REDBLK_T const * pool ) {
     492          66 :   return REDBLK_POOL_(free)(pool);
     493          66 : }
     494             : 
     495           9 : ulong REDBLK_(idx)( REDBLK_T const * pool, REDBLK_T const * node ) {
     496           9 :   return REDBLK_POOL_(idx)(pool, node);
     497           9 : }
     498             : 
     499           9 : REDBLK_T * REDBLK_(node)( REDBLK_T * pool, ulong idx ) {
     500           9 :   return REDBLK_POOL_(ele)(pool, idx);
     501           9 : }
     502             : 
     503   222669630 : REDBLK_T * REDBLK_(acquire)( REDBLK_T * pool ) {
     504   222669630 :   if ( REDBLK_POOL_(free)( pool ) == 0 )
     505        3009 :     return NULL;
     506   222666621 :   REDBLK_T * node = REDBLK_POOL_(ele_acquire)(pool);
     507   222666621 :   node->REDBLK_COLOR = REDBLK_NEW;
     508   222666621 :   return node;
     509   222669630 : }
     510             : 
     511             : #ifndef REDBLK_UNSAFE
     512  7043413998 : void REDBLK_(validate_element)( REDBLK_T * pool, REDBLK_T * node ) {
     513  7043413998 :   if ( !REDBLK_POOL_(ele_test)( pool, node ) )
     514           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     515  7043413998 :   if ( node && node->REDBLK_COLOR == REDBLK_FREE )
     516           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     517  7043413998 : }
     518           0 : void REDBLK_(validate_element_const)( REDBLK_T const * pool, REDBLK_T const * node ) {
     519           0 :   if ( !REDBLK_POOL_(ele_test)( pool, node ) )
     520           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     521           0 :   if ( node && node->REDBLK_COLOR == REDBLK_FREE )
     522           0 :     FD_LOG_ERR(( "invalid redblack node" ));
     523           0 : }
     524             : #endif
     525             : 
     526   221842146 : void REDBLK_(release)( REDBLK_T * pool, REDBLK_T * node ) {
     527   221842146 : #ifndef REDBLK_UNSAFE
     528   221842146 :   REDBLK_(validate_element)(pool, node);
     529   221842146 : #endif
     530             : 
     531   221842146 :   node->REDBLK_COLOR = REDBLK_FREE;
     532   221842146 :   REDBLK_POOL_(ele_release)(pool, node);
     533   221842146 : }
     534             : 
     535             : /*
     536             :   Recursively release all nodes in a tree to a pool. The root argument
     537             :   is invalid after this method is called.
     538             : */
     539   239555967 : void REDBLK_(release_tree)( REDBLK_T * pool, REDBLK_T * node ) {
     540   239555967 :   if (!node || node == &pool[REDBLK_NIL])
     541   130664478 :     return;
     542             : 
     543   108891489 : #ifndef REDBLK_UNSAFE
     544   108891489 :   REDBLK_(validate_element)(pool, node);
     545   108891489 : #endif
     546             :   
     547   108891489 :   REDBLK_T * left = &pool[node->REDBLK_LEFT];
     548   108891489 :   REDBLK_T * right = &pool[node->REDBLK_RIGHT];
     549             :   
     550   108891489 :   REDBLK_(release)(pool, node);
     551             : 
     552   108891489 :   REDBLK_(release_tree)(pool, left);
     553   108891489 :   REDBLK_(release_tree)(pool, right);
     554   108891489 : }
     555             : 
     556             : /*
     557             :   Return the node in a tree that has the smallest key (leftmost).
     558             : */
     559     3560868 : REDBLK_T * REDBLK_(minimum)(REDBLK_T * pool, REDBLK_T * node) {
     560     3560868 :   if (!node || node == &pool[REDBLK_NIL])
     561     1090422 :     return NULL;
     562     2470446 : #ifndef REDBLK_UNSAFE
     563     2470446 :   REDBLK_(validate_element)(pool, node);
     564     2470446 : #endif
     565     4923537 :   while (node->REDBLK_LEFT != REDBLK_NIL) {
     566     2453091 :     node = &pool[node->REDBLK_LEFT];
     567     2453091 :   }
     568     2470446 :   return node;
     569     3560868 : }
     570           0 : REDBLK_T const * REDBLK_(minimum_const)(REDBLK_T const * pool, REDBLK_T const * node) {
     571           0 :   if (!node || node == &pool[REDBLK_NIL])
     572           0 :     return NULL;
     573           0 : #ifndef REDBLK_UNSAFE
     574           0 :   REDBLK_(validate_element_const)(pool, node);
     575           0 : #endif
     576           0 :   while (node->REDBLK_LEFT != REDBLK_NIL) {
     577           0 :     node = &pool[node->REDBLK_LEFT];
     578           0 :   }
     579           0 :   return node;
     580           0 : }
     581             : 
     582             : /*
     583             :   Return the node in a tree that has the largest key (rightmost).
     584             : */
     585     2041752 : REDBLK_T * REDBLK_(maximum)(REDBLK_T * pool, REDBLK_T * node) {
     586     2041752 :   if (!node || node == &pool[REDBLK_NIL])
     587           0 :     return NULL;
     588     2041752 : #ifndef REDBLK_UNSAFE
     589     2041752 :   REDBLK_(validate_element)(pool, node);
     590     2041752 : #endif
     591     4083000 :   while (node->REDBLK_RIGHT != REDBLK_NIL) {
     592     2041248 :     node = &pool[node->REDBLK_RIGHT];
     593     2041248 :   }
     594     2041752 :   return node;
     595     2041752 : }
     596           0 : REDBLK_T const * REDBLK_(maximum_const)(REDBLK_T const * pool, REDBLK_T const * node) {
     597           0 :   if (!node || node == &pool[REDBLK_NIL])
     598           0 :     return NULL;
     599           0 : #ifndef REDBLK_UNSAFE
     600           0 :   REDBLK_(validate_element_const)(pool, node);
     601           0 : #endif
     602           0 :   while (node->REDBLK_RIGHT != REDBLK_NIL) {
     603           0 :     node = &pool[node->REDBLK_RIGHT];
     604           0 :   }
     605           0 :   return node;
     606           0 : }
     607             : 
     608             : /*
     609             :   Return the next node which is larger than the given node.
     610             : */
     611     4923522 : REDBLK_T * REDBLK_(successor)(REDBLK_T * pool, REDBLK_T * x) {
     612     4923522 : #ifndef REDBLK_UNSAFE
     613     4923522 :   REDBLK_(validate_element)(pool, x);
     614     4923522 : #endif
     615             : 
     616             :   // if the right subtree is not null,
     617             :   // the successor is the leftmost node in the
     618             :   // right subtree
     619     4923522 :   if (x->REDBLK_RIGHT != REDBLK_NIL) {
     620     2456028 :     return REDBLK_(minimum)(pool, &pool[x->REDBLK_RIGHT]);
     621     2456028 :   }
     622             : 
     623             :   // else it is the lowest ancestor of x whose
     624             :   // left child is also an ancestor of x.
     625     4923522 :   for (;;) {
     626     4923522 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     627       14406 :       return NULL;
     628     4909116 :     REDBLK_T * y = &pool[x->REDBLK_PARENT];
     629     4909116 :     if (x == &pool[y->REDBLK_LEFT])
     630     2453088 :       return y;
     631     2456028 :     x = y;
     632     2456028 :   }
     633     2467494 : }
     634           0 : REDBLK_T const * REDBLK_(successor_const)(REDBLK_T const * pool, REDBLK_T const * x) {
     635           0 : #ifndef REDBLK_UNSAFE
     636           0 :   REDBLK_(validate_element_const)(pool, x);
     637           0 : #endif
     638             : 
     639             :   // if the right subtree is not null,
     640             :   // the successor is the leftmost node in the
     641             :   // right subtree
     642           0 :   if (x->REDBLK_RIGHT != REDBLK_NIL) {
     643           0 :     return REDBLK_(minimum_const)(pool, &pool[x->REDBLK_RIGHT]);
     644           0 :   }
     645             : 
     646             :   // else it is the lowest ancestor of x whose
     647             :   // left child is also an ancestor of x.
     648           0 :   for (;;) {
     649           0 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     650           0 :       return NULL;
     651           0 :     REDBLK_T const * y = &pool[x->REDBLK_PARENT];
     652           0 :     if (x == &pool[y->REDBLK_LEFT])
     653           0 :       return y;
     654           0 :     x = y;
     655           0 :   }
     656           0 : }
     657             : 
     658             : /*
     659             :   Return the previous node which is smaller than the given node.
     660             : */
     661     4083000 : REDBLK_T * REDBLK_(predecessor)(REDBLK_T * pool, REDBLK_T * x) {
     662     4083000 : #ifndef REDBLK_UNSAFE
     663     4083000 :   REDBLK_(validate_element)(pool, x);
     664     4083000 : #endif
     665             : 
     666             :   // if the left subtree is not null,
     667             :   // the predecessor is the rightmost node in the 
     668             :   // left subtree
     669     4083000 :   if (x->REDBLK_LEFT != REDBLK_NIL) {
     670     2038752 :     return REDBLK_(maximum)(pool, &pool[x->REDBLK_LEFT]);
     671     2038752 :   }
     672             : 
     673             :   // else it is the lowest ancestor of x whose
     674             :   // right child is also an ancestor of x.
     675     4083000 :   for (;;) {
     676     4083000 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     677        3000 :       return NULL;
     678     4080000 :     REDBLK_T * y = &pool[x->REDBLK_PARENT];
     679     4080000 :     if (x == &pool[y->REDBLK_RIGHT])
     680     2041248 :       return y;
     681     2038752 :     x = y;
     682     2038752 :   }
     683     2044248 : }
     684           0 : REDBLK_T const * REDBLK_(predecessor_const)(REDBLK_T const * pool, REDBLK_T const * x) {
     685           0 : #ifndef REDBLK_UNSAFE
     686           0 :   REDBLK_(validate_element_const)(pool, x);
     687           0 : #endif
     688             : 
     689             :   // if the left subtree is not null,
     690             :   // the predecessor is the rightmost node in the 
     691             :   // left subtree
     692           0 :   if (x->REDBLK_LEFT != REDBLK_NIL) {
     693           0 :     return REDBLK_(maximum_const)(pool, &pool[x->REDBLK_LEFT]);
     694           0 :   }
     695             : 
     696             :   // else it is the lowest ancestor of x whose
     697             :   // right child is also an ancestor of x.
     698           0 :   for (;;) {
     699           0 :     if (x->REDBLK_PARENT == REDBLK_NIL)
     700           0 :       return NULL;
     701           0 :     REDBLK_T const * y = &pool[x->REDBLK_PARENT];
     702           0 :     if (x == &pool[y->REDBLK_RIGHT])
     703           0 :       return y;
     704           0 :     x = y;
     705           0 :   }
     706           0 : }
     707             : 
     708             : /*
     709             :   Perform a left rotation around a node
     710             : */
     711    98525614 : static void REDBLK_(rotateLeft)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     712    98525614 :   REDBLK_T * y = &pool[x->REDBLK_RIGHT];
     713             : 
     714             :   /* establish x->REDBLK_RIGHT link */
     715    98525614 :   x->REDBLK_RIGHT = y->REDBLK_LEFT;
     716    98525614 :   if (y->REDBLK_LEFT != REDBLK_NIL)
     717    24206583 :     pool[y->REDBLK_LEFT].REDBLK_PARENT = (uint)(x - pool);
     718             : 
     719             :   /* establish y->REDBLK_PARENT link */
     720    98525614 :   if (y != &pool[REDBLK_NIL])
     721    98525614 :     y->REDBLK_PARENT = x->REDBLK_PARENT;
     722    98525614 :   if (x->REDBLK_PARENT) {
     723    63707153 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     724    63707153 :     if (x == &pool[p->REDBLK_LEFT])
     725    17121551 :       p->REDBLK_LEFT = (uint)(y - pool);
     726    46585602 :     else
     727    46585602 :       p->REDBLK_RIGHT = (uint)(y - pool);
     728    63707153 :   } else {
     729    34818461 :     *root = y;
     730    34818461 :   }
     731             : 
     732             :   /* link x and y */
     733    98525614 :   y->REDBLK_LEFT = (uint)(x - pool);
     734    98525614 :   if (x != &pool[REDBLK_NIL])
     735    98525614 :     x->REDBLK_PARENT = (uint)(y - pool);
     736    98525614 : }
     737             : 
     738             : /*
     739             :   Perform a right rotation around a node
     740             : */
     741    34650991 : static void REDBLK_(rotateRight)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     742    34650991 :   REDBLK_T * y = &pool[x->REDBLK_LEFT];
     743             : 
     744             :   /* establish x->REDBLK_LEFT link */
     745    34650991 :   x->REDBLK_LEFT = y->REDBLK_RIGHT;
     746    34650991 :   if (y->REDBLK_RIGHT != REDBLK_NIL)
     747     5559102 :     pool[y->REDBLK_RIGHT].REDBLK_PARENT = (uint)(x - pool);
     748             : 
     749             :   /* establish y->REDBLK_PARENT link */
     750    34650991 :   if (y != &pool[REDBLK_NIL])
     751    34650991 :     y->REDBLK_PARENT = x->REDBLK_PARENT;
     752    34650991 :   if (x->REDBLK_PARENT) {
     753    24524145 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     754    24524145 :     if (x == &pool[p->REDBLK_RIGHT])
     755    16415256 :       p->REDBLK_RIGHT = (uint)(y - pool);
     756     8108889 :     else
     757     8108889 :       p->REDBLK_LEFT = (uint)(y - pool);
     758    24524145 :   } else {
     759    10126846 :     *root = y;
     760    10126846 :   }
     761             : 
     762             :   /* link x and y */
     763    34650991 :   y->REDBLK_RIGHT = (uint)(x - pool);
     764    34650991 :   if (x != &pool[REDBLK_NIL])
     765    34650991 :     x->REDBLK_PARENT = (uint)(y - pool);
     766    34650991 : }
     767             : 
     768             : /*
     769             :   Restore tree invariants after an insert.
     770             : */
     771   222666621 : static void REDBLK_(insertFixup)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     772             :   /* check Red-Black properties */
     773   222666621 :   REDBLK_T * p;
     774   397828726 :   while (x != *root && (p = &pool[x->REDBLK_PARENT])->REDBLK_COLOR == REDBLK_RED) {
     775             :     /* we have a violation */
     776   175162105 :     REDBLK_T * gp = &pool[p->REDBLK_PARENT];
     777   175162105 :     if (x->REDBLK_PARENT == gp->REDBLK_LEFT) {
     778    33146926 :       REDBLK_T * y = &pool[gp->REDBLK_RIGHT];
     779    33146926 :       if (y->REDBLK_COLOR == REDBLK_RED) {
     780             : 
     781             :         /* uncle is REDBLK_RED */
     782    16394737 :         p->REDBLK_COLOR = REDBLK_BLACK;
     783    16394737 :         y->REDBLK_COLOR = REDBLK_BLACK;
     784    16394737 :         gp->REDBLK_COLOR = REDBLK_RED;
     785    16394737 :         x = gp;
     786    16752189 :       } else {
     787             : 
     788             :         /* uncle is REDBLK_BLACK */
     789    16752189 :         if (x == &pool[p->REDBLK_RIGHT]) {
     790             :           /* make x a left child */
     791     8372916 :           x = p;
     792     8372916 :           REDBLK_(rotateLeft)(pool, root, x);
     793     8372916 :           p = &pool[x->REDBLK_PARENT];
     794     8372916 :           gp = &pool[p->REDBLK_PARENT];
     795     8372916 :         }
     796             : 
     797             :         /* recolor and rotate */
     798    16752189 :         p->REDBLK_COLOR = REDBLK_BLACK;
     799    16752189 :         gp->REDBLK_COLOR = REDBLK_RED;
     800    16752189 :         REDBLK_(rotateRight)(pool, root, gp);
     801    16752189 :       }
     802             :       
     803   142015179 :     } else {
     804             :       /* mirror image of above code */
     805   142015179 :       REDBLK_T * y = &pool[gp->REDBLK_LEFT];
     806   142015179 :       if (y->REDBLK_COLOR == REDBLK_RED) {
     807             : 
     808             :         /* uncle is REDBLK_RED */
     809    70826944 :         p->REDBLK_COLOR = REDBLK_BLACK;
     810    70826944 :         y->REDBLK_COLOR = REDBLK_BLACK;
     811    70826944 :         gp->REDBLK_COLOR = REDBLK_RED;
     812    70826944 :         x = gp;
     813    71188235 :       } else {
     814             : 
     815             :         /* uncle is REDBLK_BLACK */
     816    71188235 :         if (x == &pool[p->REDBLK_LEFT]) {
     817     8372425 :           x = p;
     818     8372425 :           REDBLK_(rotateRight)(pool, root, x);
     819     8372425 :           p = &pool[x->REDBLK_PARENT];
     820     8372425 :           gp = &pool[p->REDBLK_PARENT];
     821     8372425 :         }
     822    71188235 :         p->REDBLK_COLOR = REDBLK_BLACK;
     823    71188235 :         gp->REDBLK_COLOR = REDBLK_RED;
     824    71188235 :         REDBLK_(rotateLeft)(pool, root, gp);
     825    71188235 :       }
     826   142015179 :     }
     827   175162105 :   }
     828             : 
     829   222666621 :   (*root)->REDBLK_COLOR = REDBLK_BLACK;
     830   222666621 : }
     831             : 
     832             : /*
     833             :   Insert a node into a tree. Typically, the node must be allocated
     834             :   from a pool first.
     835             : */
     836   222666621 : REDBLK_T * REDBLK_(insert)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     837   222666621 : #ifndef REDBLK_UNSAFE
     838   222666621 :   REDBLK_(validate_element)(pool, *root);
     839   222666621 :   REDBLK_(validate_element)(pool, x);
     840   222666621 : #endif
     841             : 
     842   222666621 :   REDBLK_T * current;
     843   222666621 :   REDBLK_T * parent;
     844             : 
     845             :   /* find where node belongs */
     846   222666621 :   current = *root;
     847   222666621 :   if (current == NULL)
     848    21787347 :     current = &pool[REDBLK_NIL];
     849   222666621 :   parent = &pool[REDBLK_NIL];
     850   804570948 :   while (current != &pool[REDBLK_NIL]) {
     851   581904327 :     long c = REDBLK_(compare)(x, current);
     852   581904327 :     parent = current;
     853   581904327 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
     854   581904327 :   }
     855             : 
     856             :   /* setup new node */
     857   222666621 :   x->REDBLK_PARENT = (uint)(parent - pool);
     858   222666621 :   x->REDBLK_LEFT = REDBLK_NIL;
     859   222666621 :   x->REDBLK_RIGHT = REDBLK_NIL;
     860   222666621 :   x->REDBLK_COLOR = REDBLK_RED;
     861             : 
     862             :   /* insert node in tree */
     863   222666621 :   if (parent != &pool[REDBLK_NIL]) {
     864   200879274 :     long c = REDBLK_(compare)(x, parent);
     865   200879274 :     if (c < 0)
     866    51445879 :       parent->REDBLK_LEFT = (uint)(x - pool);
     867   149433395 :     else
     868   149433395 :       parent->REDBLK_RIGHT = (uint)(x - pool);
     869   200879274 :   } else {
     870    21787347 :     *root = x;
     871    21787347 :   }
     872             : 
     873   222666621 :   REDBLK_(insertFixup)(pool, root, x);
     874   222666621 :   return x;
     875   222666621 : }
     876             : 
     877             : /*
     878             :   Restore tree invariants after a delete
     879             : */
     880    92124722 : static void REDBLK_(deleteFixup)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * x) {
     881   166922293 :   while (x != *root && x->REDBLK_COLOR == REDBLK_BLACK) {
     882    74797571 :     REDBLK_T * p = &pool[x->REDBLK_PARENT];
     883    74797571 :     if (x == &pool[p->REDBLK_LEFT]) {
     884    37308679 :       REDBLK_T * w = &pool[p->REDBLK_RIGHT];
     885    37308679 :       if (w->REDBLK_COLOR == REDBLK_RED) {
     886     4179980 :         w->REDBLK_COLOR = REDBLK_BLACK;
     887     4179980 :         p->REDBLK_COLOR = REDBLK_RED;
     888     4179980 :         REDBLK_(rotateLeft)(pool, root, p);
     889     4179980 :         p = &pool[x->REDBLK_PARENT];
     890     4179980 :         w = &pool[p->REDBLK_RIGHT];
     891     4179980 :       }
     892    37308679 :       if (pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK &&
     893    37308679 :          pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK) {
     894    25543674 :         w->REDBLK_COLOR = REDBLK_RED;
     895    25543674 :         x = p;
     896    25543674 :       } else {
     897    11765005 :         if (pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK) {
     898     1505673 :           pool[w->REDBLK_LEFT].REDBLK_COLOR = REDBLK_BLACK;
     899     1505673 :           w->REDBLK_COLOR = REDBLK_RED;
     900     1505673 :           REDBLK_(rotateRight)(pool, root, w);
     901     1505673 :           p = &pool[x->REDBLK_PARENT];
     902     1505673 :           w = &pool[p->REDBLK_RIGHT];
     903     1505673 :         }
     904    11765005 :         w->REDBLK_COLOR = p->REDBLK_COLOR;
     905    11765005 :         p->REDBLK_COLOR = REDBLK_BLACK;
     906    11765005 :         pool[w->REDBLK_RIGHT].REDBLK_COLOR = REDBLK_BLACK;
     907    11765005 :         REDBLK_(rotateLeft)(pool, root, p);
     908    11765005 :         x = *root;
     909    11765005 :       }
     910             :       
     911    37488892 :     } else {
     912    37488892 :       REDBLK_T * w = &pool[p->REDBLK_LEFT];
     913    37488892 :       if (w->REDBLK_COLOR == REDBLK_RED) {
     914     1499665 :         w->REDBLK_COLOR = REDBLK_BLACK;
     915     1499665 :         p->REDBLK_COLOR = REDBLK_RED;
     916     1499665 :         REDBLK_(rotateRight)(pool, root, p);
     917     1499665 :         p = &pool[x->REDBLK_PARENT];
     918     1499665 :         w = &pool[p->REDBLK_LEFT];
     919     1499665 :       }
     920    37488892 :       if (pool[w->REDBLK_RIGHT].REDBLK_COLOR == REDBLK_BLACK &&
     921    37488892 :           pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK) {
     922    30967853 :         w->REDBLK_COLOR = REDBLK_RED;
     923    30967853 :         x = p;
     924    30967853 :       } else {
     925     6521039 :         if (pool[w->REDBLK_LEFT].REDBLK_COLOR == REDBLK_BLACK) {
     926     3019478 :           pool[w->REDBLK_RIGHT].REDBLK_COLOR = REDBLK_BLACK;
     927     3019478 :           w->REDBLK_COLOR = REDBLK_RED;
     928     3019478 :           REDBLK_(rotateLeft)(pool, root, w);
     929     3019478 :           p = &pool[x->REDBLK_PARENT];
     930     3019478 :           w = &pool[p->REDBLK_LEFT];
     931     3019478 :         }
     932     6521039 :         w->REDBLK_COLOR = p->REDBLK_COLOR;
     933     6521039 :         p->REDBLK_COLOR = REDBLK_BLACK;
     934     6521039 :         pool[w->REDBLK_LEFT].REDBLK_COLOR = REDBLK_BLACK;
     935     6521039 :         REDBLK_(rotateRight)(pool, root, p);
     936     6521039 :         x = *root;
     937     6521039 :       }
     938    37488892 :     }
     939    74797571 :   }
     940             :   
     941    92124722 :   x->REDBLK_COLOR = REDBLK_BLACK;
     942    92124722 : }
     943             : 
     944             : /*
     945             :   Remove a node from a tree. The node must be a member of the tree,
     946             :   usually the result of a find operation. The node is typically
     947             :   released to the pool afterwards.
     948             : */
     949   112950657 : REDBLK_T * REDBLK_(remove)(REDBLK_T * pool, REDBLK_T ** root, REDBLK_T * z) {
     950   112950657 : #ifndef REDBLK_UNSAFE
     951   112950657 :   REDBLK_(validate_element)(pool, *root);
     952   112950657 :   REDBLK_(validate_element)(pool, z);
     953   112950657 : #endif
     954             : 
     955   112950657 :   REDBLK_T * x;
     956   112950657 :   REDBLK_T * y;
     957             : 
     958   112950657 :   if (!z || z == &pool[REDBLK_NIL])
     959           0 :     return NULL;
     960             : 
     961   112950657 :   if (z->REDBLK_LEFT == REDBLK_NIL || z->REDBLK_RIGHT == REDBLK_NIL) {
     962             :     /* y has a REDBLK_NIL node as a child */
     963    81489256 :     y = z;
     964    81489256 :   } else {
     965             :     /* find tree successor with a REDBLK_NIL node as a child */
     966    31461401 :     y = &pool[z->REDBLK_RIGHT];
     967    43608893 :     while (y->REDBLK_LEFT != REDBLK_NIL)
     968    12147492 :       y = &pool[y->REDBLK_LEFT];
     969    31461401 :   }
     970             : 
     971             :   /* x is y's only child */
     972   112950657 :   if (y->REDBLK_LEFT != REDBLK_NIL)
     973     9310934 :     x = &pool[y->REDBLK_LEFT];
     974   103639723 :   else
     975   103639723 :     x = &pool[y->REDBLK_RIGHT];
     976             : 
     977             :   /* remove y from the parent chain */
     978   112950657 :   x->REDBLK_PARENT = y->REDBLK_PARENT;
     979   112950657 :   if (y->REDBLK_PARENT)
     980    96616497 :     if (y == &pool[pool[y->REDBLK_PARENT].REDBLK_LEFT])
     981    45041436 :       pool[y->REDBLK_PARENT].REDBLK_LEFT = (uint)(x - pool);
     982    51575061 :     else
     983    51575061 :       pool[y->REDBLK_PARENT].REDBLK_RIGHT = (uint)(x - pool);
     984    16334160 :   else
     985    16334160 :     *root = x;
     986             : 
     987   112950657 :   if (y->REDBLK_COLOR == REDBLK_BLACK)
     988    92124722 :     REDBLK_(deleteFixup)(pool, root, x);
     989             : 
     990   112950657 :   if (y != z) {
     991             :     /* we got rid of y instead of z. Oops! Replace z with y in the
     992             :      * tree so we don't lose y's key/value. */
     993    31461401 :     y->REDBLK_PARENT = z->REDBLK_PARENT;
     994    31461401 :     y->REDBLK_LEFT = z->REDBLK_LEFT;
     995    31461401 :     y->REDBLK_RIGHT = z->REDBLK_RIGHT;
     996    31461401 :     y->REDBLK_COLOR = z->REDBLK_COLOR;
     997    31461401 :     if (z == *root)
     998    13492888 :       *root = y;
     999    17968513 :     else if (&pool[pool[y->REDBLK_PARENT].REDBLK_LEFT] == z)
    1000     5629829 :       pool[y->REDBLK_PARENT].REDBLK_LEFT = (uint)(y - pool);
    1001    12338684 :     else
    1002    12338684 :       pool[y->REDBLK_PARENT].REDBLK_RIGHT = (uint)(y - pool);
    1003    31461401 :     pool[y->REDBLK_LEFT].REDBLK_PARENT = (uint)(y - pool);
    1004    31461401 :     pool[y->REDBLK_RIGHT].REDBLK_PARENT = (uint)(y - pool);
    1005    31461401 :   }
    1006             : 
    1007   112950657 :   if (*root == &pool[REDBLK_NIL])
    1008    10889451 :     *root = NULL;
    1009   112950657 :   z->REDBLK_COLOR = REDBLK_NEW;
    1010   112950657 :   return z;
    1011   112950657 : }
    1012             : 
    1013             : /*
    1014             :   Search for a key in the tree. In this special case, the key can be a
    1015             :   temporary instance of the node type rather than a properly
    1016             :   allocated node.
    1017             : */
    1018   447792420 : REDBLK_T * REDBLK_(find)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key) {
    1019   447792420 : #ifndef REDBLK_UNSAFE
    1020   447792420 :   REDBLK_(validate_element)(pool, root);
    1021   447792420 : #endif
    1022             : 
    1023   447792420 :   REDBLK_T * current = root;
    1024   447792420 :   if (current == NULL || current == &pool[REDBLK_NIL])
    1025    10886454 :     return NULL;
    1026  1330291451 :   while (current != &pool[REDBLK_NIL]) {
    1027  1232269742 :     long c = REDBLK_(compare)(key, current);
    1028  1232269742 :     if (c == 0)
    1029   338884257 :       return current;
    1030   893385485 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
    1031   893385485 :   }
    1032    98021709 :   return NULL;
    1033   436905966 : }
    1034             : 
    1035             : /*
    1036             :   Search for a key in the tree. If the key can't be found, a nearby
    1037             :   approximation is returned instead. This is either the greatest node
    1038             :   less than the key, or the least node greater than the key. In this
    1039             :   special case, the key can be a temporary instance of the node type
    1040             :   rather than a properly allocated node.
    1041             : */
    1042           0 : REDBLK_T * REDBLK_(nearby)(REDBLK_T * pool, REDBLK_T * root, REDBLK_T * key) {
    1043           0 : #ifndef REDBLK_UNSAFE
    1044           0 :   REDBLK_(validate_element)(pool, root);
    1045           0 : #endif
    1046             : 
    1047           0 :   REDBLK_T * current = root;
    1048           0 :   if (current == NULL || current == &pool[REDBLK_NIL])
    1049           0 :     return NULL;
    1050           0 :   REDBLK_T * result = current;
    1051           0 :   while (current != &pool[REDBLK_NIL]) {
    1052           0 :     result = current; /* Return the last non-NIL node that was touched */
    1053           0 :     long c = REDBLK_(compare)(key, current);
    1054           0 :     if (c == 0)
    1055           0 :       return current;
    1056           0 :     current = (c < 0 ? &pool[current->REDBLK_LEFT] : &pool[current->REDBLK_RIGHT]);
    1057           0 :   }
    1058           0 :   return result;
    1059           0 : }
    1060             : 
    1061             : /*
    1062             :   Count the number of nodes in a tree.
    1063             : */
    1064  3879465943 : ulong REDBLK_(size)(REDBLK_T * pool, REDBLK_T * root) {
    1065  3879465943 : #ifndef REDBLK_UNSAFE
    1066  3879465943 :   REDBLK_(validate_element)(pool, root);
    1067  3879465943 : #endif
    1068  3879465943 :  if (!root || root == &pool[REDBLK_NIL])
    1069  2098007678 :    return 0;
    1070  1781458265 :  return 1 +
    1071  1781458265 :         REDBLK_(size)(pool, &pool[root->REDBLK_LEFT]) +
    1072  1781458265 :         REDBLK_(size)(pool, &pool[root->REDBLK_RIGHT]);
    1073  3879465943 : }
    1074             : 
    1075             : /*
    1076             :   Recursive implementation of the verify function
    1077             : */
    1078  3717056266 : int REDBLK_(verify_private)(REDBLK_T * pool, REDBLK_T * node, REDBLK_T * parent, ulong curblkcnt, ulong correctblkcnt) {
    1079  7272683272 : # define REDBLK_TEST(c) do {                                                        \
    1080  7272683272 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return -1; } \
    1081  7272683272 :   } while(0)
    1082             : 
    1083  3717056266 :   if (!node || node == &pool[REDBLK_NIL]) {
    1084  2016387542 :     REDBLK_TEST(curblkcnt == correctblkcnt);
    1085  2016387542 :     return 0;
    1086  2016387542 :   }
    1087             : 
    1088  1700668724 : #ifndef REDBLK_UNSAFE
    1089  1700668724 :   REDBLK_(validate_element)(pool, node);
    1090  1700668724 : #endif
    1091             :   
    1092  1700668724 :   REDBLK_TEST(&pool[node->REDBLK_PARENT] == parent);
    1093             : 
    1094  1700668724 :   if (node->REDBLK_COLOR == REDBLK_BLACK)
    1095  1094353125 :     ++curblkcnt;
    1096   606315599 :   else {
    1097   606315599 :     REDBLK_TEST(node->REDBLK_COLOR == REDBLK_RED);
    1098   606315599 :     REDBLK_TEST(parent->REDBLK_COLOR == REDBLK_BLACK);
    1099   606315599 :   }
    1100             :   
    1101  1700668724 :   if (node->REDBLK_LEFT != REDBLK_NIL)
    1102   663986375 :     REDBLK_TEST(REDBLK_(compare)(&pool[node->REDBLK_LEFT], node) <= 0);
    1103  1700668724 :   if (node->REDBLK_RIGHT != REDBLK_NIL)
    1104   720963531 :     REDBLK_TEST(REDBLK_(compare)(node, &pool[node->REDBLK_RIGHT]) <= 0);
    1105             : 
    1106  1700668724 :   int err = REDBLK_(verify_private)(pool, &pool[node->REDBLK_LEFT], node, curblkcnt, correctblkcnt);
    1107  1700668724 :   if (err) return err;
    1108  1700668724 :   return REDBLK_(verify_private)(pool, &pool[node->REDBLK_RIGHT], node, curblkcnt, correctblkcnt);
    1109  1700668724 : }
    1110             : 
    1111             : /*
    1112             :   Verify the integrity of the tree data structure. Useful for
    1113             :   debugging memory corruption. A non-zero result is returned if an error
    1114             :   is detected.
    1115             : */
    1116   326608266 : int REDBLK_(verify)(REDBLK_T * pool, REDBLK_T * root) {
    1117   326608266 :   REDBLK_TEST(pool[REDBLK_NIL].REDBLK_LEFT == REDBLK_NIL &&
    1118   326608266 :        pool[REDBLK_NIL].REDBLK_RIGHT == REDBLK_NIL &&
    1119   326608266 :        pool[REDBLK_NIL].REDBLK_COLOR == REDBLK_BLACK);
    1120             : 
    1121   326608266 :   if (!root || root == &pool[REDBLK_NIL])
    1122    10889448 :     return 0; // Trivially correct
    1123   315718818 :   REDBLK_TEST(root->REDBLK_COLOR == REDBLK_BLACK);
    1124             : 
    1125   315718818 :   ulong sz = REDBLK_(size)(pool, root);
    1126   315718818 :   REDBLK_TEST(sz + 1 == REDBLK_POOL_(used)(pool));
    1127             : 
    1128             :   // Compute the correct number of black nodes on a path
    1129   315718818 :   ulong blkcnt = 0;
    1130   315718818 :   REDBLK_T * node = root;
    1131  1047925099 :   while (node != &pool[REDBLK_NIL]) {
    1132   732206281 :     if (node->REDBLK_COLOR == REDBLK_BLACK)
    1133   582355329 :       ++blkcnt;
    1134   732206281 :     node = &pool[node->REDBLK_LEFT];
    1135   732206281 :   }
    1136             :   // Recursive check
    1137   315718818 :   return REDBLK_(verify_private)(pool, root, &pool[REDBLK_NIL], 0, blkcnt);
    1138             : 
    1139   315718818 : #undef REDBLK_TEST
    1140   315718818 : }
    1141             : 
    1142             : #undef REDBLK_FREE
    1143             : #undef REDBLK_NEW
    1144             : #undef REDBLK_BLACK
    1145             : #undef REDBLK_RED
    1146             : #undef REDBLK_POOL_
    1147             : #undef REDBLK_PARENT
    1148             : #undef REDBLK_LEFT
    1149             : #undef REDBLK_RIGHT
    1150             : #undef REDBLK_COLOR
    1151             : 
    1152             : #endif /* REDBLK_IMPL_STYLE==0 || REDBLK_IMPL_STYLE==2 */
    1153             : 
    1154             : #undef REDBLK_
    1155             : #undef REDBLK_T
    1156             : #undef REDBLK_IMPL_STYLE

Generated by: LCOV version 1.14