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 reference operator*() const noexcept {
199 switch (tag_) {
200 case Tag::Uniq: return *std::bit_cast<D* const*>(&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() { return tag_ = Tag::Null, ptr_ = 0, *this; }
211
212 private:
213 Tag tag_;
214 uintptr_t ptr_;
215
216 friend class Set;
217 };
218
219 /// @name Construction
220 ///@{
221 constexpr Set(const Set&) noexcept = default;
222 constexpr Set(Set&&) noexcept = default;
223 constexpr Set() noexcept = default; ///< Null set
224 constexpr Set(D* d) noexcept
225 : ptr_(uintptr_t(d) | uintptr_t(Tag::Uniq)) {} ///< Uniq set.
226
227 constexpr Set& operator=(const Set&) noexcept = default;
228 ///@}
229
230 /// @name Getters
231 ///@{
232 constexpr size_t size() const noexcept {
233 if (isa_uniq()) return 1;
234 if (auto d = isa_data()) return d->size;
235 if (auto n = isa_node()) return n->size;
236 return 0; // empty
237 }
238
239 /// Is empty?
240 constexpr bool empty() const noexcept {
241 assert(tag() != Tag::Node || !ptr<Node>()->is_root());
242 return ptr_ == 0;
243 }
244
245 constexpr explicit operator bool() const noexcept { return ptr_ != 0; } ///< Not empty?
246 ///@}
247
248 /// @name Check Membership
249 ///@{
250
251 /// Is @f$d \in this@f$?.
252 bool contains(D* d) const noexcept {
253 if (auto u = isa_uniq()) return d == u;
254
255 if (auto data = isa_data()) {
256 for (auto e : *data)
257 if (d == e) return true;
258 return false;
259 }
260
261 if (auto n = isa_node()) return n->contains(d);
262
263 return false;
264 }
265
266 /// Is @f$this \cap other \neq \emptyset@f$?.
267 [[nodiscard]] bool has_intersection(Set other) const noexcept {
268 if (*this == other) return true;
269 if (this->empty() || other.empty()) return false;
270
271 auto u1 = this->isa_uniq();
272 auto u2 = other.isa_uniq();
273 if (u1) return other.contains(u1);
274 if (u2) return this->contains(u2);
275
276 auto d1 = this->isa_data();
277 auto d2 = other.isa_data();
278 if (d1 && d2) {
279 for (auto ai = d1->begin(), ae = d1->end(), bi = d2->begin(), be = d2->end(); ai != ae && bi != be;) {
280 if (*ai == *bi) return true;
281
282 if ((*ai)->gid() < (*bi)->gid())
283 ++ai;
284 else
285 ++bi;
286 }
287
288 return false;
289 }
290
291 auto n1 = this->isa_node();
292 auto n2 = other.isa_node();
293 if (n1 && n2) {
294 if (n1->min > n2->def->tid() || n1->def->tid() < n2->min) return false;
295 if (n1->def == n2->def) return true;
296 if (!n1->lca(n2)->is_root()) return true;
297
298 while (!n1->is_root() && !n2->is_root()) {
299 if (n1->def->tid() > n2->def->tid()) {
300 if (n1 = n1->find(n2->def); n2->def == n1->def) return true;
301 n1 = n1->parent;
302 } else {
303 if (n2 = n2->find(n1->def); n1->def == n2->def) return true;
304 n2 = n2->parent;
305 }
306 }
307
308 return false;
309 }
310
311 auto n = n1 ? n1 : n2;
312 for (auto e : *(d1 ? d1 : d2))
313 if (n->contains(e)) return true;
314
315 return false;
316 }
317 ///@}
318
319 /// @name Iterators
320 ///@{
321 constexpr iterator begin() const noexcept {
322 if (auto u = isa_uniq()) return {u};
323 if (auto d = isa_data()) return {d->begin()};
324 if (auto n = isa_node(); n && !n->is_root()) return {n};
325 return {};
326 }
327
328 constexpr iterator end() const noexcept {
329 if (auto data = isa_data()) return iterator(data->end());
330 return {};
331 }
332 ///@}
333
334 /// @name Comparisons
335 ///@{
336 constexpr bool operator==(Set other) const noexcept { return this->ptr_ == other.ptr_; }
337 constexpr bool operator!=(Set other) const noexcept { return this->ptr_ != other.ptr_; }
338 ///@}
339
340 /// @name Output
341 ///@{
342 std::ostream& stream(std::ostream& os) const {
343 os << '{';
344 auto sep = "";
345 for (auto d : *this) {
346 os << sep << d->gid() << '/' << d->tid();
347 sep = ", ";
348 }
349 return os << '}';
350 }
351
352 void dump() const { stream(std::cout) << std::endl; }
353 ///@}
354
355 private:
356 constexpr Tag tag() const noexcept { return Tag(ptr_ & uintptr_t(0b11)); }
357 template<class T>
358 constexpr T* ptr() const noexcept {
359 return std::bit_cast<T*>(ptr_ & (uintptr_t(-2) << uintptr_t(2)));
360 }
361 // clang-format off
362 constexpr D* isa_uniq() const noexcept { return tag() == Tag::Uniq ? ptr<D >() : nullptr; }
363 constexpr Data* isa_data() const noexcept { return tag() == Tag::Data ? ptr<Data>() : nullptr; }
364 constexpr Node* isa_node() const noexcept { return tag() == Tag::Node ? ptr<Node>() : nullptr; }
365 // clang-format on
366
367 uintptr_t ptr_ = 0;
368
369 friend class Sets;
370 friend std::ostream& operator<<(std::ostream& os, Set set) { return set.stream(os); }
371 };
372
373 static_assert(std::forward_iterator<typename Set::iterator>);
374 static_assert(std::ranges::range<Set>);
375
376 /// @name Construction
377 ///@{
378 Sets& operator=(const Sets&) = delete;
379
380 constexpr Sets() noexcept
381 : root_(make_node()) {}
382 constexpr Sets(const Sets&) noexcept = delete;
383 constexpr Sets(Sets&& other) noexcept
384 : Sets() {
385 swap(*this, other);
386 }
387 ///@}
388
389 /// @name Set Operations
390 /// @note These operations do **not** modify the input set(s); they create a **new** Set.
391 ///@{
392
393 /// Create a Set wih all elements in @p v.
394 [[nodiscard]] Set create(Vector<D*> v) {
395 auto vb = v.begin();
396 auto ve = v.end();
397 std::sort(vb, ve, [](D* d1, D* d2) { return d1->gid() < d2->gid(); });
398 auto vu = std::unique(vb, ve);
399 auto size = std::distance(vb, vu);
400
401 if (size == 0) return {};
402 if (size == 1) return {*vb};
403
404 if (size_t(size) <= N) {
405 auto [data, state] = allocate(size);
406 std::copy(vb, vu, data->begin());
407 return unify(data, state);
408 }
409
410 // sort in ascending tids but 0 goes last
411 std::sort(vb, vu, [](D* d1, D* d2) { return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
412
413 auto res = root();
414 for (auto i = vb; i != vu; ++i)
415 res = insert(res, *i);
416 return res;
417 }
418
419 /// Yields @f$s \cup \{d\}@f$.
420 [[nodiscard]] Set insert(Set s, D* d) {
421 if (auto u = s.isa_uniq()) {
422 if (d == u) return {d};
423
424 auto [data, state] = allocate(2);
425 if (d->gid() < u->gid())
426 data->elems[0] = d, data->elems[1] = u;
427 else
428 data->elems[0] = u, data->elems[1] = d;
429 return unify(data, state);
430 }
431
432 if (auto src = s.isa_data()) {
433 auto size = src->size;
434 if (size + 1 <= N) {
435 auto [dst, state] = allocate(size + 1);
436
437 // copy over and insert new element d
438 bool ins = false;
439 for (auto si = src->begin(), di = dst->begin(), se = src->end(); si != se || !ins; ++di) {
440 if (si != se && d == *si) { // already here
441 data_arena_.deallocate(state);
442 return s;
443 }
444
445 if (!ins && (si == se || d->gid() < (*si)->gid()))
446 *di = d, ins = true;
447 else
448 *di = *si++;
449 }
450
451 return unify(dst, state);
452 } else { // we need to switch from Data to Node
453 auto [dst, state] = allocate(size + 1);
454
455 // copy over
456 auto di = dst->begin();
457 for (auto si = src->begin(), se = src->end(); si != se; ++si, ++di) {
458 if (d == *si) { // already here
459 data_arena_.deallocate(state);
460 return s;
461 }
462
463 *di = *si;
464 }
465 *di = d; // put new element at last into dst->elems
466
467 // sort in ascending tids but 0 goes last
468 std::sort(dst->begin(), di,
469 [](D* d1, D* d2) { return d1->tid() != 0 && (d2->tid() == 0 || d1->tid() < d2->tid()); });
470
471 auto res = root();
472 for (auto i = dst->begin(), e = dst->end(); i != e; ++i)
473 res = insert(res, *i);
474 return res;
475 }
476 }
477
478 if (auto n = s.isa_node()) {
479 if (n->contains(d)) return n;
480 return insert(n, d);
481 }
482
483 return {d};
484 }
485
486 /// Yields @f$s_1 \cup s_2@f$.
487 [[nodiscard]] Set merge(Set s1, Set s2) {
488 if (s1.empty() || s1 == s2) return s2;
489 if (s2.empty()) return s1;
490
491 if (auto u = s1.isa_uniq()) return insert(s2, u);
492 if (auto u = s2.isa_uniq()) return insert(s1, u);
493
494 auto d1 = s1.isa_data();
495 auto d2 = s2.isa_data();
496 if (d1 && d2) {
497 auto v = Vector<D*>();
498 v.reserve(d1->size + d2->size);
499
500 for (auto d : *d1)
501 v.emplace_back(d);
502 for (auto d : *d2)
503 v.emplace_back(d);
504
505 return create(std::move(v));
506 }
507
508 auto n1 = s1.isa_node();
509 auto n2 = s2.isa_node();
510 if (n1 && n2) {
511 if (n1->is_descendant_of(n2)) return n1;
512 if (n2->is_descendant_of(n1)) return n2;
513 return merge(n1, n2);
514 }
515
516 auto n = n1 ? n1 : n2;
517 for (auto d : *(d1 ? d1 : d2))
518 if (!n->contains(d)) n = insert(n, d);
519 return n;
520 }
521
522 /// Yields @f$s \setminus \{d\}@f$.
523 [[nodiscard]] Set erase(Set s, D* d) {
524 if (auto u = s.isa_uniq()) return d == u ? Set() : s;
525
526 if (auto data = s.isa_data()) {
527 size_t i = 0, size = data->size;
528 for (; i != size; ++i)
529 if (data->elems[i] == d) break;
530
531 if (i == size--) return s;
532 if (size == 0) return {};
533 if (size == 1) return {i == 0 ? data->elems[1] : data->elems[0]};
534
535 assert(size <= N);
536 auto [new_data, state] = allocate(size);
537 auto db = data->begin();
538 std::copy(db + i + 1, data->end(), std::copy(db, db + i, new_data->elems)); // copy over, skip i
539
540 return unify(new_data, state);
541 }
542
543 if (auto n = s.isa_node()) {
544 if (d->tid() == 0 || d->tid() < n->min) return n;
545 if (!n->contains(d)) return n;
546
547 auto res = erase(n, d);
548 if (res->size > N) return res;
549
550 auto v = Vector<D*>();
551 v.reserve(res->size);
552 for (auto i = res; !i->is_root(); i = i->parent)
553 v.emplace_back(i->def);
554 return create(std::move(v));
555 }
556
557 return {};
558 }
559 ///@}
560
561 /// @name DOT output
562 void dot() {
563 auto of = std::ofstream("trie.dot");
564 dot(of);
565 }
566
567 void dot(std::ostream& os) const {
568 os << "digraph {{" << std::endl;
569 os << "ordering=out;" << std::endl;
570 os << "node [shape=box,style=filled];" << std::endl;
571 root()->dot(os);
572 os << "}}" << std::endl;
573 }
574
575 friend void swap(Sets& s1, Sets& s2) noexcept {
576 using std::swap;
577 // clang-format off
578 swap(s1.data_arena_, s2.data_arena_);
579 swap(s1.node_arena_, s2.node_arena_);
580 swap(s1.pool_, s2.pool_);
581 swap(s1.root_, s2.root_);
582 swap(s1.tid_counter_, s2.tid_counter_);
583 swap(s1.id_counter_ , s2.id_counter_ );
584 // clang-format on
585 }
586
587private:
588 D* set_tid(D* def) noexcept {
589 assert(def->tid() == 0);
590 def->tid_ = tid_counter_++;
591 return def;
592 }
593
594 // get rid of clang warnings
595 template<class T>
596 inline static constexpr size_t SizeOf = sizeof(std::conditional_t<std::is_pointer_v<T>, uintptr_t, T>);
597
598 // array helpers
599 std::pair<Data*, fe::Arena::State> allocate(size_t size) {
600 auto bytes = sizeof(Data) + size * SizeOf<D>;
601 auto state = data_arena_.state();
602 auto buff = data_arena_.allocate(bytes, alignof(Data));
603 auto data = new (buff) Data(size);
604 return {data, state};
605 }
606
607 Set unify(Data* data, fe::Arena::State state, size_t excess = 0) {
608 assert(data->size != 0);
609 auto [i, ins] = pool_.emplace(data);
610 if (ins) {
611 data_arena_.deallocate(excess * SizeOf<D>); // release excess memory
612 return Set(data);
613 }
614
615 data_arena_.deallocate(state);
616 return Set(*i);
617 }
618
619 // Trie helpers
620 constexpr Node* root() const noexcept { return root_.get(); }
621 fe::Arena::Ptr<Node> make_node() { return node_arena_.mk<Node>(id_counter_++); }
622 fe::Arena::Ptr<Node> make_node(Node* parent, D* def) { return node_arena_.mk<Node>(parent, def, id_counter_++); }
623
624 [[nodiscard]] Node* mount(Node* parent, D* def) {
625 assert(def->tid() != 0);
626 auto [i, ins] = parent->children.emplace(def, nullptr);
627 if (ins) i->second = make_node(parent, def);
628 return i->second.get();
629 }
630
631 [[nodiscard]] constexpr Node* insert(Node* n, D* d) noexcept {
632 if (d->tid() == 0) return mount(n, set_tid(d));
633 if (n->def == d) return n;
634 if (n->is_root() || n->def->tid() < d->tid()) return mount(n, d);
635 return mount(insert(n->parent, d), n->def);
636 }
637
638 [[nodiscard]] constexpr Node* merge(Node* n, Node* m) {
639 if (n == m || m->is_root()) return n;
640 if (n->is_root()) return m;
641 auto nn = n->def->tid() < m->def->tid() ? n : n->parent;
642 auto mm = n->def->tid() > m->def->tid() ? m : m->parent;
643 return mount(merge(nn, mm), n->def->tid() < m->def->tid() ? m->def : n->def);
644 }
645
646 [[nodiscard]] Node* erase(Node* n, D* d) {
647 if (d->tid() > n->def->tid()) return n;
648 if (n->def == d) return n->parent;
649 return mount(erase(n->parent, d), n->def);
650 }
651
652 fe::Arena node_arena_;
653 fe::Arena data_arena_;
654 absl::flat_hash_set<const Data*, absl::Hash<const Data*>, typename Data::Equal> pool_;
655 fe::Arena::Ptr<Node> root_;
656 u32 tid_counter_ = 1;
657 u32 id_counter_ = 0;
658};
659
660} // namespace mim
constexpr iterator & operator++() noexcept
Definition sets.h:162
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:216
D *const & reference
Definition sets.h:151
constexpr reference operator*() const noexcept
Definition sets.h:198
std::forward_iterator_tag iterator_category
Definition sets.h:147
std::ptrdiff_t difference_type
Definition sets.h:148
iterator & clear()
Definition sets.h:210
constexpr iterator operator++(int) noexcept
Definition sets.h:181
constexpr bool operator==(iterator other) const noexcept
Definition sets.h:191
bool has_intersection(Set other) const noexcept
Is ?.
Definition sets.h:267
constexpr bool empty() const noexcept
Is empty?
Definition sets.h:240
constexpr bool operator==(Set other) const noexcept
Definition sets.h:336
constexpr Set() noexcept=default
Null set.
constexpr Set(const Set &) noexcept=default
friend class Sets
Definition sets.h:369
constexpr iterator begin() const noexcept
Definition sets.h:321
void dump() const
Definition sets.h:352
constexpr size_t size() const noexcept
Definition sets.h:232
friend std::ostream & operator<<(std::ostream &os, Set set)
Definition sets.h:370
std::ostream & stream(std::ostream &os) const
Definition sets.h:342
bool contains(D *d) const noexcept
Is ?.
Definition sets.h:252
constexpr Set & operator=(const Set &) noexcept=default
constexpr Set(Set &&) noexcept=default
constexpr bool operator!=(Set other) const noexcept
Definition sets.h:337
constexpr iterator end() const noexcept
Definition sets.h:328
friend void swap(Sets &s1, Sets &s2) noexcept
Definition sets.h:575
void dot()
Definition sets.h:562
void dot(std::ostream &os) const
Definition sets.h:567
Set merge(Set s1, Set s2)
Yields .
Definition sets.h:487
constexpr Sets(const Sets &) noexcept=delete
Sets & operator=(const Sets &)=delete
constexpr Sets() noexcept
Definition sets.h:380
constexpr Sets(Sets &&other) noexcept
Definition sets.h:383
Set erase(Set s, D *d)
Yields .
Definition sets.h:523
Set insert(Set s, D *d)
Yields .
Definition sets.h:420
Set create(Vector< D * > v)
Create a Set wih all elements in v.
Definition sets.h:394
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:187
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