Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | #include <vppinfra/fheap.h> |
| 16 | |
| 17 | /* Fibonacci heaps. */ |
| 18 | always_inline fheap_node_t * |
| 19 | fheap_get_node (fheap_t * f, u32 i) |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 20 | { |
| 21 | return i != ~0 ? vec_elt_at_index (f->nodes, i) : 0; |
| 22 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 23 | |
| 24 | always_inline fheap_node_t * |
| 25 | fheap_get_root (fheap_t * f) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 26 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 27 | return fheap_get_node (f, f->min_root); |
| 28 | } |
| 29 | |
| 30 | static void |
| 31 | fheap_validate (fheap_t * f) |
| 32 | { |
| 33 | fheap_node_t *n, *m; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 34 | uword ni, si; |
| 35 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 36 | if (!CLIB_DEBUG || !f->enable_validate) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 37 | return; |
| 38 | |
| 39 | vec_foreach_index (ni, f->nodes) |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 40 | { |
| 41 | n = vec_elt_at_index (f->nodes, ni); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 42 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 43 | if (!n->is_valid) |
| 44 | continue; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 45 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 46 | /* Min root must have minimal key. */ |
| 47 | m = vec_elt_at_index (f->nodes, f->min_root); |
| 48 | ASSERT (n->key >= m->key); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 49 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 50 | /* Min root must have no parent. */ |
| 51 | if (ni == f->min_root) |
| 52 | ASSERT (n->parent == ~0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 53 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 54 | /* Check sibling linkages. */ |
| 55 | if (n->next_sibling == ~0) |
| 56 | ASSERT (n->prev_sibling == ~0); |
| 57 | else if (n->prev_sibling == ~0) |
| 58 | ASSERT (n->next_sibling == ~0); |
| 59 | else |
| 60 | { |
| 61 | fheap_node_t *prev, *next; |
| 62 | u32 si = n->next_sibling, si_start = si; |
| 63 | do |
| 64 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 65 | m = vec_elt_at_index (f->nodes, si); |
| 66 | prev = vec_elt_at_index (f->nodes, m->prev_sibling); |
| 67 | next = vec_elt_at_index (f->nodes, m->next_sibling); |
| 68 | ASSERT (prev->next_sibling == si); |
| 69 | ASSERT (next->prev_sibling == si); |
| 70 | si = m->next_sibling; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 71 | } |
| 72 | while (si != si_start); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 73 | } |
| 74 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 75 | /* Loop through all siblings. */ |
| 76 | { |
| 77 | u32 n_siblings = 0; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 78 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 79 | foreach_fheap_node_sibling (f, si, n->next_sibling, ( |
| 80 | { |
| 81 | m = |
| 82 | vec_elt_at_index |
| 83 | (f->nodes, si); |
| 84 | /* All siblings must have same parent. */ |
| 85 | ASSERT (m->parent |
| 86 | == |
| 87 | n-> |
| 88 | parent); |
| 89 | n_siblings += 1;} |
| 90 | )); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 91 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 92 | /* Either parent is non-empty or there are siblings present. */ |
| 93 | if (n->parent == ~0 && ni != f->min_root) |
| 94 | ASSERT (n_siblings > 0); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 95 | } |
| 96 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 97 | /* Loop through all children. */ |
| 98 | { |
| 99 | u32 found_first_child = n->first_child == ~0; |
| 100 | u32 n_children = 0; |
| 101 | |
| 102 | foreach_fheap_node_sibling (f, si, n->first_child, ( |
| 103 | { |
| 104 | m = |
| 105 | vec_elt_at_index |
| 106 | (f->nodes, si); |
| 107 | /* Children must have larger keys than their parent. */ |
| 108 | ASSERT (m->key >= |
| 109 | n->key); |
| 110 | if |
| 111 | (!found_first_child) |
| 112 | found_first_child = |
| 113 | si == |
| 114 | n->first_child; |
| 115 | n_children += 1;} |
| 116 | )); |
| 117 | |
| 118 | /* Check that first child is present on list. */ |
| 119 | ASSERT (found_first_child); |
| 120 | |
| 121 | /* Make sure rank is correct. */ |
| 122 | ASSERT (n->rank == n_children); |
| 123 | } |
| 124 | } |
| 125 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 126 | /* Increment serial number for each successful validate. |
| 127 | Failure can be used as condition for gdb breakpoints. */ |
| 128 | f->validate_serial++; |
| 129 | } |
| 130 | |
| 131 | always_inline void |
| 132 | fheap_node_add_sibling (fheap_t * f, u32 ni, u32 ni_to_add) |
| 133 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 134 | fheap_node_t *n = vec_elt_at_index (f->nodes, ni); |
| 135 | fheap_node_t *n_to_add = vec_elt_at_index (f->nodes, ni_to_add); |
| 136 | fheap_node_t *n_next = fheap_get_node (f, n->next_sibling); |
| 137 | fheap_node_t *parent; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 138 | |
| 139 | /* Empty list? */ |
| 140 | if (n->next_sibling == ~0) |
| 141 | { |
| 142 | ASSERT (n->prev_sibling == ~0); |
| 143 | n->next_sibling = n->prev_sibling = ni_to_add; |
| 144 | n_to_add->next_sibling = n_to_add->prev_sibling = ni; |
| 145 | } |
| 146 | else |
| 147 | { |
| 148 | /* Add node after existing node. */ |
| 149 | n_to_add->prev_sibling = ni; |
| 150 | n_to_add->next_sibling = n->next_sibling; |
| 151 | |
| 152 | n->next_sibling = ni_to_add; |
| 153 | n_next->prev_sibling = ni_to_add; |
| 154 | } |
| 155 | |
| 156 | n_to_add->parent = n->parent; |
| 157 | parent = fheap_get_node (f, n->parent); |
| 158 | if (parent) |
| 159 | parent->rank += 1; |
| 160 | } |
| 161 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 162 | void |
| 163 | fheap_add (fheap_t * f, u32 ni, u32 key) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 164 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 165 | fheap_node_t *r, *n; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 166 | u32 ri; |
| 167 | |
| 168 | n = vec_elt_at_index (f->nodes, ni); |
| 169 | |
Dave Barach | b7b9299 | 2018-10-17 10:38:51 -0400 | [diff] [blame] | 170 | clib_memset (n, 0, sizeof (n[0])); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 171 | n->parent = n->first_child = n->next_sibling = n->prev_sibling = ~0; |
| 172 | n->key = key; |
| 173 | |
| 174 | r = fheap_get_root (f); |
| 175 | ri = f->min_root; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 176 | if (!r) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 177 | { |
| 178 | /* No root? Add node as new root. */ |
| 179 | f->min_root = ni; |
| 180 | } |
| 181 | else |
| 182 | { |
| 183 | /* Add node as sibling of current root. */ |
| 184 | fheap_node_add_sibling (f, ri, ni); |
| 185 | |
| 186 | /* New node may become new root. */ |
| 187 | if (r->key > n->key) |
| 188 | f->min_root = ni; |
| 189 | } |
| 190 | |
| 191 | fheap_validate (f); |
| 192 | } |
| 193 | |
| 194 | always_inline u32 |
| 195 | fheap_node_remove_internal (fheap_t * f, u32 ni, u32 invalidate) |
| 196 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 197 | fheap_node_t *n = vec_elt_at_index (f->nodes, ni); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 198 | u32 prev_ni = n->prev_sibling; |
| 199 | u32 next_ni = n->next_sibling; |
| 200 | u32 list_has_single_element = prev_ni == ni; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 201 | fheap_node_t *prev = fheap_get_node (f, prev_ni); |
| 202 | fheap_node_t *next = fheap_get_node (f, next_ni); |
| 203 | fheap_node_t *p = fheap_get_node (f, n->parent); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 204 | |
| 205 | if (p) |
| 206 | { |
| 207 | ASSERT (p->rank > 0); |
| 208 | p->rank -= 1; |
| 209 | p->first_child = list_has_single_element ? ~0 : next_ni; |
| 210 | } |
| 211 | |
| 212 | if (prev) |
| 213 | { |
| 214 | ASSERT (prev->next_sibling == ni); |
| 215 | prev->next_sibling = next_ni; |
| 216 | } |
| 217 | if (next) |
| 218 | { |
| 219 | ASSERT (next->prev_sibling == ni); |
| 220 | next->prev_sibling = prev_ni; |
| 221 | } |
| 222 | |
| 223 | n->prev_sibling = n->next_sibling = ni; |
| 224 | n->parent = ~0; |
| 225 | n->is_valid = invalidate == 0; |
| 226 | |
| 227 | return list_has_single_element ? ~0 : next_ni; |
| 228 | } |
| 229 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 230 | always_inline u32 |
| 231 | fheap_node_remove (fheap_t * f, u32 ni) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 232 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 233 | return fheap_node_remove_internal (f, ni, /* invalidate */ 0); |
| 234 | } |
| 235 | |
| 236 | always_inline u32 |
| 237 | fheap_node_remove_and_invalidate (fheap_t * f, u32 ni) |
| 238 | { |
| 239 | return fheap_node_remove_internal (f, ni, /* invalidate */ 1); |
| 240 | } |
| 241 | |
| 242 | static void |
| 243 | fheap_link_root (fheap_t * f, u32 ni) |
| 244 | { |
| 245 | fheap_node_t *n = vec_elt_at_index (f->nodes, ni); |
| 246 | fheap_node_t *r, *lo, *hi; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 247 | u32 ri, lo_i, hi_i, k; |
| 248 | |
| 249 | while (1) |
| 250 | { |
| 251 | k = n->rank; |
| 252 | vec_validate_init_empty (f->root_list_by_rank, k, ~0); |
| 253 | ri = f->root_list_by_rank[k]; |
| 254 | r = fheap_get_node (f, ri); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 255 | if (!r) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 256 | { |
| 257 | f->root_list_by_rank[k] = ni; |
| 258 | return; |
| 259 | } |
| 260 | |
| 261 | f->root_list_by_rank[k] = ~0; |
| 262 | |
| 263 | /* Sort n/r into lo/hi by their keys. */ |
| 264 | lo = r, lo_i = ri; |
| 265 | hi = n, hi_i = ni; |
| 266 | if (hi->key < lo->key) |
| 267 | { |
| 268 | u32 ti; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 269 | fheap_node_t *tn; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 270 | ti = lo_i, tn = lo; |
| 271 | lo = hi, lo_i = hi_i; |
| 272 | hi = tn, hi_i = ti; |
| 273 | } |
| 274 | |
| 275 | /* Remove larger key. */ |
| 276 | fheap_node_remove (f, hi_i); |
| 277 | |
| 278 | /* Add larger key as child of smaller one. */ |
| 279 | if (lo->first_child == ~0) |
| 280 | { |
| 281 | hi->parent = lo_i; |
| 282 | lo->first_child = hi_i; |
| 283 | lo->rank = 1; |
| 284 | } |
| 285 | else |
| 286 | fheap_node_add_sibling (f, lo->first_child, hi_i); |
| 287 | |
| 288 | /* Following Fredman & Trajan: "When making a root node X a child of another node in a linking step, |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 289 | we unmark X". */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 290 | hi->is_marked = 0; |
| 291 | |
| 292 | ni = lo_i; |
| 293 | n = lo; |
| 294 | } |
| 295 | } |
| 296 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 297 | u32 |
| 298 | fheap_del_min (fheap_t * f, u32 * min_key) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 299 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 300 | fheap_node_t *r = fheap_get_root (f); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 301 | u32 to_delete_min_ri = f->min_root; |
| 302 | u32 ri, ni; |
| 303 | |
| 304 | /* Empty heap? */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 305 | if (!r) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 306 | return ~0; |
| 307 | |
| 308 | /* Root's children become siblings. Call this step a; see below. */ |
| 309 | if (r->first_child != ~0) |
| 310 | { |
| 311 | u32 ci, cni, rni; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 312 | fheap_node_t *c, *cn, *rn; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 313 | |
| 314 | /* Splice child & root circular lists together. */ |
| 315 | ci = r->first_child; |
| 316 | c = vec_elt_at_index (f->nodes, ci); |
| 317 | |
| 318 | cni = c->next_sibling; |
| 319 | rni = r->next_sibling; |
| 320 | cn = vec_elt_at_index (f->nodes, cni); |
| 321 | rn = vec_elt_at_index (f->nodes, rni); |
| 322 | |
| 323 | r->next_sibling = cni; |
| 324 | c->next_sibling = rni; |
| 325 | cn->prev_sibling = to_delete_min_ri; |
| 326 | rn->prev_sibling = ci; |
| 327 | } |
| 328 | |
| 329 | /* Remove min root. */ |
| 330 | ri = fheap_node_remove_and_invalidate (f, to_delete_min_ri); |
| 331 | |
| 332 | /* Find new min root from among siblings including the ones we've just added. */ |
| 333 | f->min_root = ~0; |
| 334 | if (ri != ~0) |
| 335 | { |
| 336 | u32 ri_last, ri_next, i, min_ds; |
| 337 | |
| 338 | r = fheap_get_node (f, ri); |
| 339 | ri_last = r->prev_sibling; |
| 340 | while (1) |
| 341 | { |
| 342 | /* Step a above can put children (with r->parent != ~0) on root list. */ |
| 343 | r->parent = ~0; |
| 344 | |
| 345 | ri_next = r->next_sibling; |
| 346 | fheap_link_root (f, ri); |
| 347 | if (ri == ri_last) |
| 348 | break; |
| 349 | ri = ri_next; |
| 350 | r = fheap_get_node (f, ri); |
| 351 | } |
| 352 | |
| 353 | min_ds = ~0; |
| 354 | vec_foreach_index (i, f->root_list_by_rank) |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 355 | { |
| 356 | ni = f->root_list_by_rank[i]; |
| 357 | if (ni == ~0) |
| 358 | continue; |
| 359 | f->root_list_by_rank[i] = ~0; |
| 360 | r = fheap_get_node (f, ni); |
| 361 | if (r->key < min_ds) |
| 362 | { |
| 363 | f->min_root = ni; |
| 364 | min_ds = r->key; |
| 365 | ASSERT (r->parent == ~0); |
| 366 | } |
| 367 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 368 | } |
| 369 | |
| 370 | /* Return deleted min root. */ |
| 371 | r = vec_elt_at_index (f->nodes, to_delete_min_ri); |
| 372 | if (min_key) |
| 373 | *min_key = r->key; |
| 374 | |
| 375 | fheap_validate (f); |
| 376 | |
| 377 | return to_delete_min_ri; |
| 378 | } |
| 379 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 380 | static void |
| 381 | fheap_mark_parent (fheap_t * f, u32 pi) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 382 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 383 | fheap_node_t *p = vec_elt_at_index (f->nodes, pi); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 384 | |
| 385 | /* Parent is a root: do nothing. */ |
| 386 | if (p->parent == ~0) |
| 387 | return; |
| 388 | |
| 389 | /* If not marked, mark it. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 390 | if (!p->is_marked) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 391 | { |
| 392 | p->is_marked = 1; |
| 393 | return; |
| 394 | } |
| 395 | |
| 396 | /* Its a previously marked, non-root parent. |
| 397 | Cut edge to its parent and add to root list. */ |
| 398 | fheap_node_remove (f, pi); |
| 399 | fheap_node_add_sibling (f, f->min_root, pi); |
| 400 | |
| 401 | /* Unmark it since its now a root node. */ |
| 402 | p->is_marked = 0; |
| 403 | |
| 404 | /* "Cascading cuts": check parent. */ |
| 405 | if (p->parent != ~0) |
| 406 | fheap_mark_parent (f, p->parent); |
| 407 | } |
| 408 | |
| 409 | /* Set key to new smaller value. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 410 | void |
| 411 | fheap_decrease_key (fheap_t * f, u32 ni, u32 new_key) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 412 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 413 | fheap_node_t *n = vec_elt_at_index (f->nodes, ni); |
| 414 | fheap_node_t *r = fheap_get_root (f); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 415 | |
| 416 | n->key = new_key; |
| 417 | |
| 418 | if (n->parent != ~0) |
| 419 | { |
| 420 | fheap_mark_parent (f, n->parent); |
| 421 | |
| 422 | /* Remove node and add to root list. */ |
| 423 | fheap_node_remove (f, ni); |
| 424 | fheap_node_add_sibling (f, f->min_root, ni); |
| 425 | } |
| 426 | |
| 427 | if (n->key < r->key) |
| 428 | f->min_root = ni; |
| 429 | |
| 430 | fheap_validate (f); |
| 431 | } |
| 432 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 433 | void |
| 434 | fheap_del (fheap_t * f, u32 ni) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 435 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 436 | fheap_node_t *n; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 437 | |
| 438 | n = vec_elt_at_index (f->nodes, ni); |
| 439 | |
| 440 | if (n->parent == ~0) |
| 441 | { |
| 442 | ASSERT (ni == f->min_root); |
| 443 | fheap_del_min (f, 0); |
| 444 | } |
| 445 | else |
| 446 | { |
| 447 | u32 ci; |
| 448 | |
| 449 | fheap_mark_parent (f, n->parent); |
| 450 | |
| 451 | /* Add children to root list. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 452 | foreach_fheap_node_sibling (f, ci, n->first_child, ( |
| 453 | { |
| 454 | fheap_node_remove |
| 455 | (f, ci); |
| 456 | fheap_node_add_sibling |
| 457 | (f, f->min_root, |
| 458 | ci);} |
| 459 | )); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 460 | |
| 461 | fheap_node_remove_and_invalidate (f, ni); |
| 462 | } |
| 463 | |
| 464 | fheap_validate (f); |
| 465 | } |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 466 | |
| 467 | /* |
| 468 | * fd.io coding-style-patch-verification: ON |
| 469 | * |
| 470 | * Local Variables: |
| 471 | * eval: (c-set-style "gnu") |
| 472 | * End: |
| 473 | */ |