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

Generated by: LCOV version 2.5.0-beta