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