LCOV - code coverage report
Current view: top level - source/array_tree_map.c (source / functions) Coverage Total Hit
Test: CCC Test Suite Coverage Report Lines: 98.3 % 846 832
Test Date: 2026-06-29 16:04:01 Functions: 100.0 % 96 96

            Line data    Source code
       1              : /** Copyright 2025 Alexander G. Lopez
       2              : 
       3              : Licensed under the Apache License, Version 2.0 (the "License");
       4              : you may not use this file except in compliance with the License.
       5              : You may obtain a copy of the License at
       6              : 
       7              :    http://www.apache.org/licenses/LICENSE-2.0
       8              : 
       9              : Unless required by applicable law or agreed to in writing, software
      10              : distributed under the License is distributed on an "AS IS" BASIS,
      11              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12              : See the License for the specific language governing permissions and
      13              : limitations under the License.
      14              : 
      15              : This file contains my implementation of an array tree ordered map. The added
      16              : tree prefix is to indicate that this map meets specific run time bounds
      17              : that can be relied upon consistently. This is may not be the case if a map
      18              : is implemented with some self-optimizing data structure like a Splay Tree.
      19              : 
      20              : This map, however, promises O(lg N) search, insert, and remove as a true
      21              : upper bound, inclusive. This guarantee does not consider the cost of resizing
      22              : the underlying Struct of Arrays layout. For the strict bound to be met the user
      23              : should reserve space for the needed nodes through the API. Performance could
      24              : still be strong with a more dynamic approach, however, The runtime bound is
      25              : achieved through a Weak AVL (WAVL) tree that is derived from the following two
      26              : sources.
      27              : 
      28              : [1] Bernhard Haeupler, Siddhartha Sen, and Robert E. Tarjan, 2014.
      29              : Rank-Balanced Trees, J.ACM Transactions on Algorithms 11, 4, Article 0
      30              : (June 2015), 24 pages.
      31              : https://sidsen.azurewebsites.net//papers/rb-trees-talg.pdf
      32              : 
      33              : [2] Phil Vachon (pvachon) https://github.com/pvachon/wavl_tree
      34              : This implementation is heavily influential throughout. However there have
      35              : been some major adjustments and simplifications. Namely, the allocation has
      36              : been adjusted to accommodate this library's ability to be an allocating or
      37              : non-allocating container. All left-right symmetric cases have been united
      38              : into one and I chose to tackle rotations and deletions slightly differently,
      39              : shortening the code significantly. A few other changes and improvements
      40              : suggested by the authors of the original paper are implemented. Finally, the
      41              : data structure has been placed into an array with relative indices rather
      42              : than pointers. See the required license at the bottom of the file for
      43              : BSD-2-Clause compliance.
      44              : 
      45              : Overall a WAVL tree is quite impressive for it's simplicity and purported
      46              : improvements over AVL and Red-Black trees. The rank framework is intuitive
      47              : and flexible in how it can be implemented.
      48              : 
      49              : Sorry for the symbol heavy math variable terminology in the WAVL section. It
      50              : is easiest to check work against the research paper if the variable names
      51              : remain the same. Rotations change lineage so there is no less terse approach
      52              : to that section, in my opinion. */
      53              : /** C23 provided headers. */
      54              : #include <limits.h>
      55              : #include <stdalign.h>
      56              : #include <stddef.h>
      57              : #include <stdint.h>
      58              : 
      59              : /** CCC provided headers. */
      60              : #include "ccc/array_tree_map.h"
      61              : #include "ccc/configuration.h" /* IWYU pragma: keep */
      62              : #include "ccc/private/private_array_tree_map.h"
      63              : #include "ccc/types.h"
      64              : 
      65              : /*==========================  Type Declarations   ===========================*/
      66              : 
      67              : /** @internal */
      68              : enum Link : uint8_t {
      69              :     L = 0,
      70              :     R,
      71              : };
      72              : 
      73              : /** @internal To make insertions and removals more efficient we can remember the
      74              : last node encountered on the search for the requested node. It will either be
      75              : the correct node or the parent of the missing node if it is not found. This
      76              : means insertions will not need a second search of the tree and we can insert
      77              : immediately by adding the child. */
      78              : struct Query {
      79              :     /** The last branch direction we took to the found or missing node. */
      80              :     CCC_Order last_order;
      81              :     union {
      82              :         /** The node was found so here is its index in the array. */
      83              :         size_t found;
      84              :         /** The node was not found so here is its direct parent. */
      85              :         size_t parent;
      86              :     };
      87              : };
      88              : 
      89              : #define INORDER R
      90              : #define INORDER_REVERSE L
      91              : 
      92              : enum : uint8_t {
      93              :     INSERT_ROOT_COUNT = 2,
      94              : };
      95              : 
      96              : /** @internal A block of parity bits. */
      97              : typedef typeof(*(struct CCC_Array_tree_map){}.parity) Parity_block;
      98              : 
      99              : enum : size_t {
     100              :     /** @internal Test capacity. */
     101              :     TCAP = 3,
     102              :     /* @internal Alignment of node type. */
     103              :     ALIGNOF_NODE = alignof(struct CCC_Array_tree_map_node),
     104              :     /** @internal Size of node type. */
     105              :     SIZEOF_NODE = sizeof(struct CCC_Array_tree_map_node),
     106              :     /** @internal Alignment of parity block. */
     107              :     ALIGNOF_PARITY = alignof(Parity_block),
     108              :     /** @internal Size of parity block. */
     109              :     SIZEOF_PARITY = sizeof(Parity_block),
     110              :     /** @internal The number of bits in a block of parity bits. */
     111              :     PARITY_BLOCK_BITS = SIZEOF_PARITY * CHAR_BIT,
     112              :     /** @internal Hand calculated log2 of block bits for a fast shift rather
     113              :         than division. No reasonable compile time calculation for this in C. */
     114              :     PARITY_BLOCK_BITS_LOG2 = 5,
     115              : };
     116              : static_assert(
     117              :     PARITY_BLOCK_BITS >> PARITY_BLOCK_BITS_LOG2 == 1,
     118              :     "hand coded log2 of parity block bits is always correct"
     119              : );
     120              : 
     121              : /*========================   Data Alignment Test   ==========================*/
     122              : 
     123              : /** @internal A macro version of the runtime alignment operations we perform
     124              : for calculating bytes. This way we can use in static assert. The user data type
     125              : may not be the same alignment as the nodes and therefore the nodes array must
     126              : start at next aligned byte. Similarly the parity array may not be on an aligned
     127              : byte after the nodes array, though in the current implementation it is.
     128              : Regardless, we always ensure the position is correct with respect to power of
     129              : two alignments in C. */
     130              : #define roundup(bytes_to_round, alignment)                                     \
     131              :     (((bytes_to_round) + (alignment) - 1) & ~((alignment) - 1))
     132              : 
     133              : /** @internal This is a static fixed size map exclusive to this translation unit
     134              : used to ensure assumptions about data layout are correct. The following static
     135              : asserts must be true in order to support the Struct of Array style layout we
     136              : use for the data, nodes, and parity arrays. It is important that in our user
     137              : code when we set the positions of the nodes and parity pointers relative to the
     138              : data pointer the positions are correct regardless of if our backing storage is
     139              : a fixed map or heap allocation.
     140              : 
     141              : Use an int because that will force the nodes array to be wary of
     142              : where to start. The nodes are 8 byte aligned but an int is 4. This means the
     143              : nodes need to start after 4 byte buffer of padding at end of data array. */
     144              : static __auto_type const static_data_nodes_parity_layout_test
     145              :     = CCC_private_array_tree_map_storage_for((int const[TCAP]){});
     146              : /** Some assumptions in the code assume that parity array is last so ensure that
     147              : is the case here. Also good to assume user data comes first. */
     148              : static_assert(
     149              :     ((char const *)static_data_nodes_parity_layout_test.data
     150              :      < (char const *)static_data_nodes_parity_layout_test.nodes),
     151              :     "The order of the arrays in a Struct of Arrays map is user data "
     152              :     "first, nodes second."
     153              : );
     154              : static_assert(
     155              :     ((char const *)static_data_nodes_parity_layout_test.nodes
     156              :      < (char const *)static_data_nodes_parity_layout_test.parity),
     157              :     "The order of the arrays in a Struct of Arrays map is internal "
     158              :     "nodes second, parity third."
     159              : );
     160              : static_assert(
     161              :     (char const *)static_data_nodes_parity_layout_test.data
     162              :         < (char const *)static_data_nodes_parity_layout_test.parity,
     163              :     "The order of the arrays in a Struct of Arrays map is data, then "
     164              :     "nodes, then parity."
     165              : );
     166              : /** We don't care about the alignment or padding after the parity array because
     167              : we never need to set or move any pointers to that position. The alignment is
     168              : important for the nodes and parity pointer to be set to the correct aligned
     169              : positions and so that we allocate enough bytes for our single allocation if
     170              : the map is dynamic and not a fixed type. */
     171              : static_assert(
     172              :     (char const *)&static_data_nodes_parity_layout_test
     173              :                 .parity[CCC_private_array_tree_map_blocks(TCAP)]
     174              :             - (char const *)&static_data_nodes_parity_layout_test.data[0]
     175              :         == roundup(
     176              :                (sizeof(*static_data_nodes_parity_layout_test.data) * TCAP),
     177              :                ALIGNOF_NODE
     178              :            ) + roundup((SIZEOF_NODE * TCAP), ALIGNOF_PARITY)
     179              :                + (SIZEOF_PARITY * CCC_private_array_tree_map_blocks(TCAP)),
     180              :     "The pointer difference in bytes between end of parity bit array and start "
     181              :     "of user data array must be the same as the total bytes we assume to be "
     182              :     "stored in that range. Alignment of user data must be considered."
     183              : );
     184              : static_assert(
     185              :     (char const *)&static_data_nodes_parity_layout_test.data
     186              :             + roundup(
     187              :                 (sizeof(*static_data_nodes_parity_layout_test.data) * TCAP),
     188              :                 ALIGNOF_NODE
     189              :             )
     190              :         == (char const *)&static_data_nodes_parity_layout_test.nodes,
     191              :     "The start of the nodes array must begin at the next aligned "
     192              :     "byte given alignment of a node."
     193              : );
     194              : static_assert(
     195              :     (char const *)&static_data_nodes_parity_layout_test.parity
     196              :         == ((char const *)&static_data_nodes_parity_layout_test.data
     197              :             + roundup(
     198              :                 (sizeof(*static_data_nodes_parity_layout_test.data) * TCAP),
     199              :                 ALIGNOF_NODE
     200              :             )
     201              :             + roundup((SIZEOF_NODE * TCAP), ALIGNOF_PARITY)),
     202              :     "The start of the parity array must begin at the next aligned byte given "
     203              :     "alignment of both the data and nodes array."
     204              : );
     205              : static_assert(
     206              :     ALIGNOF_NODE >= ALIGNOF_PARITY,
     207              :     "Parity bit array is always aligned after node array without any special "
     208              :     "alignment or padding considerations."
     209              : );
     210              : 
     211              : /*==============================  Prototypes   ==============================*/
     212              : 
     213              : static void insert(struct CCC_Array_tree_map *, size_t, CCC_Order, size_t);
     214              : static CCC_Result
     215              : resize(struct CCC_Array_tree_map *, size_t, CCC_Allocator const *);
     216              : static void
     217              : resize_struct_of_arrays(struct CCC_Array_tree_map const *, void *, size_t);
     218              : static size_t data_bytes(size_t, size_t);
     219              : static size_t nodes_bytes(size_t);
     220              : static size_t parities_bytes(size_t);
     221              : static struct CCC_Array_tree_map_node *
     222              : nodes_base_address(size_t, void const *, size_t);
     223              : static Parity_block *parities_base_address(size_t, void const *, size_t);
     224              : static size_t maybe_allocate_insert(
     225              :     struct CCC_Array_tree_map *,
     226              :     size_t,
     227              :     CCC_Order,
     228              :     void const *,
     229              :     CCC_Allocator const *
     230              : );
     231              : static size_t remove_fixup(struct CCC_Array_tree_map *, size_t);
     232              : static size_t allocate_slot(struct CCC_Array_tree_map *, CCC_Allocator const *);
     233              : static void
     234              : delete_nodes(struct CCC_Array_tree_map const *, CCC_Destructor const *);
     235              : static void *key_at(struct CCC_Array_tree_map const *, size_t);
     236              : static void *key_in_slot(struct CCC_Array_tree_map const *, void const *);
     237              : static struct CCC_Array_tree_map_node *
     238              : node_at(struct CCC_Array_tree_map const *, size_t);
     239              : static void *data_at(struct CCC_Array_tree_map const *, size_t);
     240              : static struct Query find(struct CCC_Array_tree_map const *, void const *);
     241              : static struct CCC_Array_tree_map_handle
     242              : handle(struct CCC_Array_tree_map const *, void const *);
     243              : static CCC_Handle_range equal_range(
     244              :     struct CCC_Array_tree_map const *, void const *, void const *, enum Link
     245              : );
     246              : static CCC_Order
     247              : order_nodes(struct CCC_Array_tree_map const *, void const *, size_t);
     248              : static size_t sibling_of(struct CCC_Array_tree_map const *, size_t);
     249              : static size_t next(struct CCC_Array_tree_map const *, size_t, enum Link);
     250              : static size_t
     251              : min_max_from(struct CCC_Array_tree_map const *, size_t, enum Link);
     252              : static size_t
     253              : branch_index(struct CCC_Array_tree_map const *, size_t, enum Link);
     254              : static size_t parent_index(struct CCC_Array_tree_map const *, size_t);
     255              : static size_t *
     256              : branch_pointer(struct CCC_Array_tree_map const *, size_t, enum Link);
     257              : static size_t *parent_pointer(struct CCC_Array_tree_map const *, size_t);
     258              : static CCC_Tribool
     259              : is_0_child(struct CCC_Array_tree_map const *, size_t, size_t);
     260              : static CCC_Tribool
     261              : is_1_child(struct CCC_Array_tree_map const *, size_t, size_t);
     262              : static CCC_Tribool
     263              : is_2_child(struct CCC_Array_tree_map const *, size_t, size_t);
     264              : static CCC_Tribool
     265              : is_3_child(struct CCC_Array_tree_map const *, size_t, size_t);
     266              : static CCC_Tribool
     267              : is_01_parent(struct CCC_Array_tree_map const *, size_t, size_t, size_t);
     268              : static CCC_Tribool
     269              : is_11_parent(struct CCC_Array_tree_map const *, size_t, size_t, size_t);
     270              : static CCC_Tribool
     271              : is_02_parent(struct CCC_Array_tree_map const *, size_t, size_t, size_t);
     272              : static CCC_Tribool
     273              : is_22_parent(struct CCC_Array_tree_map const *, size_t, size_t, size_t);
     274              : static CCC_Tribool is_leaf(struct CCC_Array_tree_map const *, size_t);
     275              : static CCC_Tribool parity(struct CCC_Array_tree_map const *, size_t);
     276              : static void set_parity(struct CCC_Array_tree_map const *, size_t, CCC_Tribool);
     277              : static size_t total_bytes(size_t, size_t);
     278              : static size_t block_count(size_t);
     279              : static CCC_Tribool validate(struct CCC_Array_tree_map const *);
     280              : static void init_node(struct CCC_Array_tree_map const *, size_t);
     281              : static void insert_fixup(struct CCC_Array_tree_map *, size_t, size_t);
     282              : static void rebalance_3_child(struct CCC_Array_tree_map *, size_t, size_t);
     283              : static void transplant(struct CCC_Array_tree_map *, size_t, size_t);
     284              : static void promote(struct CCC_Array_tree_map const *, size_t);
     285              : static void demote(struct CCC_Array_tree_map const *, size_t);
     286              : static void double_promote(struct CCC_Array_tree_map const *, size_t);
     287              : static void double_demote(struct CCC_Array_tree_map const *, size_t);
     288              : static void
     289              : rotate(struct CCC_Array_tree_map *, size_t, size_t, size_t, enum Link);
     290              : static void
     291              : double_rotate(struct CCC_Array_tree_map *, size_t, size_t, size_t, enum Link);
     292              : static void swap(void *, size_t, void *, void *);
     293              : static size_t max_size_t(size_t, size_t);
     294              : 
     295              : /*==============================  Interface    ==============================*/
     296              : 
     297              : void *
     298        16783 : CCC_array_tree_map_at(
     299              :     CCC_Array_tree_map const *const map, CCC_Handle_index const index
     300              : ) {
     301        16783 :     if (!map || !index) {
     302           13 :         return NULL;
     303              :     }
     304        16770 :     return data_at(map, index);
     305        16783 : }
     306              : 
     307              : CCC_Tribool
     308           66 : CCC_array_tree_map_contains(
     309              :     CCC_Array_tree_map const *const map, void const *const key
     310              : ) {
     311           66 :     if (!map || !key) {
     312            2 :         return CCC_TRIBOOL_ERROR;
     313              :     }
     314           64 :     return CCC_ORDER_EQUAL == find(map, key).last_order;
     315           66 : }
     316              : 
     317              : CCC_Handle_index
     318         2017 : CCC_array_tree_map_get_key_value(
     319              :     CCC_Array_tree_map const *const map, void const *const key
     320              : ) {
     321         2017 :     if (!map || !key) {
     322            2 :         return 0;
     323              :     }
     324         2015 :     struct Query const q = find(map, key);
     325         2015 :     return (CCC_ORDER_EQUAL == q.last_order) ? q.found : 0;
     326         2017 : }
     327              : 
     328              : CCC_Handle
     329         3598 : CCC_array_tree_map_swap_handle(
     330              :     CCC_Array_tree_map *const map,
     331              :     void *const type_output,
     332              :     CCC_Allocator const *const allocator
     333              : ) {
     334         3598 :     if (!map || !type_output || !allocator) {
     335            3 :         return (CCC_Handle){.status = CCC_ENTRY_ARGUMENT_ERROR};
     336              :     }
     337         3595 :     struct Query const q = find(map, key_in_slot(map, type_output));
     338         3595 :     if (CCC_ORDER_EQUAL == q.last_order) {
     339          834 :         void *const slot = data_at(map, q.found);
     340          834 :         void *const temp = data_at(map, 0);
     341          834 :         swap(temp, map->sizeof_type, type_output, slot);
     342         1668 :         return (CCC_Handle){
     343          834 :             .index = q.found,
     344              :             .status = CCC_ENTRY_OCCUPIED,
     345              :         };
     346          834 :     }
     347         5522 :     size_t const i = maybe_allocate_insert(
     348         2761 :         map, q.parent, q.last_order, type_output, allocator
     349              :     );
     350         2761 :     if (!i) {
     351            1 :         return (CCC_Handle){
     352              :             .index = 0,
     353              :             .status = CCC_ENTRY_INSERT_ERROR,
     354              :         };
     355              :     }
     356         5520 :     return (CCC_Handle){
     357         2760 :         .index = i,
     358              :         .status = CCC_ENTRY_VACANT,
     359              :     };
     360         3598 : }
     361              : 
     362              : CCC_Handle
     363          225 : CCC_array_tree_map_try_insert(
     364              :     CCC_Array_tree_map *const map,
     365              :     void const *const type,
     366              :     CCC_Allocator const *const allocator
     367              : ) {
     368          225 :     if (!map || !type || !allocator) {
     369            4 :         return (CCC_Handle){.status = CCC_ENTRY_ARGUMENT_ERROR};
     370              :     }
     371          221 :     struct Query const q = find(map, key_in_slot(map, type));
     372          221 :     if (CCC_ORDER_EQUAL == q.last_order) {
     373           90 :         return (CCC_Handle){
     374           45 :             .index = q.found,
     375              :             .status = CCC_ENTRY_OCCUPIED,
     376              :         };
     377              :     }
     378          352 :     size_t const i
     379          176 :         = maybe_allocate_insert(map, q.parent, q.last_order, type, allocator);
     380          176 :     if (!i) {
     381            1 :         return (CCC_Handle){
     382              :             .index = 0,
     383              :             .status = CCC_ENTRY_INSERT_ERROR,
     384              :         };
     385              :     }
     386          350 :     return (CCC_Handle){
     387          175 :         .index = i,
     388              :         .status = CCC_ENTRY_VACANT,
     389              :     };
     390          225 : }
     391              : 
     392              : CCC_Handle
     393         2006 : CCC_array_tree_map_insert_or_assign(
     394              :     CCC_Array_tree_map *const map,
     395              :     void const *const type,
     396              :     CCC_Allocator const *const allocator
     397              : ) {
     398         2006 :     if (!map || !type || !allocator) {
     399            3 :         return (CCC_Handle){.status = CCC_ENTRY_ARGUMENT_ERROR};
     400              :     }
     401         2003 :     struct Query const q = find(map, key_in_slot(map, type));
     402         2003 :     if (CCC_ORDER_EQUAL == q.last_order) {
     403            3 :         void *const found = data_at(map, q.found);
     404            3 :         (void)memcpy(found, type, map->sizeof_type);
     405            6 :         return (CCC_Handle){
     406            3 :             .index = q.found,
     407              :             .status = CCC_ENTRY_OCCUPIED,
     408              :         };
     409            3 :     }
     410         4000 :     size_t const i
     411         2000 :         = maybe_allocate_insert(map, q.parent, q.last_order, type, allocator);
     412         2000 :     if (!i) {
     413            3 :         return (CCC_Handle){
     414              :             .index = 0,
     415              :             .status = CCC_ENTRY_INSERT_ERROR,
     416              :         };
     417              :     }
     418         3994 :     return (CCC_Handle){
     419         1997 :         .index = i,
     420              :         .status = CCC_ENTRY_VACANT,
     421              :     };
     422         2006 : }
     423              : 
     424              : CCC_Array_tree_map_handle *
     425          112 : CCC_array_tree_map_and_modify(
     426              :     CCC_Array_tree_map_handle *const handle, CCC_Modifier const *const modifier
     427              : ) {
     428          112 :     if (!handle || !modifier) {
     429            2 :         return NULL;
     430              :     }
     431          110 :     if (modifier->modify && handle->status & CCC_ENTRY_OCCUPIED
     432          110 :         && handle->index > 0) {
     433          168 :         modifier->modify((CCC_Arguments){
     434           56 :             .type = data_at(handle->map, handle->index),
     435           56 :             modifier->context,
     436              :         });
     437           56 :     }
     438          110 :     return handle;
     439          112 : }
     440              : 
     441              : CCC_Handle_index
     442          262 : CCC_array_tree_map_or_insert(
     443              :     CCC_Array_tree_map_handle const *const h,
     444              :     void const *const type,
     445              :     CCC_Allocator const *const allocator
     446              : ) {
     447          262 :     if (!h || !type || !allocator) {
     448            3 :         return 0;
     449              :     }
     450          259 :     if (h->status == CCC_ENTRY_OCCUPIED) {
     451          153 :         return h->index;
     452              :     }
     453          106 :     return maybe_allocate_insert(
     454          106 :         h->map, h->index, h->last_order, type, allocator
     455              :     );
     456          262 : }
     457              : 
     458              : CCC_Handle_index
     459         8381 : CCC_array_tree_map_insert_handle(
     460              :     CCC_Array_tree_map_handle const *const h,
     461              :     void const *const type,
     462              :     CCC_Allocator const *const allocator
     463              : ) {
     464         8381 :     if (!h || !type || !allocator) {
     465            3 :         return 0;
     466              :     }
     467         8378 :     if (h->status == CCC_ENTRY_OCCUPIED) {
     468         3105 :         void *const slot = data_at(h->map, h->index);
     469         3105 :         if (slot != type) {
     470         3105 :             (void)memcpy(slot, type, h->map->sizeof_type);
     471         3105 :         }
     472         3105 :         return h->index;
     473         3105 :     }
     474         5273 :     return maybe_allocate_insert(
     475         5273 :         h->map, h->index, h->last_order, type, allocator
     476              :     );
     477         8381 : }
     478              : 
     479              : CCC_Array_tree_map_handle
     480        13044 : CCC_array_tree_map_handle(
     481              :     CCC_Array_tree_map const *const map, void const *const key
     482              : ) {
     483        13044 :     if (!map || !key) {
     484            2 :         return (CCC_Array_tree_map_handle){
     485              :             .status = CCC_ENTRY_ARGUMENT_ERROR,
     486              :         };
     487              :     }
     488        13042 :     return handle(map, key);
     489        13044 : }
     490              : 
     491              : CCC_Handle
     492           55 : CCC_array_tree_map_remove_handle(CCC_Array_tree_map_handle const *const h) {
     493           55 :     if (!h) {
     494            1 :         return (CCC_Handle){.status = CCC_ENTRY_ARGUMENT_ERROR};
     495              :     }
     496           54 :     if (h->status == CCC_ENTRY_OCCUPIED) {
     497           44 :         size_t const ret = remove_fixup(h->map, h->index);
     498           88 :         return (CCC_Handle){
     499           44 :             .index = ret,
     500              :             .status = CCC_ENTRY_OCCUPIED,
     501              :         };
     502           44 :     }
     503           10 :     return (CCC_Handle){
     504              :         .index = 0,
     505              :         .status = CCC_ENTRY_VACANT,
     506              :     };
     507           55 : }
     508              : 
     509              : CCC_Handle
     510         2309 : CCC_array_tree_map_remove_key_value(
     511              :     CCC_Array_tree_map *const map, void *const type_output
     512              : ) {
     513         2309 :     if (!map || !type_output) {
     514            2 :         return (CCC_Handle){.status = CCC_ENTRY_ARGUMENT_ERROR};
     515              :     }
     516         2307 :     struct Query const q = find(map, key_in_slot(map, type_output));
     517         2307 :     if (q.last_order != CCC_ORDER_EQUAL) {
     518            3 :         return (CCC_Handle){
     519              :             .index = 0,
     520              :             .status = CCC_ENTRY_VACANT,
     521              :         };
     522              :     }
     523         2304 :     size_t const removed = remove_fixup(map, q.found);
     524         2304 :     assert(removed);
     525         2304 :     void const *const r = data_at(map, removed);
     526         2304 :     if (type_output != r) {
     527         2304 :         (void)memcpy(type_output, r, map->sizeof_type);
     528         2304 :     }
     529         2304 :     return (CCC_Handle){
     530              :         .index = 0,
     531              :         .status = CCC_ENTRY_OCCUPIED,
     532              :     };
     533         2309 : }
     534              : 
     535              : CCC_Handle_range
     536            8 : CCC_array_tree_map_equal_range(
     537              :     CCC_Array_tree_map const *const map,
     538              :     void const *const begin_key,
     539              :     void const *const end_key
     540              : ) {
     541            8 :     if (!map || !begin_key || !end_key) {
     542            3 :         return (CCC_Handle_range){};
     543              :     }
     544            5 :     return equal_range(map, begin_key, end_key, INORDER);
     545            8 : }
     546              : 
     547              : CCC_Handle_range_reverse
     548            8 : CCC_array_tree_map_equal_range_reverse(
     549              :     CCC_Array_tree_map const *const map,
     550              :     void const *const reverse_begin_key,
     551              :     void const *const reverse_end_key
     552              : ) {
     553            8 :     if (!map || !reverse_begin_key || !reverse_end_key) {
     554            3 :         return (CCC_Handle_range_reverse){};
     555              :     }
     556            5 :     CCC_Handle_range const range
     557            5 :         = equal_range(map, reverse_begin_key, reverse_end_key, INORDER_REVERSE);
     558           15 :     return (CCC_Handle_range_reverse){
     559            5 :         .reverse_begin = range.begin,
     560            5 :         .reverse_end = range.end,
     561              :     };
     562            8 : }
     563              : 
     564              : CCC_Handle_index
     565           16 : CCC_array_tree_map_unwrap(CCC_Array_tree_map_handle const *const h) {
     566           16 :     if (h && h->status & CCC_ENTRY_OCCUPIED && h->index > 0) {
     567           15 :         return h->index;
     568              :     }
     569            1 :     return 0;
     570           16 : }
     571              : 
     572              : CCC_Tribool
     573            3 : CCC_array_tree_map_insert_error(CCC_Array_tree_map_handle const *const h) {
     574            3 :     if (!h) {
     575            2 :         return CCC_TRIBOOL_ERROR;
     576              :     }
     577            1 :     return (h->status & CCC_ENTRY_INSERT_ERROR) != 0;
     578            3 : }
     579              : 
     580              : CCC_Tribool
     581           84 : CCC_array_tree_map_occupied(CCC_Array_tree_map_handle const *const h) {
     582           84 :     if (!h) {
     583            1 :         return CCC_TRIBOOL_ERROR;
     584              :     }
     585           83 :     return (h->status & CCC_ENTRY_OCCUPIED) != 0;
     586           84 : }
     587              : 
     588              : CCC_Handle_status
     589            2 : CCC_array_tree_map_handle_status(CCC_Array_tree_map_handle const *const h) {
     590            2 :     return h ? h->status : CCC_ENTRY_ARGUMENT_ERROR;
     591              : }
     592              : 
     593              : CCC_Tribool
     594           31 : CCC_array_tree_map_is_empty(CCC_Array_tree_map const *const map) {
     595           31 :     if (!map) {
     596            1 :         return CCC_TRIBOOL_ERROR;
     597              :     }
     598           30 :     return !CCC_array_tree_map_count(map).count;
     599           31 : }
     600              : 
     601              : CCC_Count
     602          184 : CCC_array_tree_map_count(CCC_Array_tree_map const *const map) {
     603          184 :     if (!map) {
     604            1 :         return (CCC_Count){.error = CCC_RESULT_ARGUMENT_ERROR};
     605              :     }
     606          183 :     if (!map->count) {
     607           24 :         return (CCC_Count){.count = 0};
     608              :     }
     609              :     /* The root slot is occupied at 0 but don't don't tell user. */
     610          318 :     return (CCC_Count){
     611          159 :         .count = map->count - 1,
     612              :     };
     613          184 : }
     614              : 
     615              : CCC_Count
     616           13 : CCC_array_tree_map_capacity(CCC_Array_tree_map const *const map) {
     617           13 :     if (!map) {
     618            1 :         return (CCC_Count){.error = CCC_RESULT_ARGUMENT_ERROR};
     619              :     }
     620           24 :     return (CCC_Count){
     621           12 :         .count = map->capacity,
     622              :     };
     623           13 : }
     624              : 
     625              : CCC_Handle_index
     626           17 : CCC_array_tree_map_begin(CCC_Array_tree_map const *const map) {
     627           17 :     if (!map || !map->capacity) {
     628            3 :         return 0;
     629              :     }
     630           14 :     size_t const n = min_max_from(map, map->root, L);
     631           14 :     return n;
     632           17 : }
     633              : 
     634              : CCC_Handle_index
     635            3 : CCC_array_tree_map_reverse_begin(CCC_Array_tree_map const *const map) {
     636            3 :     if (!map || !map->capacity) {
     637            1 :         return 0;
     638              :     }
     639            2 :     size_t const n = min_max_from(map, map->root, R);
     640            2 :     return n;
     641            3 : }
     642              : 
     643              : CCC_Handle_index
     644         3021 : CCC_array_tree_map_next(
     645              :     CCC_Array_tree_map const *const map, CCC_Handle_index iterator
     646              : ) {
     647         3021 :     if (!map || !iterator || !map->capacity) {
     648            1 :         return 0;
     649              :     }
     650         3020 :     size_t const n = next(map, iterator, INORDER);
     651         3020 :     return n;
     652         3021 : }
     653              : 
     654              : CCC_Handle_index
     655         1296 : CCC_array_tree_map_reverse_next(
     656              :     CCC_Array_tree_map const *const map, CCC_Handle_index iterator
     657              : ) {
     658         1296 :     if (!map || !iterator || !map->capacity) {
     659            1 :         return 0;
     660              :     }
     661         1295 :     size_t const n = next(map, iterator, INORDER_REVERSE);
     662         1295 :     return n;
     663         1296 : }
     664              : 
     665              : CCC_Handle_index
     666         4295 : CCC_array_tree_map_end(CCC_Array_tree_map const *const) {
     667         4295 :     return 0;
     668              : }
     669              : 
     670              : CCC_Handle_index
     671            4 : CCC_array_tree_map_reverse_end(CCC_Array_tree_map const *const) {
     672            4 :     return 0;
     673              : }
     674              : 
     675              : CCC_Result
     676           16 : CCC_array_tree_map_reserve(
     677              :     CCC_Array_tree_map *const map,
     678              :     size_t const to_add,
     679              :     CCC_Allocator const *const allocator
     680              : ) {
     681           16 :     if (!map || !to_add || !allocator || !allocator->allocate) {
     682            3 :         return CCC_RESULT_ARGUMENT_ERROR;
     683              :     }
     684           13 :     size_t const needed = map->count + to_add + (map->count == 0);
     685           13 :     if (needed <= map->capacity) {
     686            1 :         return CCC_RESULT_OK;
     687              :     }
     688           12 :     size_t const old_count = map->count;
     689           12 :     size_t old_cap = map->capacity;
     690           12 :     CCC_Result const r = resize(map, needed, allocator);
     691           12 :     if (r != CCC_RESULT_OK) {
     692            1 :         return r;
     693              :     }
     694           11 :     set_parity(map, 0, CCC_TRUE);
     695           11 :     if (!old_cap) {
     696           11 :         map->count = 1;
     697           11 :     }
     698           11 :     old_cap = old_count ? old_cap : 0;
     699           11 :     size_t const new_cap = map->capacity;
     700           11 :     size_t prev = 0;
     701           11 :     size_t i = new_cap;
     702         1509 :     while (i--) {
     703         1509 :         if (i <= old_cap) {
     704           11 :             break;
     705              :         }
     706         1498 :         node_at(map, i)->next_free = prev;
     707         1498 :         prev = i;
     708              :     }
     709           11 :     if (!map->free_list) {
     710           11 :         map->free_list = prev;
     711           11 :     }
     712           11 :     return CCC_RESULT_OK;
     713           16 : }
     714              : 
     715              : CCC_Result
     716            7 : CCC_array_tree_map_copy(
     717              :     CCC_Array_tree_map *const destination,
     718              :     CCC_Array_tree_map const *const source,
     719              :     CCC_Allocator const *const allocator
     720              : ) {
     721            7 :     if (!destination || !source || !allocator || source == destination
     722            6 :         || (destination->capacity < source->capacity && !allocator->allocate)) {
     723            2 :         return CCC_RESULT_ARGUMENT_ERROR;
     724              :     }
     725            5 :     if (!source->capacity) {
     726            1 :         return CCC_RESULT_OK;
     727              :     }
     728            4 :     if (destination->capacity < source->capacity) {
     729            3 :         CCC_Result const r = resize(destination, source->capacity, allocator);
     730            3 :         if (r != CCC_RESULT_OK) {
     731            1 :             return r;
     732              :         }
     733            3 :     } else {
     734              :         /* Might not be necessary but not worth finding out. Do every time. */
     735            1 :         destination->nodes = nodes_base_address(
     736            1 :             destination->sizeof_type, destination->data, destination->capacity
     737              :         );
     738            1 :         destination->parity = parities_base_address(
     739            1 :             destination->sizeof_type, destination->data, destination->capacity
     740              :         );
     741              :     }
     742            3 :     if (!destination->data || !source->data) {
     743            1 :         return CCC_RESULT_ARGUMENT_ERROR;
     744              :     }
     745            2 :     resize_struct_of_arrays(source, destination->data, destination->capacity);
     746            2 :     destination->free_list = source->free_list;
     747            2 :     destination->root = source->root;
     748            2 :     destination->count = source->count;
     749            2 :     destination->comparator = source->comparator;
     750            2 :     destination->sizeof_type = source->sizeof_type;
     751            2 :     destination->key_offset = source->key_offset;
     752            2 :     return CCC_RESULT_OK;
     753            7 : }
     754              : 
     755              : CCC_Result
     756            2 : CCC_array_tree_map_clear(
     757              :     CCC_Array_tree_map *const map, CCC_Destructor const *const destructor
     758              : ) {
     759            2 :     if (!map || !destructor) {
     760            1 :         return CCC_RESULT_ARGUMENT_ERROR;
     761              :     }
     762            1 :     if (destructor->destroy) {
     763            1 :         delete_nodes(map, destructor);
     764            1 :     }
     765            1 :     map->count = 1;
     766            1 :     map->root = 0;
     767            1 :     return CCC_RESULT_OK;
     768            2 : }
     769              : 
     770              : CCC_Result
     771           21 : CCC_array_tree_map_clear_and_free(
     772              :     CCC_Array_tree_map *const map,
     773              :     CCC_Destructor const *const destructor,
     774              :     CCC_Allocator const *const allocator
     775              : ) {
     776           21 :     if (!map || !destructor || !allocator || !allocator->allocate) {
     777            3 :         return CCC_RESULT_ARGUMENT_ERROR;
     778              :     }
     779           18 :     if (destructor->destroy) {
     780            1 :         delete_nodes(map, destructor);
     781            1 :     }
     782           18 :     map->root = 0;
     783           18 :     map->count = 0;
     784           18 :     map->capacity = 0;
     785           72 :     (void)allocator->allocate((CCC_Allocator_arguments){
     786           18 :         .input = map->data,
     787              :         .bytes = 0,
     788           18 :         .alignment = max_size_t(ALIGNOF_NODE, map->alignof_type),
     789           18 :         .context = allocator->context,
     790              :     });
     791           18 :     map->data = NULL;
     792           18 :     map->nodes = NULL;
     793           18 :     map->parity = NULL;
     794           18 :     return CCC_RESULT_OK;
     795           21 : }
     796              : 
     797              : CCC_Tribool
     798         9906 : CCC_array_tree_map_validate(CCC_Array_tree_map const *const map) {
     799         9906 :     if (!map) {
     800            1 :         return CCC_TRIBOOL_ERROR;
     801              :     }
     802         9905 :     return validate(map);
     803         9906 : }
     804              : 
     805              : /*========================  Private Interface  ==============================*/
     806              : 
     807              : void
     808          144 : CCC_private_array_tree_map_insert(
     809              :     struct CCC_Array_tree_map *const map,
     810              :     size_t const parent_i,
     811              :     CCC_Order const last_order,
     812              :     size_t const elem_i
     813              : ) {
     814          144 :     insert(map, parent_i, last_order, elem_i);
     815          144 : }
     816              : 
     817              : struct CCC_Array_tree_map_handle
     818           48 : CCC_private_array_tree_map_handle(
     819              :     struct CCC_Array_tree_map const *const map, void const *const key
     820              : ) {
     821           48 :     return handle(map, key);
     822           48 : }
     823              : 
     824              : void *
     825         2207 : CCC_private_array_tree_map_data_at(
     826              :     struct CCC_Array_tree_map const *const map, size_t const slot
     827              : ) {
     828         2207 :     return data_at(map, slot);
     829              : }
     830              : 
     831              : void *
     832           36 : CCC_private_array_tree_map_key_at(
     833              :     struct CCC_Array_tree_map const *const map, size_t const slot
     834              : ) {
     835           36 :     return key_at(map, slot);
     836              : }
     837              : 
     838              : size_t
     839          146 : CCC_private_array_tree_map_allocate_slot(
     840              :     struct CCC_Array_tree_map *const map, CCC_Allocator const *const allocator
     841              : ) {
     842          146 :     return allocate_slot(map, allocator);
     843              : }
     844              : 
     845              : /*==========================  Static Helpers   ==============================*/
     846              : 
     847              : static size_t
     848        10316 : maybe_allocate_insert(
     849              :     struct CCC_Array_tree_map *const map,
     850              :     size_t const parent,
     851              :     CCC_Order const last_order,
     852              :     void const *const user_type,
     853              :     CCC_Allocator const *const allocator
     854              : ) {
     855        10316 :     size_t const node = allocate_slot(map, allocator);
     856        10316 :     if (!node) {
     857            8 :         return 0;
     858              :     }
     859        10308 :     (void)memcpy(data_at(map, node), user_type, map->sizeof_type);
     860        10308 :     insert(map, parent, last_order, node);
     861        10308 :     return node;
     862        10316 : }
     863              : 
     864              : static size_t
     865        10462 : allocate_slot(
     866              :     struct CCC_Array_tree_map *const map, CCC_Allocator const *const allocator
     867              : ) {
     868              :     /* The end sentinel node will always be at 0. This also means once
     869              :        initialized the internal size for implementer is always at least 1. */
     870        10462 :     size_t const old_count = map->count;
     871        10462 :     size_t old_cap = map->capacity;
     872        10462 :     if (!old_count || old_count == old_cap) {
     873           84 :         assert(!map->free_list);
     874           84 :         if (old_count == old_cap) {
     875           39 :             if (resize(
     876           39 :                     map, max_size_t(old_cap * 2, PARITY_BLOCK_BITS), allocator
     877              :                 )
     878           39 :                 != CCC_RESULT_OK) {
     879           10 :                 return 0;
     880              :             }
     881           29 :         } else {
     882           45 :             map->nodes = nodes_base_address(
     883           45 :                 map->sizeof_type, map->data, map->capacity
     884              :             );
     885           45 :             map->parity = parities_base_address(
     886           45 :                 map->sizeof_type, map->data, map->capacity
     887              :             );
     888              :         }
     889           74 :         old_cap = old_count ? old_cap : 1;
     890           74 :         size_t const new_cap = map->capacity;
     891           74 :         size_t prev = 0;
     892        16970 :         for (size_t i = new_cap - 1; i >= old_cap; prev = i, --i) {
     893        16896 :             node_at(map, i)->next_free = prev;
     894        16896 :         }
     895           74 :         map->free_list = prev;
     896           74 :         map->count = max_size_t(old_count, 1);
     897           74 :         set_parity(map, 0, CCC_TRUE);
     898           74 :     }
     899        10452 :     assert(map->free_list);
     900        10452 :     ++map->count;
     901        10452 :     size_t const slot = map->free_list;
     902        10452 :     map->free_list = node_at(map, slot)->next_free;
     903        10452 :     return slot;
     904        10462 : }
     905              : 
     906              : static CCC_Result
     907           54 : resize(
     908              :     struct CCC_Array_tree_map *const map,
     909              :     size_t const new_capacity,
     910              :     CCC_Allocator const *const allocator
     911              : ) {
     912           54 :     if (!allocator->allocate) {
     913            9 :         return CCC_RESULT_NO_ALLOCATION_FUNCTION;
     914              :     }
     915          180 :     void *const new_data = allocator->allocate((CCC_Allocator_arguments){
     916              :         .input = NULL,
     917           45 :         .bytes = total_bytes(map->sizeof_type, new_capacity),
     918           45 :         .alignment = max_size_t(ALIGNOF_NODE, map->alignof_type),
     919           45 :         .context = allocator->context,
     920              :     });
     921           45 :     if (!new_data) {
     922            3 :         return CCC_RESULT_ALLOCATOR_ERROR;
     923              :     }
     924           42 :     resize_struct_of_arrays(map, new_data, new_capacity);
     925           42 :     map->nodes = nodes_base_address(map->sizeof_type, new_data, new_capacity);
     926           42 :     map->parity
     927           84 :         = parities_base_address(map->sizeof_type, new_data, new_capacity);
     928          168 :     allocator->allocate((CCC_Allocator_arguments){
     929           42 :         .input = map->data,
     930              :         .bytes = 0,
     931           42 :         .alignment = max_size_t(ALIGNOF_NODE, map->alignof_type),
     932           42 :         .context = allocator->context,
     933              :     });
     934           42 :     map->data = new_data;
     935           42 :     map->capacity = new_capacity;
     936           42 :     return CCC_RESULT_OK;
     937           54 : }
     938              : 
     939              : static void
     940        10452 : insert(
     941              :     struct CCC_Array_tree_map *const map,
     942              :     size_t const parent_i,
     943              :     CCC_Order const last_order,
     944              :     size_t const elem_i
     945              : ) {
     946        10452 :     struct CCC_Array_tree_map_node *elem = node_at(map, elem_i);
     947        10452 :     init_node(map, elem_i);
     948        10452 :     if (map->count == INSERT_ROOT_COUNT) {
     949           61 :         map->root = elem_i;
     950           61 :         return;
     951              :     }
     952        10391 :     assert(last_order == CCC_ORDER_GREATER || last_order == CCC_ORDER_LESSER);
     953        10391 :     CCC_Tribool rank_rule_break = CCC_FALSE;
     954        10391 :     if (parent_i) {
     955        10391 :         struct CCC_Array_tree_map_node *parent = node_at(map, parent_i);
     956        10391 :         rank_rule_break = !parent->branch[L] && !parent->branch[R];
     957        10391 :         parent->branch[CCC_ORDER_GREATER == last_order] = elem_i;
     958        10391 :     }
     959        10391 :     elem->parent = parent_i;
     960        10391 :     if (rank_rule_break) {
     961         9390 :         insert_fixup(map, parent_i, elem_i);
     962         9390 :     }
     963        10452 : }
     964              : 
     965              : static struct CCC_Array_tree_map_handle
     966        13090 : handle(struct CCC_Array_tree_map const *const map, void const *const key) {
     967        13090 :     struct Query const q = find(map, key);
     968        13090 :     if (CCC_ORDER_EQUAL == q.last_order) {
     969        30056 :         return (struct CCC_Array_tree_map_handle){
     970         7514 :             .map = (struct CCC_Array_tree_map *)map,
     971         7514 :             .last_order = q.last_order,
     972         7514 :             .index = q.found,
     973              :             .status = CCC_ENTRY_OCCUPIED,
     974              :         };
     975              :     }
     976        22304 :     return (struct CCC_Array_tree_map_handle){
     977         5576 :         .map = (struct CCC_Array_tree_map *)map,
     978         5576 :         .last_order = q.last_order,
     979         5576 :         .index = q.parent,
     980              :         .status = CCC_ENTRY_NO_UNWRAP | CCC_ENTRY_VACANT,
     981              :     };
     982        13090 : }
     983              : 
     984              : static struct Query
     985        23311 : find(struct CCC_Array_tree_map const *const map, void const *const key) {
     986        23311 :     size_t parent = 0;
     987        23311 :     struct Query q = {
     988              :         .last_order = CCC_ORDER_ERROR,
     989        23311 :         .found = map->root,
     990              :     };
     991       199091 :     while (q.found) {
     992       188522 :         q.last_order = order_nodes(map, key, q.found);
     993       188522 :         if (CCC_ORDER_EQUAL == q.last_order) {
     994        12742 :             return q;
     995              :         }
     996       175780 :         parent = q.found;
     997       175780 :         q.found = branch_index(map, q.found, CCC_ORDER_GREATER == q.last_order);
     998              :     }
     999              :     /* Type punning here OK as both union members have same type and size. */
    1000        10569 :     q.parent = parent;
    1001        10569 :     return q;
    1002        23311 : }
    1003              : 
    1004              : static size_t
    1005         4322 : next(
    1006              :     struct CCC_Array_tree_map const *const map,
    1007              :     size_t n,
    1008              :     enum Link const traversal
    1009              : ) {
    1010         4322 :     if (!n) {
    1011            0 :         return 0;
    1012              :     }
    1013         4322 :     assert(!parent_index(map, map->root));
    1014         4322 :     if (branch_index(map, n, traversal)) {
    1015         5644 :         for (n = branch_index(map, n, traversal);
    1016         5644 :              branch_index(map, n, !traversal);
    1017         3321 :              n = branch_index(map, n, !traversal)) {}
    1018         2323 :         return n;
    1019              :     }
    1020         1999 :     size_t p = parent_index(map, n);
    1021         3859 :     for (; p && branch_index(map, p, !traversal) != n;
    1022         1860 :          n = p, p = parent_index(map, p)) {}
    1023         1999 :     return p;
    1024         4322 : }
    1025              : 
    1026              : static CCC_Handle_range
    1027           10 : equal_range(
    1028              :     struct CCC_Array_tree_map const *const map,
    1029              :     void const *const begin_key,
    1030              :     void const *const end_key,
    1031              :     enum Link const traversal
    1032              : ) {
    1033           10 :     if (CCC_array_tree_map_is_empty(map)) {
    1034            2 :         return (CCC_Handle_range){};
    1035              :     }
    1036            8 :     CCC_Order const les_or_grt[2] = {CCC_ORDER_LESSER, CCC_ORDER_GREATER};
    1037            8 :     struct Query b = find(map, begin_key);
    1038            8 :     if (b.last_order == les_or_grt[traversal]) {
    1039            2 :         b.found = next(map, b.found, traversal);
    1040            2 :     }
    1041            8 :     struct Query e = find(map, end_key);
    1042            8 :     if (e.last_order != les_or_grt[!traversal]) {
    1043            5 :         e.found = next(map, e.found, traversal);
    1044            5 :     }
    1045           24 :     return (CCC_Handle_range){
    1046            8 :         .begin = b.found,
    1047            8 :         .end = e.found,
    1048              :     };
    1049           10 : }
    1050              : 
    1051              : static size_t
    1052         1082 : min_max_from(
    1053              :     struct CCC_Array_tree_map const *const map,
    1054              :     size_t start,
    1055              :     enum Link const dir
    1056              : ) {
    1057         1082 :     if (!start) {
    1058            1 :         return 0;
    1059              :     }
    1060         3554 :     for (; branch_index(map, start, dir);
    1061         2473 :          start = branch_index(map, start, dir)) {}
    1062         1081 :     return start;
    1063         1082 : }
    1064              : 
    1065              : /** Deletes all nodes in the tree by calling destructor function on them in
    1066              : linear time and constant space. This function modifies nodes as it deletes the
    1067              : tree elements. Assumes the destructor function is non-null.
    1068              : 
    1069              : This function does not update any count or capacity fields of the map, it
    1070              : simply calls the destructor on each node and removes the nodes references to
    1071              : other tree elements. */
    1072              : static void
    1073            2 : delete_nodes(
    1074              :     struct CCC_Array_tree_map const *const map,
    1075              :     CCC_Destructor const *const destructor
    1076              : ) {
    1077            2 :     size_t node = map->root;
    1078           28 :     while (node) {
    1079           26 :         struct CCC_Array_tree_map_node *const e = node_at(map, node);
    1080           26 :         if (e->branch[L]) {
    1081           11 :             size_t const left = e->branch[L];
    1082           11 :             e->branch[L] = node_at(map, left)->branch[R];
    1083           11 :             node_at(map, left)->branch[R] = node;
    1084           11 :             node = left;
    1085              :             continue;
    1086           11 :         }
    1087           15 :         size_t const next = e->branch[R];
    1088           15 :         e->branch[L] = e->branch[R] = 0;
    1089           15 :         e->parent = 0;
    1090           45 :         destructor->destroy((CCC_Arguments){
    1091           15 :             .type = data_at(map, node),
    1092           15 :             .context = destructor->context,
    1093              :         });
    1094           15 :         node = next;
    1095           26 :     }
    1096            2 : }
    1097              : 
    1098              : static inline CCC_Order
    1099      7041103 : order_nodes(
    1100              :     struct CCC_Array_tree_map const *const map,
    1101              :     void const *const key,
    1102              :     size_t const node
    1103              : ) {
    1104     28164412 :     return map->comparator.compare((CCC_Key_comparator_arguments){
    1105      7041103 :         .key_left = key,
    1106      7041103 :         .type_right = data_at(map, node),
    1107      7041103 :         .context = map->comparator.context,
    1108              :     });
    1109              : }
    1110              : 
    1111              : /** Calculates the number of bytes needed for user data INCLUDING any bytes we
    1112              : need to add to the end of the array such that the following nodes array starts
    1113              : on an aligned byte boundary given the alignment requirements of a node. This
    1114              : means the value returned from this function may or may not be slightly larger
    1115              : then the raw size of just user elements if rounding up must occur. */
    1116              : static inline size_t
    1117          351 : data_bytes(size_t const sizeof_type, size_t const capacity) {
    1118          351 :     return ((sizeof_type * capacity) + ALIGNOF_NODE - 1) & ~(ALIGNOF_NODE - 1);
    1119              : }
    1120              : 
    1121              : /** Calculates the number of bytes needed for the nodes array INCLUDING any
    1122              : bytes we need to add to the end of the array such that the following parity bit
    1123              : array starts on an aligned byte boundary given the alignment requirements of
    1124              : a parity block. This means the value returned from this function may or may not
    1125              : be slightly larger then the raw size of just the nodes array if rounding up must
    1126              : occur. */
    1127              : static inline size_t
    1128          211 : nodes_bytes(size_t const capacity) {
    1129          422 :     return ((SIZEOF_NODE * capacity) + ALIGNOF_PARITY - 1)
    1130          211 :          & ~(ALIGNOF_PARITY - 1);
    1131              : }
    1132              : 
    1133              : /** Calculates the number of bytes needed for the parity block bit array. No
    1134              : rounding up or alignment concerns need apply because this is the last array
    1135              : in the allocation. */
    1136              : static inline size_t
    1137           71 : parities_bytes(size_t const capacity) {
    1138           71 :     return SIZEOF_PARITY * block_count(capacity);
    1139              : }
    1140              : 
    1141              : /** Calculates the number of bytes needed for all arrays in the Struct of Arrays
    1142              : map design INCLUDING any extra padding bytes that need to be added between the
    1143              : data and node arrays and the node and parity arrays. Padding might be needed if
    1144              : the alignment of the type in next array that follows a preceding array is
    1145              : different from the preceding array. In that case it is the preceding array's
    1146              : responsibility to add padding bytes to its end such that the next array begins
    1147              : on an aligned byte boundary for its own type. This means that the bytes returned
    1148              : by this function may be greater than summing the (sizeof(type) * capacity) for
    1149              : each array in the conceptual struct. */
    1150              : static inline size_t
    1151           45 : total_bytes(size_t const sizeof_type, size_t const capacity) {
    1152           90 :     return data_bytes(sizeof_type, capacity) + nodes_bytes(capacity)
    1153           45 :          + parities_bytes(capacity);
    1154              : }
    1155              : 
    1156              : /** Returns the base of the node array relative to the data base pointer. This
    1157              : positions is guaranteed to be the first aligned byte given the alignment of the
    1158              : node type after the data array. The data array has added any necessary padding
    1159              : after it to ensure that the base of the node array is aligned for its type. */
    1160              : static inline struct CCC_Array_tree_map_node *
    1161          140 : nodes_base_address(
    1162              :     size_t const sizeof_type, void const *const data, size_t const capacity
    1163              : ) {
    1164          280 :     return (struct CCC_Array_tree_map_node *)((char *)data
    1165          140 :                                               + data_bytes(
    1166          140 :                                                   sizeof_type, capacity
    1167              :                                               ));
    1168              : }
    1169              : 
    1170              : /** Returns the base of the parity array relative to the data base pointer. This
    1171              : positions is guaranteed to be the first aligned byte given the alignment of the
    1172              : parity block type after the data and node arrays. The node array has added any
    1173              : necessary padding after it to ensure that the base of the parity block array is
    1174              : aligned for its type. */
    1175              : static inline Parity_block *
    1176          140 : parities_base_address(
    1177              :     size_t const sizeof_type, void const *const data, size_t const capacity
    1178              : ) {
    1179          280 :     return (Parity_block *)((char *)data + data_bytes(sizeof_type, capacity)
    1180          140 :                             + nodes_bytes(capacity));
    1181              : }
    1182              : 
    1183              : /** Copies over the Struct of Arrays contained within the one contiguous
    1184              : allocation of the map to the new memory provided. Assumes the new_data pointer
    1185              : points to the base of an allocation that has been allocated with sufficient
    1186              : bytes to support the user data, nodes, and parity arrays for the provided new
    1187              : capacity. */
    1188              : static inline void
    1189           44 : resize_struct_of_arrays(
    1190              :     struct CCC_Array_tree_map const *const source,
    1191              :     void *const destination_data_base,
    1192              :     size_t const destination_capacity
    1193              : ) {
    1194           44 :     if (!source->data) {
    1195           18 :         return;
    1196              :     }
    1197           26 :     assert(destination_capacity >= source->capacity);
    1198           26 :     size_t const sizeof_type = source->sizeof_type;
    1199              :     /* Each section of the allocation "grows" when we re-size so one copy would
    1200              :        not work. Instead each component is copied over allowing each to grow. */
    1201           26 :     (void)memcpy(
    1202           26 :         destination_data_base,
    1203           26 :         source->data,
    1204           26 :         data_bytes(sizeof_type, source->capacity)
    1205              :     );
    1206           26 :     (void)memcpy(
    1207           26 :         nodes_base_address(
    1208           26 :             sizeof_type, destination_data_base, destination_capacity
    1209              :         ),
    1210           26 :         nodes_base_address(sizeof_type, source->data, source->capacity),
    1211           26 :         nodes_bytes(source->capacity)
    1212              :     );
    1213           26 :     (void)memcpy(
    1214           26 :         parities_base_address(
    1215           26 :             sizeof_type, destination_data_base, destination_capacity
    1216              :         ),
    1217           26 :         parities_base_address(sizeof_type, source->data, source->capacity),
    1218           26 :         parities_bytes(source->capacity)
    1219              :     );
    1220           70 : }
    1221              : 
    1222              : static inline void
    1223        10452 : init_node(struct CCC_Array_tree_map const *const map, size_t const node) {
    1224        10452 :     set_parity(map, node, CCC_FALSE);
    1225        10452 :     struct CCC_Array_tree_map_node *const e = node_at(map, node);
    1226        10452 :     e->branch[L] = e->branch[R] = e->parent = 0;
    1227        10452 : }
    1228              : 
    1229              : static inline void
    1230          834 : swap(void *const temp, size_t const sizeof_type, void *const a, void *const b) {
    1231          834 :     if (a == b || !a || !b) {
    1232            0 :         return;
    1233              :     }
    1234          834 :     (void)memcpy(temp, a, sizeof_type);
    1235          834 :     (void)memcpy(a, b, sizeof_type);
    1236          834 :     (void)memcpy(b, temp, sizeof_type);
    1237         1668 : }
    1238              : 
    1239              : static inline struct CCC_Array_tree_map_node *
    1240     29408597 : node_at(struct CCC_Array_tree_map const *const map, size_t const i) {
    1241     29408597 :     return &map->nodes[i];
    1242              : }
    1243              : 
    1244              : static inline void *
    1245     13930156 : data_at(struct CCC_Array_tree_map const *const map, size_t const i) {
    1246     13930156 :     return (char *)map->data + (map->sizeof_type * i);
    1247              : }
    1248              : 
    1249              : static inline Parity_block *
    1250       182601 : block_at(struct CCC_Array_tree_map const *const map, size_t const i) {
    1251              :     static_assert(
    1252              :         (typeof(i))~((typeof(i))0) >= (typeof(i))0,
    1253              :         "shifting to avoid division with power of 2 divisor is only "
    1254              :         "defined for unsigned types"
    1255              :     );
    1256       182601 :     return &map->parity[i >> PARITY_BLOCK_BITS_LOG2];
    1257              : }
    1258              : 
    1259              : static inline Parity_block
    1260       182601 : bit_on(size_t const i) {
    1261              :     static_assert(
    1262              :         (PARITY_BLOCK_BITS & (PARITY_BLOCK_BITS - 1)) == 0,
    1263              :         "the number of bits in a block is always a power of two, "
    1264              :         "avoiding modulo operations."
    1265              :     );
    1266       182601 :     return ((Parity_block)1) << (i & (PARITY_BLOCK_BITS - 1));
    1267              : }
    1268              : 
    1269              : static inline size_t
    1270     21282958 : branch_index(
    1271              :     struct CCC_Array_tree_map const *const map,
    1272              :     size_t const parent,
    1273              :     enum Link const dir
    1274              : ) {
    1275     21282958 :     return node_at(map, parent)->branch[dir];
    1276              : }
    1277              : 
    1278              : static inline size_t
    1279      3571461 : parent_index(struct CCC_Array_tree_map const *const map, size_t const child) {
    1280      3571461 :     return node_at(map, child)->parent;
    1281              : }
    1282              : 
    1283              : static inline CCC_Tribool
    1284       141740 : parity(struct CCC_Array_tree_map const *const map, size_t const node) {
    1285       141740 :     return (*block_at(map, node) & bit_on(node)) != 0;
    1286              : }
    1287              : 
    1288              : static inline void
    1289        11603 : set_parity(
    1290              :     struct CCC_Array_tree_map const *const map,
    1291              :     size_t const node,
    1292              :     CCC_Tribool const status
    1293              : ) {
    1294        11603 :     if (status) {
    1295          472 :         *block_at(map, node) |= bit_on(node);
    1296          472 :     } else {
    1297        11131 :         *block_at(map, node) &= ~bit_on(node);
    1298              :     }
    1299        11603 : }
    1300              : 
    1301              : static inline size_t
    1302           71 : block_count(size_t const node_count) {
    1303              :     static_assert(
    1304              :         (typeof(node_count))~((typeof(node_count))0) >= (typeof(node_count))0,
    1305              :         "shifting to avoid division with power of 2 divisor is only "
    1306              :         "defined for unsigned types"
    1307              :     );
    1308           71 :     return (node_count + (PARITY_BLOCK_BITS - 1)) >> PARITY_BLOCK_BITS_LOG2;
    1309              : }
    1310              : 
    1311              : static inline size_t *
    1312         3129 : branch_pointer(
    1313              :     struct CCC_Array_tree_map const *t,
    1314              :     size_t const node,
    1315              :     enum Link const branch
    1316              : ) {
    1317         3129 :     return &node_at(t, node)->branch[branch];
    1318              : }
    1319              : 
    1320              : static inline size_t *
    1321        12965 : parent_pointer(struct CCC_Array_tree_map const *t, size_t const node) {
    1322              : 
    1323        12965 :     return &node_at(t, node)->parent;
    1324              : }
    1325              : 
    1326              : static inline void *
    1327      6852617 : key_at(struct CCC_Array_tree_map const *const map, size_t const i) {
    1328      6852617 :     return (char *)data_at(map, i) + map->key_offset;
    1329              : }
    1330              : 
    1331              : static void *
    1332         8126 : key_in_slot(struct CCC_Array_tree_map const *t, void const *const user_struct) {
    1333         8126 :     return (char *)user_struct + t->key_offset;
    1334              : }
    1335              : 
    1336              : /*=======================   WAVL Tree Maintenance   =========================*/
    1337              : 
    1338              : /** Follows the specification in the "Rank-Balanced Trees" paper by Haeupler,
    1339              : Sen, and Tarjan (Fig. 2. pg 7). Assumes x's parent z is not null. */
    1340              : static void
    1341         9390 : insert_fixup(struct CCC_Array_tree_map *const map, size_t z, size_t x) {
    1342         9390 :     assert(z);
    1343         9390 :     do {
    1344        18562 :         promote(map, z);
    1345        18562 :         x = z;
    1346        18562 :         z = parent_index(map, z);
    1347        18562 :         if (!z) {
    1348          271 :             return;
    1349              :         }
    1350        18291 :     } while (is_01_parent(map, x, z, sibling_of(map, x)));
    1351              : 
    1352         9119 :     if (!is_02_parent(map, x, z, sibling_of(map, x))) {
    1353         3601 :         return;
    1354              :     }
    1355         5518 :     assert(x);
    1356         5518 :     assert(is_0_child(map, z, x));
    1357         5518 :     enum Link const p_to_x_dir = branch_index(map, z, R) == x;
    1358         5518 :     size_t const y = branch_index(map, x, !p_to_x_dir);
    1359         5518 :     if (!y || is_2_child(map, z, y)) {
    1360         4656 :         rotate(map, z, x, y, !p_to_x_dir);
    1361         4656 :         demote(map, z);
    1362         4656 :     } else {
    1363          862 :         assert(is_1_child(map, z, y));
    1364          862 :         double_rotate(map, z, x, y, p_to_x_dir);
    1365          862 :         promote(map, y);
    1366          862 :         demote(map, x);
    1367          862 :         demote(map, z);
    1368              :     }
    1369        14908 : }
    1370              : 
    1371              : static size_t
    1372         2348 : remove_fixup(struct CCC_Array_tree_map *const map, size_t const remove) {
    1373         2348 :     size_t y = 0;
    1374         2348 :     size_t x = 0;
    1375         2348 :     size_t p = 0;
    1376         2348 :     CCC_Tribool two_child = CCC_FALSE;
    1377         2348 :     if (!branch_index(map, remove, R) || !branch_index(map, remove, L)) {
    1378         1282 :         y = remove;
    1379         1282 :         p = parent_index(map, y);
    1380         1282 :         x = branch_index(map, y, !branch_index(map, y, L));
    1381         1282 :         *parent_pointer(map, x) = parent_index(map, y);
    1382         1282 :         if (!p) {
    1383           18 :             map->root = x;
    1384           18 :         } else {
    1385         1264 :             *branch_pointer(map, p, branch_index(map, p, R) == y) = x;
    1386              :         }
    1387         1282 :         two_child = is_2_child(map, p, y);
    1388         1282 :     } else {
    1389         1066 :         y = min_max_from(map, branch_index(map, remove, R), L);
    1390         1066 :         p = parent_index(map, y);
    1391         1066 :         x = branch_index(map, y, !branch_index(map, y, L));
    1392         1066 :         *parent_pointer(map, x) = parent_index(map, y);
    1393              : 
    1394              :         /* Save if check and improve readability by assuming this is true. */
    1395         1066 :         assert(p);
    1396              : 
    1397         1066 :         two_child = is_2_child(map, p, y);
    1398         1066 :         *branch_pointer(map, p, branch_index(map, p, R) == y) = x;
    1399         1066 :         transplant(map, remove, y);
    1400         1066 :         if (remove == p) {
    1401          277 :             p = y;
    1402          277 :         }
    1403              :     }
    1404              : 
    1405         2348 :     if (p) {
    1406         2330 :         if (two_child) {
    1407         1434 :             assert(p);
    1408         1434 :             rebalance_3_child(map, p, x);
    1409         2330 :         } else if (!x && branch_index(map, p, L) == branch_index(map, p, R)) {
    1410          340 :             assert(p);
    1411          680 :             CCC_Tribool const demote_makes_3_child
    1412          340 :                 = is_2_child(map, parent_index(map, p), p);
    1413          340 :             demote(map, p);
    1414          340 :             if (demote_makes_3_child) {
    1415          142 :                 rebalance_3_child(map, parent_index(map, p), p);
    1416          142 :             }
    1417          340 :         }
    1418         2330 :         assert(!is_leaf(map, p) || !parity(map, p));
    1419         2330 :     }
    1420         2348 :     node_at(map, remove)->next_free = map->free_list;
    1421         2348 :     map->free_list = remove;
    1422         2348 :     --map->count;
    1423         4696 :     return remove;
    1424         2348 : }
    1425              : 
    1426              : static void
    1427         1066 : transplant(
    1428              :     struct CCC_Array_tree_map *const map,
    1429              :     size_t const remove,
    1430              :     size_t const replacement
    1431              : ) {
    1432         1066 :     assert(remove);
    1433         1066 :     assert(replacement);
    1434         1066 :     *parent_pointer(map, replacement) = parent_index(map, remove);
    1435         1066 :     if (!parent_index(map, remove)) {
    1436          267 :         map->root = replacement;
    1437          267 :     } else {
    1438          799 :         size_t const p = parent_index(map, remove);
    1439          799 :         *branch_pointer(map, p, branch_index(map, p, R) == remove)
    1440         1598 :             = replacement;
    1441          799 :     }
    1442         1066 :     struct CCC_Array_tree_map_node *const remove_r = node_at(map, remove);
    1443         1066 :     struct CCC_Array_tree_map_node *const replace_r = node_at(map, replacement);
    1444         1066 :     *parent_pointer(map, remove_r->branch[R]) = replacement;
    1445         1066 :     *parent_pointer(map, remove_r->branch[L]) = replacement;
    1446         1066 :     replace_r->branch[R] = remove_r->branch[R];
    1447         1066 :     replace_r->branch[L] = remove_r->branch[L];
    1448         1066 :     set_parity(map, replacement, parity(map, remove));
    1449         1066 : }
    1450              : 
    1451              : /** Follows the specification in the "Rank-Balanced Trees" paper by Haeupler,
    1452              : Sen, and Tarjan (Fig. 3. pg 8). */
    1453              : static void
    1454         1576 : rebalance_3_child(struct CCC_Array_tree_map *const map, size_t z, size_t x) {
    1455         1576 :     CCC_Tribool made_3_child = CCC_TRUE;
    1456         2935 :     while (z && made_3_child) {
    1457         2155 :         assert(branch_index(map, z, L) == x || branch_index(map, z, R) == x);
    1458         2155 :         size_t const g = parent_index(map, z);
    1459         2155 :         size_t const y = branch_index(map, z, branch_index(map, z, L) == x);
    1460         2155 :         made_3_child = g && is_2_child(map, g, z);
    1461         2155 :         if (is_2_child(map, z, y)) {
    1462         1191 :             demote(map, z);
    1463         2155 :         } else if (y
    1464          964 :                    && is_22_parent(
    1465          964 :                        map, branch_index(map, y, L), y, branch_index(map, y, R)
    1466              :                    )) {
    1467          168 :             demote(map, z);
    1468          168 :             demote(map, y);
    1469          964 :         } else if (y) {
    1470              :             /* p(x) is 1,3, y is not a 2,2 parent, and x is 3-child.*/
    1471          796 :             assert(is_1_child(map, z, y));
    1472          796 :             assert(is_3_child(map, z, x));
    1473          796 :             assert(!is_2_child(map, z, y));
    1474          796 :             assert(!is_22_parent(
    1475          796 :                 map, branch_index(map, y, L), y, branch_index(map, y, R)
    1476              :             ));
    1477          796 :             enum Link const z_to_x_dir = branch_index(map, z, R) == x;
    1478          796 :             size_t const w = branch_index(map, y, !z_to_x_dir);
    1479          796 :             if (is_1_child(map, y, w)) {
    1480          553 :                 rotate(map, z, y, branch_index(map, y, z_to_x_dir), z_to_x_dir);
    1481          553 :                 promote(map, y);
    1482          553 :                 demote(map, z);
    1483          553 :                 if (is_leaf(map, z)) {
    1484          144 :                     demote(map, z);
    1485          144 :                 }
    1486          553 :             } else {
    1487              :                 /* w is a 2-child and v will be a 1-child. */
    1488          243 :                 size_t const v = branch_index(map, y, z_to_x_dir);
    1489          243 :                 assert(is_2_child(map, y, w));
    1490          243 :                 assert(is_1_child(map, y, v));
    1491          243 :                 double_rotate(map, z, y, v, !z_to_x_dir);
    1492          243 :                 double_promote(map, v);
    1493          243 :                 demote(map, y);
    1494          243 :                 double_demote(map, z);
    1495              :                 /* Optional "Rebalancing with Promotion," defined as follows:
    1496              :                        if node z is a non-leaf 1,1 node, we promote it;
    1497              :                        otherwise, if y is a non-leaf 1,1 node, we promote it.
    1498              :                        (See Figure 4.) (Haeupler et. al. 2014, 17).
    1499              :                    This reduces constants in some of theorems mentioned in the
    1500              :                    paper but may not be worth doing. Rotations stay at 2 worst
    1501              :                    case. Should revisit after more performance testing. */
    1502          243 :                 if (!is_leaf(map, z)
    1503          243 :                     && is_11_parent(
    1504          110 :                         map, branch_index(map, z, L), z, branch_index(map, z, R)
    1505              :                     )) {
    1506           62 :                     promote(map, z);
    1507          243 :                 } else if (!is_leaf(map, y)
    1508          181 :                            && is_11_parent(
    1509           48 :                                map,
    1510           48 :                                branch_index(map, y, L),
    1511           48 :                                y,
    1512           48 :                                branch_index(map, y, R)
    1513              :                            )) {
    1514           32 :                     promote(map, y);
    1515           32 :                 }
    1516          243 :             }
    1517              :             /* Returning here confirms O(1) rotations for re-balance. */
    1518              :             return;
    1519          796 :         }
    1520         1359 :         x = z;
    1521         1359 :         z = g;
    1522         2155 :     }
    1523         1576 : }
    1524              : 
    1525              : /** A single rotation is symmetric. Here is the right case. Lowercase are nodes
    1526              : and uppercase are arbitrary subtrees.
    1527              :         z            x
    1528              :      ╭──┴──╮      ╭──┴──╮
    1529              :      x     C      A     z
    1530              :    ╭─┴─╮      ->      ╭─┴─╮
    1531              :    A   y              y   C
    1532              :        │              │
    1533              :        B              B
    1534              : Using a link allows both cases to be coded at once. */
    1535              : static void
    1536         5209 : rotate(
    1537              :     struct CCC_Array_tree_map *const map,
    1538              :     size_t const z,
    1539              :     size_t const x,
    1540              :     size_t const y,
    1541              :     enum Link const dir
    1542              : ) {
    1543         5209 :     assert(z);
    1544         5209 :     struct CCC_Array_tree_map_node *const z_r = node_at(map, z);
    1545         5209 :     struct CCC_Array_tree_map_node *const x_r = node_at(map, x);
    1546         5209 :     size_t const g = parent_index(map, z);
    1547         5209 :     x_r->parent = g;
    1548         5209 :     if (!g) {
    1549          163 :         map->root = x;
    1550          163 :     } else {
    1551         5046 :         struct CCC_Array_tree_map_node *const g_r = node_at(map, g);
    1552         5046 :         g_r->branch[g_r->branch[R] == z] = x;
    1553         5046 :     }
    1554         5209 :     x_r->branch[dir] = z;
    1555         5209 :     z_r->parent = x;
    1556         5209 :     z_r->branch[!dir] = y;
    1557         5209 :     *parent_pointer(map, y) = z;
    1558         5209 : }
    1559              : 
    1560              : /** A double rotation shouldn't actually be two calls to rotate because that
    1561              : would invoke pointless memory writes. Here is an example of double right.
    1562              : Lowercase are nodes and uppercase are arbitrary subtrees.
    1563              : 
    1564              :         z            y
    1565              :      ╭──┴──╮      ╭──┴──╮
    1566              :      x     D      x     z
    1567              :    ╭─┴─╮     -> ╭─┴─╮ ╭─┴─╮
    1568              :    A   y        A   B C   D
    1569              :      ╭─┴─╮
    1570              :      B   C
    1571              : 
    1572              : Taking a link as input allows us to code both symmetrical cases at once. */
    1573              : static void
    1574         1105 : double_rotate(
    1575              :     struct CCC_Array_tree_map *const map,
    1576              :     size_t const z,
    1577              :     size_t const x,
    1578              :     size_t const y,
    1579              :     enum Link const dir
    1580              : ) {
    1581         1105 :     assert(z && x && y);
    1582         1105 :     struct CCC_Array_tree_map_node *const z_r = node_at(map, z);
    1583         1105 :     struct CCC_Array_tree_map_node *const x_r = node_at(map, x);
    1584         1105 :     struct CCC_Array_tree_map_node *const y_r = node_at(map, y);
    1585         1105 :     size_t const g = z_r->parent;
    1586         1105 :     y_r->parent = g;
    1587         1105 :     if (!g) {
    1588            6 :         map->root = y;
    1589            6 :     } else {
    1590         1099 :         struct CCC_Array_tree_map_node *const g_r = node_at(map, g);
    1591         1099 :         g_r->branch[g_r->branch[R] == z] = y;
    1592         1099 :     }
    1593         1105 :     x_r->branch[!dir] = y_r->branch[dir];
    1594         1105 :     *parent_pointer(map, y_r->branch[dir]) = x;
    1595         1105 :     y_r->branch[dir] = x;
    1596         1105 :     x_r->parent = y;
    1597              : 
    1598         1105 :     z_r->branch[dir] = y_r->branch[!dir];
    1599         1105 :     *parent_pointer(map, y_r->branch[!dir]) = z;
    1600         1105 :     y_r->branch[!dir] = z;
    1601         1105 :     z_r->parent = y;
    1602         1105 : }
    1603              : 
    1604              : /** Returns true for rank difference 0 (rule break) between the parent and node.
    1605              :          p
    1606              :       0╭─╯
    1607              :        x */
    1608              : [[maybe_unused]] static inline CCC_Tribool
    1609         5518 : is_0_child(
    1610              :     struct CCC_Array_tree_map const *const map, size_t const p, size_t const x
    1611              : ) {
    1612         5518 :     return p && parity(map, p) == parity(map, x);
    1613              : }
    1614              : 
    1615              : /** Returns true for rank difference 1 between the parent and node.
    1616              :          p
    1617              :       1╭─╯
    1618              :        x */
    1619              : static inline CCC_Tribool
    1620         2697 : is_1_child(
    1621              :     struct CCC_Array_tree_map const *const map, size_t const p, size_t const x
    1622              : ) {
    1623         2697 :     return p && parity(map, p) != parity(map, x);
    1624              : }
    1625              : 
    1626              : /** Returns true for rank difference 2 between the parent and node.
    1627              :          p
    1628              :       2╭─╯
    1629              :        x */
    1630              : static inline CCC_Tribool
    1631        10410 : is_2_child(
    1632              :     struct CCC_Array_tree_map const *const map, size_t const p, size_t const x
    1633              : ) {
    1634        10410 :     return p && parity(map, p) == parity(map, x);
    1635              : }
    1636              : 
    1637              : /** Returns true for rank difference 3 between the parent and node.
    1638              :          p
    1639              :       3╭─╯
    1640              :        x */
    1641              : [[maybe_unused]] static inline CCC_Tribool
    1642          796 : is_3_child(
    1643              :     struct CCC_Array_tree_map const *const map, size_t const p, size_t const x
    1644              : ) {
    1645          796 :     return p && parity(map, p) != parity(map, x);
    1646              : }
    1647              : 
    1648              : /** Returns true if a parent is a 0,1 or 1,0 node, which is not allowed. Either
    1649              : child may be the sentinel node which has a parity of 1 and rank -1.
    1650              :          p
    1651              :       0╭─┴─╮1
    1652              :        x   y */
    1653              : static inline CCC_Tribool
    1654        18291 : is_01_parent(
    1655              :     struct CCC_Array_tree_map const *const map,
    1656              :     size_t const x,
    1657              :     size_t const p,
    1658              :     size_t const y
    1659              : ) {
    1660        18291 :     assert(p);
    1661        33513 :     return (!parity(map, x) && !parity(map, p) && parity(map, y))
    1662        18291 :         || (parity(map, x) && parity(map, p) && !parity(map, y));
    1663              : }
    1664              : 
    1665              : /** Returns true if a parent is a 1,1 node. Either child may be the sentinel
    1666              : node which has a parity of 1 and rank -1.
    1667              :          p
    1668              :       1╭─┴─╮1
    1669              :        x   y */
    1670              : static inline CCC_Tribool
    1671          158 : is_11_parent(
    1672              :     struct CCC_Array_tree_map const *const map,
    1673              :     size_t const x,
    1674              :     size_t const p,
    1675              :     size_t const y
    1676              : ) {
    1677          158 :     assert(p);
    1678          240 :     return (!parity(map, x) && parity(map, p) && !parity(map, y))
    1679          158 :         || (parity(map, x) && !parity(map, p) && parity(map, y));
    1680              : }
    1681              : 
    1682              : /** Returns true if a parent is a 0,2 or 2,0 node, which is not allowed. Either
    1683              : child may be the sentinel node which has a parity of 1 and rank -1.
    1684              :          p
    1685              :       0╭─┴─╮2
    1686              :        x   y */
    1687              : static inline CCC_Tribool
    1688         9119 : is_02_parent(
    1689              :     struct CCC_Array_tree_map const *const map,
    1690              :     size_t const x,
    1691              :     size_t const p,
    1692              :     size_t const y
    1693              : ) {
    1694         9119 :     assert(p);
    1695        14637 :     return (parity(map, x) == parity(map, p))
    1696         9119 :         && (parity(map, p) == parity(map, y));
    1697              : }
    1698              : 
    1699              : /* Returns true if a parent is a 2,2 node, which is allowed. 2,2 nodes are
    1700              : allowed in a WAVL tree but the absence of any 2,2 nodes is the exact equivalent
    1701              : of a normal AVL tree which can occur if only insertions occur for a WAVL tree.
    1702              : Either child may be the sentinel node which has a parity of 1 and rank -1.
    1703              :          p
    1704              :       2╭─┴─╮2
    1705              :        x   y */
    1706              : static inline CCC_Tribool
    1707         1760 : is_22_parent(
    1708              :     struct CCC_Array_tree_map const *const map,
    1709              :     size_t const x,
    1710              :     size_t const p,
    1711              :     size_t const y
    1712              : ) {
    1713         1760 :     assert(p);
    1714         2480 :     return (parity(map, x) == parity(map, p))
    1715         1760 :         && (parity(map, p) == parity(map, y));
    1716              : }
    1717              : 
    1718              : static inline void
    1719        29258 : promote(struct CCC_Array_tree_map const *const map, size_t const x) {
    1720        29258 :     if (x) {
    1721        29258 :         *block_at(map, x) ^= bit_on(x);
    1722        29258 :     }
    1723        29258 : }
    1724              : 
    1725              : static inline void
    1726         9187 : demote(struct CCC_Array_tree_map const *const map, size_t const x) {
    1727         9187 :     promote(map, x);
    1728         9187 : }
    1729              : 
    1730              : /** Parity based ranks mean this is no-op but leave in case implementation ever
    1731              : changes. Also, makes clear what sections of code are trying to do. */
    1732              : static inline void
    1733          243 : double_promote(struct CCC_Array_tree_map const *const, size_t const) {
    1734          243 : }
    1735              : 
    1736              : /** Parity based ranks mean this is no-op but leave in case implementation ever
    1737              : changes. Also, makes clear what sections of code are trying to do. */
    1738              : static inline void
    1739          243 : double_demote(struct CCC_Array_tree_map const *const, size_t const) {
    1740          243 : }
    1741              : 
    1742              : static inline CCC_Tribool
    1743         3307 : is_leaf(struct CCC_Array_tree_map const *const map, size_t const x) {
    1744         3307 :     return !branch_index(map, x, L) && !branch_index(map, x, R);
    1745              : }
    1746              : 
    1747              : static inline size_t
    1748        27410 : sibling_of(struct CCC_Array_tree_map const *const map, size_t const x) {
    1749        27410 :     size_t const p = parent_index(map, x);
    1750        27410 :     assert(p);
    1751              :     /* We want the sibling so we need the truthy value to be opposite of x. */
    1752        54820 :     return node_at(map, p)->branch[branch_index(map, p, L) == x];
    1753        27410 : }
    1754              : 
    1755              : static inline size_t
    1756          218 : max_size_t(size_t const a, size_t const b) {
    1757          218 :     return a > b ? a : b;
    1758              : }
    1759              : 
    1760              : /*===========================   Validation   ===============================*/
    1761              : 
    1762              : /* NOLINTBEGIN(*misc-no-recursion) */
    1763              : 
    1764              : /** @internal */
    1765              : struct Tree_range {
    1766              :     size_t low;
    1767              :     size_t root;
    1768              :     size_t high;
    1769              : };
    1770              : 
    1771              : static size_t
    1772      7013564 : recursive_count(struct CCC_Array_tree_map const *const map, size_t const r) {
    1773      7013564 :     if (!r) {
    1774      3511729 :         return 0;
    1775              :     }
    1776      7003670 :     return 1 + recursive_count(map, branch_index(map, r, R))
    1777      3501835 :          + recursive_count(map, branch_index(map, r, L));
    1778      7013564 : }
    1779              : 
    1780              : static CCC_Tribool
    1781      7013564 : are_subtrees_valid(
    1782              :     struct CCC_Array_tree_map const *t, struct Tree_range const r
    1783              : ) {
    1784      7013564 :     if (!r.root) {
    1785      3511729 :         return CCC_TRUE;
    1786              :     }
    1787      3501835 :     if (r.low && order_nodes(t, key_at(t, r.low), r.root) != CCC_ORDER_LESSER) {
    1788            0 :         return CCC_FALSE;
    1789              :     }
    1790      3501835 :     if (r.high
    1791      3501835 :         && order_nodes(t, key_at(t, r.high), r.root) != CCC_ORDER_GREATER) {
    1792            0 :         return CCC_FALSE;
    1793              :     }
    1794      7003670 :     return are_subtrees_valid(
    1795      3501835 :                t,
    1796     14007340 :                (struct Tree_range){
    1797      3501835 :                    .low = r.low,
    1798      3501835 :                    .root = branch_index(t, r.root, L),
    1799      3501835 :                    .high = r.root,
    1800              :                }
    1801              :            )
    1802      3501835 :         && are_subtrees_valid(
    1803      3501835 :                t,
    1804     14007340 :                (struct Tree_range){
    1805      3501835 :                    .low = r.root,
    1806      3501835 :                    .root = branch_index(t, r.root, R),
    1807      3501835 :                    .high = r.high,
    1808              :                }
    1809              :         );
    1810      7013564 : }
    1811              : 
    1812              : static CCC_Tribool
    1813      7013564 : is_storing_parent(
    1814              :     struct CCC_Array_tree_map const *const map,
    1815              :     size_t const p,
    1816              :     size_t const root
    1817              : ) {
    1818      7013564 :     if (!root) {
    1819      3511729 :         return CCC_TRUE;
    1820              :     }
    1821      3501835 :     if (parent_index(map, root) != p) {
    1822            0 :         return CCC_FALSE;
    1823              :     }
    1824      7003670 :     return is_storing_parent(map, root, branch_index(map, root, L))
    1825      3501835 :         && is_storing_parent(map, root, branch_index(map, root, R));
    1826      7013564 : }
    1827              : 
    1828              : static CCC_Tribool
    1829         9894 : is_free_list_valid(struct CCC_Array_tree_map const *const map) {
    1830         9894 :     if (!map->count) {
    1831            0 :         return CCC_TRUE;
    1832              :     }
    1833         9894 :     size_t list_count = 0;
    1834         9894 :     size_t cur_free_index = map->free_list;
    1835      4436021 :     while (cur_free_index && list_count < map->capacity) {
    1836      4426127 :         cur_free_index = node_at(map, cur_free_index)->next_free;
    1837      4426127 :         ++list_count;
    1838              :     }
    1839         9894 :     if (cur_free_index) {
    1840            0 :         return CCC_FALSE;
    1841              :     }
    1842         9894 :     if (list_count + map->count != map->capacity) {
    1843            0 :         return CCC_FALSE;
    1844              :     }
    1845         9894 :     return CCC_TRUE;
    1846         9894 : }
    1847              : 
    1848              : static inline CCC_Tribool
    1849         9905 : validate(struct CCC_Array_tree_map const *const map) {
    1850         9905 :     if (!map->capacity) {
    1851            7 :         return CCC_TRUE;
    1852              :     }
    1853         9898 :     if (map->data && (!map->nodes || !map->parity)) {
    1854            4 :         return CCC_TRUE;
    1855              :     }
    1856         9894 :     if (!map->data) {
    1857            0 :         return CCC_TRUE;
    1858              :     }
    1859         9894 :     if (!map->count && !parity(map, 0)) {
    1860            0 :         return CCC_FALSE;
    1861              :     }
    1862         9894 :     if (!are_subtrees_valid(map, (struct Tree_range){.root = map->root})) {
    1863            0 :         return CCC_FALSE;
    1864              :     }
    1865         9894 :     size_t const size = recursive_count(map, map->root);
    1866         9894 :     if (size && size != map->count - 1) {
    1867            0 :         return CCC_FALSE;
    1868              :     }
    1869         9894 :     if (!is_storing_parent(map, 0, map->root)) {
    1870            0 :         return CCC_FALSE;
    1871              :     }
    1872         9894 :     if (!is_free_list_valid(map)) {
    1873            0 :         return CCC_FALSE;
    1874              :     }
    1875         9894 :     return CCC_TRUE;
    1876         9905 : }
    1877              : 
    1878              : /* NOLINTEND(*misc-no-recursion) */
    1879              : 
    1880              : /* Below you will find the required license for code that inspired the
    1881              : implementation of a WAVL tree in this repository for some map containers.
    1882              : 
    1883              : The original repository can be found here:
    1884              : 
    1885              : https://github.com/pvachon/wavl_tree
    1886              : 
    1887              : The original implementation has be changed to eliminate left and right cases,
    1888              : simplify deletion, and work within the C Container Collection memory framework.
    1889              : 
    1890              : Redistribution and use in source and binary forms, with or without
    1891              : modification, are permitted provided that the following conditions are met:
    1892              : 
    1893              : 1. Redistributions of source code must retain the above copyright notice, this
    1894              :    list of conditions and the following disclaimer.
    1895              : 
    1896              : 2. Redistributions in binary form must reproduce the above copyright notice,
    1897              :    this list of conditions and the following disclaimer in the documentation
    1898              :    and/or other materials provided with the distribution.
    1899              : 
    1900              : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1901              : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1902              : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    1903              : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    1904              : FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1905              : DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    1906              : SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    1907              : CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1908              : OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1909              : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
        

Generated by: LCOV version 2.4-beta