00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef lint
00036 static const char libbu_rb_insert_RCSid[] = "@(#) $Header: /cvsroot/brlcad/brlcad/src/libbu/rb_insert.c,v 14.13 2006/08/31 23:16:38 lbutler Exp $";
00037 #endif
00038
00039 #include "common.h"
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044
00045 #include "machine.h"
00046 #include "bu.h"
00047 #include "./rb_internals.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static int _rb_insert (bu_rb_tree *tree, int order, struct bu_rb_node *new_node)
00060 {
00061 struct bu_rb_node *node;
00062 struct bu_rb_node *parent;
00063 struct bu_rb_node *grand_parent;
00064 struct bu_rb_node *y;
00065 int (*compare)();
00066 int comparison=0xdeadbeef;
00067 int direction;
00068 int result = 0;
00069
00070
00071 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00072 BU_RB_CKORDER(tree, order);
00073 BU_CKMAG(new_node, BU_RB_NODE_MAGIC, "red-black node");
00074
00075
00076
00077
00078 bu_rb_parent(new_node, order) =
00079 bu_rb_left_child(new_node, order) =
00080 bu_rb_right_child(new_node, order) = bu_rb_null(tree);
00081 bu_rb_size(new_node, order) = 1;
00082 if (tree -> rbt_debug & BU_RB_DEBUG_OS)
00083 bu_log("_rb_insert(%x): size(%x, %d)=%d\n",
00084 new_node, new_node, order, bu_rb_size(new_node, order));
00085
00086
00087
00088
00089 parent = bu_rb_null(tree);
00090 node = bu_rb_root(tree, order);
00091 compare = bu_rb_order_func(tree, order);
00092 while (node != bu_rb_null(tree))
00093 {
00094 parent = node;
00095 ++bu_rb_size(parent, order);
00096 if (tree -> rbt_debug & BU_RB_DEBUG_OS)
00097 bu_log("_rb_insert(%x): size(%x, %d)=%d\n",
00098 new_node, parent, order, bu_rb_size(parent, order));
00099 comparison = (*compare)(bu_rb_data(new_node, order),
00100 bu_rb_data(node, order));
00101 if (comparison < 0)
00102 {
00103 if (tree -> rbt_debug & BU_RB_DEBUG_INSERT)
00104 bu_log("_rb_insert(%x): <_%d <%x>, going left\n",
00105 new_node, order, node);
00106 node = bu_rb_left_child(node, order);
00107 }
00108 else
00109 {
00110 if (tree -> rbt_debug & BU_RB_DEBUG_INSERT)
00111 bu_log("_rb_insert(%x): >=_%d <%x>, going right\n",
00112 new_node, order, node);
00113 node = bu_rb_right_child(node, order);
00114 if (comparison == 0)
00115 result = 1;
00116 }
00117 }
00118 bu_rb_parent(new_node, order) = parent;
00119 if (parent == bu_rb_null(tree))
00120 bu_rb_root(tree, order) = new_node;
00121 else if ((*compare)(bu_rb_data(new_node, order),
00122 bu_rb_data(parent, order)) < 0)
00123 bu_rb_left_child(parent, order) = new_node;
00124 else
00125 bu_rb_right_child(parent, order) = new_node;
00126
00127
00128
00129
00130 bu_rb_set_color(new_node, order, BU_RB_RED);
00131 node = new_node;
00132 parent = bu_rb_parent(node, order);
00133 grand_parent = bu_rb_parent(parent, order);
00134 while ((node != bu_rb_root(tree, order))
00135 && (bu_rb_get_color(parent, order) == BU_RB_RED))
00136 {
00137 if (parent == bu_rb_left_child(grand_parent, order))
00138 direction = BU_RB_LEFT;
00139 else
00140 direction = BU_RB_RIGHT;
00141
00142 y = bu_rb_other_child(grand_parent, order, direction);
00143 if (bu_rb_get_color(y, order) == BU_RB_RED)
00144 {
00145 bu_rb_set_color(parent, order, BU_RB_BLACK);
00146 bu_rb_set_color(y, order, BU_RB_BLACK);
00147 bu_rb_set_color(grand_parent, order, BU_RB_RED);
00148 node = grand_parent;
00149 parent = bu_rb_parent(node, order);
00150 grand_parent = bu_rb_parent(parent, order);
00151 }
00152 else
00153 {
00154 if (node == bu_rb_other_child(parent, order, direction))
00155 {
00156 node = parent;
00157 bu_rb_rotate(node, order, direction);
00158 parent = bu_rb_parent(node, order);
00159 grand_parent = bu_rb_parent(parent, order);
00160 }
00161 bu_rb_set_color(parent, order, BU_RB_BLACK);
00162 bu_rb_set_color(grand_parent, order, BU_RB_RED);
00163 bu_rb_other_rotate(grand_parent, order, direction);
00164 }
00165 }
00166 bu_rb_set_color(bu_rb_root(tree, order), order, BU_RB_BLACK);
00167
00168 if (tree -> rbt_debug & BU_RB_DEBUG_INSERT)
00169 bu_log("_rb_insert(%x): comparison = %d, returning %d\n",
00170 new_node, comparison, result);
00171
00172 return (result);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 int bu_rb_insert (bu_rb_tree *tree, void *data)
00188 {
00189 int nm_orders;
00190 int order;
00191 int result = 0;
00192 struct bu_rb_node *node;
00193 struct bu_rb_package *package;
00194 struct bu_rb_list *rblp;
00195
00196 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00197
00198 nm_orders = tree -> rbt_nm_orders;
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 for (order = 0; order < nm_orders; ++order)
00209 if (bu_rb_get_uniqueness(tree, order) &&
00210 (bu_rb_search(tree, order, data) != NULL))
00211 {
00212 if (tree -> rbt_debug & BU_RB_DEBUG_UNIQ)
00213 bu_log("bu_rb_insert(<%x>, <%x>, TBD) will return %d\n",
00214 tree, data, -(order + 1));
00215 return (-(order + 1));
00216 }
00217
00218
00219
00220
00221
00222 package = (struct bu_rb_package *)
00223 bu_malloc(sizeof(struct bu_rb_package), "red-black package");
00224 package -> rbp_node = (struct bu_rb_node **)
00225 bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
00226 "red-black package nodes");
00227 rblp = (struct bu_rb_list *)
00228 bu_malloc(sizeof(struct bu_rb_list),
00229 "red-black list element");
00230 rblp -> rbl_magic = BU_RB_LIST_MAGIC;
00231 rblp -> rbl_package = package;
00232 BU_LIST_PUSH(&(tree -> rbt_packages.l), rblp);
00233 package -> rbp_list_pos = rblp;
00234
00235
00236
00237
00238
00239 node = (struct bu_rb_node *)
00240 bu_malloc(sizeof(struct bu_rb_node), "red-black node");
00241 node -> rbn_parent = (struct bu_rb_node **)
00242 bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
00243 "red-black parents");
00244 node -> rbn_left = (struct bu_rb_node **)
00245 bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
00246 "red-black left children");
00247 node -> rbn_right = (struct bu_rb_node **)
00248 bu_malloc(nm_orders * sizeof(struct bu_rb_node *),
00249 "red-black right children");
00250 node -> rbn_color = (char *)
00251 bu_malloc((size_t) ceil((double) (nm_orders / 8.0)),
00252 "red-black colors");
00253 node -> rbn_size = (int *)
00254 bu_malloc(nm_orders * sizeof(int),
00255 "red-black subtree sizes");
00256 node -> rbn_package = (struct bu_rb_package **)
00257 bu_malloc(nm_orders * sizeof(struct bu_rb_package *),
00258 "red-black packages");
00259 rblp = (struct bu_rb_list *)
00260 bu_malloc(sizeof(struct bu_rb_list),
00261 "red-black list element");
00262 rblp -> rbl_magic = BU_RB_LIST_MAGIC;
00263 rblp -> rbl_node = node;
00264 BU_LIST_PUSH(&(tree -> rbt_nodes.l), rblp);
00265 node -> rbn_list_pos = rblp;
00266
00267
00268
00269
00270 package -> rbp_magic = BU_RB_PKG_MAGIC;
00271 package -> rbp_data = data;
00272 for (order = 0; order < nm_orders; ++order)
00273 (package -> rbp_node)[order] = node;
00274
00275
00276
00277
00278 node -> rbn_magic = BU_RB_NODE_MAGIC;
00279 node -> rbn_tree = tree;
00280 for (order = 0; order < nm_orders; ++order)
00281 (node -> rbn_package)[order] = package;
00282 node -> rbn_pkg_refs = nm_orders;
00283
00284
00285
00286
00287
00288 if (bu_rb_root(tree, 0) == bu_rb_null(tree))
00289 for (order = 0; order < nm_orders; ++order)
00290 {
00291 bu_rb_root(tree, order) = node;
00292 bu_rb_parent(node, order) =
00293 bu_rb_left_child(node, order) =
00294 bu_rb_right_child(node, order) = bu_rb_null(tree);
00295 bu_rb_set_color(node, order, BU_RB_BLACK);
00296 bu_rb_size(node, order) = 1;
00297 if (tree -> rbt_debug & BU_RB_DEBUG_OS)
00298 bu_log("bu_rb_insert(<%x>, <%x>, <%x>): size(%x, %d)=%d\n",
00299 tree, data, node, node, order, bu_rb_size(node, order));
00300 }
00301
00302 else
00303 {
00304 for (order = 0; order < nm_orders; ++order)
00305 result += _rb_insert(tree, order, node);
00306 if (tree -> rbt_debug & BU_RB_DEBUG_UNIQ)
00307 bu_log("bu_rb_insert(<%x>, <%x>, <%x>) will return %d\n",
00308 tree, data, node, result);
00309 }
00310
00311 ++(tree -> rbt_nm_nodes);
00312 bu_rb_current(tree) = node;
00313 return (result);
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 static int _rb_set_uniq (bu_rb_tree *tree, int order, int new_value)
00327 {
00328 int prev_value;
00329
00330 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00331 BU_RB_CKORDER(tree, order);
00332 new_value = (new_value != 0);
00333
00334 prev_value = bu_rb_get_uniqueness(tree, order);
00335 bu_rb_set_uniqueness(tree, order, new_value);
00336 return (prev_value);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 int bu_rb_uniq_on (bu_rb_tree *tree, int order)
00350 {
00351 return (_rb_set_uniq(tree, order, 1));
00352 }
00353
00354 int bu_rb_uniq_off (bu_rb_tree *tree, int order)
00355 {
00356 return (_rb_set_uniq(tree, order, 0));
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366 int bu_rb_is_uniq (bu_rb_tree *tree, int order)
00367 {
00368 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00369 BU_RB_CKORDER(tree, order);
00370
00371 return(bu_rb_get_uniqueness(tree, order));
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 void bu_rb_set_uniqv (bu_rb_tree *tree, bitv_t flag_rep)
00387 {
00388 int nm_orders;
00389 int order;
00390
00391 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00392
00393 nm_orders = tree -> rbt_nm_orders;
00394 for (order = 0; order < nm_orders; ++order)
00395 bu_rb_set_uniqueness(tree, order, 0);
00396
00397 for (order = 0; (flag_rep != 0) && (order < nm_orders); flag_rep >>= 1,
00398 ++order)
00399 if (flag_rep & 0x1)
00400 bu_rb_set_uniqueness(tree, order, 1);
00401
00402 if (flag_rep != 0)
00403 bu_log("bu_rb_set_uniqv(): Ignoring bits beyond rightmost %d\n",
00404 nm_orders);
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 static void _rb_set_uniq_all (bu_rb_tree *tree, int new_value)
00416 {
00417 int nm_orders;
00418 int order;
00419
00420 BU_CKMAG(tree, BU_RB_TREE_MAGIC, "red-black tree");
00421 new_value = (new_value != 0);
00422
00423 nm_orders = tree -> rbt_nm_orders;
00424 for (order = 0; order < nm_orders; ++order)
00425 bu_rb_set_uniqueness(tree, order, new_value);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 void bu_rb_uniq_all_on (bu_rb_tree *tree)
00437 {
00438 _rb_set_uniq_all(tree, 1);
00439 }
00440
00441 void bu_rb_uniq_all_off (bu_rb_tree *tree)
00442 {
00443 _rb_set_uniq_all(tree, 0);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455