5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Xyla, a library of binary trees.
12 * Xyla is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Lesser General Public License as published by the
14 * Free Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * Xyla is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 * License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with Xyla. If not, see <https://www.gnu.org/licenses/>.
29 /*----- Coverage instrumentation ------------------------------------------*/
31 /* Verbosity control. */
34 extern unsigned xyla__verbose;
35 extern FILE *xyla__verbout;
43 /* Verbosity flags. */
44 #define XYLA__VF_ITER 0x0001
45 #define XYLA__VF_PATH 0x0002
46 #define XYLA__VF_PROBE 0x0004
47 #define XYLA__VF_INSERT 0x0008
48 #define XYLA__VF_REMOVE 0x0010
49 #define XYLA__VF_SPLIT 0x0020
50 #define XYLA__VF_JOIN 0x0040
51 #define XYLA__VF_UNISECT 0x0080
52 #define XYLA__VF_DIFFSECT 0x0100
53 #define XYLA__VF_SPLAY 0x1000
55 /*----- Compiler-specific features ----------------------------------------*/
58 # define CLANG_VERSION_P(maj, min) \
59 (__clang_major__ > (maj) || \
60 (__clang_major__ == (maj) && __clang_minor__ >= (min)))
61 # define GCC_VERSION_P(maj, min) 0 /* Clang is /not/ GCC */
63 # define CLANG_VERSION_P(maj, min) 0
65 # define GCC_VERSION_P(maj, min) \
66 (__GNUC__ > (maj) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))
68 # define GCC_VERSION_P(maj, min) 0
73 # define MSC_VERSION_P(maj, min) (_MSC_VER >= (maj)*100 + (min))
75 # define MSC_VERSION_P(maj, min) 0
78 #if GCC_VERSION_P(2, 5) || CLANG_VERSION_P(3, 3)
79 # define NORETURN __attribute__((__noreturn__))
82 #if GCC_VERSION_P(4, 0) || CLANG_VERSION_P(3, 3)
83 # define PRINTF_LIKE(fix, aix) __attribute__((__format__(printf, fix, aix)))
86 #if MSC_VERSION_P(8, 0)
87 # define NORETURN __declspec(noreturn)
95 # define PRINTF_LIKE(fix, aix)
98 /*----- Conversion utilities ----------------------------------------------*/
100 #define CHECK_TYPE(expty, x) (!sizeof(*(expty *)0 = (x)))
102 #define CONVERT_CAREFULLY(newty, expty, x) \
103 (CHECK_TYPE(expty, x) ? \
104 (/*unconst unvolatile*/ newty)(x) : \
105 (/*unconst unvolatile*/ newty)(x))
107 #define CONTAINER(type, mem, p) \
108 (!sizeof((p) == &((type *)0)->mem) + \
109 (type *)((unsigned char *)(p) - offsetof(type, mem)))
111 #define UNCONST(type, p) CONVERT_CAREFULLY(type *, const type *, p)
113 #define ORDER_OPS(ops) CONTAINER(const struct xyla_bt_ordops, node, ops)
114 #define CHECK_OPS(ops) CONTAINER(const struct xyla_bt_chkops, node, ops)
116 /*----- AVL tree utilities ------------------------------------------------*/
119 #define AVL_NODE(node) \
120 CONVERT_CAREFULLY(struct xyla_avl_node *, \
121 struct xyla_bt_node *, \
123 #define CONST_AVL_NODE(node) \
124 CONVERT_CAREFULLY(const struct xyla_avl_node *, \
125 const struct xyla_bt_node *, \
128 /* Diagnostic output. */
129 #define AVL_BALCH(node) ("=-+"[(node)->avl.f&XYLA_AVLF_BALMASK])
130 /* Return the AVL balance character for NODE. */
132 /* Combinatorial logic for balance-annotation adjustments. */
133 #define AVL_REBAL_EEL(bal) ((bal) >> 1)
134 #define AVL_REBAL_REE(bal) (((bal) << 1)&XYLA_AVLF_BALMASK)
135 #define AVL_REBAL_XRE(bal) ((bal) ^ XYLA_AVLBAL_RBIAS)
136 #define AVL_REBAL_XLE(bal) (((bal) ^ XYLA_AVLBAL_RBIAS) >> 1)
137 #define AVL_REBAL_ELX(bal) ((bal) ^ XYLA_AVLBAL_LBIAS)
138 #define AVL_REBAL_ERX(bal) (((bal) ^ XYLA_AVLBAL_LBIAS) << 1)
140 /*----- Red-black tree utilities ------------------------------------------*/
143 #define RB_NODE(node) \
144 CONVERT_CAREFULLY(struct xyla_rb_node *, \
145 struct xyla_bt_node *, \
147 #define CONST_RB_NODE(node) \
148 CONVERT_CAREFULLY(const struct xyla_rb_node *, \
149 const struct xyla_bt_node *, \
152 /*----- Splay tree utilities ----------------------------------------------*/
155 #define SPLAY_NODE(node) \
156 CONVERT_CAREFULLY(struct xyla_splay_node *, \
157 struct xyla_bt_node *, \
159 #define CONST_SPLAY_NODE(node) \
160 CONVERT_CAREFULLY(const struct xyla_splay_node *, \
161 const struct xyla_bt_node *, \
164 /* Side constants. */
165 #define SPLAY_LEFT 0u
166 #define SPLAY_RIGHT 1u
169 struct xyla_bt_nodecls;
170 struct xyla_splay_node;
171 struct xyla_splay_path;
173 extern void xyla__splay_split(struct xyla_bt_nodecls */*cls*/,
174 struct xyla_bt_node **/*left_inout*/,
175 struct xyla_bt_node **/*right_inout*/,
176 struct xyla_splay_node */*parent*/,
178 /* Splay the tree at a possibly fictional node. The node is promoted to
179 * the tree root, and the child links are updated.
181 * The PARENT and SIDE arguments identify the node's initial position in
182 * the tree, and *LEFT_INOUT and *RIGHT_INOUT identify its child links. It
183 * is valid if the node is already the tree root: in this case, PARENT is
184 * null and SIDE is ignored; otherwise SIDE must be one of the constants
185 * `SPLAY_LEFT' or `SPLAY_RIGHT'.
187 * The `xyla__splay_splay' function below calls this with a real node,
188 * determining the PARENT and SIDE appropriately; `xyla_splay_insert' uses
189 * this to prepare the tree before the new node is linked in;
190 * `xyla_splay_split' uses this to handle both its full and empty path
194 extern void xyla__splay_splay(struct xyla_bt_nodecls */*cls*/,
195 struct xyla_splay_node */*node*/);
196 /* Splay the tree at NODE. The NODE becomes the new tree root; updating
197 * this is the caller's responsibility. The NODE is /not/ updated, since
198 * the caller may want to make further changes before it's ready.
201 extern void *xyla__splay_join(struct xyla_bt_nodecls */*cls*/,
202 struct xyla_splay_node */*left*/,
203 struct xyla_splay_node */*right*/);
204 /* Join the two trees LEFT and RIGHT, without an intervening node. The
205 * input tree roots' parent links need not be cleared before calling.
208 extern unsigned xyla__splay_resolve_path(struct xyla_splay_path */*path*/);
209 /* The PATH must be empty -- i.e., refer to a null link rather than a real
210 * node -- and nontrivial -- so the tree must not be empty. If the tree
211 * has been reorganized since the path was constructed, then the `gap'
212 * referred to by the path may have moved, so that the link referenced
213 * isn't actually null any more. Modify the PATH so that it refers to the
214 * actual null link at the same position in the tree's ordering, and return
215 * `SPLAY_LEFT' or `SPLAY_RIGHT' suitable for calling `xyla__splay_split'.
218 /*----- Treap utilities ---------------------------------------------------*/
221 #define TREAP_NODE(node) \
222 CONVERT_CAREFULLY(struct xyla_treap_node *, \
223 struct xyla_bt_node *, \
225 #define CONST_TREAP_NODE(node) \
226 CONVERT_CAREFULLY(const struct xyla_treap_node *, \
227 const struct xyla_bt_node *, \
230 extern NORETURN void xyla__treap_boundfail(void);
231 /* Report a failure in the height bound.
233 * The default implementation calls on `fputs' and `abort'. If you want to
234 * embed the library in an environment which doesn't have these, then
235 * you'll need to replace this function with something else that crashes in
239 /*----- That's all, folks -------------------------------------------------*/