annotate DEPENDENCIES/generic/include/boost/pending/relaxed_heap.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright 2004 The Trustees of Indiana University.
Chris@16 2
Chris@16 3 // Use, modification and distribution is subject to the Boost Software
Chris@16 4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 // Authors: Douglas Gregor
Chris@16 8 // Andrew Lumsdaine
Chris@16 9 #ifndef BOOST_RELAXED_HEAP_HEADER
Chris@16 10 #define BOOST_RELAXED_HEAP_HEADER
Chris@16 11
Chris@16 12 #include <functional>
Chris@16 13 #include <boost/property_map/property_map.hpp>
Chris@16 14 #include <boost/optional.hpp>
Chris@16 15 #include <vector>
Chris@16 16 #include <climits> // for CHAR_BIT
Chris@16 17 #include <boost/none.hpp>
Chris@16 18
Chris@16 19 #ifdef BOOST_RELAXED_HEAP_DEBUG
Chris@16 20 # include <iostream>
Chris@16 21 #endif // BOOST_RELAXED_HEAP_DEBUG
Chris@16 22
Chris@16 23 #if defined(BOOST_MSVC)
Chris@16 24 # pragma warning(push)
Chris@16 25 # pragma warning(disable:4355) // complaint about using 'this' to
Chris@16 26 #endif // initialize a member
Chris@16 27
Chris@16 28 namespace boost {
Chris@16 29
Chris@16 30 template<typename IndexedType,
Chris@16 31 typename Compare = std::less<IndexedType>,
Chris@16 32 typename ID = identity_property_map>
Chris@16 33 class relaxed_heap
Chris@16 34 {
Chris@16 35 struct group;
Chris@16 36
Chris@16 37 typedef relaxed_heap self_type;
Chris@16 38 typedef std::size_t rank_type;
Chris@16 39
Chris@16 40 public:
Chris@16 41 typedef IndexedType value_type;
Chris@16 42 typedef rank_type size_type;
Chris@16 43
Chris@16 44 private:
Chris@16 45 /**
Chris@16 46 * The kind of key that a group has. The actual values are discussed
Chris@16 47 * in-depth in the documentation of the @c kind field of the @c group
Chris@16 48 * structure. Note that the order of the enumerators *IS* important
Chris@16 49 * and must not be changed.
Chris@16 50 */
Chris@16 51 enum group_key_kind { smallest_key, stored_key, largest_key };
Chris@16 52
Chris@16 53 struct group {
Chris@16 54 explicit group(group_key_kind kind = largest_key)
Chris@16 55 : kind(kind), parent(this), rank(0) { }
Chris@16 56
Chris@16 57 /** The value associated with this group. This value is only valid
Chris@16 58 * when @c kind!=largest_key (which indicates a deleted
Chris@16 59 * element). Note that the use of boost::optional increases the
Chris@16 60 * memory requirements slightly but does not result in extraneous
Chris@16 61 * memory allocations or deallocations. The optional could be
Chris@16 62 * eliminated when @c value_type is a model of
Chris@16 63 * DefaultConstructible.
Chris@16 64 */
Chris@16 65 ::boost::optional<value_type> value;
Chris@16 66
Chris@16 67 /**
Chris@16 68 * The kind of key stored at this group. This may be @c
Chris@16 69 * smallest_key, which indicates that the key is infinitely small;
Chris@16 70 * @c largest_key, which indicates that the key is infinitely
Chris@16 71 * large; or @c stored_key, which means that the key is unknown,
Chris@16 72 * but its relationship to other keys can be determined via the
Chris@16 73 * comparison function object.
Chris@16 74 */
Chris@16 75 group_key_kind kind;
Chris@16 76
Chris@16 77 /// The parent of this group. Will only be NULL for the dummy root group
Chris@16 78 group* parent;
Chris@16 79
Chris@16 80 /// The rank of this group. Equivalent to the number of children in
Chris@16 81 /// the group.
Chris@16 82 rank_type rank;
Chris@16 83
Chris@16 84 /** The children of this group. For the dummy root group, these are
Chris@16 85 * the roots. This is an array of length log n containing pointers
Chris@16 86 * to the child groups.
Chris@16 87 */
Chris@16 88 group** children;
Chris@16 89 };
Chris@16 90
Chris@16 91 size_type log_base_2(size_type n) // log2 is a macro on some platforms
Chris@16 92 {
Chris@16 93 size_type leading_zeroes = 0;
Chris@16 94 do {
Chris@16 95 size_type next = n << 1;
Chris@16 96 if (n == (next >> 1)) {
Chris@16 97 ++leading_zeroes;
Chris@16 98 n = next;
Chris@16 99 } else {
Chris@16 100 break;
Chris@16 101 }
Chris@16 102 } while (true);
Chris@16 103 return sizeof(size_type) * CHAR_BIT - leading_zeroes - 1;
Chris@16 104 }
Chris@16 105
Chris@16 106 public:
Chris@16 107 relaxed_heap(size_type n, const Compare& compare = Compare(),
Chris@16 108 const ID& id = ID())
Chris@16 109 : compare(compare), id(id), root(smallest_key), groups(n),
Chris@16 110 smallest_value(0)
Chris@16 111 {
Chris@16 112 if (n == 0) {
Chris@16 113 root.children = new group*[1];
Chris@16 114 return;
Chris@16 115 }
Chris@16 116
Chris@16 117 log_n = log_base_2(n);
Chris@16 118 if (log_n == 0) log_n = 1;
Chris@16 119 size_type g = n / log_n;
Chris@16 120 if (n % log_n > 0) ++g;
Chris@16 121 size_type log_g = log_base_2(g);
Chris@16 122 size_type r = log_g;
Chris@16 123
Chris@16 124 // Reserve an appropriate amount of space for data structures, so
Chris@16 125 // that we do not need to expand them.
Chris@16 126 index_to_group.resize(g);
Chris@16 127 A.resize(r + 1, 0);
Chris@16 128 root.rank = r + 1;
Chris@16 129 root.children = new group*[(log_g + 1) * (g + 1)];
Chris@16 130 for (rank_type i = 0; i < r+1; ++i) root.children[i] = 0;
Chris@16 131
Chris@16 132 // Build initial heap
Chris@16 133 size_type idx = 0;
Chris@16 134 while (idx < g) {
Chris@16 135 root.children[r] = &index_to_group[idx];
Chris@16 136 idx = build_tree(root, idx, r, log_g + 1);
Chris@16 137 if (idx != g)
Chris@16 138 r = static_cast<size_type>(log_base_2(g-idx));
Chris@16 139 }
Chris@16 140 }
Chris@16 141
Chris@16 142 ~relaxed_heap() { delete [] root.children; }
Chris@16 143
Chris@16 144 void push(const value_type& x)
Chris@16 145 {
Chris@16 146 groups[get(id, x)] = x;
Chris@16 147 update(x);
Chris@16 148 }
Chris@16 149
Chris@16 150 void update(const value_type& x)
Chris@16 151 {
Chris@16 152 group* a = &index_to_group[get(id, x) / log_n];
Chris@16 153 if (!a->value
Chris@16 154 || *a->value == x
Chris@16 155 || compare(x, *a->value)) {
Chris@16 156 if (a != smallest_value) smallest_value = 0;
Chris@16 157 a->kind = stored_key;
Chris@16 158 a->value = x;
Chris@16 159 promote(a);
Chris@16 160 }
Chris@16 161 }
Chris@16 162
Chris@16 163 void remove(const value_type& x)
Chris@16 164 {
Chris@16 165 group* a = &index_to_group[get(id, x) / log_n];
Chris@101 166 assert(groups[get(id, x)]);
Chris@16 167 a->value = x;
Chris@16 168 a->kind = smallest_key;
Chris@16 169 promote(a);
Chris@16 170 smallest_value = a;
Chris@16 171 pop();
Chris@16 172 }
Chris@16 173
Chris@16 174 value_type& top()
Chris@16 175 {
Chris@16 176 find_smallest();
Chris@16 177 assert(smallest_value->value != none);
Chris@16 178 return *smallest_value->value;
Chris@16 179 }
Chris@16 180
Chris@16 181 const value_type& top() const
Chris@16 182 {
Chris@16 183 find_smallest();
Chris@16 184 assert(smallest_value->value != none);
Chris@16 185 return *smallest_value->value;
Chris@16 186 }
Chris@16 187
Chris@16 188 bool empty() const
Chris@16 189 {
Chris@16 190 find_smallest();
Chris@16 191 return !smallest_value || (smallest_value->kind == largest_key);
Chris@16 192 }
Chris@16 193
Chris@16 194 bool contains(const value_type& x) const { return groups[get(id, x)]; }
Chris@16 195
Chris@16 196 void pop()
Chris@16 197 {
Chris@16 198 // Fill in smallest_value. This is the group x.
Chris@16 199 find_smallest();
Chris@16 200 group* x = smallest_value;
Chris@16 201 smallest_value = 0;
Chris@16 202
Chris@16 203 // Make x a leaf, giving it the smallest value within its group
Chris@16 204 rank_type r = x->rank;
Chris@16 205 group* p = x->parent;
Chris@16 206 {
Chris@16 207 assert(x->value != none);
Chris@16 208
Chris@16 209 // Find x's group
Chris@16 210 size_type start = get(id, *x->value) - get(id, *x->value) % log_n;
Chris@16 211 size_type end = start + log_n;
Chris@16 212 if (end > groups.size()) end = groups.size();
Chris@16 213
Chris@16 214 // Remove the smallest value from the group, and find the new
Chris@16 215 // smallest value.
Chris@16 216 groups[get(id, *x->value)].reset();
Chris@16 217 x->value.reset();
Chris@16 218 x->kind = largest_key;
Chris@16 219 for (size_type i = start; i < end; ++i) {
Chris@16 220 if (groups[i] && (!x->value || compare(*groups[i], *x->value))) {
Chris@16 221 x->kind = stored_key;
Chris@16 222 x->value = groups[i];
Chris@16 223 }
Chris@16 224 }
Chris@16 225 }
Chris@16 226 x->rank = 0;
Chris@16 227
Chris@16 228 // Combine prior children of x with x
Chris@16 229 group* y = x;
Chris@16 230 for (size_type c = 0; c < r; ++c) {
Chris@16 231 group* child = x->children[c];
Chris@16 232 if (A[c] == child) A[c] = 0;
Chris@16 233 y = combine(y, child);
Chris@16 234 }
Chris@16 235
Chris@16 236 // If we got back something other than x, let y take x's place
Chris@16 237 if (y != x) {
Chris@16 238 y->parent = p;
Chris@16 239 p->children[r] = y;
Chris@16 240
Chris@16 241 assert(r == y->rank);
Chris@16 242 if (A[y->rank] == x)
Chris@16 243 A[y->rank] = do_compare(y, p)? y : 0;
Chris@16 244 }
Chris@16 245 }
Chris@16 246
Chris@16 247 #ifdef BOOST_RELAXED_HEAP_DEBUG
Chris@16 248 /*************************************************************************
Chris@16 249 * Debugging support *
Chris@16 250 *************************************************************************/
Chris@16 251 void dump_tree() { dump_tree(std::cout); }
Chris@16 252 void dump_tree(std::ostream& out) { dump_tree(out, &root); }
Chris@16 253
Chris@16 254 void dump_tree(std::ostream& out, group* p, bool in_progress = false)
Chris@16 255 {
Chris@16 256 if (!in_progress) {
Chris@16 257 out << "digraph heap {\n"
Chris@16 258 << " edge[dir=\"back\"];\n";
Chris@16 259 }
Chris@16 260
Chris@16 261 size_type p_index = 0;
Chris@16 262 if (p != &root) while (&index_to_group[p_index] != p) ++p_index;
Chris@16 263
Chris@16 264 for (size_type i = 0; i < p->rank; ++i) {
Chris@16 265 group* c = p->children[i];
Chris@16 266 if (c) {
Chris@16 267 size_type c_index = 0;
Chris@16 268 if (c != &root) while (&index_to_group[c_index] != c) ++c_index;
Chris@16 269
Chris@16 270 out << " ";
Chris@16 271 if (p == &root) out << 'p'; else out << p_index;
Chris@16 272 out << " -> ";
Chris@16 273 if (c == &root) out << 'p'; else out << c_index;
Chris@16 274 if (A[c->rank] == c) out << " [style=\"dotted\"]";
Chris@16 275 out << ";\n";
Chris@16 276 dump_tree(out, c, true);
Chris@16 277
Chris@16 278 // Emit node information
Chris@16 279 out << " ";
Chris@16 280 if (c == &root) out << 'p'; else out << c_index;
Chris@16 281 out << " [label=\"";
Chris@16 282 if (c == &root) out << 'p'; else out << c_index;
Chris@16 283 out << ":";
Chris@16 284 size_type start = c_index * log_n;
Chris@16 285 size_type end = start + log_n;
Chris@16 286 if (end > groups.size()) end = groups.size();
Chris@16 287 while (start != end) {
Chris@16 288 if (groups[start]) {
Chris@16 289 out << " " << get(id, *groups[start]);
Chris@16 290 if (*groups[start] == *c->value) out << "(*)";
Chris@16 291 }
Chris@16 292 ++start;
Chris@16 293 }
Chris@16 294 out << '"';
Chris@16 295
Chris@16 296 if (do_compare(c, p)) {
Chris@16 297 out << " ";
Chris@16 298 if (c == &root) out << 'p'; else out << c_index;
Chris@16 299 out << ", style=\"filled\", fillcolor=\"gray\"";
Chris@16 300 }
Chris@16 301 out << "];\n";
Chris@16 302 } else {
Chris@16 303 assert(p->parent == p);
Chris@16 304 }
Chris@16 305 }
Chris@16 306 if (!in_progress) out << "}\n";
Chris@16 307 }
Chris@16 308
Chris@16 309 bool valid()
Chris@16 310 {
Chris@16 311 // Check that the ranks in the A array match the ranks of the
Chris@16 312 // groups stored there. Also, the active groups must be the last
Chris@16 313 // child of their parent.
Chris@16 314 for (size_type r = 0; r < A.size(); ++r) {
Chris@16 315 if (A[r] && A[r]->rank != r) return false;
Chris@16 316
Chris@16 317 if (A[r] && A[r]->parent->children[A[r]->parent->rank-1] != A[r])
Chris@16 318 return false;
Chris@16 319 }
Chris@16 320
Chris@16 321 // The root must have no value and a key of -Infinity
Chris@16 322 if (root.kind != smallest_key) return false;
Chris@16 323
Chris@16 324 return valid(&root);
Chris@16 325 }
Chris@16 326
Chris@16 327 bool valid(group* p)
Chris@16 328 {
Chris@16 329 for (size_type i = 0; i < p->rank; ++i) {
Chris@16 330 group* c = p->children[i];
Chris@16 331 if (c) {
Chris@16 332 // Check link structure
Chris@16 333 if (c->parent != p) return false;
Chris@16 334 if (c->rank != i) return false;
Chris@16 335
Chris@16 336 // A bad group must be active
Chris@16 337 if (do_compare(c, p) && A[i] != c) return false;
Chris@16 338
Chris@16 339 // Check recursively
Chris@16 340 if (!valid(c)) return false;
Chris@16 341 } else {
Chris@16 342 // Only the root may
Chris@16 343 if (p != &root) return false;
Chris@16 344 }
Chris@16 345 }
Chris@16 346 return true;
Chris@16 347 }
Chris@16 348
Chris@16 349 #endif // BOOST_RELAXED_HEAP_DEBUG
Chris@16 350
Chris@16 351 private:
Chris@16 352 size_type
Chris@16 353 build_tree(group& parent, size_type idx, size_type r, size_type max_rank)
Chris@16 354 {
Chris@16 355 group& this_group = index_to_group[idx];
Chris@16 356 this_group.parent = &parent;
Chris@16 357 ++idx;
Chris@16 358
Chris@16 359 this_group.children = root.children + (idx * max_rank);
Chris@16 360 this_group.rank = r;
Chris@16 361 for (size_type i = 0; i < r; ++i) {
Chris@16 362 this_group.children[i] = &index_to_group[idx];
Chris@16 363 idx = build_tree(this_group, idx, i, max_rank);
Chris@16 364 }
Chris@16 365 return idx;
Chris@16 366 }
Chris@16 367
Chris@16 368 void find_smallest() const
Chris@16 369 {
Chris@16 370 group** roots = root.children;
Chris@16 371
Chris@16 372 if (!smallest_value) {
Chris@16 373 std::size_t i;
Chris@16 374 for (i = 0; i < root.rank; ++i) {
Chris@16 375 if (roots[i] &&
Chris@16 376 (!smallest_value || do_compare(roots[i], smallest_value))) {
Chris@16 377 smallest_value = roots[i];
Chris@16 378 }
Chris@16 379 }
Chris@16 380 for (i = 0; i < A.size(); ++i) {
Chris@16 381 if (A[i] && (!smallest_value || do_compare(A[i], smallest_value)))
Chris@16 382 smallest_value = A[i];
Chris@16 383 }
Chris@16 384 }
Chris@16 385 }
Chris@16 386
Chris@16 387 bool do_compare(group* x, group* y) const
Chris@16 388 {
Chris@16 389 return (x->kind < y->kind
Chris@16 390 || (x->kind == y->kind
Chris@16 391 && x->kind == stored_key
Chris@16 392 && compare(*x->value, *y->value)));
Chris@16 393 }
Chris@16 394
Chris@16 395 void promote(group* a)
Chris@16 396 {
Chris@16 397 assert(a != 0);
Chris@16 398 rank_type r = a->rank;
Chris@16 399 group* p = a->parent;
Chris@16 400 assert(p != 0);
Chris@16 401 if (do_compare(a, p)) {
Chris@16 402 // s is the rank + 1 sibling
Chris@16 403 group* s = p->rank > r + 1? p->children[r + 1] : 0;
Chris@16 404
Chris@16 405 // If a is the last child of p
Chris@16 406 if (r == p->rank - 1) {
Chris@16 407 if (!A[r]) A[r] = a;
Chris@16 408 else if (A[r] != a) pair_transform(a);
Chris@16 409 } else {
Chris@16 410 assert(s != 0);
Chris@16 411 if (A[r + 1] == s) active_sibling_transform(a, s);
Chris@16 412 else good_sibling_transform(a, s);
Chris@16 413 }
Chris@16 414 }
Chris@16 415 }
Chris@16 416
Chris@16 417 group* combine(group* a1, group* a2)
Chris@16 418 {
Chris@16 419 assert(a1->rank == a2->rank);
Chris@16 420 if (do_compare(a2, a1)) do_swap(a1, a2);
Chris@16 421 a1->children[a1->rank++] = a2;
Chris@16 422 a2->parent = a1;
Chris@16 423 clean(a1);
Chris@16 424 return a1;
Chris@16 425 }
Chris@16 426
Chris@16 427 void clean(group* q)
Chris@16 428 {
Chris@16 429 if (2 > q->rank) return;
Chris@16 430 group* qp = q->children[q->rank-1];
Chris@16 431 rank_type s = q->rank - 2;
Chris@16 432 group* x = q->children[s];
Chris@16 433 group* xp = qp->children[s];
Chris@16 434 assert(s == x->rank);
Chris@16 435
Chris@16 436 // If x is active, swap x and xp
Chris@16 437 if (A[s] == x) {
Chris@16 438 q->children[s] = xp;
Chris@16 439 xp->parent = q;
Chris@16 440 qp->children[s] = x;
Chris@16 441 x->parent = qp;
Chris@16 442 }
Chris@16 443 }
Chris@16 444
Chris@16 445 void pair_transform(group* a)
Chris@16 446 {
Chris@16 447 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 448 std::cerr << "- pair transform\n";
Chris@16 449 #endif
Chris@16 450 rank_type r = a->rank;
Chris@16 451
Chris@16 452 // p is a's parent
Chris@16 453 group* p = a->parent;
Chris@16 454 assert(p != 0);
Chris@16 455
Chris@16 456 // g is p's parent (a's grandparent)
Chris@16 457 group* g = p->parent;
Chris@16 458 assert(g != 0);
Chris@16 459
Chris@16 460 // a' <- A(r)
Chris@16 461 assert(A[r] != 0);
Chris@16 462 group* ap = A[r];
Chris@16 463 assert(ap != 0);
Chris@16 464
Chris@16 465 // A(r) <- nil
Chris@16 466 A[r] = 0;
Chris@16 467
Chris@16 468 // let a' have parent p'
Chris@16 469 group* pp = ap->parent;
Chris@16 470 assert(pp != 0);
Chris@16 471
Chris@16 472 // let a' have grandparent g'
Chris@16 473 group* gp = pp->parent;
Chris@16 474 assert(gp != 0);
Chris@16 475
Chris@16 476 // Remove a and a' from their parents
Chris@16 477 assert(ap == pp->children[pp->rank-1]); // Guaranteed because ap is active
Chris@16 478 --pp->rank;
Chris@16 479
Chris@16 480 // Guaranteed by caller
Chris@16 481 assert(a == p->children[p->rank-1]);
Chris@16 482 --p->rank;
Chris@16 483
Chris@16 484 // Note: a, ap, p, pp all have rank r
Chris@16 485 if (do_compare(pp, p)) {
Chris@16 486 do_swap(a, ap);
Chris@16 487 do_swap(p, pp);
Chris@16 488 do_swap(g, gp);
Chris@16 489 }
Chris@16 490
Chris@16 491 // Assuming k(p) <= k(p')
Chris@16 492 // make p' the rank r child of p
Chris@16 493 assert(r == p->rank);
Chris@16 494 p->children[p->rank++] = pp;
Chris@16 495 pp->parent = p;
Chris@16 496
Chris@16 497 // Combine a, ap into a rank r+1 group c
Chris@16 498 group* c = combine(a, ap);
Chris@16 499
Chris@16 500 // make c the rank r+1 child of g'
Chris@16 501 assert(gp->rank > r+1);
Chris@16 502 gp->children[r+1] = c;
Chris@16 503 c->parent = gp;
Chris@16 504
Chris@16 505 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 506 std::cerr << "After pair transform...\n";
Chris@16 507 dump_tree();
Chris@16 508 #endif
Chris@16 509
Chris@16 510 if (A[r+1] == pp) A[r+1] = c;
Chris@16 511 else promote(c);
Chris@16 512 }
Chris@16 513
Chris@16 514 void active_sibling_transform(group* a, group* s)
Chris@16 515 {
Chris@16 516 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 517 std::cerr << "- active sibling transform\n";
Chris@16 518 #endif
Chris@16 519 group* p = a->parent;
Chris@16 520 group* g = p->parent;
Chris@16 521
Chris@16 522 // remove a, s from their parents
Chris@16 523 assert(s->parent == p);
Chris@16 524 assert(p->children[p->rank-1] == s);
Chris@16 525 --p->rank;
Chris@16 526 assert(p->children[p->rank-1] == a);
Chris@16 527 --p->rank;
Chris@16 528
Chris@16 529 rank_type r = a->rank;
Chris@16 530 A[r+1] = 0;
Chris@16 531 a = combine(p, a);
Chris@16 532 group* c = combine(a, s);
Chris@16 533
Chris@16 534 // make c the rank r+2 child of g
Chris@16 535 assert(g->children[r+2] == p);
Chris@16 536 g->children[r+2] = c;
Chris@16 537 c->parent = g;
Chris@16 538 if (A[r+2] == p) A[r+2] = c;
Chris@16 539 else promote(c);
Chris@16 540 }
Chris@16 541
Chris@16 542 void good_sibling_transform(group* a, group* s)
Chris@16 543 {
Chris@16 544 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 545 std::cerr << "- good sibling transform\n";
Chris@16 546 #endif
Chris@16 547 rank_type r = a->rank;
Chris@16 548 group* c = s->children[s->rank-1];
Chris@16 549 assert(c->rank == r);
Chris@16 550 if (A[r] == c) {
Chris@16 551 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 552 std::cerr << "- good sibling pair transform\n";
Chris@16 553 #endif
Chris@16 554 A[r] = 0;
Chris@16 555 group* p = a->parent;
Chris@16 556
Chris@16 557 // Remove c from its parent
Chris@16 558 --s->rank;
Chris@16 559
Chris@16 560 // Make s the rank r child of p
Chris@16 561 s->parent = p;
Chris@16 562 p->children[r] = s;
Chris@16 563
Chris@16 564 // combine a, c and let the result by the rank r+1 child of p
Chris@16 565 assert(p->rank > r+1);
Chris@16 566 group* x = combine(a, c);
Chris@16 567 x->parent = p;
Chris@16 568 p->children[r+1] = x;
Chris@16 569
Chris@16 570 if (A[r+1] == s) A[r+1] = x;
Chris@16 571 else promote(x);
Chris@16 572
Chris@16 573 #if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
Chris@16 574 dump_tree(std::cerr);
Chris@16 575 #endif
Chris@16 576 // pair_transform(a);
Chris@16 577 } else {
Chris@16 578 // Clean operation
Chris@16 579 group* p = a->parent;
Chris@16 580 s->children[r] = a;
Chris@16 581 a->parent = s;
Chris@16 582 p->children[r] = c;
Chris@16 583 c->parent = p;
Chris@16 584
Chris@16 585 promote(a);
Chris@16 586 }
Chris@16 587 }
Chris@16 588
Chris@16 589 static void do_swap(group*& x, group*& y)
Chris@16 590 {
Chris@16 591 group* tmp = x;
Chris@16 592 x = y;
Chris@16 593 y = tmp;
Chris@16 594 }
Chris@16 595
Chris@16 596 /// Function object that compares two values in the heap
Chris@16 597 Compare compare;
Chris@16 598
Chris@16 599 /// Mapping from values to indices in the range [0, n).
Chris@16 600 ID id;
Chris@16 601
Chris@16 602 /** The root group of the queue. This group is special because it will
Chris@16 603 * never store a value, but it acts as a parent to all of the
Chris@16 604 * roots. Thus, its list of children is the list of roots.
Chris@16 605 */
Chris@16 606 group root;
Chris@16 607
Chris@16 608 /** Mapping from the group index of a value to the group associated
Chris@16 609 * with that value. If a value is not in the queue, then the "value"
Chris@16 610 * field will be empty.
Chris@16 611 */
Chris@16 612 std::vector<group> index_to_group;
Chris@16 613
Chris@16 614 /** Flat data structure containing the values in each of the
Chris@16 615 * groups. It will be indexed via the id of the values. The groups
Chris@16 616 * are each log_n long, with the last group potentially being
Chris@16 617 * smaller.
Chris@16 618 */
Chris@16 619 std::vector< ::boost::optional<value_type> > groups;
Chris@16 620
Chris@16 621 /** The list of active groups, indexed by rank. When A[r] is null,
Chris@16 622 * there is no active group of rank r. Otherwise, A[r] is the active
Chris@16 623 * group of rank r.
Chris@16 624 */
Chris@16 625 std::vector<group*> A;
Chris@16 626
Chris@16 627 /** The group containing the smallest value in the queue, which must
Chris@16 628 * be either a root or an active group. If this group is null, then we
Chris@16 629 * will need to search for this group when it is needed.
Chris@16 630 */
Chris@16 631 mutable group* smallest_value;
Chris@16 632
Chris@16 633 /// Cached value log_base_2(n)
Chris@16 634 size_type log_n;
Chris@16 635 };
Chris@16 636
Chris@16 637
Chris@16 638 } // end namespace boost
Chris@16 639
Chris@16 640 #if defined(BOOST_MSVC)
Chris@16 641 # pragma warning(pop)
Chris@16 642 #endif
Chris@16 643
Chris@16 644 #endif // BOOST_RELAXED_HEAP_HEADER