162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Sparse bit array 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2018, Google LLC. 662306a36Sopenharmony_ci * Copyright (C) 2018, Red Hat, Inc. (code style cleanup and fuzzing driver) 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This library provides functions to support a memory efficient bit array, 962306a36Sopenharmony_ci * with an index size of 2^64. A sparsebit array is allocated through 1062306a36Sopenharmony_ci * the use sparsebit_alloc() and free'd via sparsebit_free(), 1162306a36Sopenharmony_ci * such as in the following: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * struct sparsebit *s; 1462306a36Sopenharmony_ci * s = sparsebit_alloc(); 1562306a36Sopenharmony_ci * sparsebit_free(&s); 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * The struct sparsebit type resolves down to a struct sparsebit. 1862306a36Sopenharmony_ci * Note that, sparsebit_free() takes a pointer to the sparsebit 1962306a36Sopenharmony_ci * structure. This is so that sparsebit_free() is able to poison 2062306a36Sopenharmony_ci * the pointer (e.g. set it to NULL) to the struct sparsebit before 2162306a36Sopenharmony_ci * returning to the caller. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Between the return of sparsebit_alloc() and the call of 2462306a36Sopenharmony_ci * sparsebit_free(), there are multiple query and modifying operations 2562306a36Sopenharmony_ci * that can be performed on the allocated sparsebit array. All of 2662306a36Sopenharmony_ci * these operations take as a parameter the value returned from 2762306a36Sopenharmony_ci * sparsebit_alloc() and most also take a bit index. Frequently 2862306a36Sopenharmony_ci * used routines include: 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * ---- Query Operations 3162306a36Sopenharmony_ci * sparsebit_is_set(s, idx) 3262306a36Sopenharmony_ci * sparsebit_is_clear(s, idx) 3362306a36Sopenharmony_ci * sparsebit_any_set(s) 3462306a36Sopenharmony_ci * sparsebit_first_set(s) 3562306a36Sopenharmony_ci * sparsebit_next_set(s, prev_idx) 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * ---- Modifying Operations 3862306a36Sopenharmony_ci * sparsebit_set(s, idx) 3962306a36Sopenharmony_ci * sparsebit_clear(s, idx) 4062306a36Sopenharmony_ci * sparsebit_set_num(s, idx, num); 4162306a36Sopenharmony_ci * sparsebit_clear_num(s, idx, num); 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * A common operation, is to itterate over all the bits set in a test 4462306a36Sopenharmony_ci * sparsebit array. This can be done via code with the following structure: 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * sparsebit_idx_t idx; 4762306a36Sopenharmony_ci * if (sparsebit_any_set(s)) { 4862306a36Sopenharmony_ci * idx = sparsebit_first_set(s); 4962306a36Sopenharmony_ci * do { 5062306a36Sopenharmony_ci * ... 5162306a36Sopenharmony_ci * idx = sparsebit_next_set(s, idx); 5262306a36Sopenharmony_ci * } while (idx != 0); 5362306a36Sopenharmony_ci * } 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * The index of the first bit set needs to be obtained via 5662306a36Sopenharmony_ci * sparsebit_first_set(), because sparsebit_next_set(), needs 5762306a36Sopenharmony_ci * the index of the previously set. The sparsebit_idx_t type is 5862306a36Sopenharmony_ci * unsigned, so there is no previous index before 0 that is available. 5962306a36Sopenharmony_ci * Also, the call to sparsebit_first_set() is not made unless there 6062306a36Sopenharmony_ci * is at least 1 bit in the array set. This is because sparsebit_first_set() 6162306a36Sopenharmony_ci * aborts if sparsebit_first_set() is called with no bits set. 6262306a36Sopenharmony_ci * It is the callers responsibility to assure that the 6362306a36Sopenharmony_ci * sparsebit array has at least a single bit set before calling 6462306a36Sopenharmony_ci * sparsebit_first_set(). 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * ==== Implementation Overview ==== 6762306a36Sopenharmony_ci * For the most part the internal implementation of sparsebit is 6862306a36Sopenharmony_ci * opaque to the caller. One important implementation detail that the 6962306a36Sopenharmony_ci * caller may need to be aware of is the spatial complexity of the 7062306a36Sopenharmony_ci * implementation. This implementation of a sparsebit array is not 7162306a36Sopenharmony_ci * only sparse, in that it uses memory proportional to the number of bits 7262306a36Sopenharmony_ci * set. It is also efficient in memory usage when most of the bits are 7362306a36Sopenharmony_ci * set. 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * At a high-level the state of the bit settings are maintained through 7662306a36Sopenharmony_ci * the use of a binary-search tree, where each node contains at least 7762306a36Sopenharmony_ci * the following members: 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * typedef uint64_t sparsebit_idx_t; 8062306a36Sopenharmony_ci * typedef uint64_t sparsebit_num_t; 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * sparsebit_idx_t idx; 8362306a36Sopenharmony_ci * uint32_t mask; 8462306a36Sopenharmony_ci * sparsebit_num_t num_after; 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * The idx member contains the bit index of the first bit described by this 8762306a36Sopenharmony_ci * node, while the mask member stores the setting of the first 32-bits. 8862306a36Sopenharmony_ci * The setting of the bit at idx + n, where 0 <= n < 32, is located in the 8962306a36Sopenharmony_ci * mask member at 1 << n. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Nodes are sorted by idx and the bits described by two nodes will never 9262306a36Sopenharmony_ci * overlap. The idx member is always aligned to the mask size, i.e. a 9362306a36Sopenharmony_ci * multiple of 32. 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * Beyond a typical implementation, the nodes in this implementation also 9662306a36Sopenharmony_ci * contains a member named num_after. The num_after member holds the 9762306a36Sopenharmony_ci * number of bits immediately after the mask bits that are contiguously set. 9862306a36Sopenharmony_ci * The use of the num_after member allows this implementation to efficiently 9962306a36Sopenharmony_ci * represent cases where most bits are set. For example, the case of all 10062306a36Sopenharmony_ci * but the last two bits set, is represented by the following two nodes: 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * node 0 - idx: 0x0 mask: 0xffffffff num_after: 0xffffffffffffffc0 10362306a36Sopenharmony_ci * node 1 - idx: 0xffffffffffffffe0 mask: 0x3fffffff num_after: 0 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * ==== Invariants ==== 10662306a36Sopenharmony_ci * This implementation usses the following invariants: 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * + Node are only used to represent bits that are set. 10962306a36Sopenharmony_ci * Nodes with a mask of 0 and num_after of 0 are not allowed. 11062306a36Sopenharmony_ci * 11162306a36Sopenharmony_ci * + Sum of bits set in all the nodes is equal to the value of 11262306a36Sopenharmony_ci * the struct sparsebit_pvt num_set member. 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * + The setting of at least one bit is always described in a nodes 11562306a36Sopenharmony_ci * mask (mask >= 1). 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * + A node with all mask bits set only occurs when the last bit 11862306a36Sopenharmony_ci * described by the previous node is not equal to this nodes 11962306a36Sopenharmony_ci * starting index - 1. All such occurences of this condition are 12062306a36Sopenharmony_ci * avoided by moving the setting of the nodes mask bits into 12162306a36Sopenharmony_ci * the previous nodes num_after setting. 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * + Node starting index is evenly divisible by the number of bits 12462306a36Sopenharmony_ci * within a nodes mask member. 12562306a36Sopenharmony_ci * 12662306a36Sopenharmony_ci * + Nodes never represent a range of bits that wrap around the 12762306a36Sopenharmony_ci * highest supported index. 12862306a36Sopenharmony_ci * 12962306a36Sopenharmony_ci * (idx + MASK_BITS + num_after - 1) <= ((sparsebit_idx_t) 0) - 1) 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * As a consequence of the above, the num_after member of a node 13262306a36Sopenharmony_ci * will always be <=: 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * maximum_index - nodes_starting_index - number_of_mask_bits 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * + Nodes within the binary search tree are sorted based on each 13762306a36Sopenharmony_ci * nodes starting index. 13862306a36Sopenharmony_ci * 13962306a36Sopenharmony_ci * + The range of bits described by any two nodes do not overlap. The 14062306a36Sopenharmony_ci * range of bits described by a single node is: 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * start: node->idx 14362306a36Sopenharmony_ci * end (inclusive): node->idx + MASK_BITS + node->num_after - 1; 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * Note, at times these invariants are temporarily violated for a 14662306a36Sopenharmony_ci * specific portion of the code. For example, when setting a mask 14762306a36Sopenharmony_ci * bit, there is a small delay between when the mask bit is set and the 14862306a36Sopenharmony_ci * value in the struct sparsebit_pvt num_set member is updated. Other 14962306a36Sopenharmony_ci * temporary violations occur when node_split() is called with a specified 15062306a36Sopenharmony_ci * index and assures that a node where its mask represents the bit 15162306a36Sopenharmony_ci * at the specified index exists. At times to do this node_split() 15262306a36Sopenharmony_ci * must split an existing node into two nodes or create a node that 15362306a36Sopenharmony_ci * has no bits set. Such temporary violations must be corrected before 15462306a36Sopenharmony_ci * returning to the caller. These corrections are typically performed 15562306a36Sopenharmony_ci * by the local function node_reduce(). 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#include "test_util.h" 15962306a36Sopenharmony_ci#include "sparsebit.h" 16062306a36Sopenharmony_ci#include <limits.h> 16162306a36Sopenharmony_ci#include <assert.h> 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define DUMP_LINE_MAX 100 /* Does not include indent amount */ 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_citypedef uint32_t mask_t; 16662306a36Sopenharmony_ci#define MASK_BITS (sizeof(mask_t) * CHAR_BIT) 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistruct node { 16962306a36Sopenharmony_ci struct node *parent; 17062306a36Sopenharmony_ci struct node *left; 17162306a36Sopenharmony_ci struct node *right; 17262306a36Sopenharmony_ci sparsebit_idx_t idx; /* index of least-significant bit in mask */ 17362306a36Sopenharmony_ci sparsebit_num_t num_after; /* num contiguously set after mask */ 17462306a36Sopenharmony_ci mask_t mask; 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistruct sparsebit { 17862306a36Sopenharmony_ci /* 17962306a36Sopenharmony_ci * Points to root node of the binary search 18062306a36Sopenharmony_ci * tree. Equal to NULL when no bits are set in 18162306a36Sopenharmony_ci * the entire sparsebit array. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci struct node *root; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* 18662306a36Sopenharmony_ci * A redundant count of the total number of bits set. Used for 18762306a36Sopenharmony_ci * diagnostic purposes and to change the time complexity of 18862306a36Sopenharmony_ci * sparsebit_num_set() from O(n) to O(1). 18962306a36Sopenharmony_ci * Note: Due to overflow, a value of 0 means none or all set. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci sparsebit_num_t num_set; 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/* Returns the number of set bits described by the settings 19562306a36Sopenharmony_ci * of the node pointed to by nodep. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_cistatic sparsebit_num_t node_num_set(struct node *nodep) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci return nodep->num_after + __builtin_popcount(nodep->mask); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* Returns a pointer to the node that describes the 20362306a36Sopenharmony_ci * lowest bit index. 20462306a36Sopenharmony_ci */ 20562306a36Sopenharmony_cistatic struct node *node_first(struct sparsebit *s) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct node *nodep; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci for (nodep = s->root; nodep && nodep->left; nodep = nodep->left) 21062306a36Sopenharmony_ci ; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return nodep; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* Returns a pointer to the node that describes the 21662306a36Sopenharmony_ci * lowest bit index > the index of the node pointed to by np. 21762306a36Sopenharmony_ci * Returns NULL if no node with a higher index exists. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_cistatic struct node *node_next(struct sparsebit *s, struct node *np) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct node *nodep = np; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* 22462306a36Sopenharmony_ci * If current node has a right child, next node is the left-most 22562306a36Sopenharmony_ci * of the right child. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci if (nodep->right) { 22862306a36Sopenharmony_ci for (nodep = nodep->right; nodep->left; nodep = nodep->left) 22962306a36Sopenharmony_ci ; 23062306a36Sopenharmony_ci return nodep; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * No right child. Go up until node is left child of a parent. 23562306a36Sopenharmony_ci * That parent is then the next node. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci while (nodep->parent && nodep == nodep->parent->right) 23862306a36Sopenharmony_ci nodep = nodep->parent; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return nodep->parent; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* Searches for and returns a pointer to the node that describes the 24462306a36Sopenharmony_ci * highest index < the index of the node pointed to by np. 24562306a36Sopenharmony_ci * Returns NULL if no node with a lower index exists. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_cistatic struct node *node_prev(struct sparsebit *s, struct node *np) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct node *nodep = np; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* 25262306a36Sopenharmony_ci * If current node has a left child, next node is the right-most 25362306a36Sopenharmony_ci * of the left child. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci if (nodep->left) { 25662306a36Sopenharmony_ci for (nodep = nodep->left; nodep->right; nodep = nodep->right) 25762306a36Sopenharmony_ci ; 25862306a36Sopenharmony_ci return (struct node *) nodep; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* 26262306a36Sopenharmony_ci * No left child. Go up until node is right child of a parent. 26362306a36Sopenharmony_ci * That parent is then the next node. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci while (nodep->parent && nodep == nodep->parent->left) 26662306a36Sopenharmony_ci nodep = nodep->parent; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return (struct node *) nodep->parent; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci/* Allocates space to hold a copy of the node sub-tree pointed to by 27362306a36Sopenharmony_ci * subtree and duplicates the bit settings to the newly allocated nodes. 27462306a36Sopenharmony_ci * Returns the newly allocated copy of subtree. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_cistatic struct node *node_copy_subtree(struct node *subtree) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct node *root; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Duplicate the node at the root of the subtree */ 28162306a36Sopenharmony_ci root = calloc(1, sizeof(*root)); 28262306a36Sopenharmony_ci if (!root) { 28362306a36Sopenharmony_ci perror("calloc"); 28462306a36Sopenharmony_ci abort(); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci root->idx = subtree->idx; 28862306a36Sopenharmony_ci root->mask = subtree->mask; 28962306a36Sopenharmony_ci root->num_after = subtree->num_after; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* As needed, recursively duplicate the left and right subtrees */ 29262306a36Sopenharmony_ci if (subtree->left) { 29362306a36Sopenharmony_ci root->left = node_copy_subtree(subtree->left); 29462306a36Sopenharmony_ci root->left->parent = root; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (subtree->right) { 29862306a36Sopenharmony_ci root->right = node_copy_subtree(subtree->right); 29962306a36Sopenharmony_ci root->right->parent = root; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return root; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/* Searches for and returns a pointer to the node that describes the setting 30662306a36Sopenharmony_ci * of the bit given by idx. A node describes the setting of a bit if its 30762306a36Sopenharmony_ci * index is within the bits described by the mask bits or the number of 30862306a36Sopenharmony_ci * contiguous bits set after the mask. Returns NULL if there is no such node. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_cistatic struct node *node_find(struct sparsebit *s, sparsebit_idx_t idx) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct node *nodep; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* Find the node that describes the setting of the bit at idx */ 31562306a36Sopenharmony_ci for (nodep = s->root; nodep; 31662306a36Sopenharmony_ci nodep = nodep->idx > idx ? nodep->left : nodep->right) { 31762306a36Sopenharmony_ci if (idx >= nodep->idx && 31862306a36Sopenharmony_ci idx <= nodep->idx + MASK_BITS + nodep->num_after - 1) 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci return nodep; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* Entry Requirements: 32662306a36Sopenharmony_ci * + A node that describes the setting of idx is not already present. 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * Adds a new node to describe the setting of the bit at the index given 32962306a36Sopenharmony_ci * by idx. Returns a pointer to the newly added node. 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * TODO(lhuemill): Degenerate cases causes the tree to get unbalanced. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_cistatic struct node *node_add(struct sparsebit *s, sparsebit_idx_t idx) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct node *nodep, *parentp, *prev; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci /* Allocate and initialize the new node. */ 33862306a36Sopenharmony_ci nodep = calloc(1, sizeof(*nodep)); 33962306a36Sopenharmony_ci if (!nodep) { 34062306a36Sopenharmony_ci perror("calloc"); 34162306a36Sopenharmony_ci abort(); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci nodep->idx = idx & -MASK_BITS; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* If no nodes, set it up as the root node. */ 34762306a36Sopenharmony_ci if (!s->root) { 34862306a36Sopenharmony_ci s->root = nodep; 34962306a36Sopenharmony_ci return nodep; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* 35362306a36Sopenharmony_ci * Find the parent where the new node should be attached 35462306a36Sopenharmony_ci * and add the node there. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci parentp = s->root; 35762306a36Sopenharmony_ci while (true) { 35862306a36Sopenharmony_ci if (idx < parentp->idx) { 35962306a36Sopenharmony_ci if (!parentp->left) { 36062306a36Sopenharmony_ci parentp->left = nodep; 36162306a36Sopenharmony_ci nodep->parent = parentp; 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci parentp = parentp->left; 36562306a36Sopenharmony_ci } else { 36662306a36Sopenharmony_ci assert(idx > parentp->idx + MASK_BITS + parentp->num_after - 1); 36762306a36Sopenharmony_ci if (!parentp->right) { 36862306a36Sopenharmony_ci parentp->right = nodep; 36962306a36Sopenharmony_ci nodep->parent = parentp; 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci parentp = parentp->right; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* 37762306a36Sopenharmony_ci * Does num_after bits of previous node overlap with the mask 37862306a36Sopenharmony_ci * of the new node? If so set the bits in the new nodes mask 37962306a36Sopenharmony_ci * and reduce the previous nodes num_after. 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_ci prev = node_prev(s, nodep); 38262306a36Sopenharmony_ci while (prev && prev->idx + MASK_BITS + prev->num_after - 1 >= nodep->idx) { 38362306a36Sopenharmony_ci unsigned int n1 = (prev->idx + MASK_BITS + prev->num_after - 1) 38462306a36Sopenharmony_ci - nodep->idx; 38562306a36Sopenharmony_ci assert(prev->num_after > 0); 38662306a36Sopenharmony_ci assert(n1 < MASK_BITS); 38762306a36Sopenharmony_ci assert(!(nodep->mask & (1 << n1))); 38862306a36Sopenharmony_ci nodep->mask |= (1 << n1); 38962306a36Sopenharmony_ci prev->num_after--; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci return nodep; 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* Returns whether all the bits in the sparsebit array are set. */ 39662306a36Sopenharmony_cibool sparsebit_all_set(struct sparsebit *s) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci /* 39962306a36Sopenharmony_ci * If any nodes there must be at least one bit set. Only case 40062306a36Sopenharmony_ci * where a bit is set and total num set is 0, is when all bits 40162306a36Sopenharmony_ci * are set. 40262306a36Sopenharmony_ci */ 40362306a36Sopenharmony_ci return s->root && s->num_set == 0; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* Clears all bits described by the node pointed to by nodep, then 40762306a36Sopenharmony_ci * removes the node. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_cistatic void node_rm(struct sparsebit *s, struct node *nodep) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct node *tmp; 41262306a36Sopenharmony_ci sparsebit_num_t num_set; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci num_set = node_num_set(nodep); 41562306a36Sopenharmony_ci assert(s->num_set >= num_set || sparsebit_all_set(s)); 41662306a36Sopenharmony_ci s->num_set -= node_num_set(nodep); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* Have both left and right child */ 41962306a36Sopenharmony_ci if (nodep->left && nodep->right) { 42062306a36Sopenharmony_ci /* 42162306a36Sopenharmony_ci * Move left children to the leftmost leaf node 42262306a36Sopenharmony_ci * of the right child. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci for (tmp = nodep->right; tmp->left; tmp = tmp->left) 42562306a36Sopenharmony_ci ; 42662306a36Sopenharmony_ci tmp->left = nodep->left; 42762306a36Sopenharmony_ci nodep->left = NULL; 42862306a36Sopenharmony_ci tmp->left->parent = tmp; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* Left only child */ 43262306a36Sopenharmony_ci if (nodep->left) { 43362306a36Sopenharmony_ci if (!nodep->parent) { 43462306a36Sopenharmony_ci s->root = nodep->left; 43562306a36Sopenharmony_ci nodep->left->parent = NULL; 43662306a36Sopenharmony_ci } else { 43762306a36Sopenharmony_ci nodep->left->parent = nodep->parent; 43862306a36Sopenharmony_ci if (nodep == nodep->parent->left) 43962306a36Sopenharmony_ci nodep->parent->left = nodep->left; 44062306a36Sopenharmony_ci else { 44162306a36Sopenharmony_ci assert(nodep == nodep->parent->right); 44262306a36Sopenharmony_ci nodep->parent->right = nodep->left; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci nodep->parent = nodep->left = nodep->right = NULL; 44762306a36Sopenharmony_ci free(nodep); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci return; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci /* Right only child */ 45462306a36Sopenharmony_ci if (nodep->right) { 45562306a36Sopenharmony_ci if (!nodep->parent) { 45662306a36Sopenharmony_ci s->root = nodep->right; 45762306a36Sopenharmony_ci nodep->right->parent = NULL; 45862306a36Sopenharmony_ci } else { 45962306a36Sopenharmony_ci nodep->right->parent = nodep->parent; 46062306a36Sopenharmony_ci if (nodep == nodep->parent->left) 46162306a36Sopenharmony_ci nodep->parent->left = nodep->right; 46262306a36Sopenharmony_ci else { 46362306a36Sopenharmony_ci assert(nodep == nodep->parent->right); 46462306a36Sopenharmony_ci nodep->parent->right = nodep->right; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci nodep->parent = nodep->left = nodep->right = NULL; 46962306a36Sopenharmony_ci free(nodep); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci return; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* Leaf Node */ 47562306a36Sopenharmony_ci if (!nodep->parent) { 47662306a36Sopenharmony_ci s->root = NULL; 47762306a36Sopenharmony_ci } else { 47862306a36Sopenharmony_ci if (nodep->parent->left == nodep) 47962306a36Sopenharmony_ci nodep->parent->left = NULL; 48062306a36Sopenharmony_ci else { 48162306a36Sopenharmony_ci assert(nodep == nodep->parent->right); 48262306a36Sopenharmony_ci nodep->parent->right = NULL; 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci nodep->parent = nodep->left = nodep->right = NULL; 48762306a36Sopenharmony_ci free(nodep); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/* Splits the node containing the bit at idx so that there is a node 49362306a36Sopenharmony_ci * that starts at the specified index. If no such node exists, a new 49462306a36Sopenharmony_ci * node at the specified index is created. Returns the new node. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * idx must start of a mask boundary. 49762306a36Sopenharmony_ci */ 49862306a36Sopenharmony_cistatic struct node *node_split(struct sparsebit *s, sparsebit_idx_t idx) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci struct node *nodep1, *nodep2; 50162306a36Sopenharmony_ci sparsebit_idx_t offset; 50262306a36Sopenharmony_ci sparsebit_num_t orig_num_after; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci assert(!(idx % MASK_BITS)); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* 50762306a36Sopenharmony_ci * Is there a node that describes the setting of idx? 50862306a36Sopenharmony_ci * If not, add it. 50962306a36Sopenharmony_ci */ 51062306a36Sopenharmony_ci nodep1 = node_find(s, idx); 51162306a36Sopenharmony_ci if (!nodep1) 51262306a36Sopenharmony_ci return node_add(s, idx); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* 51562306a36Sopenharmony_ci * All done if the starting index of the node is where the 51662306a36Sopenharmony_ci * split should occur. 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_ci if (nodep1->idx == idx) 51962306a36Sopenharmony_ci return nodep1; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci /* 52262306a36Sopenharmony_ci * Split point not at start of mask, so it must be part of 52362306a36Sopenharmony_ci * bits described by num_after. 52462306a36Sopenharmony_ci */ 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * Calculate offset within num_after for where the split is 52862306a36Sopenharmony_ci * to occur. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci offset = idx - (nodep1->idx + MASK_BITS); 53162306a36Sopenharmony_ci orig_num_after = nodep1->num_after; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* 53462306a36Sopenharmony_ci * Add a new node to describe the bits starting at 53562306a36Sopenharmony_ci * the split point. 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci nodep1->num_after = offset; 53862306a36Sopenharmony_ci nodep2 = node_add(s, idx); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* Move bits after the split point into the new node */ 54162306a36Sopenharmony_ci nodep2->num_after = orig_num_after - offset; 54262306a36Sopenharmony_ci if (nodep2->num_after >= MASK_BITS) { 54362306a36Sopenharmony_ci nodep2->mask = ~(mask_t) 0; 54462306a36Sopenharmony_ci nodep2->num_after -= MASK_BITS; 54562306a36Sopenharmony_ci } else { 54662306a36Sopenharmony_ci nodep2->mask = (1 << nodep2->num_after) - 1; 54762306a36Sopenharmony_ci nodep2->num_after = 0; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci return nodep2; 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci/* Iteratively reduces the node pointed to by nodep and its adjacent 55462306a36Sopenharmony_ci * nodes into a more compact form. For example, a node with a mask with 55562306a36Sopenharmony_ci * all bits set adjacent to a previous node, will get combined into a 55662306a36Sopenharmony_ci * single node with an increased num_after setting. 55762306a36Sopenharmony_ci * 55862306a36Sopenharmony_ci * After each reduction, a further check is made to see if additional 55962306a36Sopenharmony_ci * reductions are possible with the new previous and next nodes. Note, 56062306a36Sopenharmony_ci * a search for a reduction is only done across the nodes nearest nodep 56162306a36Sopenharmony_ci * and those that became part of a reduction. Reductions beyond nodep 56262306a36Sopenharmony_ci * and the adjacent nodes that are reduced are not discovered. It is the 56362306a36Sopenharmony_ci * responsibility of the caller to pass a nodep that is within one node 56462306a36Sopenharmony_ci * of each possible reduction. 56562306a36Sopenharmony_ci * 56662306a36Sopenharmony_ci * This function does not fix the temporary violation of all invariants. 56762306a36Sopenharmony_ci * For example it does not fix the case where the bit settings described 56862306a36Sopenharmony_ci * by two or more nodes overlap. Such a violation introduces the potential 56962306a36Sopenharmony_ci * complication of a bit setting for a specific index having different settings 57062306a36Sopenharmony_ci * in different nodes. This would then introduce the further complication 57162306a36Sopenharmony_ci * of which node has the correct setting of the bit and thus such conditions 57262306a36Sopenharmony_ci * are not allowed. 57362306a36Sopenharmony_ci * 57462306a36Sopenharmony_ci * This function is designed to fix invariant violations that are introduced 57562306a36Sopenharmony_ci * by node_split() and by changes to the nodes mask or num_after members. 57662306a36Sopenharmony_ci * For example, when setting a bit within a nodes mask, the function that 57762306a36Sopenharmony_ci * sets the bit doesn't have to worry about whether the setting of that 57862306a36Sopenharmony_ci * bit caused the mask to have leading only or trailing only bits set. 57962306a36Sopenharmony_ci * Instead, the function can call node_reduce(), with nodep equal to the 58062306a36Sopenharmony_ci * node address that it set a mask bit in, and node_reduce() will notice 58162306a36Sopenharmony_ci * the cases of leading or trailing only bits and that there is an 58262306a36Sopenharmony_ci * adjacent node that the bit settings could be merged into. 58362306a36Sopenharmony_ci * 58462306a36Sopenharmony_ci * This implementation specifically detects and corrects violation of the 58562306a36Sopenharmony_ci * following invariants: 58662306a36Sopenharmony_ci * 58762306a36Sopenharmony_ci * + Node are only used to represent bits that are set. 58862306a36Sopenharmony_ci * Nodes with a mask of 0 and num_after of 0 are not allowed. 58962306a36Sopenharmony_ci * 59062306a36Sopenharmony_ci * + The setting of at least one bit is always described in a nodes 59162306a36Sopenharmony_ci * mask (mask >= 1). 59262306a36Sopenharmony_ci * 59362306a36Sopenharmony_ci * + A node with all mask bits set only occurs when the last bit 59462306a36Sopenharmony_ci * described by the previous node is not equal to this nodes 59562306a36Sopenharmony_ci * starting index - 1. All such occurences of this condition are 59662306a36Sopenharmony_ci * avoided by moving the setting of the nodes mask bits into 59762306a36Sopenharmony_ci * the previous nodes num_after setting. 59862306a36Sopenharmony_ci */ 59962306a36Sopenharmony_cistatic void node_reduce(struct sparsebit *s, struct node *nodep) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci bool reduction_performed; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci do { 60462306a36Sopenharmony_ci reduction_performed = false; 60562306a36Sopenharmony_ci struct node *prev, *next, *tmp; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* 1) Potential reductions within the current node. */ 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci /* Nodes with all bits cleared may be removed. */ 61062306a36Sopenharmony_ci if (nodep->mask == 0 && nodep->num_after == 0) { 61162306a36Sopenharmony_ci /* 61262306a36Sopenharmony_ci * About to remove the node pointed to by 61362306a36Sopenharmony_ci * nodep, which normally would cause a problem 61462306a36Sopenharmony_ci * for the next pass through the reduction loop, 61562306a36Sopenharmony_ci * because the node at the starting point no longer 61662306a36Sopenharmony_ci * exists. This potential problem is handled 61762306a36Sopenharmony_ci * by first remembering the location of the next 61862306a36Sopenharmony_ci * or previous nodes. Doesn't matter which, because 61962306a36Sopenharmony_ci * once the node at nodep is removed, there will be 62062306a36Sopenharmony_ci * no other nodes between prev and next. 62162306a36Sopenharmony_ci * 62262306a36Sopenharmony_ci * Note, the checks performed on nodep against both 62362306a36Sopenharmony_ci * both prev and next both check for an adjacent 62462306a36Sopenharmony_ci * node that can be reduced into a single node. As 62562306a36Sopenharmony_ci * such, after removing the node at nodep, doesn't 62662306a36Sopenharmony_ci * matter whether the nodep for the next pass 62762306a36Sopenharmony_ci * through the loop is equal to the previous pass 62862306a36Sopenharmony_ci * prev or next node. Either way, on the next pass 62962306a36Sopenharmony_ci * the one not selected will become either the 63062306a36Sopenharmony_ci * prev or next node. 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci tmp = node_next(s, nodep); 63362306a36Sopenharmony_ci if (!tmp) 63462306a36Sopenharmony_ci tmp = node_prev(s, nodep); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci node_rm(s, nodep); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci nodep = tmp; 63962306a36Sopenharmony_ci reduction_performed = true; 64062306a36Sopenharmony_ci continue; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* 64462306a36Sopenharmony_ci * When the mask is 0, can reduce the amount of num_after 64562306a36Sopenharmony_ci * bits by moving the initial num_after bits into the mask. 64662306a36Sopenharmony_ci */ 64762306a36Sopenharmony_ci if (nodep->mask == 0) { 64862306a36Sopenharmony_ci assert(nodep->num_after != 0); 64962306a36Sopenharmony_ci assert(nodep->idx + MASK_BITS > nodep->idx); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci nodep->idx += MASK_BITS; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (nodep->num_after >= MASK_BITS) { 65462306a36Sopenharmony_ci nodep->mask = ~0; 65562306a36Sopenharmony_ci nodep->num_after -= MASK_BITS; 65662306a36Sopenharmony_ci } else { 65762306a36Sopenharmony_ci nodep->mask = (1u << nodep->num_after) - 1; 65862306a36Sopenharmony_ci nodep->num_after = 0; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci reduction_performed = true; 66262306a36Sopenharmony_ci continue; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* 66662306a36Sopenharmony_ci * 2) Potential reductions between the current and 66762306a36Sopenharmony_ci * previous nodes. 66862306a36Sopenharmony_ci */ 66962306a36Sopenharmony_ci prev = node_prev(s, nodep); 67062306a36Sopenharmony_ci if (prev) { 67162306a36Sopenharmony_ci sparsebit_idx_t prev_highest_bit; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* Nodes with no bits set can be removed. */ 67462306a36Sopenharmony_ci if (prev->mask == 0 && prev->num_after == 0) { 67562306a36Sopenharmony_ci node_rm(s, prev); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci reduction_performed = true; 67862306a36Sopenharmony_ci continue; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* 68262306a36Sopenharmony_ci * All mask bits set and previous node has 68362306a36Sopenharmony_ci * adjacent index. 68462306a36Sopenharmony_ci */ 68562306a36Sopenharmony_ci if (nodep->mask + 1 == 0 && 68662306a36Sopenharmony_ci prev->idx + MASK_BITS == nodep->idx) { 68762306a36Sopenharmony_ci prev->num_after += MASK_BITS + nodep->num_after; 68862306a36Sopenharmony_ci nodep->mask = 0; 68962306a36Sopenharmony_ci nodep->num_after = 0; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci reduction_performed = true; 69262306a36Sopenharmony_ci continue; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* 69662306a36Sopenharmony_ci * Is node adjacent to previous node and the node 69762306a36Sopenharmony_ci * contains a single contiguous range of bits 69862306a36Sopenharmony_ci * starting from the beginning of the mask? 69962306a36Sopenharmony_ci */ 70062306a36Sopenharmony_ci prev_highest_bit = prev->idx + MASK_BITS - 1 + prev->num_after; 70162306a36Sopenharmony_ci if (prev_highest_bit + 1 == nodep->idx && 70262306a36Sopenharmony_ci (nodep->mask | (nodep->mask >> 1)) == nodep->mask) { 70362306a36Sopenharmony_ci /* 70462306a36Sopenharmony_ci * How many contiguous bits are there? 70562306a36Sopenharmony_ci * Is equal to the total number of set 70662306a36Sopenharmony_ci * bits, due to an earlier check that 70762306a36Sopenharmony_ci * there is a single contiguous range of 70862306a36Sopenharmony_ci * set bits. 70962306a36Sopenharmony_ci */ 71062306a36Sopenharmony_ci unsigned int num_contiguous 71162306a36Sopenharmony_ci = __builtin_popcount(nodep->mask); 71262306a36Sopenharmony_ci assert((num_contiguous > 0) && 71362306a36Sopenharmony_ci ((1ULL << num_contiguous) - 1) == nodep->mask); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci prev->num_after += num_contiguous; 71662306a36Sopenharmony_ci nodep->mask = 0; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci /* 71962306a36Sopenharmony_ci * For predictable performance, handle special 72062306a36Sopenharmony_ci * case where all mask bits are set and there 72162306a36Sopenharmony_ci * is a non-zero num_after setting. This code 72262306a36Sopenharmony_ci * is functionally correct without the following 72362306a36Sopenharmony_ci * conditionalized statements, but without them 72462306a36Sopenharmony_ci * the value of num_after is only reduced by 72562306a36Sopenharmony_ci * the number of mask bits per pass. There are 72662306a36Sopenharmony_ci * cases where num_after can be close to 2^64. 72762306a36Sopenharmony_ci * Without this code it could take nearly 72862306a36Sopenharmony_ci * (2^64) / 32 passes to perform the full 72962306a36Sopenharmony_ci * reduction. 73062306a36Sopenharmony_ci */ 73162306a36Sopenharmony_ci if (num_contiguous == MASK_BITS) { 73262306a36Sopenharmony_ci prev->num_after += nodep->num_after; 73362306a36Sopenharmony_ci nodep->num_after = 0; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci reduction_performed = true; 73762306a36Sopenharmony_ci continue; 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci /* 74262306a36Sopenharmony_ci * 3) Potential reductions between the current and 74362306a36Sopenharmony_ci * next nodes. 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci next = node_next(s, nodep); 74662306a36Sopenharmony_ci if (next) { 74762306a36Sopenharmony_ci /* Nodes with no bits set can be removed. */ 74862306a36Sopenharmony_ci if (next->mask == 0 && next->num_after == 0) { 74962306a36Sopenharmony_ci node_rm(s, next); 75062306a36Sopenharmony_ci reduction_performed = true; 75162306a36Sopenharmony_ci continue; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci /* 75562306a36Sopenharmony_ci * Is next node index adjacent to current node 75662306a36Sopenharmony_ci * and has a mask with all bits set? 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci if (next->idx == nodep->idx + MASK_BITS + nodep->num_after && 75962306a36Sopenharmony_ci next->mask == ~(mask_t) 0) { 76062306a36Sopenharmony_ci nodep->num_after += MASK_BITS; 76162306a36Sopenharmony_ci next->mask = 0; 76262306a36Sopenharmony_ci nodep->num_after += next->num_after; 76362306a36Sopenharmony_ci next->num_after = 0; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci node_rm(s, next); 76662306a36Sopenharmony_ci next = NULL; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci reduction_performed = true; 76962306a36Sopenharmony_ci continue; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci } while (nodep && reduction_performed); 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci/* Returns whether the bit at the index given by idx, within the 77662306a36Sopenharmony_ci * sparsebit array is set or not. 77762306a36Sopenharmony_ci */ 77862306a36Sopenharmony_cibool sparsebit_is_set(struct sparsebit *s, sparsebit_idx_t idx) 77962306a36Sopenharmony_ci{ 78062306a36Sopenharmony_ci struct node *nodep; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci /* Find the node that describes the setting of the bit at idx */ 78362306a36Sopenharmony_ci for (nodep = s->root; nodep; 78462306a36Sopenharmony_ci nodep = nodep->idx > idx ? nodep->left : nodep->right) 78562306a36Sopenharmony_ci if (idx >= nodep->idx && 78662306a36Sopenharmony_ci idx <= nodep->idx + MASK_BITS + nodep->num_after - 1) 78762306a36Sopenharmony_ci goto have_node; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci return false; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cihave_node: 79262306a36Sopenharmony_ci /* Bit is set if it is any of the bits described by num_after */ 79362306a36Sopenharmony_ci if (nodep->num_after && idx >= nodep->idx + MASK_BITS) 79462306a36Sopenharmony_ci return true; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci /* Is the corresponding mask bit set */ 79762306a36Sopenharmony_ci assert(idx >= nodep->idx && idx - nodep->idx < MASK_BITS); 79862306a36Sopenharmony_ci return !!(nodep->mask & (1 << (idx - nodep->idx))); 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci/* Within the sparsebit array pointed to by s, sets the bit 80262306a36Sopenharmony_ci * at the index given by idx. 80362306a36Sopenharmony_ci */ 80462306a36Sopenharmony_cistatic void bit_set(struct sparsebit *s, sparsebit_idx_t idx) 80562306a36Sopenharmony_ci{ 80662306a36Sopenharmony_ci struct node *nodep; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* Skip bits that are already set */ 80962306a36Sopenharmony_ci if (sparsebit_is_set(s, idx)) 81062306a36Sopenharmony_ci return; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* 81362306a36Sopenharmony_ci * Get a node where the bit at idx is described by the mask. 81462306a36Sopenharmony_ci * The node_split will also create a node, if there isn't 81562306a36Sopenharmony_ci * already a node that describes the setting of bit. 81662306a36Sopenharmony_ci */ 81762306a36Sopenharmony_ci nodep = node_split(s, idx & -MASK_BITS); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* Set the bit within the nodes mask */ 82062306a36Sopenharmony_ci assert(idx >= nodep->idx && idx <= nodep->idx + MASK_BITS - 1); 82162306a36Sopenharmony_ci assert(!(nodep->mask & (1 << (idx - nodep->idx)))); 82262306a36Sopenharmony_ci nodep->mask |= 1 << (idx - nodep->idx); 82362306a36Sopenharmony_ci s->num_set++; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci node_reduce(s, nodep); 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci/* Within the sparsebit array pointed to by s, clears the bit 82962306a36Sopenharmony_ci * at the index given by idx. 83062306a36Sopenharmony_ci */ 83162306a36Sopenharmony_cistatic void bit_clear(struct sparsebit *s, sparsebit_idx_t idx) 83262306a36Sopenharmony_ci{ 83362306a36Sopenharmony_ci struct node *nodep; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* Skip bits that are already cleared */ 83662306a36Sopenharmony_ci if (!sparsebit_is_set(s, idx)) 83762306a36Sopenharmony_ci return; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci /* Is there a node that describes the setting of this bit? */ 84062306a36Sopenharmony_ci nodep = node_find(s, idx); 84162306a36Sopenharmony_ci if (!nodep) 84262306a36Sopenharmony_ci return; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * If a num_after bit, split the node, so that the bit is 84662306a36Sopenharmony_ci * part of a node mask. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci if (idx >= nodep->idx + MASK_BITS) 84962306a36Sopenharmony_ci nodep = node_split(s, idx & -MASK_BITS); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci /* 85262306a36Sopenharmony_ci * After node_split above, bit at idx should be within the mask. 85362306a36Sopenharmony_ci * Clear that bit. 85462306a36Sopenharmony_ci */ 85562306a36Sopenharmony_ci assert(idx >= nodep->idx && idx <= nodep->idx + MASK_BITS - 1); 85662306a36Sopenharmony_ci assert(nodep->mask & (1 << (idx - nodep->idx))); 85762306a36Sopenharmony_ci nodep->mask &= ~(1 << (idx - nodep->idx)); 85862306a36Sopenharmony_ci assert(s->num_set > 0 || sparsebit_all_set(s)); 85962306a36Sopenharmony_ci s->num_set--; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci node_reduce(s, nodep); 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci/* Recursively dumps to the FILE stream given by stream the contents 86562306a36Sopenharmony_ci * of the sub-tree of nodes pointed to by nodep. Each line of output 86662306a36Sopenharmony_ci * is prefixed by the number of spaces given by indent. On each 86762306a36Sopenharmony_ci * recursion, the indent amount is increased by 2. This causes nodes 86862306a36Sopenharmony_ci * at each level deeper into the binary search tree to be displayed 86962306a36Sopenharmony_ci * with a greater indent. 87062306a36Sopenharmony_ci */ 87162306a36Sopenharmony_cistatic void dump_nodes(FILE *stream, struct node *nodep, 87262306a36Sopenharmony_ci unsigned int indent) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci char *node_type; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci /* Dump contents of node */ 87762306a36Sopenharmony_ci if (!nodep->parent) 87862306a36Sopenharmony_ci node_type = "root"; 87962306a36Sopenharmony_ci else if (nodep == nodep->parent->left) 88062306a36Sopenharmony_ci node_type = "left"; 88162306a36Sopenharmony_ci else { 88262306a36Sopenharmony_ci assert(nodep == nodep->parent->right); 88362306a36Sopenharmony_ci node_type = "right"; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci fprintf(stream, "%*s---- %s nodep: %p\n", indent, "", node_type, nodep); 88662306a36Sopenharmony_ci fprintf(stream, "%*s parent: %p left: %p right: %p\n", indent, "", 88762306a36Sopenharmony_ci nodep->parent, nodep->left, nodep->right); 88862306a36Sopenharmony_ci fprintf(stream, "%*s idx: 0x%lx mask: 0x%x num_after: 0x%lx\n", 88962306a36Sopenharmony_ci indent, "", nodep->idx, nodep->mask, nodep->num_after); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci /* If present, dump contents of left child nodes */ 89262306a36Sopenharmony_ci if (nodep->left) 89362306a36Sopenharmony_ci dump_nodes(stream, nodep->left, indent + 2); 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci /* If present, dump contents of right child nodes */ 89662306a36Sopenharmony_ci if (nodep->right) 89762306a36Sopenharmony_ci dump_nodes(stream, nodep->right, indent + 2); 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic inline sparsebit_idx_t node_first_set(struct node *nodep, int start) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci mask_t leading = (mask_t)1 << start; 90362306a36Sopenharmony_ci int n1 = __builtin_ctz(nodep->mask & -leading); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci return nodep->idx + n1; 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic inline sparsebit_idx_t node_first_clear(struct node *nodep, int start) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci mask_t leading = (mask_t)1 << start; 91162306a36Sopenharmony_ci int n1 = __builtin_ctz(~nodep->mask & -leading); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci return nodep->idx + n1; 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci/* Dumps to the FILE stream specified by stream, the implementation dependent 91762306a36Sopenharmony_ci * internal state of s. Each line of output is prefixed with the number 91862306a36Sopenharmony_ci * of spaces given by indent. The output is completely implementation 91962306a36Sopenharmony_ci * dependent and subject to change. Output from this function should only 92062306a36Sopenharmony_ci * be used for diagnostic purposes. For example, this function can be 92162306a36Sopenharmony_ci * used by test cases after they detect an unexpected condition, as a means 92262306a36Sopenharmony_ci * to capture diagnostic information. 92362306a36Sopenharmony_ci */ 92462306a36Sopenharmony_cistatic void sparsebit_dump_internal(FILE *stream, struct sparsebit *s, 92562306a36Sopenharmony_ci unsigned int indent) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci /* Dump the contents of s */ 92862306a36Sopenharmony_ci fprintf(stream, "%*sroot: %p\n", indent, "", s->root); 92962306a36Sopenharmony_ci fprintf(stream, "%*snum_set: 0x%lx\n", indent, "", s->num_set); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci if (s->root) 93262306a36Sopenharmony_ci dump_nodes(stream, s->root, indent); 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/* Allocates and returns a new sparsebit array. The initial state 93662306a36Sopenharmony_ci * of the newly allocated sparsebit array has all bits cleared. 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_cistruct sparsebit *sparsebit_alloc(void) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci struct sparsebit *s; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci /* Allocate top level structure. */ 94362306a36Sopenharmony_ci s = calloc(1, sizeof(*s)); 94462306a36Sopenharmony_ci if (!s) { 94562306a36Sopenharmony_ci perror("calloc"); 94662306a36Sopenharmony_ci abort(); 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci return s; 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci/* Frees the implementation dependent data for the sparsebit array 95362306a36Sopenharmony_ci * pointed to by s and poisons the pointer to that data. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_civoid sparsebit_free(struct sparsebit **sbitp) 95662306a36Sopenharmony_ci{ 95762306a36Sopenharmony_ci struct sparsebit *s = *sbitp; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci if (!s) 96062306a36Sopenharmony_ci return; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci sparsebit_clear_all(s); 96362306a36Sopenharmony_ci free(s); 96462306a36Sopenharmony_ci *sbitp = NULL; 96562306a36Sopenharmony_ci} 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci/* Makes a copy of the sparsebit array given by s, to the sparsebit 96862306a36Sopenharmony_ci * array given by d. Note, d must have already been allocated via 96962306a36Sopenharmony_ci * sparsebit_alloc(). It can though already have bits set, which 97062306a36Sopenharmony_ci * if different from src will be cleared. 97162306a36Sopenharmony_ci */ 97262306a36Sopenharmony_civoid sparsebit_copy(struct sparsebit *d, struct sparsebit *s) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci /* First clear any bits already set in the destination */ 97562306a36Sopenharmony_ci sparsebit_clear_all(d); 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci if (s->root) { 97862306a36Sopenharmony_ci d->root = node_copy_subtree(s->root); 97962306a36Sopenharmony_ci d->num_set = s->num_set; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci/* Returns whether num consecutive bits starting at idx are all set. */ 98462306a36Sopenharmony_cibool sparsebit_is_set_num(struct sparsebit *s, 98562306a36Sopenharmony_ci sparsebit_idx_t idx, sparsebit_num_t num) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci sparsebit_idx_t next_cleared; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci assert(num > 0); 99062306a36Sopenharmony_ci assert(idx + num - 1 >= idx); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci /* With num > 0, the first bit must be set. */ 99362306a36Sopenharmony_ci if (!sparsebit_is_set(s, idx)) 99462306a36Sopenharmony_ci return false; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci /* Find the next cleared bit */ 99762306a36Sopenharmony_ci next_cleared = sparsebit_next_clear(s, idx); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* 100062306a36Sopenharmony_ci * If no cleared bits beyond idx, then there are at least num 100162306a36Sopenharmony_ci * set bits. idx + num doesn't wrap. Otherwise check if 100262306a36Sopenharmony_ci * there are enough set bits between idx and the next cleared bit. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_ci return next_cleared == 0 || next_cleared - idx >= num; 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci/* Returns whether the bit at the index given by idx. */ 100862306a36Sopenharmony_cibool sparsebit_is_clear(struct sparsebit *s, 100962306a36Sopenharmony_ci sparsebit_idx_t idx) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci return !sparsebit_is_set(s, idx); 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci/* Returns whether num consecutive bits starting at idx are all cleared. */ 101562306a36Sopenharmony_cibool sparsebit_is_clear_num(struct sparsebit *s, 101662306a36Sopenharmony_ci sparsebit_idx_t idx, sparsebit_num_t num) 101762306a36Sopenharmony_ci{ 101862306a36Sopenharmony_ci sparsebit_idx_t next_set; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci assert(num > 0); 102162306a36Sopenharmony_ci assert(idx + num - 1 >= idx); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* With num > 0, the first bit must be cleared. */ 102462306a36Sopenharmony_ci if (!sparsebit_is_clear(s, idx)) 102562306a36Sopenharmony_ci return false; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci /* Find the next set bit */ 102862306a36Sopenharmony_ci next_set = sparsebit_next_set(s, idx); 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci /* 103162306a36Sopenharmony_ci * If no set bits beyond idx, then there are at least num 103262306a36Sopenharmony_ci * cleared bits. idx + num doesn't wrap. Otherwise check if 103362306a36Sopenharmony_ci * there are enough cleared bits between idx and the next set bit. 103462306a36Sopenharmony_ci */ 103562306a36Sopenharmony_ci return next_set == 0 || next_set - idx >= num; 103662306a36Sopenharmony_ci} 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci/* Returns the total number of bits set. Note: 0 is also returned for 103962306a36Sopenharmony_ci * the case of all bits set. This is because with all bits set, there 104062306a36Sopenharmony_ci * is 1 additional bit set beyond what can be represented in the return 104162306a36Sopenharmony_ci * value. Use sparsebit_any_set(), instead of sparsebit_num_set() > 0, 104262306a36Sopenharmony_ci * to determine if the sparsebit array has any bits set. 104362306a36Sopenharmony_ci */ 104462306a36Sopenharmony_cisparsebit_num_t sparsebit_num_set(struct sparsebit *s) 104562306a36Sopenharmony_ci{ 104662306a36Sopenharmony_ci return s->num_set; 104762306a36Sopenharmony_ci} 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci/* Returns whether any bit is set in the sparsebit array. */ 105062306a36Sopenharmony_cibool sparsebit_any_set(struct sparsebit *s) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci /* 105362306a36Sopenharmony_ci * Nodes only describe set bits. If any nodes then there 105462306a36Sopenharmony_ci * is at least 1 bit set. 105562306a36Sopenharmony_ci */ 105662306a36Sopenharmony_ci if (!s->root) 105762306a36Sopenharmony_ci return false; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci /* 106062306a36Sopenharmony_ci * Every node should have a non-zero mask. For now will 106162306a36Sopenharmony_ci * just assure that the root node has a non-zero mask, 106262306a36Sopenharmony_ci * which is a quick check that at least 1 bit is set. 106362306a36Sopenharmony_ci */ 106462306a36Sopenharmony_ci assert(s->root->mask != 0); 106562306a36Sopenharmony_ci assert(s->num_set > 0 || 106662306a36Sopenharmony_ci (s->root->num_after == ((sparsebit_num_t) 0) - MASK_BITS && 106762306a36Sopenharmony_ci s->root->mask == ~(mask_t) 0)); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci return true; 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci/* Returns whether all the bits in the sparsebit array are cleared. */ 107362306a36Sopenharmony_cibool sparsebit_all_clear(struct sparsebit *s) 107462306a36Sopenharmony_ci{ 107562306a36Sopenharmony_ci return !sparsebit_any_set(s); 107662306a36Sopenharmony_ci} 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci/* Returns whether all the bits in the sparsebit array are set. */ 107962306a36Sopenharmony_cibool sparsebit_any_clear(struct sparsebit *s) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci return !sparsebit_all_set(s); 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci/* Returns the index of the first set bit. Abort if no bits are set. 108562306a36Sopenharmony_ci */ 108662306a36Sopenharmony_cisparsebit_idx_t sparsebit_first_set(struct sparsebit *s) 108762306a36Sopenharmony_ci{ 108862306a36Sopenharmony_ci struct node *nodep; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci /* Validate at least 1 bit is set */ 109162306a36Sopenharmony_ci assert(sparsebit_any_set(s)); 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci nodep = node_first(s); 109462306a36Sopenharmony_ci return node_first_set(nodep, 0); 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci/* Returns the index of the first cleared bit. Abort if 109862306a36Sopenharmony_ci * no bits are cleared. 109962306a36Sopenharmony_ci */ 110062306a36Sopenharmony_cisparsebit_idx_t sparsebit_first_clear(struct sparsebit *s) 110162306a36Sopenharmony_ci{ 110262306a36Sopenharmony_ci struct node *nodep1, *nodep2; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci /* Validate at least 1 bit is cleared. */ 110562306a36Sopenharmony_ci assert(sparsebit_any_clear(s)); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci /* If no nodes or first node index > 0 then lowest cleared is 0 */ 110862306a36Sopenharmony_ci nodep1 = node_first(s); 110962306a36Sopenharmony_ci if (!nodep1 || nodep1->idx > 0) 111062306a36Sopenharmony_ci return 0; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci /* Does the mask in the first node contain any cleared bits. */ 111362306a36Sopenharmony_ci if (nodep1->mask != ~(mask_t) 0) 111462306a36Sopenharmony_ci return node_first_clear(nodep1, 0); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci /* 111762306a36Sopenharmony_ci * All mask bits set in first node. If there isn't a second node 111862306a36Sopenharmony_ci * then the first cleared bit is the first bit after the bits 111962306a36Sopenharmony_ci * described by the first node. 112062306a36Sopenharmony_ci */ 112162306a36Sopenharmony_ci nodep2 = node_next(s, nodep1); 112262306a36Sopenharmony_ci if (!nodep2) { 112362306a36Sopenharmony_ci /* 112462306a36Sopenharmony_ci * No second node. First cleared bit is first bit beyond 112562306a36Sopenharmony_ci * bits described by first node. 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_ci assert(nodep1->mask == ~(mask_t) 0); 112862306a36Sopenharmony_ci assert(nodep1->idx + MASK_BITS + nodep1->num_after != (sparsebit_idx_t) 0); 112962306a36Sopenharmony_ci return nodep1->idx + MASK_BITS + nodep1->num_after; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci /* 113362306a36Sopenharmony_ci * There is a second node. 113462306a36Sopenharmony_ci * If it is not adjacent to the first node, then there is a gap 113562306a36Sopenharmony_ci * of cleared bits between the nodes, and the first cleared bit 113662306a36Sopenharmony_ci * is the first bit within the gap. 113762306a36Sopenharmony_ci */ 113862306a36Sopenharmony_ci if (nodep1->idx + MASK_BITS + nodep1->num_after != nodep2->idx) 113962306a36Sopenharmony_ci return nodep1->idx + MASK_BITS + nodep1->num_after; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci /* 114262306a36Sopenharmony_ci * Second node is adjacent to the first node. 114362306a36Sopenharmony_ci * Because it is adjacent, its mask should be non-zero. If all 114462306a36Sopenharmony_ci * its mask bits are set, then with it being adjacent, it should 114562306a36Sopenharmony_ci * have had the mask bits moved into the num_after setting of the 114662306a36Sopenharmony_ci * previous node. 114762306a36Sopenharmony_ci */ 114862306a36Sopenharmony_ci return node_first_clear(nodep2, 0); 114962306a36Sopenharmony_ci} 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci/* Returns index of next bit set within s after the index given by prev. 115262306a36Sopenharmony_ci * Returns 0 if there are no bits after prev that are set. 115362306a36Sopenharmony_ci */ 115462306a36Sopenharmony_cisparsebit_idx_t sparsebit_next_set(struct sparsebit *s, 115562306a36Sopenharmony_ci sparsebit_idx_t prev) 115662306a36Sopenharmony_ci{ 115762306a36Sopenharmony_ci sparsebit_idx_t lowest_possible = prev + 1; 115862306a36Sopenharmony_ci sparsebit_idx_t start; 115962306a36Sopenharmony_ci struct node *nodep; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci /* A bit after the highest index can't be set. */ 116262306a36Sopenharmony_ci if (lowest_possible == 0) 116362306a36Sopenharmony_ci return 0; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci /* 116662306a36Sopenharmony_ci * Find the leftmost 'candidate' overlapping or to the right 116762306a36Sopenharmony_ci * of lowest_possible. 116862306a36Sopenharmony_ci */ 116962306a36Sopenharmony_ci struct node *candidate = NULL; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci /* True iff lowest_possible is within candidate */ 117262306a36Sopenharmony_ci bool contains = false; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci /* 117562306a36Sopenharmony_ci * Find node that describes setting of bit at lowest_possible. 117662306a36Sopenharmony_ci * If such a node doesn't exist, find the node with the lowest 117762306a36Sopenharmony_ci * starting index that is > lowest_possible. 117862306a36Sopenharmony_ci */ 117962306a36Sopenharmony_ci for (nodep = s->root; nodep;) { 118062306a36Sopenharmony_ci if ((nodep->idx + MASK_BITS + nodep->num_after - 1) 118162306a36Sopenharmony_ci >= lowest_possible) { 118262306a36Sopenharmony_ci candidate = nodep; 118362306a36Sopenharmony_ci if (candidate->idx <= lowest_possible) { 118462306a36Sopenharmony_ci contains = true; 118562306a36Sopenharmony_ci break; 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci nodep = nodep->left; 118862306a36Sopenharmony_ci } else { 118962306a36Sopenharmony_ci nodep = nodep->right; 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci if (!candidate) 119362306a36Sopenharmony_ci return 0; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci assert(candidate->mask != 0); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci /* Does the candidate node describe the setting of lowest_possible? */ 119862306a36Sopenharmony_ci if (!contains) { 119962306a36Sopenharmony_ci /* 120062306a36Sopenharmony_ci * Candidate doesn't describe setting of bit at lowest_possible. 120162306a36Sopenharmony_ci * Candidate points to the first node with a starting index 120262306a36Sopenharmony_ci * > lowest_possible. 120362306a36Sopenharmony_ci */ 120462306a36Sopenharmony_ci assert(candidate->idx > lowest_possible); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci return node_first_set(candidate, 0); 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci /* 121062306a36Sopenharmony_ci * Candidate describes setting of bit at lowest_possible. 121162306a36Sopenharmony_ci * Note: although the node describes the setting of the bit 121262306a36Sopenharmony_ci * at lowest_possible, its possible that its setting and the 121362306a36Sopenharmony_ci * setting of all latter bits described by this node are 0. 121462306a36Sopenharmony_ci * For now, just handle the cases where this node describes 121562306a36Sopenharmony_ci * a bit at or after an index of lowest_possible that is set. 121662306a36Sopenharmony_ci */ 121762306a36Sopenharmony_ci start = lowest_possible - candidate->idx; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci if (start < MASK_BITS && candidate->mask >= (1 << start)) 122062306a36Sopenharmony_ci return node_first_set(candidate, start); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci if (candidate->num_after) { 122362306a36Sopenharmony_ci sparsebit_idx_t first_num_after_idx = candidate->idx + MASK_BITS; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci return lowest_possible < first_num_after_idx 122662306a36Sopenharmony_ci ? first_num_after_idx : lowest_possible; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* 123062306a36Sopenharmony_ci * Although candidate node describes setting of bit at 123162306a36Sopenharmony_ci * the index of lowest_possible, all bits at that index and 123262306a36Sopenharmony_ci * latter that are described by candidate are cleared. With 123362306a36Sopenharmony_ci * this, the next bit is the first bit in the next node, if 123462306a36Sopenharmony_ci * such a node exists. If a next node doesn't exist, then 123562306a36Sopenharmony_ci * there is no next set bit. 123662306a36Sopenharmony_ci */ 123762306a36Sopenharmony_ci candidate = node_next(s, candidate); 123862306a36Sopenharmony_ci if (!candidate) 123962306a36Sopenharmony_ci return 0; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci return node_first_set(candidate, 0); 124262306a36Sopenharmony_ci} 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci/* Returns index of next bit cleared within s after the index given by prev. 124562306a36Sopenharmony_ci * Returns 0 if there are no bits after prev that are cleared. 124662306a36Sopenharmony_ci */ 124762306a36Sopenharmony_cisparsebit_idx_t sparsebit_next_clear(struct sparsebit *s, 124862306a36Sopenharmony_ci sparsebit_idx_t prev) 124962306a36Sopenharmony_ci{ 125062306a36Sopenharmony_ci sparsebit_idx_t lowest_possible = prev + 1; 125162306a36Sopenharmony_ci sparsebit_idx_t idx; 125262306a36Sopenharmony_ci struct node *nodep1, *nodep2; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci /* A bit after the highest index can't be set. */ 125562306a36Sopenharmony_ci if (lowest_possible == 0) 125662306a36Sopenharmony_ci return 0; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci /* 125962306a36Sopenharmony_ci * Does a node describing the setting of lowest_possible exist? 126062306a36Sopenharmony_ci * If not, the bit at lowest_possible is cleared. 126162306a36Sopenharmony_ci */ 126262306a36Sopenharmony_ci nodep1 = node_find(s, lowest_possible); 126362306a36Sopenharmony_ci if (!nodep1) 126462306a36Sopenharmony_ci return lowest_possible; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci /* Does a mask bit in node 1 describe the next cleared bit. */ 126762306a36Sopenharmony_ci for (idx = lowest_possible - nodep1->idx; idx < MASK_BITS; idx++) 126862306a36Sopenharmony_ci if (!(nodep1->mask & (1 << idx))) 126962306a36Sopenharmony_ci return nodep1->idx + idx; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* 127262306a36Sopenharmony_ci * Next cleared bit is not described by node 1. If there 127362306a36Sopenharmony_ci * isn't a next node, then next cleared bit is described 127462306a36Sopenharmony_ci * by bit after the bits described by the first node. 127562306a36Sopenharmony_ci */ 127662306a36Sopenharmony_ci nodep2 = node_next(s, nodep1); 127762306a36Sopenharmony_ci if (!nodep2) 127862306a36Sopenharmony_ci return nodep1->idx + MASK_BITS + nodep1->num_after; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci /* 128162306a36Sopenharmony_ci * There is a second node. 128262306a36Sopenharmony_ci * If it is not adjacent to the first node, then there is a gap 128362306a36Sopenharmony_ci * of cleared bits between the nodes, and the next cleared bit 128462306a36Sopenharmony_ci * is the first bit within the gap. 128562306a36Sopenharmony_ci */ 128662306a36Sopenharmony_ci if (nodep1->idx + MASK_BITS + nodep1->num_after != nodep2->idx) 128762306a36Sopenharmony_ci return nodep1->idx + MASK_BITS + nodep1->num_after; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci /* 129062306a36Sopenharmony_ci * Second node is adjacent to the first node. 129162306a36Sopenharmony_ci * Because it is adjacent, its mask should be non-zero. If all 129262306a36Sopenharmony_ci * its mask bits are set, then with it being adjacent, it should 129362306a36Sopenharmony_ci * have had the mask bits moved into the num_after setting of the 129462306a36Sopenharmony_ci * previous node. 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_ci return node_first_clear(nodep2, 0); 129762306a36Sopenharmony_ci} 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci/* Starting with the index 1 greater than the index given by start, finds 130062306a36Sopenharmony_ci * and returns the index of the first sequence of num consecutively set 130162306a36Sopenharmony_ci * bits. Returns a value of 0 of no such sequence exists. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_cisparsebit_idx_t sparsebit_next_set_num(struct sparsebit *s, 130462306a36Sopenharmony_ci sparsebit_idx_t start, sparsebit_num_t num) 130562306a36Sopenharmony_ci{ 130662306a36Sopenharmony_ci sparsebit_idx_t idx; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci assert(num >= 1); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci for (idx = sparsebit_next_set(s, start); 131162306a36Sopenharmony_ci idx != 0 && idx + num - 1 >= idx; 131262306a36Sopenharmony_ci idx = sparsebit_next_set(s, idx)) { 131362306a36Sopenharmony_ci assert(sparsebit_is_set(s, idx)); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci /* 131662306a36Sopenharmony_ci * Does the sequence of bits starting at idx consist of 131762306a36Sopenharmony_ci * num set bits? 131862306a36Sopenharmony_ci */ 131962306a36Sopenharmony_ci if (sparsebit_is_set_num(s, idx, num)) 132062306a36Sopenharmony_ci return idx; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci /* 132362306a36Sopenharmony_ci * Sequence of set bits at idx isn't large enough. 132462306a36Sopenharmony_ci * Skip this entire sequence of set bits. 132562306a36Sopenharmony_ci */ 132662306a36Sopenharmony_ci idx = sparsebit_next_clear(s, idx); 132762306a36Sopenharmony_ci if (idx == 0) 132862306a36Sopenharmony_ci return 0; 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci return 0; 133262306a36Sopenharmony_ci} 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci/* Starting with the index 1 greater than the index given by start, finds 133562306a36Sopenharmony_ci * and returns the index of the first sequence of num consecutively cleared 133662306a36Sopenharmony_ci * bits. Returns a value of 0 of no such sequence exists. 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_cisparsebit_idx_t sparsebit_next_clear_num(struct sparsebit *s, 133962306a36Sopenharmony_ci sparsebit_idx_t start, sparsebit_num_t num) 134062306a36Sopenharmony_ci{ 134162306a36Sopenharmony_ci sparsebit_idx_t idx; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci assert(num >= 1); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci for (idx = sparsebit_next_clear(s, start); 134662306a36Sopenharmony_ci idx != 0 && idx + num - 1 >= idx; 134762306a36Sopenharmony_ci idx = sparsebit_next_clear(s, idx)) { 134862306a36Sopenharmony_ci assert(sparsebit_is_clear(s, idx)); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* 135162306a36Sopenharmony_ci * Does the sequence of bits starting at idx consist of 135262306a36Sopenharmony_ci * num cleared bits? 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ci if (sparsebit_is_clear_num(s, idx, num)) 135562306a36Sopenharmony_ci return idx; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci /* 135862306a36Sopenharmony_ci * Sequence of cleared bits at idx isn't large enough. 135962306a36Sopenharmony_ci * Skip this entire sequence of cleared bits. 136062306a36Sopenharmony_ci */ 136162306a36Sopenharmony_ci idx = sparsebit_next_set(s, idx); 136262306a36Sopenharmony_ci if (idx == 0) 136362306a36Sopenharmony_ci return 0; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci return 0; 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci/* Sets the bits * in the inclusive range idx through idx + num - 1. */ 137062306a36Sopenharmony_civoid sparsebit_set_num(struct sparsebit *s, 137162306a36Sopenharmony_ci sparsebit_idx_t start, sparsebit_num_t num) 137262306a36Sopenharmony_ci{ 137362306a36Sopenharmony_ci struct node *nodep, *next; 137462306a36Sopenharmony_ci unsigned int n1; 137562306a36Sopenharmony_ci sparsebit_idx_t idx; 137662306a36Sopenharmony_ci sparsebit_num_t n; 137762306a36Sopenharmony_ci sparsebit_idx_t middle_start, middle_end; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci assert(num > 0); 138062306a36Sopenharmony_ci assert(start + num - 1 >= start); 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci /* 138362306a36Sopenharmony_ci * Leading - bits before first mask boundary. 138462306a36Sopenharmony_ci * 138562306a36Sopenharmony_ci * TODO(lhuemill): With some effort it may be possible to 138662306a36Sopenharmony_ci * replace the following loop with a sequential sequence 138762306a36Sopenharmony_ci * of statements. High level sequence would be: 138862306a36Sopenharmony_ci * 138962306a36Sopenharmony_ci * 1. Use node_split() to force node that describes setting 139062306a36Sopenharmony_ci * of idx to be within the mask portion of a node. 139162306a36Sopenharmony_ci * 2. Form mask of bits to be set. 139262306a36Sopenharmony_ci * 3. Determine number of mask bits already set in the node 139362306a36Sopenharmony_ci * and store in a local variable named num_already_set. 139462306a36Sopenharmony_ci * 4. Set the appropriate mask bits within the node. 139562306a36Sopenharmony_ci * 5. Increment struct sparsebit_pvt num_set member 139662306a36Sopenharmony_ci * by the number of bits that were actually set. 139762306a36Sopenharmony_ci * Exclude from the counts bits that were already set. 139862306a36Sopenharmony_ci * 6. Before returning to the caller, use node_reduce() to 139962306a36Sopenharmony_ci * handle the multiple corner cases that this method 140062306a36Sopenharmony_ci * introduces. 140162306a36Sopenharmony_ci */ 140262306a36Sopenharmony_ci for (idx = start, n = num; n > 0 && idx % MASK_BITS != 0; idx++, n--) 140362306a36Sopenharmony_ci bit_set(s, idx); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci /* Middle - bits spanning one or more entire mask */ 140662306a36Sopenharmony_ci middle_start = idx; 140762306a36Sopenharmony_ci middle_end = middle_start + (n & -MASK_BITS) - 1; 140862306a36Sopenharmony_ci if (n >= MASK_BITS) { 140962306a36Sopenharmony_ci nodep = node_split(s, middle_start); 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci /* 141262306a36Sopenharmony_ci * As needed, split just after end of middle bits. 141362306a36Sopenharmony_ci * No split needed if end of middle bits is at highest 141462306a36Sopenharmony_ci * supported bit index. 141562306a36Sopenharmony_ci */ 141662306a36Sopenharmony_ci if (middle_end + 1 > middle_end) 141762306a36Sopenharmony_ci (void) node_split(s, middle_end + 1); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci /* Delete nodes that only describe bits within the middle. */ 142062306a36Sopenharmony_ci for (next = node_next(s, nodep); 142162306a36Sopenharmony_ci next && (next->idx < middle_end); 142262306a36Sopenharmony_ci next = node_next(s, nodep)) { 142362306a36Sopenharmony_ci assert(next->idx + MASK_BITS + next->num_after - 1 <= middle_end); 142462306a36Sopenharmony_ci node_rm(s, next); 142562306a36Sopenharmony_ci next = NULL; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci /* As needed set each of the mask bits */ 142962306a36Sopenharmony_ci for (n1 = 0; n1 < MASK_BITS; n1++) { 143062306a36Sopenharmony_ci if (!(nodep->mask & (1 << n1))) { 143162306a36Sopenharmony_ci nodep->mask |= 1 << n1; 143262306a36Sopenharmony_ci s->num_set++; 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci s->num_set -= nodep->num_after; 143762306a36Sopenharmony_ci nodep->num_after = middle_end - middle_start + 1 - MASK_BITS; 143862306a36Sopenharmony_ci s->num_set += nodep->num_after; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci node_reduce(s, nodep); 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci idx = middle_end + 1; 144362306a36Sopenharmony_ci n -= middle_end - middle_start + 1; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci /* Trailing - bits at and beyond last mask boundary */ 144662306a36Sopenharmony_ci assert(n < MASK_BITS); 144762306a36Sopenharmony_ci for (; n > 0; idx++, n--) 144862306a36Sopenharmony_ci bit_set(s, idx); 144962306a36Sopenharmony_ci} 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci/* Clears the bits * in the inclusive range idx through idx + num - 1. */ 145262306a36Sopenharmony_civoid sparsebit_clear_num(struct sparsebit *s, 145362306a36Sopenharmony_ci sparsebit_idx_t start, sparsebit_num_t num) 145462306a36Sopenharmony_ci{ 145562306a36Sopenharmony_ci struct node *nodep, *next; 145662306a36Sopenharmony_ci unsigned int n1; 145762306a36Sopenharmony_ci sparsebit_idx_t idx; 145862306a36Sopenharmony_ci sparsebit_num_t n; 145962306a36Sopenharmony_ci sparsebit_idx_t middle_start, middle_end; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci assert(num > 0); 146262306a36Sopenharmony_ci assert(start + num - 1 >= start); 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci /* Leading - bits before first mask boundary */ 146562306a36Sopenharmony_ci for (idx = start, n = num; n > 0 && idx % MASK_BITS != 0; idx++, n--) 146662306a36Sopenharmony_ci bit_clear(s, idx); 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci /* Middle - bits spanning one or more entire mask */ 146962306a36Sopenharmony_ci middle_start = idx; 147062306a36Sopenharmony_ci middle_end = middle_start + (n & -MASK_BITS) - 1; 147162306a36Sopenharmony_ci if (n >= MASK_BITS) { 147262306a36Sopenharmony_ci nodep = node_split(s, middle_start); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci /* 147562306a36Sopenharmony_ci * As needed, split just after end of middle bits. 147662306a36Sopenharmony_ci * No split needed if end of middle bits is at highest 147762306a36Sopenharmony_ci * supported bit index. 147862306a36Sopenharmony_ci */ 147962306a36Sopenharmony_ci if (middle_end + 1 > middle_end) 148062306a36Sopenharmony_ci (void) node_split(s, middle_end + 1); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci /* Delete nodes that only describe bits within the middle. */ 148362306a36Sopenharmony_ci for (next = node_next(s, nodep); 148462306a36Sopenharmony_ci next && (next->idx < middle_end); 148562306a36Sopenharmony_ci next = node_next(s, nodep)) { 148662306a36Sopenharmony_ci assert(next->idx + MASK_BITS + next->num_after - 1 <= middle_end); 148762306a36Sopenharmony_ci node_rm(s, next); 148862306a36Sopenharmony_ci next = NULL; 148962306a36Sopenharmony_ci } 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /* As needed clear each of the mask bits */ 149262306a36Sopenharmony_ci for (n1 = 0; n1 < MASK_BITS; n1++) { 149362306a36Sopenharmony_ci if (nodep->mask & (1 << n1)) { 149462306a36Sopenharmony_ci nodep->mask &= ~(1 << n1); 149562306a36Sopenharmony_ci s->num_set--; 149662306a36Sopenharmony_ci } 149762306a36Sopenharmony_ci } 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci /* Clear any bits described by num_after */ 150062306a36Sopenharmony_ci s->num_set -= nodep->num_after; 150162306a36Sopenharmony_ci nodep->num_after = 0; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci /* 150462306a36Sopenharmony_ci * Delete the node that describes the beginning of 150562306a36Sopenharmony_ci * the middle bits and perform any allowed reductions 150662306a36Sopenharmony_ci * with the nodes prev or next of nodep. 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_ci node_reduce(s, nodep); 150962306a36Sopenharmony_ci nodep = NULL; 151062306a36Sopenharmony_ci } 151162306a36Sopenharmony_ci idx = middle_end + 1; 151262306a36Sopenharmony_ci n -= middle_end - middle_start + 1; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci /* Trailing - bits at and beyond last mask boundary */ 151562306a36Sopenharmony_ci assert(n < MASK_BITS); 151662306a36Sopenharmony_ci for (; n > 0; idx++, n--) 151762306a36Sopenharmony_ci bit_clear(s, idx); 151862306a36Sopenharmony_ci} 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci/* Sets the bit at the index given by idx. */ 152162306a36Sopenharmony_civoid sparsebit_set(struct sparsebit *s, sparsebit_idx_t idx) 152262306a36Sopenharmony_ci{ 152362306a36Sopenharmony_ci sparsebit_set_num(s, idx, 1); 152462306a36Sopenharmony_ci} 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci/* Clears the bit at the index given by idx. */ 152762306a36Sopenharmony_civoid sparsebit_clear(struct sparsebit *s, sparsebit_idx_t idx) 152862306a36Sopenharmony_ci{ 152962306a36Sopenharmony_ci sparsebit_clear_num(s, idx, 1); 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci/* Sets the bits in the entire addressable range of the sparsebit array. */ 153362306a36Sopenharmony_civoid sparsebit_set_all(struct sparsebit *s) 153462306a36Sopenharmony_ci{ 153562306a36Sopenharmony_ci sparsebit_set(s, 0); 153662306a36Sopenharmony_ci sparsebit_set_num(s, 1, ~(sparsebit_idx_t) 0); 153762306a36Sopenharmony_ci assert(sparsebit_all_set(s)); 153862306a36Sopenharmony_ci} 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci/* Clears the bits in the entire addressable range of the sparsebit array. */ 154162306a36Sopenharmony_civoid sparsebit_clear_all(struct sparsebit *s) 154262306a36Sopenharmony_ci{ 154362306a36Sopenharmony_ci sparsebit_clear(s, 0); 154462306a36Sopenharmony_ci sparsebit_clear_num(s, 1, ~(sparsebit_idx_t) 0); 154562306a36Sopenharmony_ci assert(!sparsebit_any_set(s)); 154662306a36Sopenharmony_ci} 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_cistatic size_t display_range(FILE *stream, sparsebit_idx_t low, 154962306a36Sopenharmony_ci sparsebit_idx_t high, bool prepend_comma_space) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci char *fmt_str; 155262306a36Sopenharmony_ci size_t sz; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci /* Determine the printf format string */ 155562306a36Sopenharmony_ci if (low == high) 155662306a36Sopenharmony_ci fmt_str = prepend_comma_space ? ", 0x%lx" : "0x%lx"; 155762306a36Sopenharmony_ci else 155862306a36Sopenharmony_ci fmt_str = prepend_comma_space ? ", 0x%lx:0x%lx" : "0x%lx:0x%lx"; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci /* 156162306a36Sopenharmony_ci * When stream is NULL, just determine the size of what would 156262306a36Sopenharmony_ci * have been printed, else print the range. 156362306a36Sopenharmony_ci */ 156462306a36Sopenharmony_ci if (!stream) 156562306a36Sopenharmony_ci sz = snprintf(NULL, 0, fmt_str, low, high); 156662306a36Sopenharmony_ci else 156762306a36Sopenharmony_ci sz = fprintf(stream, fmt_str, low, high); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci return sz; 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci/* Dumps to the FILE stream given by stream, the bit settings 157462306a36Sopenharmony_ci * of s. Each line of output is prefixed with the number of 157562306a36Sopenharmony_ci * spaces given by indent. The length of each line is implementation 157662306a36Sopenharmony_ci * dependent and does not depend on the indent amount. The following 157762306a36Sopenharmony_ci * is an example output of a sparsebit array that has bits: 157862306a36Sopenharmony_ci * 157962306a36Sopenharmony_ci * 0x5, 0x8, 0xa:0xe, 0x12 158062306a36Sopenharmony_ci * 158162306a36Sopenharmony_ci * This corresponds to a sparsebit whose bits 5, 8, 10, 11, 12, 13, 14, 18 158262306a36Sopenharmony_ci * are set. Note that a ':', instead of a '-' is used to specify a range of 158362306a36Sopenharmony_ci * contiguous bits. This is done because '-' is used to specify command-line 158462306a36Sopenharmony_ci * options, and sometimes ranges are specified as command-line arguments. 158562306a36Sopenharmony_ci */ 158662306a36Sopenharmony_civoid sparsebit_dump(FILE *stream, struct sparsebit *s, 158762306a36Sopenharmony_ci unsigned int indent) 158862306a36Sopenharmony_ci{ 158962306a36Sopenharmony_ci size_t current_line_len = 0; 159062306a36Sopenharmony_ci size_t sz; 159162306a36Sopenharmony_ci struct node *nodep; 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci if (!sparsebit_any_set(s)) 159462306a36Sopenharmony_ci return; 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci /* Display initial indent */ 159762306a36Sopenharmony_ci fprintf(stream, "%*s", indent, ""); 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci /* For each node */ 160062306a36Sopenharmony_ci for (nodep = node_first(s); nodep; nodep = node_next(s, nodep)) { 160162306a36Sopenharmony_ci unsigned int n1; 160262306a36Sopenharmony_ci sparsebit_idx_t low, high; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* For each group of bits in the mask */ 160562306a36Sopenharmony_ci for (n1 = 0; n1 < MASK_BITS; n1++) { 160662306a36Sopenharmony_ci if (nodep->mask & (1 << n1)) { 160762306a36Sopenharmony_ci low = high = nodep->idx + n1; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci for (; n1 < MASK_BITS; n1++) { 161062306a36Sopenharmony_ci if (nodep->mask & (1 << n1)) 161162306a36Sopenharmony_ci high = nodep->idx + n1; 161262306a36Sopenharmony_ci else 161362306a36Sopenharmony_ci break; 161462306a36Sopenharmony_ci } 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci if ((n1 == MASK_BITS) && nodep->num_after) 161762306a36Sopenharmony_ci high += nodep->num_after; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci /* 162062306a36Sopenharmony_ci * How much room will it take to display 162162306a36Sopenharmony_ci * this range. 162262306a36Sopenharmony_ci */ 162362306a36Sopenharmony_ci sz = display_range(NULL, low, high, 162462306a36Sopenharmony_ci current_line_len != 0); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci /* 162762306a36Sopenharmony_ci * If there is not enough room, display 162862306a36Sopenharmony_ci * a newline plus the indent of the next 162962306a36Sopenharmony_ci * line. 163062306a36Sopenharmony_ci */ 163162306a36Sopenharmony_ci if (current_line_len + sz > DUMP_LINE_MAX) { 163262306a36Sopenharmony_ci fputs("\n", stream); 163362306a36Sopenharmony_ci fprintf(stream, "%*s", indent, ""); 163462306a36Sopenharmony_ci current_line_len = 0; 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci /* Display the range */ 163862306a36Sopenharmony_ci sz = display_range(stream, low, high, 163962306a36Sopenharmony_ci current_line_len != 0); 164062306a36Sopenharmony_ci current_line_len += sz; 164162306a36Sopenharmony_ci } 164262306a36Sopenharmony_ci } 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci /* 164562306a36Sopenharmony_ci * If num_after and most significant-bit of mask is not 164662306a36Sopenharmony_ci * set, then still need to display a range for the bits 164762306a36Sopenharmony_ci * described by num_after. 164862306a36Sopenharmony_ci */ 164962306a36Sopenharmony_ci if (!(nodep->mask & (1 << (MASK_BITS - 1))) && nodep->num_after) { 165062306a36Sopenharmony_ci low = nodep->idx + MASK_BITS; 165162306a36Sopenharmony_ci high = nodep->idx + MASK_BITS + nodep->num_after - 1; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci /* 165462306a36Sopenharmony_ci * How much room will it take to display 165562306a36Sopenharmony_ci * this range. 165662306a36Sopenharmony_ci */ 165762306a36Sopenharmony_ci sz = display_range(NULL, low, high, 165862306a36Sopenharmony_ci current_line_len != 0); 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci /* 166162306a36Sopenharmony_ci * If there is not enough room, display 166262306a36Sopenharmony_ci * a newline plus the indent of the next 166362306a36Sopenharmony_ci * line. 166462306a36Sopenharmony_ci */ 166562306a36Sopenharmony_ci if (current_line_len + sz > DUMP_LINE_MAX) { 166662306a36Sopenharmony_ci fputs("\n", stream); 166762306a36Sopenharmony_ci fprintf(stream, "%*s", indent, ""); 166862306a36Sopenharmony_ci current_line_len = 0; 166962306a36Sopenharmony_ci } 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci /* Display the range */ 167262306a36Sopenharmony_ci sz = display_range(stream, low, high, 167362306a36Sopenharmony_ci current_line_len != 0); 167462306a36Sopenharmony_ci current_line_len += sz; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci } 167762306a36Sopenharmony_ci fputs("\n", stream); 167862306a36Sopenharmony_ci} 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci/* Validates the internal state of the sparsebit array given by 168162306a36Sopenharmony_ci * s. On error, diagnostic information is printed to stderr and 168262306a36Sopenharmony_ci * abort is called. 168362306a36Sopenharmony_ci */ 168462306a36Sopenharmony_civoid sparsebit_validate_internal(struct sparsebit *s) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci bool error_detected = false; 168762306a36Sopenharmony_ci struct node *nodep, *prev = NULL; 168862306a36Sopenharmony_ci sparsebit_num_t total_bits_set = 0; 168962306a36Sopenharmony_ci unsigned int n1; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci /* For each node */ 169262306a36Sopenharmony_ci for (nodep = node_first(s); nodep; 169362306a36Sopenharmony_ci prev = nodep, nodep = node_next(s, nodep)) { 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci /* 169662306a36Sopenharmony_ci * Increase total bits set by the number of bits set 169762306a36Sopenharmony_ci * in this node. 169862306a36Sopenharmony_ci */ 169962306a36Sopenharmony_ci for (n1 = 0; n1 < MASK_BITS; n1++) 170062306a36Sopenharmony_ci if (nodep->mask & (1 << n1)) 170162306a36Sopenharmony_ci total_bits_set++; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci total_bits_set += nodep->num_after; 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci /* 170662306a36Sopenharmony_ci * Arbitrary choice as to whether a mask of 0 is allowed 170762306a36Sopenharmony_ci * or not. For diagnostic purposes it is beneficial to 170862306a36Sopenharmony_ci * have only one valid means to represent a set of bits. 170962306a36Sopenharmony_ci * To support this an arbitrary choice has been made 171062306a36Sopenharmony_ci * to not allow a mask of zero. 171162306a36Sopenharmony_ci */ 171262306a36Sopenharmony_ci if (nodep->mask == 0) { 171362306a36Sopenharmony_ci fprintf(stderr, "Node mask of zero, " 171462306a36Sopenharmony_ci "nodep: %p nodep->mask: 0x%x", 171562306a36Sopenharmony_ci nodep, nodep->mask); 171662306a36Sopenharmony_ci error_detected = true; 171762306a36Sopenharmony_ci break; 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci /* 172162306a36Sopenharmony_ci * Validate num_after is not greater than the max index 172262306a36Sopenharmony_ci * - the number of mask bits. The num_after member 172362306a36Sopenharmony_ci * uses 0-based indexing and thus has no value that 172462306a36Sopenharmony_ci * represents all bits set. This limitation is handled 172562306a36Sopenharmony_ci * by requiring a non-zero mask. With a non-zero mask, 172662306a36Sopenharmony_ci * MASK_BITS worth of bits are described by the mask, 172762306a36Sopenharmony_ci * which makes the largest needed num_after equal to: 172862306a36Sopenharmony_ci * 172962306a36Sopenharmony_ci * (~(sparsebit_num_t) 0) - MASK_BITS + 1 173062306a36Sopenharmony_ci */ 173162306a36Sopenharmony_ci if (nodep->num_after 173262306a36Sopenharmony_ci > (~(sparsebit_num_t) 0) - MASK_BITS + 1) { 173362306a36Sopenharmony_ci fprintf(stderr, "num_after too large, " 173462306a36Sopenharmony_ci "nodep: %p nodep->num_after: 0x%lx", 173562306a36Sopenharmony_ci nodep, nodep->num_after); 173662306a36Sopenharmony_ci error_detected = true; 173762306a36Sopenharmony_ci break; 173862306a36Sopenharmony_ci } 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci /* Validate node index is divisible by the mask size */ 174162306a36Sopenharmony_ci if (nodep->idx % MASK_BITS) { 174262306a36Sopenharmony_ci fprintf(stderr, "Node index not divisible by " 174362306a36Sopenharmony_ci "mask size,\n" 174462306a36Sopenharmony_ci " nodep: %p nodep->idx: 0x%lx " 174562306a36Sopenharmony_ci "MASK_BITS: %lu\n", 174662306a36Sopenharmony_ci nodep, nodep->idx, MASK_BITS); 174762306a36Sopenharmony_ci error_detected = true; 174862306a36Sopenharmony_ci break; 174962306a36Sopenharmony_ci } 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci /* 175262306a36Sopenharmony_ci * Validate bits described by node don't wrap beyond the 175362306a36Sopenharmony_ci * highest supported index. 175462306a36Sopenharmony_ci */ 175562306a36Sopenharmony_ci if ((nodep->idx + MASK_BITS + nodep->num_after - 1) < nodep->idx) { 175662306a36Sopenharmony_ci fprintf(stderr, "Bits described by node wrap " 175762306a36Sopenharmony_ci "beyond highest supported index,\n" 175862306a36Sopenharmony_ci " nodep: %p nodep->idx: 0x%lx\n" 175962306a36Sopenharmony_ci " MASK_BITS: %lu nodep->num_after: 0x%lx", 176062306a36Sopenharmony_ci nodep, nodep->idx, MASK_BITS, nodep->num_after); 176162306a36Sopenharmony_ci error_detected = true; 176262306a36Sopenharmony_ci break; 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci /* Check parent pointers. */ 176662306a36Sopenharmony_ci if (nodep->left) { 176762306a36Sopenharmony_ci if (nodep->left->parent != nodep) { 176862306a36Sopenharmony_ci fprintf(stderr, "Left child parent pointer " 176962306a36Sopenharmony_ci "doesn't point to this node,\n" 177062306a36Sopenharmony_ci " nodep: %p nodep->left: %p " 177162306a36Sopenharmony_ci "nodep->left->parent: %p", 177262306a36Sopenharmony_ci nodep, nodep->left, 177362306a36Sopenharmony_ci nodep->left->parent); 177462306a36Sopenharmony_ci error_detected = true; 177562306a36Sopenharmony_ci break; 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci if (nodep->right) { 178062306a36Sopenharmony_ci if (nodep->right->parent != nodep) { 178162306a36Sopenharmony_ci fprintf(stderr, "Right child parent pointer " 178262306a36Sopenharmony_ci "doesn't point to this node,\n" 178362306a36Sopenharmony_ci " nodep: %p nodep->right: %p " 178462306a36Sopenharmony_ci "nodep->right->parent: %p", 178562306a36Sopenharmony_ci nodep, nodep->right, 178662306a36Sopenharmony_ci nodep->right->parent); 178762306a36Sopenharmony_ci error_detected = true; 178862306a36Sopenharmony_ci break; 178962306a36Sopenharmony_ci } 179062306a36Sopenharmony_ci } 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci if (!nodep->parent) { 179362306a36Sopenharmony_ci if (s->root != nodep) { 179462306a36Sopenharmony_ci fprintf(stderr, "Unexpected root node, " 179562306a36Sopenharmony_ci "s->root: %p nodep: %p", 179662306a36Sopenharmony_ci s->root, nodep); 179762306a36Sopenharmony_ci error_detected = true; 179862306a36Sopenharmony_ci break; 179962306a36Sopenharmony_ci } 180062306a36Sopenharmony_ci } 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci if (prev) { 180362306a36Sopenharmony_ci /* 180462306a36Sopenharmony_ci * Is index of previous node before index of 180562306a36Sopenharmony_ci * current node? 180662306a36Sopenharmony_ci */ 180762306a36Sopenharmony_ci if (prev->idx >= nodep->idx) { 180862306a36Sopenharmony_ci fprintf(stderr, "Previous node index " 180962306a36Sopenharmony_ci ">= current node index,\n" 181062306a36Sopenharmony_ci " prev: %p prev->idx: 0x%lx\n" 181162306a36Sopenharmony_ci " nodep: %p nodep->idx: 0x%lx", 181262306a36Sopenharmony_ci prev, prev->idx, nodep, nodep->idx); 181362306a36Sopenharmony_ci error_detected = true; 181462306a36Sopenharmony_ci break; 181562306a36Sopenharmony_ci } 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci /* 181862306a36Sopenharmony_ci * Nodes occur in asscending order, based on each 181962306a36Sopenharmony_ci * nodes starting index. 182062306a36Sopenharmony_ci */ 182162306a36Sopenharmony_ci if ((prev->idx + MASK_BITS + prev->num_after - 1) 182262306a36Sopenharmony_ci >= nodep->idx) { 182362306a36Sopenharmony_ci fprintf(stderr, "Previous node bit range " 182462306a36Sopenharmony_ci "overlap with current node bit range,\n" 182562306a36Sopenharmony_ci " prev: %p prev->idx: 0x%lx " 182662306a36Sopenharmony_ci "prev->num_after: 0x%lx\n" 182762306a36Sopenharmony_ci " nodep: %p nodep->idx: 0x%lx " 182862306a36Sopenharmony_ci "nodep->num_after: 0x%lx\n" 182962306a36Sopenharmony_ci " MASK_BITS: %lu", 183062306a36Sopenharmony_ci prev, prev->idx, prev->num_after, 183162306a36Sopenharmony_ci nodep, nodep->idx, nodep->num_after, 183262306a36Sopenharmony_ci MASK_BITS); 183362306a36Sopenharmony_ci error_detected = true; 183462306a36Sopenharmony_ci break; 183562306a36Sopenharmony_ci } 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci /* 183862306a36Sopenharmony_ci * When the node has all mask bits set, it shouldn't 183962306a36Sopenharmony_ci * be adjacent to the last bit described by the 184062306a36Sopenharmony_ci * previous node. 184162306a36Sopenharmony_ci */ 184262306a36Sopenharmony_ci if (nodep->mask == ~(mask_t) 0 && 184362306a36Sopenharmony_ci prev->idx + MASK_BITS + prev->num_after == nodep->idx) { 184462306a36Sopenharmony_ci fprintf(stderr, "Current node has mask with " 184562306a36Sopenharmony_ci "all bits set and is adjacent to the " 184662306a36Sopenharmony_ci "previous node,\n" 184762306a36Sopenharmony_ci " prev: %p prev->idx: 0x%lx " 184862306a36Sopenharmony_ci "prev->num_after: 0x%lx\n" 184962306a36Sopenharmony_ci " nodep: %p nodep->idx: 0x%lx " 185062306a36Sopenharmony_ci "nodep->num_after: 0x%lx\n" 185162306a36Sopenharmony_ci " MASK_BITS: %lu", 185262306a36Sopenharmony_ci prev, prev->idx, prev->num_after, 185362306a36Sopenharmony_ci nodep, nodep->idx, nodep->num_after, 185462306a36Sopenharmony_ci MASK_BITS); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci error_detected = true; 185762306a36Sopenharmony_ci break; 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci } 186062306a36Sopenharmony_ci } 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci if (!error_detected) { 186362306a36Sopenharmony_ci /* 186462306a36Sopenharmony_ci * Is sum of bits set in each node equal to the count 186562306a36Sopenharmony_ci * of total bits set. 186662306a36Sopenharmony_ci */ 186762306a36Sopenharmony_ci if (s->num_set != total_bits_set) { 186862306a36Sopenharmony_ci fprintf(stderr, "Number of bits set mismatch,\n" 186962306a36Sopenharmony_ci " s->num_set: 0x%lx total_bits_set: 0x%lx", 187062306a36Sopenharmony_ci s->num_set, total_bits_set); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci error_detected = true; 187362306a36Sopenharmony_ci } 187462306a36Sopenharmony_ci } 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci if (error_detected) { 187762306a36Sopenharmony_ci fputs(" dump_internal:\n", stderr); 187862306a36Sopenharmony_ci sparsebit_dump_internal(stderr, s, 4); 187962306a36Sopenharmony_ci abort(); 188062306a36Sopenharmony_ci } 188162306a36Sopenharmony_ci} 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci#ifdef FUZZ 188562306a36Sopenharmony_ci/* A simple but effective fuzzing driver. Look for bugs with the help 188662306a36Sopenharmony_ci * of some invariants and of a trivial representation of sparsebit. 188762306a36Sopenharmony_ci * Just use 512 bytes of /dev/zero and /dev/urandom as inputs, and let 188862306a36Sopenharmony_ci * afl-fuzz do the magic. :) 188962306a36Sopenharmony_ci */ 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci#include <stdlib.h> 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistruct range { 189462306a36Sopenharmony_ci sparsebit_idx_t first, last; 189562306a36Sopenharmony_ci bool set; 189662306a36Sopenharmony_ci}; 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_cistruct sparsebit *s; 189962306a36Sopenharmony_cistruct range ranges[1000]; 190062306a36Sopenharmony_ciint num_ranges; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_cistatic bool get_value(sparsebit_idx_t idx) 190362306a36Sopenharmony_ci{ 190462306a36Sopenharmony_ci int i; 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci for (i = num_ranges; --i >= 0; ) 190762306a36Sopenharmony_ci if (ranges[i].first <= idx && idx <= ranges[i].last) 190862306a36Sopenharmony_ci return ranges[i].set; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci return false; 191162306a36Sopenharmony_ci} 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_cistatic void operate(int code, sparsebit_idx_t first, sparsebit_idx_t last) 191462306a36Sopenharmony_ci{ 191562306a36Sopenharmony_ci sparsebit_num_t num; 191662306a36Sopenharmony_ci sparsebit_idx_t next; 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci if (first < last) { 191962306a36Sopenharmony_ci num = last - first + 1; 192062306a36Sopenharmony_ci } else { 192162306a36Sopenharmony_ci num = first - last + 1; 192262306a36Sopenharmony_ci first = last; 192362306a36Sopenharmony_ci last = first + num - 1; 192462306a36Sopenharmony_ci } 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci switch (code) { 192762306a36Sopenharmony_ci case 0: 192862306a36Sopenharmony_ci sparsebit_set(s, first); 192962306a36Sopenharmony_ci assert(sparsebit_is_set(s, first)); 193062306a36Sopenharmony_ci assert(!sparsebit_is_clear(s, first)); 193162306a36Sopenharmony_ci assert(sparsebit_any_set(s)); 193262306a36Sopenharmony_ci assert(!sparsebit_all_clear(s)); 193362306a36Sopenharmony_ci if (get_value(first)) 193462306a36Sopenharmony_ci return; 193562306a36Sopenharmony_ci if (num_ranges == 1000) 193662306a36Sopenharmony_ci exit(0); 193762306a36Sopenharmony_ci ranges[num_ranges++] = (struct range) 193862306a36Sopenharmony_ci { .first = first, .last = first, .set = true }; 193962306a36Sopenharmony_ci break; 194062306a36Sopenharmony_ci case 1: 194162306a36Sopenharmony_ci sparsebit_clear(s, first); 194262306a36Sopenharmony_ci assert(!sparsebit_is_set(s, first)); 194362306a36Sopenharmony_ci assert(sparsebit_is_clear(s, first)); 194462306a36Sopenharmony_ci assert(sparsebit_any_clear(s)); 194562306a36Sopenharmony_ci assert(!sparsebit_all_set(s)); 194662306a36Sopenharmony_ci if (!get_value(first)) 194762306a36Sopenharmony_ci return; 194862306a36Sopenharmony_ci if (num_ranges == 1000) 194962306a36Sopenharmony_ci exit(0); 195062306a36Sopenharmony_ci ranges[num_ranges++] = (struct range) 195162306a36Sopenharmony_ci { .first = first, .last = first, .set = false }; 195262306a36Sopenharmony_ci break; 195362306a36Sopenharmony_ci case 2: 195462306a36Sopenharmony_ci assert(sparsebit_is_set(s, first) == get_value(first)); 195562306a36Sopenharmony_ci assert(sparsebit_is_clear(s, first) == !get_value(first)); 195662306a36Sopenharmony_ci break; 195762306a36Sopenharmony_ci case 3: 195862306a36Sopenharmony_ci if (sparsebit_any_set(s)) 195962306a36Sopenharmony_ci assert(get_value(sparsebit_first_set(s))); 196062306a36Sopenharmony_ci if (sparsebit_any_clear(s)) 196162306a36Sopenharmony_ci assert(!get_value(sparsebit_first_clear(s))); 196262306a36Sopenharmony_ci sparsebit_set_all(s); 196362306a36Sopenharmony_ci assert(!sparsebit_any_clear(s)); 196462306a36Sopenharmony_ci assert(sparsebit_all_set(s)); 196562306a36Sopenharmony_ci num_ranges = 0; 196662306a36Sopenharmony_ci ranges[num_ranges++] = (struct range) 196762306a36Sopenharmony_ci { .first = 0, .last = ~(sparsebit_idx_t)0, .set = true }; 196862306a36Sopenharmony_ci break; 196962306a36Sopenharmony_ci case 4: 197062306a36Sopenharmony_ci if (sparsebit_any_set(s)) 197162306a36Sopenharmony_ci assert(get_value(sparsebit_first_set(s))); 197262306a36Sopenharmony_ci if (sparsebit_any_clear(s)) 197362306a36Sopenharmony_ci assert(!get_value(sparsebit_first_clear(s))); 197462306a36Sopenharmony_ci sparsebit_clear_all(s); 197562306a36Sopenharmony_ci assert(!sparsebit_any_set(s)); 197662306a36Sopenharmony_ci assert(sparsebit_all_clear(s)); 197762306a36Sopenharmony_ci num_ranges = 0; 197862306a36Sopenharmony_ci break; 197962306a36Sopenharmony_ci case 5: 198062306a36Sopenharmony_ci next = sparsebit_next_set(s, first); 198162306a36Sopenharmony_ci assert(next == 0 || next > first); 198262306a36Sopenharmony_ci assert(next == 0 || get_value(next)); 198362306a36Sopenharmony_ci break; 198462306a36Sopenharmony_ci case 6: 198562306a36Sopenharmony_ci next = sparsebit_next_clear(s, first); 198662306a36Sopenharmony_ci assert(next == 0 || next > first); 198762306a36Sopenharmony_ci assert(next == 0 || !get_value(next)); 198862306a36Sopenharmony_ci break; 198962306a36Sopenharmony_ci case 7: 199062306a36Sopenharmony_ci next = sparsebit_next_clear(s, first); 199162306a36Sopenharmony_ci if (sparsebit_is_set_num(s, first, num)) { 199262306a36Sopenharmony_ci assert(next == 0 || next > last); 199362306a36Sopenharmony_ci if (first) 199462306a36Sopenharmony_ci next = sparsebit_next_set(s, first - 1); 199562306a36Sopenharmony_ci else if (sparsebit_any_set(s)) 199662306a36Sopenharmony_ci next = sparsebit_first_set(s); 199762306a36Sopenharmony_ci else 199862306a36Sopenharmony_ci return; 199962306a36Sopenharmony_ci assert(next == first); 200062306a36Sopenharmony_ci } else { 200162306a36Sopenharmony_ci assert(sparsebit_is_clear(s, first) || next <= last); 200262306a36Sopenharmony_ci } 200362306a36Sopenharmony_ci break; 200462306a36Sopenharmony_ci case 8: 200562306a36Sopenharmony_ci next = sparsebit_next_set(s, first); 200662306a36Sopenharmony_ci if (sparsebit_is_clear_num(s, first, num)) { 200762306a36Sopenharmony_ci assert(next == 0 || next > last); 200862306a36Sopenharmony_ci if (first) 200962306a36Sopenharmony_ci next = sparsebit_next_clear(s, first - 1); 201062306a36Sopenharmony_ci else if (sparsebit_any_clear(s)) 201162306a36Sopenharmony_ci next = sparsebit_first_clear(s); 201262306a36Sopenharmony_ci else 201362306a36Sopenharmony_ci return; 201462306a36Sopenharmony_ci assert(next == first); 201562306a36Sopenharmony_ci } else { 201662306a36Sopenharmony_ci assert(sparsebit_is_set(s, first) || next <= last); 201762306a36Sopenharmony_ci } 201862306a36Sopenharmony_ci break; 201962306a36Sopenharmony_ci case 9: 202062306a36Sopenharmony_ci sparsebit_set_num(s, first, num); 202162306a36Sopenharmony_ci assert(sparsebit_is_set_num(s, first, num)); 202262306a36Sopenharmony_ci assert(!sparsebit_is_clear_num(s, first, num)); 202362306a36Sopenharmony_ci assert(sparsebit_any_set(s)); 202462306a36Sopenharmony_ci assert(!sparsebit_all_clear(s)); 202562306a36Sopenharmony_ci if (num_ranges == 1000) 202662306a36Sopenharmony_ci exit(0); 202762306a36Sopenharmony_ci ranges[num_ranges++] = (struct range) 202862306a36Sopenharmony_ci { .first = first, .last = last, .set = true }; 202962306a36Sopenharmony_ci break; 203062306a36Sopenharmony_ci case 10: 203162306a36Sopenharmony_ci sparsebit_clear_num(s, first, num); 203262306a36Sopenharmony_ci assert(!sparsebit_is_set_num(s, first, num)); 203362306a36Sopenharmony_ci assert(sparsebit_is_clear_num(s, first, num)); 203462306a36Sopenharmony_ci assert(sparsebit_any_clear(s)); 203562306a36Sopenharmony_ci assert(!sparsebit_all_set(s)); 203662306a36Sopenharmony_ci if (num_ranges == 1000) 203762306a36Sopenharmony_ci exit(0); 203862306a36Sopenharmony_ci ranges[num_ranges++] = (struct range) 203962306a36Sopenharmony_ci { .first = first, .last = last, .set = false }; 204062306a36Sopenharmony_ci break; 204162306a36Sopenharmony_ci case 11: 204262306a36Sopenharmony_ci sparsebit_validate_internal(s); 204362306a36Sopenharmony_ci break; 204462306a36Sopenharmony_ci default: 204562306a36Sopenharmony_ci break; 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci} 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ciunsigned char get8(void) 205062306a36Sopenharmony_ci{ 205162306a36Sopenharmony_ci int ch; 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci ch = getchar(); 205462306a36Sopenharmony_ci if (ch == EOF) 205562306a36Sopenharmony_ci exit(0); 205662306a36Sopenharmony_ci return ch; 205762306a36Sopenharmony_ci} 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ciuint64_t get64(void) 206062306a36Sopenharmony_ci{ 206162306a36Sopenharmony_ci uint64_t x; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci x = get8(); 206462306a36Sopenharmony_ci x = (x << 8) | get8(); 206562306a36Sopenharmony_ci x = (x << 8) | get8(); 206662306a36Sopenharmony_ci x = (x << 8) | get8(); 206762306a36Sopenharmony_ci x = (x << 8) | get8(); 206862306a36Sopenharmony_ci x = (x << 8) | get8(); 206962306a36Sopenharmony_ci x = (x << 8) | get8(); 207062306a36Sopenharmony_ci return (x << 8) | get8(); 207162306a36Sopenharmony_ci} 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ciint main(void) 207462306a36Sopenharmony_ci{ 207562306a36Sopenharmony_ci s = sparsebit_alloc(); 207662306a36Sopenharmony_ci for (;;) { 207762306a36Sopenharmony_ci uint8_t op = get8() & 0xf; 207862306a36Sopenharmony_ci uint64_t first = get64(); 207962306a36Sopenharmony_ci uint64_t last = get64(); 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci operate(op, first, last); 208262306a36Sopenharmony_ci } 208362306a36Sopenharmony_ci} 208462306a36Sopenharmony_ci#endif 2085