285 D*
max() const noexcept {
return edge(
true); }
290 bool contains(D* d)
const noexcept {
return lookup(KT::key(d)) !=
nullptr; }
294 if (this->
empty() || other.empty())
return false;
295 if (*
this == other)
return true;
297 auto n1 = this->isa_br();
298 auto n2 = other.isa_br();
300 if (!n1)
return this->any_in(other);
301 if (!n2)
return other.any_in(*
this);
303 switch (rel(n1, n2)) {
305 return this->left().has_intersection(other.left()) || this->right().has_intersection(other.right());
306 case Rel::L1:
return this->left().has_intersection(other);
307 case Rel::R1:
return this->right().has_intersection(other);
310 case Rel::None:
return false;
316 [[nodiscard]]
bool subset_of(Set other)
const noexcept {
317 if (*
this == other || this->
empty())
return true;
318 if (this->
size() > other.size())
return false;
320 auto n1 = this->isa_br();
321 auto n2 = other.isa_br();
323 if (!n1)
return this->all_in(other);
324 if (!n2)
return false;
326 switch (rel(n1, n2)) {
327 case Rel::Same:
return this->left().subset_of(other.left()) && this->right().subset_of(other.right());
328 case Rel::L2:
return this->
subset_of(other.left());
329 case Rel::R2:
return this->
subset_of(other.right());
330 default:
return false;
346 }
else if (
auto d = isa_uniq()) {
349 for (
const auto& e : entries())
358 constexpr bool operator==(Set other)
const noexcept {
return this->word_ == other.word_; }
363 std::ostream&
stream(std::ostream& os)
const {
366 for (
auto d : *
this) {
368 if constexpr (
requires { KT::stream(os, d); })
379 void dot(std::ostream& os)
const {
380 std::print(os,
"digraph {{\nordering=out;\nnode [shape=box,style=filled];\n");
382 std::print(os,
"}}\n");
390 D*
lookup(K key)
const noexcept {
391 for (
auto s = *
this;;) {
392 if (
auto n = s.isa_br()) {
393 if (!match_prefix(key, n->prefix, n->mask))
return nullptr;
394 s = zero_bit(key, n->mask) ? s.left() : s.right();
395 }
else if (
auto d = s.isa_uniq()) {
396 return KT::key(d) == key ? d :
nullptr;
398 for (
const auto& e : s.entries())
399 if (e.key == key)
return e.d;
405 D* edge(
bool last)
const noexcept {
407 while (
auto n = s.isa_br())
408 s = last ? s.right() : s.left();
409 if (
auto d = s.isa_uniq())
return d;
410 auto es = s.entries();
411 return es.empty() ? nullptr : (last ? es.back().d : es.front().d);
417 bool any_in(Set other)
const noexcept {
418 if (
auto d = isa_uniq())
return other.contains(d);
419 return std::ranges::any_of(entries(), [other](
const Entry& e) {
return other.lookup(e.key); });
422 bool all_in(Set other)
const noexcept {
423 if (
auto d = isa_uniq())
return other.contains(d);
424 return std::ranges::all_of(entries(), [other](
const Entry& e) {
return other.lookup(e.key); });
430 O copy(O o)
const noexcept {
431 if (
auto d = isa_uniq())
return *o++ = Entry{KT::key(d), d}, o;
432 return std::ranges::copy(entries(), o).out;
435 static void dot(std::ostream& os, Set s) {
436 if (
auto n = s.isa_br()) {
437 std::print(os,
"n{} [label=\"{:#x}/{:#x}\"];\n", s.word_, uint64_t(n->prefix), uint64_t(n->mask));
438 for (
auto child : {s.left(), s.right()}) {
439 std::print(os,
"n{} -> n{};\n", s.word_, child.word_);
443 std::print(os,
"n{} [label=\"", s.word_);
445 std::print(os,
"\"];\n");
455 static_assert(std::forward_iterator<typename Set::iterator>);
456 static_assert(std::ranges::range<Set>);
463 : arr_arena_(page_size)
464 , br_arena_(page_size) {}
477 template<std::ranges::input_range R>
478 requires std::convertible_to<std::ranges::range_reference_t<R>, D*> [[nodiscard]]
Set create(R&& r) {
481 v.emplace_back(Entry{KT::key(d), d});
490 auto key = KT::key(d);
494 if (
auto u = s.isa_uniq()) {
496 if (k == key)
return s;
499 es[0] = Entry{key, d}, es[1] = Entry{k, u};
501 es[0] = Entry{k, u}, es[1] = Entry{key, d};
505 if (
auto n = s.isa_br()) {
506 if (!match_prefix(key, n->prefix, n->mask))
return join(s,
Set(d));
508 if (zero_bit(key, n->mask)) {
509 auto l =
insert(s.left(), d);
510 return l == s.left() ? s : br(n->prefix, n->mask, l, s.right());
513 auto r =
insert(s.right(), d);
514 return r == s.right() ? s : br(n->prefix, n->mask, s.left(), r);
517 auto es = s.entries();
518 auto i = std::ranges::lower_bound(es, key, {}, &Entry::key);
519 if (i != es.end() && i->key == key)
return s;
521 auto pos = size_t(i - es.begin());
522 auto buf = std::array<Entry, N + 1>();
523 auto o = std::ranges::copy(es.first(pos), buf.begin()).out;
524 *o++ = Entry{key, d};
525 o = std::ranges::copy(es.subspan(pos), o).out;
526 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
531 auto key = KT::key(d);
533 if (
auto u = s.isa_uniq())
return KT::key(u) == key ?
Set() : s;
535 if (
auto n = s.isa_br()) {
536 if (!match_prefix(key, n->prefix, n->mask))
return s;
538 if (zero_bit(key, n->mask)) {
539 auto l =
erase(s.left(), d);
540 return l == s.left() ? s : br(n->prefix, n->mask, l, s.right());
543 auto r =
erase(s.right(), d);
544 return r == s.right() ? s : br(n->prefix, n->mask, s.left(), r);
547 auto es = s.entries();
548 auto i = std::ranges::find(es, key, &Entry::key);
549 if (i == es.end())
return s;
551 auto pos = size_t(i - es.begin());
552 auto buf = std::array<Entry, N>();
553 auto o = std::ranges::copy(es.first(pos), buf.begin()).out;
554 o = std::ranges::copy(es.subspan(pos + 1), o).out;
555 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
560 if (s1 == s2 || s2.
empty())
return s1;
561 if (s1.
empty())
return s2;
563 auto n1 = s1.isa_br();
564 auto n2 = s2.isa_br();
566 if (!n1 && !n2)
return merge_blocks(s1, s2);
567 if (!n1)
return insert_all(s2, s1);
568 if (!n2)
return insert_all(s1, s2);
570 switch (rel(n1, n2)) {
571 case Rel::Same:
return br(n1->prefix, n1->mask,
merge(s1.left(), s2.left()),
merge(s1.right(), s2.right()));
572 case Rel::L1:
return br(n1->prefix, n1->mask,
merge(s1.left(), s2), s1.right());
573 case Rel::R1:
return br(n1->prefix, n1->mask, s1.left(),
merge(s1.right(), s2));
574 case Rel::L2:
return br(n2->prefix, n2->mask,
merge(s1, s2.left()), s2.right());
575 case Rel::R2:
return br(n2->prefix, n2->mask, s2.left(),
merge(s1, s2.right()));
576 case Rel::None:
return join(s1, s2);
583 if (s1 == s2)
return s1;
586 auto n1 = s1.isa_br();
587 auto n2 = s2.isa_br();
589 if (!n1)
return filter(s1, s2,
true);
590 if (!n2)
return filter(s2, s1,
true);
592 switch (rel(n1, n2)) {
594 return br(n1->prefix, n1->mask,
intersect(s1.left(), s2.left()),
intersect(s1.right(), s2.right()));
595 case Rel::L1:
return intersect(s1.left(), s2);
596 case Rel::R1:
return intersect(s1.right(), s2);
597 case Rel::L2:
return intersect(s1, s2.left());
598 case Rel::R2:
return intersect(s1, s2.right());
599 case Rel::None:
return {};
606 if (s1 == s2)
return {};
609 auto n1 = s1.isa_br();
610 auto n2 = s2.isa_br();
612 if (!n1)
return filter(s1, s2,
false);
613 if (!n2)
return erase_all(s1, s2);
615 switch (rel(n1, n2)) {
616 case Rel::Same:
return br(n1->prefix, n1->mask,
diff(s1.left(), s2.left()),
diff(s1.right(), s2.right()));
617 case Rel::L1:
return br(n1->prefix, n1->mask,
diff(s1.left(), s2), s1.right());
618 case Rel::R1:
return br(n1->prefix, n1->mask, s1.left(),
diff(s1.right(), s2));
619 case Rel::L2:
return diff(s1, s2.left());
620 case Rel::R2:
return diff(s1, s2.right());
621 case Rel::None:
return s1;
630 swap(p1.arr_arena_, p2.arr_arena_);
631 swap(p1.br_arena_, p2.br_arena_);
632 swap(p1.arrs_, p2.arrs_);
633 swap(p1.brs_, p2.brs_);
643 Set merge_blocks(Set s1, Set s2) {
644 if (
auto d = s1.isa_uniq())
return insert(s2, d);
645 if (
auto d = s2.isa_uniq())
return insert(s1, d);
647 auto es1 = s1.entries();
648 auto es2 = s2.entries();
649 auto buf = std::array<Entry, 2 * N>();
650 auto i1 = es1.begin(), i2 = es2.begin();
651 auto o = buf.begin();
653 while (i1 != es1.end() && i2 != es2.end())
654 if (i1->key < i2->key)
656 else if (i2->key < i1->key)
661 o = std::ranges::copy(std::ranges::subrange(i1, es1.end()), o).out;
662 o = std::ranges::copy(std::ranges::subrange(i2, es2.end()), o).out;
663 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
667 Set insert_all(Set t, Set s) {
668 if (
auto d = s.isa_uniq())
return insert(t, d);
669 for (
const auto& e : s.entries())
675 if (
auto d = s.isa_uniq())
return erase(t, d);
676 for (
const auto& e : s.entries())
683 if (
auto d = s.isa_uniq())
return other.contains(d) == in ? s :
Set();
685 auto buf = std::array<Entry, N>();
686 auto o = buf.begin();
687 for (
const auto& e : s.entries())
688 if (
bool(other.lookup(e.key)) == in) *o++ = e;
689 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
698 Set build(Vector<Entry>& v) {
699 std::ranges::stable_sort(v, {}, &Entry::key);
700 auto rest = std::ranges::unique(v, {}, &Entry::key);
701 return make(
View<Entry>(v.data(),
size_t(rest.begin() - v.begin())));
706 if (es.empty())
return {};
707 if (es.size() == 1)
return Set(es.front().d);
708 if (es.size() <= N)
return arr(es);
710 auto m = branching_bit(es.front().key, es.back().key);
711 auto p = mask_of(es.front().key, m);
713 = size_t(std::ranges::partition_point(es, [m](
const Entry& e) {
return zero_bit(e.key, m); }) - es.begin());
714 return br(p, m, make(es.first(mid)), make(es.subspan(mid)));
719 auto p1 = s1.prefix();
720 auto p2 = s2.prefix();
721 auto m = branching_bit(p1, p2);
722 auto p = mask_of(p1, m);
723 return zero_bit(p1, m) ? br(p, m, s1, s2) : br(p, m, s2, s1);
727 assert(2 <= es.size() && es.size() <= N);
728 auto state = arr_arena_.state();
729 auto buff = arr_arena_.allocate(
sizeof(Arr) + es.size() *
sizeof(Entry),
alignof(Arr));
730 auto node =
new (buff) Arr(hash_entries(es), uint32_t(es.size()));
731 std::uninitialized_copy(es.begin(), es.end(), node->entries);
732 auto [i, ins] = arrs_.emplace(node);
733 if (!ins) arr_arena_.deallocate(state);
739 if (l.empty())
return r;
740 if (r.empty())
return l;
742 auto size = l.size() + r.size();
744 auto buf = std::array<Entry, N>();
745 auto o = l.copy(buf.begin());
750 auto state = br_arena_.state();
751 auto node =
new (br_arena_.allocate<Br>(1)) Br(prefix, mask, size, l.word_, r.word_);
752 auto [i, ins] = brs_.emplace(node);
753 if (!ins) br_arena_.deallocate(state);
761 static size_t hash_entries(
View<Entry> es)
noexcept {
763 for (
const auto& e : es)
769 using is_avalanching = void;
771 size_t operator()(
const Arr* n)
const noexcept {
return n->hash; }
775 bool operator()(
const Arr* n1,
const Arr* n2)
const noexcept {
776 if (n1->size != n2->size)
return false;
777 for (uint32_t i = 0; i != n1->size; ++i)
778 if (n1->entries[i].d != n2->entries[i].d)
return false;
784 using is_avalanching = void;
786 size_t operator()(
const Br* n)
const noexcept {
787 return ankerl::unordered_dense::hash<std::tuple<K, K, uintptr_t, uintptr_t>>()(
788 {n->prefix, n->mask, n->l, n->r});
793 bool operator()(
const Br* n1,
const Br* n2)
const noexcept {
795 return n1->prefix == n2->prefix && n1->mask == n2->mask && n1->l == n2->l && n1->r == n2->r;
799 template<
class T,
class H,
class E>
800 using Pool = ankerl::unordered_dense::set<const T*, H, E>;
806 Pool<Arr, ArrHash, ArrEq> arrs_;
807 Pool<Br, BrHash, BrEq> brs_;