42 using is_avalanching = void;
44 size_t operator()(D* d)
const noexcept {
return ankerl::unordered_dense::hash<uint32_t>()(K::gid(d)); }
48 using Map = ankerl::unordered_dense::map<D*, V, Hash>;
56 constexpr Node(uint32_t
id) noexcept
63 constexpr Node(Node*
parent, D* def, uint32_t
id) noexcept
72 constexpr bool lt(D* d)
const noexcept {
return this->is_root() || K::tid(this->def) < K::tid(d); }
73 constexpr bool eq(D* d)
const noexcept {
return this->def == d; }
75 void dot(std::ostream& os) {
76 using namespace std::string_literals;
78 auto node2str = [](
const Node* n) {
79 return "n_"s + (n->def ? std::to_string(K::tid(n->def)) :
"root"s) +
"_"s + std::to_string(n->id);
82 std::print(os,
"{} [tooltip=\"gid: {}, min: {}\"];\n", node2str(
this), def ? K::gid(def) : 0, min);
84 for (
const auto& [_, child] : children)
85 std::print(os,
"{} -> {}\n", node2str(
this), node2str(child.get()));
86 for (
const auto& [_, child] : children)
92 constexpr bool is_root()
const noexcept {
return def ==
nullptr; }
95 [[nodiscard]]
bool contains(D* d)
noexcept {
96 size_t tid = K::tid(d), lo = min, hi = K::tid(def);
97 if (tid == lo || tid == hi)
return true;
111 Map<Arena::Ptr<Node>> children;
115 constexpr Data(
size_t size) noexcept
122 constexpr bool operator()(
const Data* d1,
const Data* d2)
const noexcept {
123 return d1->size == d2->size && std::equal(d1->begin(), d1->end(), d2->begin());
140 constexpr D** begin() noexcept {
return elems; }
141 constexpr D** end() noexcept {
return elems + size; }
142 constexpr D*
const* begin() const noexcept {
return elems; }
143 constexpr D*
const* end() const noexcept {
return elems + size; }
147 using Pool = ankerl::unordered_dense::set<const Data*, typename Data::Hash, typename Data::Equal>;
152 enum class Tag : uintptr_t { Null, Uniq, Data, Node };
154 constexpr Set(
const Data* data) noexcept
155 : ptr_(uintptr_t(data) | uintptr_t(Tag::Data)) {}
156 constexpr Set(Node* node) noexcept
157 : ptr_(uintptr_t(node) | uintptr_t(Tag::Node)) {}
164 , ptr_(std::bit_cast<uintptr_t>(d)) {}
165 constexpr iterator(D*
const* elems) noexcept
167 , ptr_(std::bit_cast<uintptr_t>(elems)) {}
168 constexpr iterator(Node* node) noexcept
170 , ptr_(std::bit_cast<uintptr_t>(node)) {}
190 constexpr iterator& operator++() noexcept {
193 case Tag::Uniq:
return clear();
194 case Tag::Data:
return ptr_ = std::bit_cast<uintptr_t>(std::bit_cast<D* const*>(ptr_) + 1), *
this;
196 auto node = std::bit_cast<Node*>(ptr_);
201 ptr_ = std::bit_cast<uintptr_t>(node);
204 default: std::unreachable();
219 return this->tag_ == other.tag_ && this->ptr_ == other.ptr_;
227 case Tag::Uniq:
return std::bit_cast<D*>(ptr_);
228 case Tag::Data:
return *std::bit_cast<D* const*>(ptr_);
229 case Tag::Node:
return std::bit_cast<Node*>(ptr_)->def;
230 default: std::unreachable();
237 constexpr iterator&
clear() noexcept {
return *
this = {}; }
240 Tag tag_ = Tag::Null;
248 constexpr Set() noexcept = default;
249 constexpr Set(D* d) noexcept
250 : ptr_(uintptr_t(d) | uintptr_t(Tag::Uniq)) {}
255 constexpr size_t size() const noexcept {
256 if (isa_uniq())
return 1;
257 if (
auto d = isa_data())
return d->size;
258 if (
auto n = isa_node())
return n->size;
263 constexpr bool empty() const noexcept {
264 assert(tag() != Tag::Node || !ptr<Node>()->is_root());
268 constexpr explicit operator bool() const noexcept {
return !
empty(); }
276 if (
auto u = isa_uniq())
return d == u;
278 if (
auto data = isa_data()) {
280 if (d == e)
return true;
284 if (
auto n = isa_node())
return n->contains(d);
291 if (this->
empty() || other.empty())
return false;
292 if (*
this == other)
return true;
294 auto u1 = this->isa_uniq();
295 auto u2 = other.isa_uniq();
296 if (u1)
return other.contains(u1);
299 auto d1 = this->isa_data();
300 auto d2 = other.isa_data();
302 for (
auto ai = d1->begin(), ae = d1->end(), bi = d2->begin(), be = d2->end(); ai != ae && bi != be;) {
303 if (*ai == *bi)
return true;
305 if (K::gid(*ai) < K::gid(*bi))
314 auto n1 = this->isa_node();
315 auto n2 = other.isa_node();
317 if (n1->min > K::tid(n2->def) || K::tid(n1->def) < n2->min)
return false;
318 if (n1->def == n2->def)
return true;
319 if (!n1->lca(n2)->is_root())
return true;
321 while (!n1->is_root() && !n2->is_root()) {
322 if (K::tid(n1->def) > K::tid(n2->def)) {
323 if (n1 = n1->find(n2->def); n2->def == n1->def)
return true;
326 if (n2 = n2->find(n1->def); n1->def == n2->def)
return true;
334 auto n = n1 ? n1 : n2;
335 for (
auto e : *(d1 ? d1 : d2))
336 if (n->contains(e))
return true;
345 if (
auto u = isa_uniq())
return {u};
346 if (
auto d = isa_data())
return {d->begin()};
347 if (
auto n = isa_node(); n && !n->is_root())
return {n};
352 if (
auto data = isa_data())
return iterator(data->end());
359 constexpr bool operator==(Set other)
const noexcept {
return this->ptr_ == other.ptr_; }
364 std::ostream&
stream(std::ostream& os)
const {
367 for (
auto d : *
this) {
369 if constexpr (
requires { K::stream(os, d); })
382 constexpr Tag tag() const noexcept {
return Tag(ptr_ & uintptr_t(0b11)); }
384 constexpr T* ptr() const noexcept {
385 return std::bit_cast<T*>(ptr_ & ~uintptr_t(0b11));
388 constexpr D* isa_uniq() const noexcept {
return tag() == Tag::Uniq ? ptr<D >() : nullptr; }
389 constexpr Data* isa_data() const noexcept {
return tag() == Tag::Data ? ptr<Data>() : nullptr; }
390 constexpr Node* isa_node() const noexcept {
return tag() == Tag::Node ? ptr<Node>() : nullptr; }
399 static_assert(std::forward_iterator<typename Set::iterator>);
400 static_assert(std::ranges::range<Set>);
407 : root_(make_node()) {}
421 template<std::random_access_iterator I>
423 std::sort(begin, end, gid_lt);
424 auto u = std::unique(begin, end);
425 auto size = size_t(std::distance(begin, u));
427 if (size == 0)
return {};
428 if (size == 1)
return {*begin};
431 auto [data, state] = allocate(size);
432 std::copy(begin, u, data->begin());
433 return unify(data, state);
436 return create_trie(begin, u);
440 template<std::ranges::input_range R>
442 auto v =
fe::Vector<D*>(std::ranges::begin(r), std::ranges::end(r));
443 return create(v.begin(), v.end());
447 [[nodiscard]]
Set create(std::initializer_list<D*> list) {
449 return create(v.begin(), v.end());
454 if (
auto u = s.isa_uniq()) {
455 if (d == u)
return {d};
457 auto [data, state] = allocate(2);
458 if (K::gid(d) < K::gid(u))
459 data->elems[0] = d, data->elems[1] = u;
461 data->elems[0] = u, data->elems[1] = d;
462 return unify(data, state);
465 if (
auto src = s.isa_data()) {
466 auto size = src->size;
470 if (d == e)
return s;
475 auto [scratch, state] = allocate(N + 1);
476 auto o = std::copy(src->begin(), src->end(), scratch->begin());
479 auto scratch_state = data_arena_.state();
481 auto res = create_trie(scratch->begin(), o);
482 assert(scratch_state == data_arena_.state() &&
"create_trie must only draw from node_arena_");
483 data_arena_.deallocate(state);
487 auto [dst, state] = allocate(size + 1);
488 auto i = std::upper_bound(src->begin(), src->end(), d, gid_lt);
489 auto o = std::copy(src->begin(), i, dst->begin());
491 std::copy(i, src->end(), o);
492 return unify(dst, state);
495 if (
auto n = s.isa_node()) {
496 if (n->contains(d))
return n;
505 if (s1.
empty() || s1 == s2)
return s2;
506 if (s2.
empty())
return s1;
508 if (
auto u = s1.isa_uniq())
return insert(s2, u);
509 if (
auto u = s2.isa_uniq())
return insert(s1, u);
511 auto d1 = s1.isa_data();
512 auto d2 = s2.isa_data();
519 auto [data, state] = allocate(d1->size + d2->size);
520 auto i1 = d1->begin(), e1 = d1->end();
521 auto i2 = d2->begin(), e2 = d2->end();
522 auto o = data->begin();
524 while (i1 != e1 && i2 != e2) {
525 auto g1 = K::gid(*i1);
526 auto g2 = K::gid(*i2);
534 o = std::copy(i1, e1, o);
535 o = std::copy(i2, e2, o);
537 auto size = size_t(o - data->begin());
540 auto scratch_state = data_arena_.state();
542 auto res = create_trie(data->begin(), o);
543 assert(scratch_state == data_arena_.state() &&
"create_trie must only draw from node_arena_");
544 data_arena_.deallocate(state);
548 auto excess = data->size - size;
550 return unify(data, state, excess);
553 auto n1 = s1.isa_node();
554 auto n2 = s2.isa_node();
556 if (n1->is_descendant_of(n2))
return n1;
557 if (n2->is_descendant_of(n1))
return n2;
558 return merge(n1, n2);
561 auto n = n1 ? n1 : n2;
562 for (
auto d : *(d1 ? d1 : d2))
563 if (!n->contains(d)) n =
insert(n, d);
569 if (
auto u = s.isa_uniq())
return d == u ?
Set() : s;
571 if (
auto data = s.isa_data()) {
572 auto b = data->begin(), e = data->end();
573 auto i = std::find(b, e, d);
574 if (i == e)
return s;
576 auto size = data->size - 1;
577 if (size == 0)
return {};
578 if (size == 1)
return {i == b ? b[1] : b[0]};
581 auto [new_data, state] = allocate(size);
582 std::copy(i + 1, e, std::copy(b, i, new_data->begin()));
583 return unify(new_data, state);
586 if (
auto n = s.isa_node()) {
587 if (!n->contains(d))
return n;
589 auto res =
erase(n, d);
590 if (res->size > N)
return res;
592 auto v = std::array<D*, N>();
594 for (
auto i = res; !i->is_root(); i = i->parent)
596 return create(v.begin(), o);
605 auto of = std::ofstream(
"trie.dot");
609 void dot(std::ostream& os)
const {
610 std::print(os,
"digraph {{\n");
611 std::print(os,
"ordering=out;\n");
612 std::print(os,
"node [shape=box,style=filled];\n");
614 std::print(os,
"}}\n");
620 swap(s1.data_arena_, s2.data_arena_);
621 swap(s1.node_arena_, s2.node_arena_);
622 swap(s1.pool_, s2.pool_);
623 swap(s1.root_, s2.root_);
624 swap(s1.tid_counter_, s2.tid_counter_);
625 swap(s1.id_counter_ , s2.id_counter_ );
630 D* set_tid(D* d)
noexcept {
631 assert(K::tid(d) == 0);
632 K::set_tid(d, tid_counter_++);
637 static constexpr bool gid_lt(D* d1, D* d2)
noexcept {
return K::gid(d1) < K::gid(d2); }
641 std::pair<Data*, Arena::State> allocate(
size_t size) {
642 auto bytes =
sizeof(Data) + size *
sizeof(D*);
643 auto state = data_arena_.state();
644 auto buff = data_arena_.allocate(bytes,
alignof(Data));
645 auto data =
new (buff) Data(size);
646 return {data, state};
652 assert(data->size != 0);
653 auto [i, ins] = pool_.emplace(data);
655 data_arena_.deallocate(excess *
sizeof(D*));
659 data_arena_.deallocate(state);
670 [[nodiscard]]
Set create_trie(I begin, I end) {
676 std::sort(begin, end,
677 [](D* d1, D* d2) {
return K::tid(d1) != 0 && (K::tid(d2) == 0 || K::tid(d1) < K::tid(d2)); });
680 for (
auto i = begin; i != end; ++i)
686 Node* root() const noexcept {
return root_.get(); }
687 Arena::Ptr<Node> make_node() {
return node_arena_.mk<Node>(id_counter_++); }
688 Arena::Ptr<Node> make_node(Node* parent, D* def) {
return node_arena_.mk<Node>(parent, def, id_counter_++); }
690 [[nodiscard]] Node* mount(Node* parent, D* d) {
691 assert(K::tid(d) != 0);
692 auto [i, ins] = parent->children.emplace(d,
nullptr);
693 if (ins) i->second = make_node(parent, d);
694 return i->second.get();
697 [[nodiscard]] Node*
insert(Node* n, D* d) {
698 if (K::tid(d) == 0)
return mount(n, set_tid(d));
699 if (n->def == d)
return n;
700 if (n->is_root() || K::tid(n->def) < K::tid(d))
return mount(n, d);
701 return mount(
insert(n->parent, d), n->def);
704 [[nodiscard]] Node*
merge(Node* n, Node* m) {
705 if (n == m || m->is_root())
return n;
706 if (n->is_root())
return m;
707 auto nn = K::tid(n->def) < K::tid(m->def) ? n : n->parent;
708 auto mm = K::tid(n->def) > K::tid(m->def) ? m : m->parent;
709 return mount(
merge(nn, mm), K::tid(n->def) < K::tid(m->def) ? m->def : n->def);
712 [[nodiscard]] Node*
erase(Node* n, D* d) {
713 if (K::tid(d) > K::tid(n->def))
return n;
714 if (n->def == d)
return n->parent;
715 return mount(
erase(n->parent, d), n->def);
721 Arena::Ptr<Node> root_;
722 uint32_t tid_counter_ = 1;
723 uint32_t id_counter_ = 0;