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: 97.4 % 869 846
Test Date: 2026-08-22 15:52:04 Functions: 100.0 % 95 95

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

Generated by: LCOV version 2.4-beta