287 D*
max() const noexcept {
return edge(
true); }
292 bool contains(D* d)
const noexcept {
return lookup(KT::key(d)) !=
nullptr; }
296 if (this->
empty() || other.empty())
return false;
297 if (*
this == other)
return true;
299 auto n1 = this->isa_br();
300 auto n2 = other.isa_br();
302 if (!n1)
return this->any_in(other);
303 if (!n2)
return other.any_in(*
this);
305 switch (rel(n1, n2)) {
307 return this->left().has_intersection(other.left()) || this->right().has_intersection(other.right());
308 case Rel::L1:
return this->left().has_intersection(other);
309 case Rel::R1:
return this->right().has_intersection(other);
312 case Rel::None:
return false;
318 [[nodiscard]]
bool subset_of(Set other)
const noexcept {
319 if (*
this == other || this->
empty())
return true;
320 if (this->
size() > other.size())
return false;
322 auto n1 = this->isa_br();
323 auto n2 = other.isa_br();
325 if (!n1)
return this->all_in(other);
326 if (!n2)
return false;
328 switch (rel(n1, n2)) {
329 case Rel::Same:
return this->left().subset_of(other.left()) && this->right().subset_of(other.right());
330 case Rel::L2:
return this->
subset_of(other.left());
331 case Rel::R2:
return this->
subset_of(other.right());
332 default:
return false;
349 }
else if (
auto d = isa_uniq()) {
352 for (
const auto& e : entries())
361 constexpr bool operator==(Set other)
const noexcept {
return this->word_ == other.word_; }
366 std::ostream&
stream(std::ostream& os)
const {
369 for (
auto d : *
this) {
371 if constexpr (
requires { KT::stream(os, d); })
382 void dot(std::ostream& os)
const {
383 std::print(os,
"digraph {{\nordering=out;\nnode [shape=box,style=filled];\n");
385 std::print(os,
"}}\n");
393 D*
lookup(K key)
const noexcept {
394 for (
auto s = *
this;;) {
395 if (
auto n = s.isa_br()) {
396 if (!match_prefix(key, n->prefix, n->mask))
return nullptr;
397 s = zero_bit(key, n->mask) ? s.left() : s.right();
398 }
else if (
auto d = s.isa_uniq()) {
399 return KT::key(d) == key ? d :
nullptr;
401 for (
const auto& e : s.entries())
402 if (e.key == key)
return e.d;
408 D* edge(
bool last)
const noexcept {
410 while (
auto n = s.isa_br())
411 s = last ? s.right() : s.left();
412 if (
auto d = s.isa_uniq())
return d;
413 auto es = s.entries();
414 return es.empty() ? nullptr : (last ? es.back().d : es.front().d);
420 bool any_in(Set other)
const noexcept {
421 if (
auto d = isa_uniq())
return other.contains(d);
422 return std::ranges::any_of(entries(), [other](
const Entry& e) {
return other.lookup(e.key); });
425 bool all_in(Set other)
const noexcept {
426 if (
auto d = isa_uniq())
return other.contains(d);
427 return std::ranges::all_of(entries(), [other](
const Entry& e) {
return other.lookup(e.key); });
433 O copy(O o)
const noexcept {
434 if (
auto d = isa_uniq())
return *o++ = Entry{KT::key(d), d}, o;
435 return std::ranges::copy(entries(), o).out;
438 static void dot(std::ostream& os, Set s) {
439 if (
auto n = s.isa_br()) {
440 std::print(os,
"n{} [label=\"{:#x}/{:#x}\"];\n", s.word_, uint64_t(n->prefix), uint64_t(n->mask));
441 for (
auto child : {s.left(), s.right()}) {
442 std::print(os,
"n{} -> n{};\n", s.word_, child.word_);
446 std::print(os,
"n{} [label=\"", s.word_);
448 std::print(os,
"\"];\n");
458 static_assert(std::forward_iterator<typename Set::iterator>);
459 static_assert(std::ranges::range<Set>);
466 : arr_arena_(page_size)
467 , br_arena_(page_size) {}
480 template<std::ranges::input_range R>
481 requires std::convertible_to<std::ranges::range_reference_t<R>, D*> [[nodiscard]]
Set create(R&& r) {
484 v.emplace_back(Entry{KT::key(d), d});
493 auto key = KT::key(d);
497 if (
auto u = s.isa_uniq()) {
499 if (k == key)
return s;
502 es[0] = Entry{key, d}, es[1] = Entry{k, u};
504 es[0] = Entry{k, u}, es[1] = Entry{key, d};
508 if (
auto n = s.isa_br()) {
509 if (!match_prefix(key, n->prefix, n->mask))
return join(s,
Set(d));
511 if (zero_bit(key, n->mask)) {
512 auto l =
insert(s.left(), d);
513 return l == s.left() ? s : br(n->prefix, n->mask, l, s.right());
516 auto r =
insert(s.right(), d);
517 return r == s.right() ? s : br(n->prefix, n->mask, s.left(), r);
520 auto es = s.entries();
521 auto i = std::ranges::lower_bound(es, key, {}, &Entry::key);
522 if (i != es.end() && i->key == key)
return s;
524 auto pos = size_t(i - es.begin());
525 auto buf = std::array<Entry, N + 1>();
526 auto o = std::ranges::copy(es.first(pos), buf.begin()).out;
527 *o++ = Entry{key, d};
528 o = std::ranges::copy(es.subspan(pos), o).out;
529 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
534 auto key = KT::key(d);
536 if (
auto u = s.isa_uniq())
return KT::key(u) == key ?
Set() : s;
538 if (
auto n = s.isa_br()) {
539 if (!match_prefix(key, n->prefix, n->mask))
return s;
541 if (zero_bit(key, n->mask)) {
542 auto l =
erase(s.left(), d);
543 return l == s.left() ? s : br(n->prefix, n->mask, l, s.right());
546 auto r =
erase(s.right(), d);
547 return r == s.right() ? s : br(n->prefix, n->mask, s.left(), r);
550 auto es = s.entries();
551 auto i = std::ranges::find(es, key, &Entry::key);
552 if (i == es.end())
return s;
554 auto pos = size_t(i - es.begin());
555 auto buf = std::array<Entry, N>();
556 auto o = std::ranges::copy(es.first(pos), buf.begin()).out;
557 o = std::ranges::copy(es.subspan(pos + 1), o).out;
558 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
563 if (s1 == s2 || s2.
empty())
return s1;
564 if (s1.
empty())
return s2;
566 auto n1 = s1.isa_br();
567 auto n2 = s2.isa_br();
569 if (!n1 && !n2)
return merge_blocks(s1, s2);
570 if (!n1)
return insert_all(s2, s1);
571 if (!n2)
return insert_all(s1, s2);
573 switch (rel(n1, n2)) {
574 case Rel::Same:
return br(n1->prefix, n1->mask,
merge(s1.left(), s2.left()),
merge(s1.right(), s2.right()));
575 case Rel::L1:
return br(n1->prefix, n1->mask,
merge(s1.left(), s2), s1.right());
576 case Rel::R1:
return br(n1->prefix, n1->mask, s1.left(),
merge(s1.right(), s2));
577 case Rel::L2:
return br(n2->prefix, n2->mask,
merge(s1, s2.left()), s2.right());
578 case Rel::R2:
return br(n2->prefix, n2->mask, s2.left(),
merge(s1, s2.right()));
579 case Rel::None:
return join(s1, s2);
586 if (s1 == s2)
return s1;
589 auto n1 = s1.isa_br();
590 auto n2 = s2.isa_br();
592 if (!n1)
return filter(s1, s2,
true);
593 if (!n2)
return filter(s2, s1,
true);
595 switch (rel(n1, n2)) {
597 return br(n1->prefix, n1->mask,
intersect(s1.left(), s2.left()),
intersect(s1.right(), s2.right()));
598 case Rel::L1:
return intersect(s1.left(), s2);
599 case Rel::R1:
return intersect(s1.right(), s2);
600 case Rel::L2:
return intersect(s1, s2.left());
601 case Rel::R2:
return intersect(s1, s2.right());
602 case Rel::None:
return {};
609 if (s1 == s2)
return {};
612 auto n1 = s1.isa_br();
613 auto n2 = s2.isa_br();
615 if (!n1)
return filter(s1, s2,
false);
616 if (!n2)
return erase_all(s1, s2);
618 switch (rel(n1, n2)) {
619 case Rel::Same:
return br(n1->prefix, n1->mask,
diff(s1.left(), s2.left()),
diff(s1.right(), s2.right()));
620 case Rel::L1:
return br(n1->prefix, n1->mask,
diff(s1.left(), s2), s1.right());
621 case Rel::R1:
return br(n1->prefix, n1->mask, s1.left(),
diff(s1.right(), s2));
622 case Rel::L2:
return diff(s1, s2.left());
623 case Rel::R2:
return diff(s1, s2.right());
624 case Rel::None:
return s1;
633 swap(p1.arr_arena_, p2.arr_arena_);
634 swap(p1.br_arena_, p2.br_arena_);
635 swap(p1.arrs_, p2.arrs_);
636 swap(p1.brs_, p2.brs_);
646 Set merge_blocks(Set s1, Set s2) {
647 if (
auto d = s1.isa_uniq())
return insert(s2, d);
648 if (
auto d = s2.isa_uniq())
return insert(s1, d);
650 auto es1 = s1.entries();
651 auto es2 = s2.entries();
652 auto buf = std::array<Entry, 2 * N>();
653 auto i1 = es1.begin(), i2 = es2.begin();
654 auto o = buf.begin();
656 while (i1 != es1.end() && i2 != es2.end())
657 if (i1->key < i2->key)
659 else if (i2->key < i1->key)
664 o = std::ranges::copy(std::ranges::subrange(i1, es1.end()), o).out;
665 o = std::ranges::copy(std::ranges::subrange(i2, es2.end()), o).out;
666 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
670 Set insert_all(Set t, Set s) {
671 if (
auto d = s.isa_uniq())
return insert(t, d);
672 for (
const auto& e : s.entries())
678 if (
auto d = s.isa_uniq())
return erase(t, d);
679 for (
const auto& e : s.entries())
686 if (
auto d = s.isa_uniq())
return other.contains(d) == in ? s :
Set();
688 auto buf = std::array<Entry, N>();
689 auto o = buf.begin();
690 for (
const auto& e : s.entries())
691 if (
bool(other.lookup(e.key)) == in) *o++ = e;
692 return make(
View<Entry>(buf.data(),
size_t(o - buf.begin())));
702 std::ranges::stable_sort(v, {}, &Entry::key);
703 auto rest = std::ranges::unique(v, {}, &Entry::key);
704 return make(
View<Entry>(v.data(),
size_t(rest.begin() - v.begin())));
709 if (es.empty())
return {};
710 if (es.size() == 1)
return Set(es.front().d);
711 if (es.size() <= N)
return arr(es);
713 auto m = branching_bit(es.front().key, es.back().key);
714 auto p = mask_of(es.front().key, m);
716 = size_t(std::ranges::partition_point(es, [m](
const Entry& e) {
return zero_bit(e.key, m); }) - es.begin());
717 return br(p, m, make(es.first(mid)), make(es.subspan(mid)));
722 auto p1 = s1.prefix();
723 auto p2 = s2.prefix();
724 auto m = branching_bit(p1, p2);
725 auto p = mask_of(p1, m);
726 return zero_bit(p1, m) ? br(p, m, s1, s2) : br(p, m, s2, s1);
730 assert(2 <= es.size() && es.size() <= N);
731 auto state = arr_arena_.state();
732 auto buff = arr_arena_.allocate(
sizeof(Arr) + es.size() *
sizeof(Entry),
alignof(Arr));
733 auto node =
new (buff) Arr(hash_entries(es), uint32_t(es.size()));
734 std::uninitialized_copy(es.begin(), es.end(), node->entries);
735 auto [i, ins] = arrs_.emplace(node);
736 if (!ins) arr_arena_.deallocate(state);
742 if (l.empty())
return r;
743 if (r.empty())
return l;
745 auto size = l.size() + r.size();
747 auto buf = std::array<Entry, N>();
748 auto o = l.copy(buf.begin());
753 auto state = br_arena_.state();
754 auto node =
new (br_arena_.allocate<Br>(1)) Br(prefix, mask, size, l.word_, r.word_);
755 auto [i, ins] = brs_.emplace(node);
756 if (!ins) br_arena_.deallocate(state);
764 static size_t hash_entries(
View<Entry> es)
noexcept {
766 for (
const auto& e : es)
772 size_t operator()(
const Arr* n)
const noexcept {
return n->hash; }
776 bool operator()(
const Arr* n1,
const Arr* n2)
const noexcept {
777 if (n1->size != n2->size)
return false;
778 for (uint32_t i = 0; i != n1->size; ++i)
779 if (n1->entries[i].d != n2->entries[i].d)
return false;
785 size_t operator()(
const Br* n)
const noexcept {
792 bool operator()(
const Br* n1,
const Br* n2)
const noexcept {
794 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 = absl::flat_hash_set<const T*, H, E>;
802 template<
class T,
class H,
class E>
803 using Pool = std::unordered_set<const T*, H, E>;
810 Pool<Arr, ArrHash, ArrEq> arrs_;
811 Pool<Br, BrHash, BrEq> brs_;