MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
sets.h
Go to the documentation of this file.
1#pragma once
2
3#include <fstream>
4
6#include "mim/util/util.h"
7#include "mim/util/vector.h"
8
9#include "fe/arena.h"
10
11namespace mim {
12
13template<class D, size_t N = 16>
14class Sets {
15private:
16 /// Trie Node.
17 class Node : public lct::Node<Node, D*> {
18 private:
19 using LCT = lct::Node<Node, D*>;
20
21 public:
22 constexpr Node(u32 id) noexcept
23 : parent(nullptr)
24 , def(nullptr)
25 , size(0)
26 , min(size_t(-1))
27 , id(id) {}
28
29 constexpr Node(Node* parent, D* def, u32 id) noexcept
30 : parent(parent)
31 , def(def)
32 , size(parent->size + 1)
33 , min(parent->def ? parent->min : def->tid())
34 , id(id) {
35 parent->link(this);
36 }
37
38 constexpr bool lt(D* d) const noexcept { return this->is_root() || this->def->tid() < d->tid(); }
39 constexpr bool eq(D* d) const noexcept { return this->def == d; }
40
41 void dot(std::ostream& os) {
42 using namespace std::string_literals;
43
44 auto node2str = [](const Node* n) {
45 return "n_"s + (n->def ? std::to_string(n->def->tid()) : "root"s) + "_"s + std::to_string(n->id);
46 };
47
48 println(os, "{} [tooltip=\"gid: {}, min: {}\"];", node2str(this), def ? def->gid() : 0, min);
49
50 for (const auto& [def, child] : children)
51 println(os, "{} -> {}", node2str(this), node2str(child.get()));
52 for (const auto& [_, child] : children)
53 child->dot(os);
54
55#if 0
56 // clang-format off
57 if (auto par = LCT::path_parent()) println(os, "{} -> {} [constraint=false,color=\"#0000ff\",style=dashed];", node2str(this), node2str(par));
58 if (auto top = aux.top ) println(os, "{} -> {} [constraint=false,color=\"#ff0000\"];", node2str(this), node2str(top));
59 if (auto bot = aux.bot ) println(os, "{} -> {} [constraint=false,color=\"#00ff00\"];", node2str(this), node2str(bot));
60 // clang-format on
61#endif
62 }
63
64 ///@name Getters
65 ///@{
66 constexpr bool is_root() const noexcept { return def == 0; }
67
68 [[nodiscard]] bool contains(D* d) noexcept {
69 auto tid = d->tid();
70 // clang-format off
71 if (tid == this->min || tid == this->def->tid()) return true;
72 if (tid < this->min || tid > this->def->tid()) return false;
73 // clang-format on
74
75 return LCT::contains(d);
76 }
77
78 using LCT::find;
79 ///@}
80
81 Node* const parent;
82 D* const def;
83 const size_t size;
84 const size_t min;
85 u32 const id;
87 };
88
89 struct Data {
90 constexpr Data() noexcept = default;
91 constexpr Data(size_t size) noexcept
92 : size(size) {}
93
94 size_t size = 0;
95 D* elems[];
96
97 struct Equal {
98 constexpr bool operator()(const Data* d1, const Data* d2) const noexcept {
99 bool res = d1->size == d2->size;
100 for (size_t i = 0, e = d1->size; res && i != e; ++i)
101 res &= d1->elems[i] == d2->elems[i];
102 return res;
103 }
104 };
105
106 /// @name Iterators
107 ///@{
108 constexpr D** begin() noexcept { return elems; }
109 constexpr D** end() noexcept { return elems + size; }
110 constexpr D* const* begin() const noexcept { return elems; }
111 constexpr D* const* end() const noexcept { return elems + size; }
112 ///@}
113
114 template<class H>
115 friend constexpr H AbslHashValue(H h, const Data* d) noexcept {
116 if (!d) return H::combine(std::move(h), 0);
117 return H::combine_contiguous(std::move(h), d->elems, d->size);
118 }
119 };
120
121public:
122 class Set {
123 private:
124 enum class Tag : uintptr_t { Null, Uniq, Data, Node };
125
126 constexpr Set(const Data* data) noexcept
127 : ptr_(uintptr_t(data) | uintptr_t(Tag::Data)) {} ///< Data Set.
128 constexpr Set(Node* node) noexcept
129 : ptr_(uintptr_t(node) | uintptr_t(Tag::Node)) {} ///< Node set.
130
131 public:
132 class iterator {
133 private:
134 constexpr iterator(D* d) noexcept
135 : tag_(Tag::Uniq)
136 , ptr_(std::bit_cast<uintptr_t>(d)) {}
137 constexpr iterator(D* const* elems) noexcept
138 : tag_(Tag::Data)
139 , ptr_(std::bit_cast<uintptr_t>(elems)) {}
140 constexpr iterator(Node* node) noexcept
141 : tag_(Tag::Node)
142 , ptr_(std::bit_cast<uintptr_t>(node)) {}
143
144 public:
145 /// @name Iterator Properties
146 ///@{
147 using iterator_category = std::forward_iterator_tag;
148 using difference_type = std::ptrdiff_t;
149 using value_type = D*;
150 using pointer = D* const*;
151 using reference = D* const&;
152 ///@}
153
154 /// @name Construction
155 ///@{
156 constexpr iterator() noexcept = default;
157 ///@}
158
159 /// @name Increment
160 /// @note These operations only change the *view* of this Set; the Set itself is **not** modified.
161 ///@{
162 constexpr iterator& operator++() noexcept {
163 // clang-format off
164 switch (tag_) {
165 case Tag::Uniq: return clear();
166 case Tag::Data: return ptr_ = std::bit_cast<uintptr_t>(std::bit_cast<D* const*>(ptr_) + 1), *this;
167 case Tag::Node: {
168 auto node = std::bit_cast<Node*>(ptr_);
169 node = node->parent;
170 if (node->is_root())
171 clear();
172 else
173 ptr_ = std::bit_cast<uintptr_t>(node);
174 return *this;
175 }
176 default: fe::unreachable();
177 }
178 // clang-format on
179 }
180
181 constexpr iterator operator++(int) noexcept {
182 auto res = *this;
183 this->operator++();
184 return res;
185 }
186 ///@}
187
188 /// @name Comparisons
189 ///@{
190 // clang-format off
191 constexpr bool operator==(iterator other) const noexcept { return this->tag_ == other.tag_ && this->ptr_ == other.ptr_; }
192 constexpr bool operator!=(iterator other) const noexcept { return this->tag_ != other.tag_ || this->ptr_ != other.ptr_; }
193 // clang-format on
194 ///@}
195
196 /// @name Dereference
197 ///@{
198 constexpr value_type operator*() const noexcept {
199 switch (tag_) {
200 case Tag::Uniq: return std::bit_cast<D*>(ptr_);
201 case Tag::Data: return *std::bit_cast<D* const*>(ptr_);
202 case Tag::Node: return std::bit_cast<Node*>(ptr_)->def;
203 default: fe::unreachable();
204 }
205 }
206
207 constexpr pointer operator->() const noexcept { return this->operator*(); }
208 ///@}
209
210 iterator& clear() noexcept {
211 tag_ = Tag::Null;
212 ptr_ = 0;
213 return *this;
214 }
215
216 private:
217 Tag tag_;
218 uintptr_t ptr_;
219
220 friend class Set;
221 };
222
223 /// @name Construction
224 ///@{
225 constexpr Set(const Set&) noexcept = default;
226 constexpr Set(Set&&) noexcept = default;
227 constexpr Set() noexcept = default; ///< Null set
228 constexpr Set(D* d) noexcept
229 : ptr_(uintptr_t(d) | uintptr_t(Tag::Uniq)) {} ///< Uniq set.
230
231 constexpr Set& operator=(const Set&) noexcept = default;
232 ///@}
233
234 /// @name Getters
235 ///@{
236 constexpr size_t size() const noexcept {
237 if (isa_uniq()) return 1;
238 if (auto d = isa_data()) return d->size;
239 if (auto n = isa_node()) return n->size;
240 return 0; // empty
241 }
242
243 /// Is empty?
244 constexpr bool empty() const noexcept {
245 assert(tag() != Tag::Node || !ptr<Node>()->is_root());
246 return ptr_ == 0;
247 }
248
249 constexpr explicit operator bool() const noexcept { return ptr_ != 0; } ///< Not empty?
250 ///@}
251
252 /// @name Check Membership
253 ///@{
254
255 /// Is @f$d \in this@f$?.
256 bool contains(D* d) const noexcept {
257 if (auto u = isa_uniq()) return d == u;
258
259 if (auto data = isa_data()) {
260 for (auto e : *data)
261 if (d == e) return true;
262 return false;
263 }
264
265 if (auto n = isa_node()) return n->contains(d);
266
267 return false;
268 }
269
270 /// Is @f$this \cap other \neq \emptyset@f$?.
271 [[nodiscard]] bool has_intersection(Set other) const noexcept {
272 if (*this == other) return true;
273 if (this->empty() || other.empty()) return false;
274
275 auto u1 = this->isa_uniq();
276 auto u2 = other.isa_uniq();
277 if (u1) return other.contains(u1);
278 if (u2) return this->contains(u2);
279
280 auto d1 = this->isa_data();
281 auto d2 = other.isa_data();
282 if (d1 && d2) {
283 for (auto ai = d1->begin(), ae = d1->end(), bi = d2->begin(), be = d2->end(); ai != ae && bi != be;) {
284 if (*ai == *bi) return true;
285
286 if ((*ai)->gid() < (*bi)->gid())
287 ++ai;
288 else
289 ++bi;
290 }
291
292 return false;
293 }
294
295 auto n1 = this->isa_node();
296 auto n2 = other.isa_node();
297 if (n1 && n2) {
298 if (n1->min > n2->def->tid() || n1->def->tid() < n2->min) return false;
299 if (n1->def == n2->def) return true;
300 if (!n1->lca(n2)->is_root()) return true;
301
302 while (!n1->is_root() && !n2->is_root()) {
303 if (n1->def->tid() > n2->def->tid()) {
304 if (n1 = n1->find(n2->def); n2->def == n1->def) return true;
305 n1 = n1->parent;
306 } else {
307 if (n2 = n2->find(n1->def); n1->def == n2->def) return true;
308 n2 = n2->parent;
309 }
310 }
311
312 return false;
313 }
314
315 auto n = n1 ? n1 : n2;
316 for (auto e : *(d1 ? d1 : d2))
317 if (n->contains(e)) return true;
318
319 return false;
320 }
321 ///@}
322
323 /// @name Iterators
324 ///@{
325 constexpr iterator begin() const noexcept {
326 if (auto u = isa_uniq()) return {u};
327 if (auto d = isa_data()) return {d->begin()};
328 if (auto n = isa_node(); n && !n->is_root()) return {n};
329 return {};
330 }
331
332 constexpr iterator end() const noexcept {
333 if (auto data = isa_data()) return iterator(data->end());
334 return {};
335 }
336 ///@}
337
338 /// @name Comparisons
339 ///@{
340 constexpr bool operator==(Set other) const noexcept { return this->ptr_ == other.ptr_; }
341 constexpr bool operator!=(Set other) const noexcept { return this->ptr_ != other.ptr_; }
342 ///@}
343
344 /// @name Output
345 ///@{
346 std::ostream& stream(std::ostream& os) const {
347 os << '{';
348 auto sep = "";
349 for (auto d : *this) {
350 os << sep << d->gid() << '/' << d->tid();
351 sep = ", ";
352 }
353 return os << '}';
354 }
355
356 void dump() const { stream(std::cout) << std::endl; }
357 ///@}
358
359 private:
360 constexpr Tag tag() const noexcept { return Tag(ptr_ & uintptr_t(0b11)); }
361 template<class T>
362 constexpr T* ptr() const noexcept {
363 return std::bit_cast<T*>(ptr_ & (uintptr_t(-2) << uintptr_t(2)));
364 }
365 // clang-format off
366 constexpr D* isa_uniq() const noexcept { return tag() == Tag::Uniq ? ptr<D >() : nullptr; }
367 constexpr Data* isa_data() const noexcept { return tag() == Tag::Data ? ptr<Data>() : nullptr; }
368 constexpr Node* isa_node() const noexcept { return tag() == Tag::Node ? ptr<Node>() : nullptr; }
369 // clang-format on
370
371 uintptr_t ptr_ = 0;
372
373 friend class Sets;
374 friend std::ostream& operator<<(std::ostream& os, Set set) { return set.stream(os); }
375 };
376
377 static_assert(std::forward_iterator<typename Set::iterator>);
378 static_assert(std::ranges::range<Set>);
379
380 /// @name Construction
381 ///@{
382 Sets& operator=(const Sets&) = delete;
383
384 constexpr Sets() noexcept
385 : root_(make_node()) {}
386 constexpr Sets(const Sets&) noexcept = delete;
387 constexpr Sets(Sets&& other) noexcept
388 : Sets() {
389 swap(*this, other);
390 }
391 ///@}
392
393 /// @name Set Operations
394 /// @note These operations do **not** modify the input set(s); they create a **new** Set.
395 ///@{
396
397 /// Create a Set wih all elements in @p v.
398 [[nodiscard]] Set create(Vector<D*> v) {
399 auto vb = v.begin();
400 auto ve = v.end();
401 std::sort(vb, ve, [](D* d1, D* d2) { return d1->gid() < d2->gid(); });
402 auto vu = std::unique(vb, ve);
403 auto size = std::distance(vb, vu);
404
405 if (size == 0) return {};
406 if (size == 1) return {*vb};
407
408 if (size_t(size) <= N) {
409 auto [data, state] = allocate(size);
410 std::copy(vb, vu, data->begin());
411 return unify(data, state);
412 }
413
414 // sort in ascending tids but 0 goes last
415 std::sort(vb, vu, [](D* d1, D* d2) { return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
416
417 auto res = root();
418 for (auto i = vb; i != vu; ++i)
419 res = insert(res, *i);
420 return res;
421 }
422
423 /// Yields @f$s \cup \{d\}@f$.
424 [[nodiscard]] Set insert(Set s, D* d) {
425 if (auto u = s.isa_uniq()) {
426 if (d == u) return {d};
427
428 auto [data, state] = allocate(2);
429 if (d->gid() < u->gid())
430 data->elems[0] = d, data->elems[1] = u;
431 else
432 data->elems[0] = u, data->elems[1] = d;
433 return unify(data, state);
434 }
435
436 if (auto src = s.isa_data()) {
437 auto size = src->size;
438 if (size + 1 <= N) {
439 auto [dst, state] = allocate(size + 1);
440
441 // copy over and insert new element d
442 bool ins = false;
443 for (auto si = src->begin(), di = dst->begin(), se = src->end(); si != se || !ins; ++di) {
444 if (si != se && d == *si) { // already here
445 data_arena_.deallocate(state);
446 return s;
447 }
448
449 if (!ins && (si == se || d->gid() < (*si)->gid()))
450 *di = d, ins = true;
451 else
452 *di = *si++;
453 }
454
455 return unify(dst, state);
456 } else { // we need to switch from Data to Node
457 auto [dst, state] = allocate(size + 1);
458
459 // copy over
460 auto di = dst->begin();
461 for (auto si = src->begin(), se = src->end(); si != se; ++si, ++di) {
462 if (d == *si) { // already here
463 data_arena_.deallocate(state);
464 return s;
465 }
466
467 *di = *si;
468 }
469 *di = d; // put new element at last into dst->elems
470
471 // sort in ascending tids but 0 goes last
472 std::sort(dst->begin(), di,
473 [](D* d1, D* d2) { return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
474
475 auto res = root();
476 for (auto i = dst->begin(), e = dst->end(); i != e; ++i)
477 res = insert(res, *i);
478 return res;
479 }
480 }
481
482 if (auto n = s.isa_node()) {
483 if (n->contains(d)) return n;
484 return insert(n, d);
485 }
486
487 return {d};
488 }
489
490 /// Yields @f$s_1 \cup s_2@f$.
491 [[nodiscard]] Set merge(Set s1, Set s2) {
492 if (s1.empty() || s1 == s2) return s2;
493 if (s2.empty()) return s1;
494
495 if (auto u = s1.isa_uniq()) return insert(s2, u);
496 if (auto u = s2.isa_uniq()) return insert(s1, u);
497
498 auto d1 = s1.isa_data();
499 auto d2 = s2.isa_data();
500 if (d1 && d2) {
501 auto v = Vector<D*>();
502 v.reserve(d1->size + d2->size);
503
504 for (auto d : *d1)
505 v.emplace_back(d);
506 for (auto d : *d2)
507 v.emplace_back(d);
508
509 return create(std::move(v));
510 }
511
512 auto n1 = s1.isa_node();
513 auto n2 = s2.isa_node();
514 if (n1 && n2) {
515 if (n1->is_descendant_of(n2)) return n1;
516 if (n2->is_descendant_of(n1)) return n2;
517 return merge(n1, n2);
518 }
519
520 auto n = n1 ? n1 : n2;
521 for (auto d : *(d1 ? d1 : d2))
522 if (!n->contains(d)) n = insert(n, d);
523 return n;
524 }
525
526 /// Yields @f$s \setminus \{d\}@f$.
527 [[nodiscard]] Set erase(Set s, D* d) {
528 if (auto u = s.isa_uniq()) return d == u ? Set() : s;
529
530 if (auto data = s.isa_data()) {
531 size_t i = 0, size = data->size;
532 for (; i != size; ++i)
533 if (data->elems[i] == d) break;
534
535 if (i == size--) return s;
536 if (size == 0) return {};
537 if (size == 1) return {i == 0 ? data->elems[1] : data->elems[0]};
538
539 assert(size <= N);
540 auto [new_data, state] = allocate(size);
541 auto db = data->begin();
542 std::copy(db + i + 1, data->end(), std::copy(db, db + i, new_data->elems)); // copy over, skip i
543
544 return unify(new_data, state);
545 }
546
547 if (auto n = s.isa_node()) {
548 if (d->tid() == 0 || d->tid() < n->min) return n;
549 if (!n->contains(d)) return n;
550
551 auto res = erase(n, d);
552 if (res->size > N) return res;
553
554 auto v = Vector<D*>();
555 v.reserve(res->size);
556 for (auto i = res; !i->is_root(); i = i->parent)
557 v.emplace_back(i->def);
558 return create(std::move(v));
559 }
560
561 return {};
562 }
563 ///@}
564
565 /// @name DOT output
566 void dot() {
567 auto of = std::ofstream("trie.dot");
568 dot(of);
569 }
570
571 void dot(std::ostream& os) const {
572 os << "digraph {{" << std::endl;
573 os << "ordering=out;" << std::endl;
574 os << "node [shape=box,style=filled];" << std::endl;
575 root()->dot(os);
576 os << "}}" << std::endl;
577 }
578
579 friend void swap(Sets& s1, Sets& s2) noexcept {
580 using std::swap;
581 // clang-format off
582 swap(s1.data_arena_, s2.data_arena_);
583 swap(s1.node_arena_, s2.node_arena_);
584 swap(s1.pool_, s2.pool_);
585 swap(s1.root_, s2.root_);
586 swap(s1.tid_counter_, s2.tid_counter_);
587 swap(s1.id_counter_ , s2.id_counter_ );
588 // clang-format on
589 }
590
591private:
592 D* set_tid(D* def) noexcept {
593 assert(def->tid() == 0);
594 def->tid_ = tid_counter_++;
595 return def;
596 }
597
598 // get rid of clang warnings
599 template<class T>
600 inline static constexpr size_t SizeOf = sizeof(std::conditional_t<std::is_pointer_v<T>, uintptr_t, T>);
601
602 // array helpers
603 std::pair<Data*, fe::Arena::State> allocate(size_t size) {
604 auto bytes = sizeof(Data) + size * SizeOf<D>;
605 auto state = data_arena_.state();
606 auto buff = data_arena_.allocate(bytes, alignof(Data));
607 auto data = new (buff) Data(size);
608 return {data, state};
609 }
610
611 Set unify(Data* data, fe::Arena::State state, size_t excess = 0) {
612 assert(data->size != 0);
613 auto [i, ins] = pool_.emplace(data);
614 if (ins) {
615 data_arena_.deallocate(excess * SizeOf<D>); // release excess memory
616 return Set(data);
617 }
618
619 data_arena_.deallocate(state);
620 return Set(*i);
621 }
622
623 // Trie helpers
624 constexpr Node* root() const noexcept { return root_.get(); }
625 fe::Arena::Ptr<Node> make_node() { return node_arena_.mk<Node>(id_counter_++); }
626 fe::Arena::Ptr<Node> make_node(Node* parent, D* def) { return node_arena_.mk<Node>(parent, def, id_counter_++); }
627
628 [[nodiscard]] Node* mount(Node* parent, D* def) {
629 assert(def->tid() != 0);
630 auto [i, ins] = parent->children.emplace(def, nullptr);
631 if (ins) i->second = make_node(parent, def);
632 return i->second.get();
633 }
634
635 [[nodiscard]] constexpr Node* insert(Node* n, D* d) noexcept {
636 if (d->tid() == 0) return mount(n, set_tid(d));
637 if (n->def == d) return n;
638 if (n->is_root() || n->def->tid() < d->tid()) return mount(n, d);
639 return mount(insert(n->parent, d), n->def);
640 }
641
642 [[nodiscard]] constexpr Node* merge(Node* n, Node* m) {
643 if (n == m || m->is_root()) return n;
644 if (n->is_root()) return m;
645 auto nn = n->def->tid() < m->def->tid() ? n : n->parent;
646 auto mm = n->def->tid() > m->def->tid() ? m : m->parent;
647 return mount(merge(nn, mm), n->def->tid() < m->def->tid() ? m->def : n->def);
648 }
649
650 [[nodiscard]] Node* erase(Node* n, D* d) {
651 if (d->tid() > n->def->tid()) return n;
652 if (n->def == d) return n->parent;
653 return mount(erase(n->parent, d), n->def);
654 }
655
656 fe::Arena node_arena_;
657 fe::Arena data_arena_;
658 absl::flat_hash_set<const Data*, absl::Hash<const Data*>, typename Data::Equal> pool_;
659 fe::Arena::Ptr<Node> root_;
660 u32 tid_counter_ = 1;
661 u32 id_counter_ = 0;
662};
663
664} // namespace mim
constexpr iterator & operator++() noexcept
Definition sets.h:162
constexpr value_type operator*() const noexcept
Definition sets.h:198
constexpr iterator() noexcept=default
D *const * pointer
Definition sets.h:150
constexpr pointer operator->() const noexcept
Definition sets.h:207
constexpr bool operator!=(iterator other) const noexcept
Definition sets.h:192
friend class Set
Definition sets.h:220
D *const & reference
Definition sets.h:151
std::forward_iterator_tag iterator_category
Definition sets.h:147
std::ptrdiff_t difference_type
Definition sets.h:148
constexpr iterator operator++(int) noexcept
Definition sets.h:181
constexpr bool operator==(iterator other) const noexcept
Definition sets.h:191
iterator & clear() noexcept
Definition sets.h:210
bool has_intersection(Set other) const noexcept
Is ?.
Definition sets.h:271
constexpr bool empty() const noexcept
Is empty?
Definition sets.h:244
constexpr bool operator==(Set other) const noexcept
Definition sets.h:340
constexpr Set() noexcept=default
Null set.
constexpr Set(const Set &) noexcept=default
friend class Sets
Definition sets.h:373
constexpr iterator begin() const noexcept
Definition sets.h:325
void dump() const
Definition sets.h:356
constexpr size_t size() const noexcept
Definition sets.h:236
friend std::ostream & operator<<(std::ostream &os, Set set)
Definition sets.h:374
std::ostream & stream(std::ostream &os) const
Definition sets.h:346
bool contains(D *d) const noexcept
Is ?.
Definition sets.h:256
constexpr Set & operator=(const Set &) noexcept=default
constexpr Set(Set &&) noexcept=default
constexpr bool operator!=(Set other) const noexcept
Definition sets.h:341
constexpr iterator end() const noexcept
Definition sets.h:332
friend void swap(Sets &s1, Sets &s2) noexcept
Definition sets.h:579
void dot()
Definition sets.h:566
void dot(std::ostream &os) const
Definition sets.h:571
Set merge(Set s1, Set s2)
Yields .
Definition sets.h:491
constexpr Sets(const Sets &) noexcept=delete
Sets & operator=(const Sets &)=delete
constexpr Sets() noexcept
Definition sets.h:384
constexpr Sets(Sets &&other) noexcept
Definition sets.h:387
Set erase(Set s, D *d)
Yields .
Definition sets.h:527
Set insert(Set s, D *d)
Yields .
Definition sets.h:424
Set create(Vector< D * > v)
Create a Set wih all elements in v.
Definition sets.h:398
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
Definition vector.h:18
This is an intrusive Link-Cut-Tree.
constexpr void link(Node *child) noexcept
Registers the edge this -> child in the aux tree.
bool contains(const D *&k) noexcept
constexpr Node * path_parent() noexcept
constexpr Node * find(const D *&k) noexcept
constexpr Node() noexcept=default
Definition ast.h:14
absl::flat_hash_map< K, V, GIDHash< K > > GIDMap
Definition util.h:195
bool u1
Definition types.h:38
uint32_t u32
Definition types.h:34
std::ostream & println(std::ostream &os, const char *fmt, Args &&... args)
As above but end with std::endl.
Definition print.h:157
Vector(I, I, A=A()) -> Vector< typename std::iterator_traits< I >::value_type, Default_Inlined_Size< typename std::iterator_traits< I >::value_type >, A >
constexpr bool operator()(const Data *d1, const Data *d2) const noexcept
Definition sets.h:98