/src/utils/uint_rbtrees.c

https://github.com/SRI-CSL/yices2 · C · 439 lines · 242 code · 77 blank · 120 comment · 79 complexity · 83dd8a8df1370faaa2af66fb89d032c3 MD5 · raw file

  1. /*
  2. * This file is part of the Yices SMT Solver.
  3. * Copyright (C) 2017 SRI International.
  4. *
  5. * Yices is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Yices is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Yices. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. * RED-BLACK TREES TO STORE SETS OF UNSIGNED 32-BIT INTEGERS
  20. */
  21. #include "utils/memalloc.h"
  22. #include "utils/uint_rbtrees.h"
  23. /*
  24. * Initialize tree
  25. * - n = initial size
  26. * - if n = 0, the default size is used
  27. */
  28. void init_rbtree(rbtree_t *tree, uint32_t n) {
  29. if (n == 0) {
  30. n = DEF_RBTREE_SIZE;
  31. }
  32. if (n >= MAX_RBTREE_SIZE) {
  33. out_of_memory();
  34. }
  35. tree->data = (uint32_t *) safe_malloc(n * sizeof(uint32_t));
  36. tree->node = (rbnode_t *) safe_malloc(n * sizeof(rbnode_t));
  37. tree->isred = allocate_bitvector(n);
  38. tree->size = n;
  39. init_ivector(&tree->stack, 20);
  40. assert(n > 0 && null_rbnode == 0);
  41. // initialize the null_node
  42. tree->data[0] = 0;
  43. tree->node[0][0] = 0;
  44. tree->node[0][1] = 0;
  45. clr_bit(tree->isred, 0); // black node
  46. tree->nbnodes = 1;
  47. tree->root = 0;
  48. }
  49. /*
  50. * Resize the tree: make it 50% larger
  51. */
  52. static void extend_rbtree(rbtree_t *tree) {
  53. uint32_t n;
  54. n = tree->size + 1;
  55. n += n>>1;
  56. if (n >= MAX_RBTREE_SIZE) {
  57. out_of_memory();
  58. }
  59. tree->data = (uint32_t *) safe_realloc(tree->data, n * sizeof(uint32_t));
  60. tree->node = (rbnode_t *) safe_realloc(tree->node, n * sizeof(rbnode_t));
  61. tree->isred = extend_bitvector(tree->isred, n);
  62. tree->size = n;
  63. }
  64. /*
  65. * Allocate a new node and return its id
  66. * - the node is not initialized
  67. */
  68. static uint32_t rbtree_new_node(rbtree_t *tree) {
  69. uint32_t i;
  70. i = tree->nbnodes;
  71. if (i == tree->size) {
  72. extend_rbtree(tree);
  73. }
  74. assert(i < tree->size);
  75. tree->nbnodes = i+1;
  76. return i;
  77. }
  78. /*
  79. * Delete tree: free memory
  80. */
  81. void delete_rbtree(rbtree_t *tree) {
  82. safe_free(tree->data);
  83. safe_free(tree->node);
  84. delete_bitvector(tree->isred);
  85. delete_ivector(&tree->stack);
  86. tree->data = NULL;
  87. tree->node = NULL;
  88. tree->isred = NULL;
  89. }
  90. /*
  91. * Reset: empty the tree
  92. */
  93. void reset_rbtree(rbtree_t *tree) {
  94. tree->nbnodes = 1;
  95. tree->root = null_rbnode;
  96. ivector_reset(&tree->stack);
  97. }
  98. /*
  99. * Search for a node of value x
  100. * - return its id or null_rbnode if there's no such node
  101. */
  102. uint32_t rbtree_find(rbtree_t *tree, uint32_t x) {
  103. uint32_t i, k;
  104. // to force termination: store x in the null_node
  105. tree->data[0] = x;
  106. i = tree->root;
  107. assert(i < tree->nbnodes);
  108. while (tree->data[i] != x) {
  109. k = (tree->data[i] < x);
  110. assert((k == 0 && x < tree->data[i]) ||
  111. (k == 1 && x > tree->data[i]));
  112. i = tree->node[i][k];
  113. assert(i < tree->nbnodes);
  114. }
  115. return i;
  116. }
  117. /*
  118. * Auxiliary functions for balancing the tree
  119. */
  120. /*
  121. * Check whether p is parent of q
  122. * - both must be valid node indices
  123. */
  124. #ifndef NDEBUG
  125. static inline bool is_parent_node(rbtree_t *tree, uint32_t p, uint32_t q) {
  126. assert(p < tree->nbnodes && q < tree->nbnodes);
  127. return tree->node[p][0] == q || tree->node[p][1] == q;
  128. }
  129. #endif
  130. /*
  131. * Child-index(p, q):
  132. * - q must be a child of node p
  133. * - returns 0 if q is the left child
  134. * returns 1 if q is the right child
  135. * So i = child_index(treee, p, q) implies tree->node[p][i] = q
  136. */
  137. static inline uint32_t child_index(rbtree_t *tree, uint32_t p, uint32_t q) {
  138. assert(is_parent_node(tree, p, q));
  139. return tree->node[p][1] == q;
  140. }
  141. /*
  142. * Get sibling of q in p
  143. * - both p and q must be valid node indices
  144. * - q must be a child of p
  145. */
  146. static inline uint32_t sibling(rbtree_t *tree, uint32_t p, uint32_t q) {
  147. assert(is_parent_node(tree, p, q));
  148. return (tree->node[p][0] ^ tree->node[p][1]) ^ q;
  149. }
  150. /*
  151. * Check color of node p
  152. */
  153. static inline bool is_red(rbtree_t *tree, uint32_t p) {
  154. assert(p < tree->nbnodes);
  155. return tst_bit(tree->isred, p);
  156. }
  157. #ifndef NDEBUG
  158. static inline bool is_black(rbtree_t *tree, uint32_t p) {
  159. return ! is_red(tree, p);
  160. }
  161. #endif
  162. /*
  163. * Set the color of node p
  164. */
  165. static inline void mark_red(rbtree_t *tree, uint32_t p) {
  166. assert(p < tree->nbnodes);
  167. set_bit(tree->isred, p);
  168. }
  169. static inline void mark_black(rbtree_t *tree, uint32_t p) {
  170. assert(p < tree->nbnodes);
  171. clr_bit(tree->isred, p);
  172. }
  173. /*
  174. * Balance the tree:
  175. * - p = new node just added (must be red)
  176. * - q = parent of p
  177. * - tree->stack contains [null_rbnode, root, ..., r],
  178. * which describes a path form the root to r where r = parent of q.
  179. * - the root must be black
  180. */
  181. static void rbtree_balance(rbtree_t *tree, uint32_t p, uint32_t q) {
  182. uint32_t r, s;
  183. uint32_t i, j;
  184. assert(is_parent_node(tree, q, p) && is_red(tree, p) && is_black(tree, tree->root));
  185. while (is_red(tree, q)) {
  186. r = ivector_pop2(&tree->stack); // r = parent of q
  187. assert(is_black(tree, r));
  188. s = sibling(tree, r, q); // s = sibling of q
  189. if (is_red(tree, s)) {
  190. // flip colors of q and s
  191. mark_black(tree, s);
  192. mark_black(tree, q);
  193. // if r is the root, we're done
  194. if (r == tree->root) break;
  195. // otherwise, we color r red
  196. // and move up to p := r, q := parent of r
  197. mark_red(tree, r);
  198. p = r;
  199. q = ivector_pop2(&tree->stack); // q = parent of r
  200. assert(is_parent_node(tree, q, p));
  201. } else {
  202. // Balance the tree with one or two rotations
  203. i = child_index(tree, r, q);
  204. j = child_index(tree, q, p);
  205. if (i != j) {
  206. /*
  207. * Rotate p and q
  208. * q becomes a child of p
  209. * p becomes a child of r
  210. */
  211. assert(q != 0 && p != 0 && r != 0 &&
  212. tree->node[r][i] == q &&
  213. tree->node[q][j] == p);
  214. tree->node[r][i] = p;
  215. tree->node[q][j] = tree->node[p][i];
  216. tree->node[p][i] = q;
  217. // prepare for second rotation:
  218. q = p;
  219. }
  220. /*
  221. * rotate r and q
  222. * and fix the colors: r becomes red, q becomes black
  223. */
  224. assert(tree->node[r][i] == q);
  225. p = ivector_pop2(&tree->stack);
  226. if (p == null_rbnode) {
  227. assert(r == tree->root);
  228. tree->root = q;
  229. } else {
  230. // p is r's parent
  231. j = child_index(tree, p, r);
  232. assert(tree->node[p][j] == r);
  233. tree->node[p][j] = q;
  234. }
  235. tree->node[r][i] = tree->node[q][1-i];
  236. tree->node[q][1-i] = r;
  237. mark_red(tree, r);
  238. mark_black(tree, q);
  239. break;
  240. }
  241. }
  242. }
  243. /*
  244. * Search or add node of value x
  245. * - return the node id
  246. * - set new_node to true if that's a new node (x was not present)
  247. */
  248. uint32_t rbtree_get(rbtree_t *tree, uint32_t x, bool *new_node) {
  249. uint32_t k, i, p;
  250. assert(tree->stack.size == 0);
  251. // to force termination: store x in the null_node
  252. tree->data[0] = x;
  253. k = 0; // stop GCC bogus warning
  254. p = null_rbnode; // parent
  255. i = tree->root;
  256. assert(i < tree->nbnodes);
  257. while (tree->data[i] != x) {
  258. k = (tree->data[i] < x);
  259. assert((k == 0 && x < tree->data[i]) ||
  260. (k == 1 && x > tree->data[i]));
  261. // save p on the stack for balancing
  262. ivector_push(&tree->stack, p);
  263. p = i;
  264. i = tree->node[i][k];
  265. assert(i < tree->nbnodes);
  266. }
  267. *new_node = false;
  268. if (i == 0) {
  269. // x is not in the current tree: add it
  270. *new_node = true;
  271. i = rbtree_new_node(tree);
  272. tree->data[i] = x;
  273. tree->node[i][0] = null_rbnode;
  274. tree->node[i][1] = null_rbnode;
  275. if (p == null_rbnode) {
  276. // make sure the root is always black
  277. tree->root = i;
  278. mark_black(tree, i);
  279. } else {
  280. // add i as child of p then balance the tree
  281. assert(p < tree->nbnodes && tree->node[p][k] == null_rbnode);
  282. tree->node[p][k] = i;
  283. mark_red(tree, i);
  284. rbtree_balance(tree, i, p);
  285. }
  286. }
  287. ivector_reset(&tree->stack);
  288. assert(i > 0 && tree->data[i] == x);
  289. return i;
  290. }
  291. /*
  292. * To scan the tree:
  293. * - return the id of the node whose value is the smallest
  294. * element in the tree that's >= x.
  295. * - return null_rbnode (i.e., 0) if all elements are smaller than x.
  296. */
  297. uint32_t rbtree_find_sup(rbtree_t *tree, uint32_t x) {
  298. uint32_t i, j;
  299. // to force termination: store x in the null_node
  300. tree->data[0] = x;
  301. // j = either null_node or
  302. // such that tree->data[j] > x
  303. j = null_rbnode;
  304. i = tree->root;
  305. while (tree->data[i] != x) {
  306. if (tree->data[i] < x) {
  307. i = tree->node[i][1];
  308. } else {
  309. j = i;
  310. i = tree->node[i][0];
  311. }
  312. }
  313. if (i > 0) {
  314. assert(tree->data[i] == x);
  315. return i;
  316. } else {
  317. return j;
  318. }
  319. }
  320. #if 0
  321. /*
  322. * Search or add node of value x
  323. * - return the node id
  324. * - set new_node to true if that's a new node (x was not present)
  325. * Don't balance the tree
  326. */
  327. uint32_t rbtree_get_var(rbtree_t *tree, uint32_t x, bool *new_node) {
  328. uint32_t k, i, p;
  329. // to force termination: store x in the null_node
  330. tree->data[0] = x;
  331. k = 0; // stop GCC bogus warning
  332. p = null_rbnode; // parent
  333. i = tree->root;
  334. assert(i < tree->nbnodes);
  335. while (tree->data[i] != x) {
  336. k = (tree->data[i] < x);
  337. assert((k == 0 && x < tree->data[i]) ||
  338. (k == 1 && x > tree->data[i]));
  339. p = i;
  340. i = tree->node[i][k];
  341. assert(i < tree->nbnodes);
  342. }
  343. *new_node = false;
  344. if (i == 0) {
  345. // x is not in the current tree: add it
  346. *new_node = true;
  347. i = rbtree_new_node(tree);
  348. tree->data[i] = x;
  349. tree->node[i][0] = null_rbnode;
  350. tree->node[i][1] = null_rbnode;
  351. mark_black(tree, i);
  352. if (p == null_rbnode) {
  353. tree->root = i;
  354. } else {
  355. assert(p < tree->nbnodes && tree->node[p][k] == null_rbnode);
  356. tree->node[p][k] = i;
  357. }
  358. }
  359. assert(i > 0 && tree->data[i] == x);
  360. return i;
  361. }
  362. #endif