mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
ADT.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <climits>
5#include <cstdint>
6#include <iostream>
7#include <limits>
8#include <memory>
10#include <mutable/util/fn.hpp>
13#include <sstream>
14#include <string>
15#include <type_traits>
16#include <utility>
17#ifdef __BMI2__
18#include <x86intrin.h>
19#endif
20
21
22namespace m {
23
26{
27 static constexpr std::size_t CAPACITY = 64;
28
30 template<bool C>
31 struct Proxy
32 {
33 static constexpr bool Is_Const = C;
34
35 private:
36 using reference_type = std::conditional_t<Is_Const, const SmallBitset&, SmallBitset&>;
37
39 std::size_t offset_;
40
41 public:
42 Proxy(reference_type S, std::size_t offset) : S_(S), offset_(offset) { M_insist(offset_ < CAPACITY); }
43
44 operator bool() const { return (S_.bits_ >> offset_) & 0b1; }
45
46 template <bool C_ = Is_Const>
47 requires (not C_)
48 Proxy& operator=(bool val) { setbit(&S_.bits_, val, offset_); return *this; }
49
50 Proxy & operator=(const Proxy &other) {
51 static_assert(not Is_Const, "can only assign to proxy of non-const SmallBitset");
52 return operator=(bool(other));
53 }
54 };
55
56 private:
57 uint64_t bits_;
58
59 struct iterator
60 {
61 private:
62 uint64_t bits_;
63
64 public:
65 iterator(uint64_t bits) : bits_(bits) { }
66
67 bool operator==(iterator other) const { return this->bits_ == other.bits_; }
68 bool operator!=(iterator other) const { return not operator==(other); }
69
71#ifdef __BMI__
72 bits_ = _blsr_u64(bits_); // BMI1: reset lowest set bit
73#else
74 bits_ = bits_ & (bits_ - 1UL); // reset lowest set bit
75#endif
76 return *this;
77 }
78 iterator operator++(int) { auto clone = *this; operator++(); return clone; }
79
80 std::size_t operator*() const { M_insist(bits_ != 0); return std::countr_zero(bits_); }
82#ifdef __BMI__
83 return SmallBitset(_blsi_u64(bits_)); // BMI1: extract lowest set isolated bit
84#else
85 return SmallBitset(bits_ & -bits_); // extract lowest set isolated bit
86#endif
87 }
88 };
89
91 {
92 private:
93 uint64_t bits_;
94
95 public:
96 reverse_iterator(uint64_t bits) : bits_(bits) { }
97
98 bool operator==(reverse_iterator other) const { return this->bits_ == other.bits_; }
99 bool operator!=(reverse_iterator other) const { return not operator==(other); }
100
101 reverse_iterator & operator++() { bits_ = bits_ & ~(1UL << operator*()); return *this; }
102 reverse_iterator operator++(int) { auto clone = *this; operator++(); return clone; }
103
104 std::size_t operator*() const {
105 M_insist(bits_ != 0);
106 const unsigned lz = std::countl_zero(bits_);
107 return CHAR_BIT * sizeof(bits_) - 1UL - lz;
108 }
109 SmallBitset as_set() const { return SmallBitset::Singleton(operator*()); }
110 };
111
112 public:
113 SmallBitset() : bits_(0) { };
114 explicit SmallBitset(uint64_t bits) : bits_(bits) { };
115
117 static SmallBitset All(std::size_t n) {
118 M_insist(n <= CAPACITY);
119 if (n == CAPACITY) [[unlikely]]
120 return ~SmallBitset(0);
121 return SmallBitset((uint64_t(1) << n) - uint64_t(1));
122 }
123
125 static SmallBitset Singleton(std::size_t n) {
126 M_insist(n < CAPACITY);
127 return SmallBitset(uint64_t(1) << n);
128 }
129
131 Proxy<true> operator()(std::size_t offset) const { return Proxy<true>(*this, offset); }
132
134 Proxy<false> operator()(std::size_t offset) { return Proxy<false>(*this, offset); }
135
137 Proxy<true> operator[](std::size_t offset) const { return operator()(offset); }
138
140 Proxy<false> operator[](std::size_t offset) { return operator()(offset); }
141
144 Proxy<true> at(std::size_t offset) const {
145 if (offset >= CAPACITY)
146 throw m::out_of_range("offset is out of bounds");
147 return operator()(offset);
148 }
149
152 Proxy<false> at(std::size_t offset) {
153 if (offset >= CAPACITY)
154 throw m::out_of_range("offset is out of bounds");
155 return operator()(offset);
156 }
157
159 constexpr std::size_t capacity() { return CAPACITY; }
161 std::size_t size() const { return std::popcount(bits_); }
163 bool empty() const { return bits_ == 0; }
164 /* Returns `true` if this set is a singleton set, i.e. the set contains exactly one element. */
165 bool is_singleton() const { return size() == 1; }
166
168 SmallBitset hi() const {
169 unsigned lz = std::countl_zero(bits_);
170 return SmallBitset::Singleton(CHAR_BIT * sizeof(bits_) - lz - 1U);
171 }
172
173 auto begin() const { return iterator(bits_); }
174 auto cbegin() const { return begin(); }
175 auto end() const { return iterator(0); }
176 auto cend() const { return end(); }
177
178 auto rbegin() const { return reverse_iterator(bits_); }
179 auto crbegin() const { return rbegin(); }
180 auto rend() const { return reverse_iterator(0); }
181 auto crend() const { return rend(); }
182
184 explicit operator uint64_t() const { return bits_; }
185 explicit operator bool() const { return not empty(); }
186
187 bool operator==(SmallBitset other) const { return this->bits_ == other.bits_; }
188 bool operator!=(SmallBitset other) const { return not operator==(other); }
189
192
194 bool is_subset(SmallBitset other) const { return this->bits_ == (other.bits_ & this->bits_); }
195
198 M_insist(not empty());
199#ifdef __BMI__
200 return SmallBitset(_blsmsk_u64(bits_)); // BMI1: get mask up to lowest set bit
201#else
202 return SmallBitset(bits_ ^ (bits_ - 1UL)); // get mask up to lowest set bit
203#endif
204 }
205
208 M_insist(is_singleton(), "not a singleton set");
209 return SmallBitset(bits_ - 1UL);
210 }
211
213 friend SmallBitset unify(SmallBitset left, SmallBitset right) { return SmallBitset(left.bits_ | right.bits_); }
215 friend SmallBitset intersect(SmallBitset left, SmallBitset right) { return SmallBitset(left.bits_ & right.bits_); }
217 friend SmallBitset subtract(SmallBitset left, SmallBitset right) { return SmallBitset(left.bits_ & ~right.bits_); }
219 friend SmallBitset operator|(SmallBitset left, SmallBitset right) { return unify(left, right); }
221 friend SmallBitset operator&(SmallBitset left, SmallBitset right) { return intersect(left, right); }
223 friend SmallBitset operator-(SmallBitset left, SmallBitset right) { return subtract(left, right); }
224
225 SmallBitset & operator|=(SmallBitset other) { return *this = *this | other; }
226 SmallBitset & operator&=(SmallBitset other) { return *this = *this & other; }
227 SmallBitset & operator-=(SmallBitset other) { return *this = *this - other; }
228
232 SmallBitset & operator++() { M_insist(~bits_ != 0UL, "must not have all bits set"); bits_ += 1UL; return *this; }
236 SmallBitset operator++(int) { SmallBitset clone(*this); operator++(); return clone; }
237
241 SmallBitset & operator--() { M_insist(bits_, "at least one bit must be set"); bits_ -= 1UL; return *this; }
245 SmallBitset operator--(int) { SmallBitset clone(*this); operator--(); return clone; }
246
249 friend std::ostream & operator<<(std::ostream &out, SmallBitset s) {
250 for (uint64_t i = CAPACITY; i --> 0;)
251 out << s(i);
252 return out;
253 }
254
256 void print_fixed_length(std::ostream &out, std::size_t size) const {
257 for (uint64_t i = size; i --> 0;)
258 out << (*this)(i);
259 }
260
261 void dump(std::ostream &out) const;
262 void dump() const;
264};
265
267inline SmallBitset least_subset(SmallBitset S) { return SmallBitset(uint64_t(S) & -uint64_t(S)); }
268
271{
272 return SmallBitset(uint64_t(subset) - uint64_t(set)) & set;
273}
274
276template<typename T>
278{
279 using value_type = T;
280 using size_type = std::size_t;
283
284 private:
285 std::unique_ptr<value_type[]> arr_;
286 std::size_t size_;
287
288 public:
290 dyn_array() : size_(0) { }
291
293 explicit dyn_array(std::size_t size)
294 : arr_(std::make_unique<value_type[]>(size))
295 , size_(size)
296 { }
297
300 template<typename InputIt>
301 dyn_array(InputIt begin, InputIt end)
302 : dyn_array(std::distance(begin, end))
303 {
304 auto ptr = data();
305 for (auto it = begin; it != end; ++it)
306 new (ptr++) value_type(*it);
307 }
308
310 explicit dyn_array(const dyn_array &other)
311 : dyn_array(other.size())
312 {
313 for (std::size_t i = 0; i != other.size(); ++i)
314 new (&data()[i]) value_type(other[i]);
315 }
316
317 dyn_array(dyn_array&&) = default;
319
321 size_type size() const { return size_; }
322
324 const value_type * data() const { return arr_.get(); }
326 value_type * data() { return arr_.get(); }
327
329 const value_type & operator[](std::size_t pos) const {
330 M_insist(pos < size(), "index out of bounds");
331 return data()[pos];
332 }
333
335 value_type & operator[](std::size_t pos) {
336 M_insist(pos < size(), "index out of bounds");
337 return data()[pos];
338 }
339
341 const value_type & at(std::size_t pos) const {
342 if (pos >= size())
343 throw m::out_of_range("index out of bounds");
344 return (*this)[pos];
345 }
346
348 value_type & at(std::size_t pos) {
349 if (pos >= size())
350 throw m::out_of_range("index out of bounds");
351 return (*this)[pos];
352 }
353
354 iterator begin() { return data(); }
355 iterator end() { return data() + size(); }
356 const_iterator begin() const { return data(); }
357 const_iterator end() const { return data() + size(); }
358 const_iterator cbegin() const { return begin(); }
359 const_iterator cend() const { return end(); }
360
363 bool operator==(const dyn_array &other) const {
364 if (this->size() != other.size())
365 return false;
366
367 for (std::size_t i = 0; i != size(); ++i) {
368 if ((*this)[i] != other[i])
369 return false;
370 }
371
372 return true;
373 }
376 bool operator!=(const dyn_array &other) const { return not operator==(other); }
377};
378
380template<
381 typename T,
382 is_allocator Allocator = malloc_allocator
383>
385{
386 using value_type = T;
387 using size_type = std::size_t;
388 using allocator_type = Allocator;
389
391 using const_reference_type = const T&;
392
394 {
395 std::uintptr_t ptrxor_;
397 };
398
399 private:
402
404 node_type *head_ = nullptr;
406 node_type *tail_ = nullptr;
409
410 template<bool C>
412 {
413 friend struct doubly_linked_list;
414
415 static constexpr bool Is_Const = C;
416
417 using iterator_category = std::bidirectional_iterator_tag;
418 using value_type = T;
419 using difference_type = std::ptrdiff_t;
420 using pointer = std::conditional_t<Is_Const, const T*, T*>;
421 using reference = std::conditional_t<Is_Const, const T&, T&>;
422
423 private:
425 std::uintptr_t prev_;
426
427 public:
428 the_iterator(node_type *node, std::uintptr_t prev) : node_(node), prev_(prev) { }
429
431 M_insist(node_, "cannot advance a past-the-end iterator");
432 node_type *curr = node_;
433 node_ = reinterpret_cast<node_type*>(prev_ ^ node_->ptrxor_);
434 prev_ = reinterpret_cast<std::uintptr_t>(curr);
435 return *this;
436 }
437
438 the_iterator operator++(int) { the_iterator clone = *this; operator++(); return clone; }
439
441 node_type *prev = reinterpret_cast<node_type*>(prev_);
442 M_insist(prev, "cannot retreat past the beginning");
443 prev_ = prev->ptrxor_ ^ reinterpret_cast<std::uintptr_t>(node_);
444 node_ = prev;
445 return *this;
446 }
447
448 the_iterator operator--(int) { the_iterator clone = *this; operator--(); return clone; }
449
450 reference operator*() const { return node_->value_; }
451 pointer operator->() const { return &node_->value_; }
452
453 bool operator==(const the_iterator &other) const {
454 return this->node_ == other.node_ and this->prev_ == other.prev_;
455 }
456 bool operator!=(const the_iterator &other) const { return not operator==(other); }
457
458 operator the_iterator<true>() const { return the_iterator<true>(node_, prev_); }
459 };
460
461 public:
464
465 friend void swap(doubly_linked_list &first, doubly_linked_list &second) {
466 using std::swap;
467 swap(first.head_, second.head_);
468 swap(first.tail_, second.tail_);
469 swap(first.size_, second.size_);
470 swap(first.allocator_, second.allocator_);
471 }
472
473 /*----- Constructors & Destructor --------------------------------------------------------------------------------*/
475
476 template<is_allocator A = allocator_type>
478 : allocator_(std::forward<A>(allocator))
479 { }
480
481 template<typename InputIt>
484 {
485 for (auto it = begin; it != end; ++it)
486 push_back(*it);
487 }
488
490
492 insert(begin(), other.cbegin(), other.cend());
493 }
494
496
497 doubly_linked_list & operator=(doubly_linked_list other) { swap(*this, other); return *this; }
498
499 allocator_type & get_allocator() const noexcept { return allocator_; }
500
501 /*----- Element access -------------------------------------------------------------------------------------------*/
506
507 /*----- Iterators ------------------------------------------------------------------------------------------------*/
508 iterator begin() { return iterator(head_, 0); }
509 iterator end() { return iterator(nullptr, reinterpret_cast<std::uintptr_t>(tail_)); }
510 const_iterator begin() const { return const_iterator(head_, 0); }
511 const_iterator end() const { return const_iterator(nullptr, reinterpret_cast<std::uintptr_t>(tail_)); }
512 const_iterator cbegin() const { return begin(); }
513 const_iterator cend() const { return end(); }
514
515 iterator rbegin() { return iterator(tail_, 0); }
516 iterator rend() { return iterator(nullptr, reinterpret_cast<std::uintptr_t>(head_)); }
518 const_iterator rend() const { return const_iterator(nullptr, reinterpret_cast<std::uintptr_t>(head_)); }
519 const_iterator crbegin() const { return rbegin(); }
520 const_iterator crend() const { return rend(); }
521
522 /*----- Capacity -------------------------------------------------------------------------------------------------*/
523 bool empty() const { return size_ == 0; }
524 size_type size() const { return size_; }
525 size_type max_size() const { return std::numeric_limits<size_type>::max(); }
526
527 /*----- Modifiers ------------------------------------------------------------------------------------------------*/
528 template<typename... Args>
530 node_type *node = allocate_node();
531 new (&node->value_) value_type(std::forward<Args>(args)...);
532 node->ptrxor_ = pos.prev_ ^ reinterpret_cast<std::uintptr_t>(pos.node_);
533
534 node_type *prev = reinterpret_cast<node_type*>(pos.prev_);
535 if (prev)
536 prev->ptrxor_ ^= reinterpret_cast<std::uintptr_t>(pos.node_) ^ reinterpret_cast<std::uintptr_t>(node);
537 else // insert at front
538 head_ = node;
539 if (pos.node_)
540 pos.node_->ptrxor_ ^= pos.prev_ ^ reinterpret_cast<std::uintptr_t>(node);
541 else // insert at end
542 tail_ = node;
543
544 ++size_;
545 return iterator(node, pos.prev_);
546 }
547
548 template<typename... Args>
550 auto it = emplace(end(), std::forward<Args>(args)...);
551 return *it;
552 }
553
554 template<typename... Args>
556 auto it = emplace(begin(), std::forward<Args>(args)...);
557 return *it;
558 }
559
560 void push_back(const value_type &value) { emplace_back(value); }
561 void push_back(value_type &&value) { emplace_back(std::move(value)); }
562 void push_front(const value_type &value) { emplace_front(value); }
563 void push_front(value_type &&value) { emplace_front(std::move(value)); }
564
565 iterator insert(const_iterator pos, const value_type &value) { return emplace(pos, value); }
566 iterator insert(const_iterator pos, value_type &&value) { return emplace(pos, std::move(value)); }
568 iterator it(pos.node_, pos.prev_);
569 while (count--) it = insert(it, value);
570 return it;
571 }
572
573 template<typename InputIt,
574 typename = decltype(*std::declval<InputIt&>(), std::declval<InputIt&>()++, void())>
575 iterator insert(const_iterator pos, InputIt first, InputIt last) {
576 if (first == last) return iterator(pos.node_, pos.prev_);
577
578 iterator begin = insert(pos, *first++);
579 M_insist(begin != end());
581 iterator it = begin;
582 while (first != last) it = insert(++it, *first++);
583
584 return begin;
585 }
586
587 iterator insert(const_iterator pos, std::initializer_list<value_type> ilist) {
588 return insert(pos, ilist.begin(), ilist.end());
589 }
590
592 M_insist(pos.node_);
594 node_type *prev = reinterpret_cast<node_type*>(pos.prev_);
595 node_type *next = reinterpret_cast<node_type*>(pos.node_->ptrxor_ ^ pos.prev_);
596 if (prev)
597 prev->ptrxor_ ^= reinterpret_cast<std::uintptr_t>(pos.node_) ^ reinterpret_cast<std::uintptr_t>(next);
598 else // erased first node
599 head_ = next;
600 if (next)
601 next->ptrxor_ ^= reinterpret_cast<std::uintptr_t>(pos.node_) ^ reinterpret_cast<std::uintptr_t>(prev);
602 else // erased last node
603 tail_ = prev;
605 --size_;
606 return iterator(next, pos.prev_);
607 }
608
610
612 reverse();
613 value_type value = pop_front();
614 reverse();
615 return value;
616 }
617
622 value_type value = std::move(head_->value_);
623 erase(begin());
624 return value;
625 }
626
627 void clear() { while (head_) pop_front(); M_insist(size_ == 0); }
628
629 /*----- Operations -----------------------------------------------------------------------------------------------*/
630 void reverse() { std::swap(head_, tail_); }
631
632 /*----- Text -----------------------------------------------------------------------------------------------------*/
634 friend std::ostream & operator<<(std::ostream &out, const doubly_linked_list &L) {
635 if (L.empty())
636 return out << "+-+";
637
638 out << "+-> ";
639 for (auto it = L.cbegin(); it != L.cend(); ++it) {
640 if (it != L.cbegin()) out << " <-> ";
641 if constexpr (is_streamable<std::ostream&, decltype(*it)>::value)
642 out << *it;
643 else
644 out << 'o';
645 }
646 return out << " <-+";
647 }
648
649 friend std::string to_string(const doubly_linked_list &L) {
650 std::ostringstream oss;
651 oss << L;
652 return oss.str();
653 }
654
655 void dump(std::ostream &out) const { out << *this << std::endl; }
656 void dump() const { dump(std::cerr); }
658
659 private:
660 node_type * allocate_node() { return allocator_.template allocate<node_type>(); }
661 void deallocate_node(node_type *ptr) { allocator_.template deallocate<node_type>(ptr); }
662};
663
664template<typename It>
665struct range
666{
667 using iterator_type = It;
668
670 static constexpr bool reversible = requires { typename std::reverse_iterator<It>; } and
671 requires (It it) { std::make_reverse_iterator(it); };
672
673 private:
674 It begin_, end_;
675
676 public:
677 range() { }
678 range(It begin, It end) : begin_(begin), end_(end) { }
679
680 bool empty() const { return begin() == end(); }
681 std::size_t size() const { return std::distance(begin(), end()); }
682
683 It begin() const { return begin_; }
684 It end() const { return end_; }
685 It cbegin() const { return begin_; }
686 It cend() const { return end_; }
687
688 std::reverse_iterator<It> rbegin() const requires reversible { return std::make_reverse_iterator(end_); }
689 std::reverse_iterator<It> rend() const requires reversible { return std::make_reverse_iterator(begin_); }
690 std::reverse_iterator<It> crbegin() const requires reversible { return std::make_reverse_iterator(end_); }
691 std::reverse_iterator<It> crend() const requires reversible { return std::make_reverse_iterator(begin_); }
692
694 range<std::reverse_iterator<It>> reverse() const requires reversible {
695 return range<std::reverse_iterator<It>>(rbegin(), rend());
696 }
697};
698
699template<typename It, typename Fn, bool OwnsProjection = true>
701
702template<typename It, typename ReturnType, bool OwnsProjection>
703struct projecting_iterator<It, ReturnType&(It), OwnsProjection>
704{
705 using difference_type = typename It::difference_type;
706 using value_type = ReturnType;
709 using iterator_category = std::random_access_iterator_tag;
710 using projection_type = std::function<ReturnType&(It)>;
711
712 private:
713 It it_;
714 std::conditional_t<OwnsProjection, projection_type, const projection_type&> project_;
715
716 public:
717 projecting_iterator(It it, projection_type project) requires OwnsProjection : it_(it), project_(std::move(project)) { }
718 projecting_iterator(It it, const projection_type &project) requires (not OwnsProjection) : it_(it), project_(project) { }
719
720 bool operator==(projecting_iterator other) const requires requires (It it) { { it == it } -> std::same_as<bool>; } {
721 return this->it_ == other.it_;
722 }
723 bool operator!=(projecting_iterator other) const requires requires (It it) { { it != it } -> std::same_as<bool>; } {
724 return this->it_ != other.it_;
725 }
726
727 projecting_iterator & operator++() requires requires (It it) { ++it; } { ++it_; return *this; }
728 projecting_iterator operator++(int) requires requires (It it) { it++; } { return it_++; }
729
730 projecting_iterator & operator--() requires requires (It it) { --it; } { --it_; return *this; }
731 projecting_iterator operator--(int) requires requires (It it) { it--; } { return it_--; }
732
733 projecting_iterator & operator+=(int offset) requires requires (It it) { it += offset; } { it_ += offset; return *this; }
734 projecting_iterator & operator-=(int offset) requires requires (It it) { it -= offset; } { it_ -= offset; return *this; }
735
737 requires requires (It it) { { it - it } -> std::convertible_to<difference_type>; } {
738 return this->it_ - other.it_;
739 }
740
741 reference operator*() const requires requires (projection_type p, It it) { p(it); } { return project_(it_); }
742 pointer operator->() const requires requires (projection_type p, It it) { p(it); } { return &project_(it_); }
743};
744
745// class template argument deduction guides
746template<typename It, typename Fn>
748
749template<typename It, typename Fn>
750struct view;
751
752template<typename It, typename ReturnType>
753struct view<It, ReturnType&(It)>
754{
755 using iterator_type = It;
756 using projection_type = std::function<ReturnType&(It)>;
757 using projecting_iterator_type = projecting_iterator<It, ReturnType&(It), false>; // share projection by reference
758
759 private:
762
763 public:
764 view(range<It> range, projection_type project) : range_(range), project_(std::move(project)) { }
765 view(It begin, It end, projection_type project) : range_(begin, end), project_(std::move(project)) { }
766 template<typename Fn>
767 view(range<It> range, Fn &&fn) : range_(range), project_(std::forward<Fn>(fn)) { }
768 template<typename Fn>
769 view(It begin, It end, Fn &&fn) : range_(begin, end), project_(std::forward<Fn>(fn)) { }
770
771 projecting_iterator_type begin() const { return projecting_iterator_type(range_.begin(), project_); }
772 projecting_iterator_type end() const { return projecting_iterator_type(range_.end(), project_); }
773};
774
775// class template argument deduction guides
776template<typename It, typename Fn>
778template<typename It, typename Fn>
780
782template<typename T, typename Compare = std::less<T>>
784{
785 using vector_type = std::vector<T>;
786 using value_type = T;
787 using size_type = typename vector_type::size_type;
788
789 private:
790 Compare comp_;
792
793 public:
794 sorted_vector(Compare comp = Compare()) : comp_(comp) { }
795
796 auto begin() { return v_.begin(); }
797 auto end() { return v_.end(); }
798 auto begin() const { return v_.begin(); }
799 auto end() const { return v_.end(); }
800 auto cbegin() const { return v_.cbegin(); }
801 auto cend() const { return v_.cend(); }
802
804 auto empty() const { return v_.empty(); }
806 auto size() const { return v_.size(); }
808 auto reserve(size_type new_cap) { return v_.reserve(new_cap); }
809
811 bool contains(const T &value) const {
812 auto pos = std::lower_bound(begin(), end(), value, comp_);
813 return pos != end() and *pos == value;
814 }
815
817 auto insert(T value) { return v_.insert(std::lower_bound(begin(), end(), value), value, comp_); }
818
820 template<typename InsertIt>
821 void insert(InsertIt first, InsertIt last) {
822 while (first != last)
823 insert(*first++);
824 }
825};
826
830{
831 private:
833 uint64_t limit_;
834
836
837 public:
839 static GospersHack enumerate_all(uint64_t k, uint64_t n) {
840 M_insist(k <= n, "invalid enumeration");
841 M_insist(n < 64, "n exceeds range");
842 GospersHack GH;
843 GH.set_ = SmallBitset::All(k);
844 GH.limit_ = 1UL << n;
845 return GH;
846 }
849 static GospersHack enumerate_from(SmallBitset set, uint64_t n) {
850 M_insist(n < 64, "n exceeds range");
851 GospersHack GH;
852 GH.set_ = set;
853 GH.limit_ = 1UL << n;
854 M_insist(uint64_t(set) <= GH.limit_, "set exceeds the limit");
855 return GH;
856 }
857
860 const uint64_t s(set_);
861#ifdef __BMI__
862 const uint64_t c = _blsi_u64(s); // BMI1: extract lowest set isolated bit -> c is a power of 2
863#else
864 const uint64_t c = s & -s; // extract lowest set isolated bit -> c is a power of 2
865#endif
866 const uint64_t r = s + c; // flip lowest block of 1-bits and following 0-bit
867 const uint64_t m = r ^ s; // mask flipped bits, i.e. lowest block of 1-bits and following 0-bit
868#ifdef __BMI2__
869 const uint64_t l = _pext_u64(m, m); // BMI2: deposit all set bits in the low bits
870#else
871 const uint64_t l = (1UL << __builtin_popcount(m)) - 1UL; // deposit all set bits in the low bits
872#endif
873 set_ = SmallBitset((l >> 2U) | r); // instead of divide by c, rshift by log2(c)
874 return *this;
875 }
876
878 operator bool() const { return uint64_t(set_) < limit_; }
879
882};
883
886{
887 private:
892
893 public:
894 SubsetEnumerator(SmallBitset set, uint64_t size)
895 : set_(set)
896 , GH_(GospersHack::enumerate_all(size, set.size()))
897 {
898 M_insist(size <= set.size());
899 }
900
901 SubsetEnumerator & operator++() { ++GH_; return *this; }
902 operator bool() const { return bool(GH_); }
904 auto gh_set = *GH_;
905 return SmallBitset(_pdep_u64(uint64_t(gh_set), uint64_t(set_)));
906 }
907};
908
909}
struct @5 args
Check whether.
Definition: concepts.hpp:39
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
bool M_EXPORT subset(const Container &subset, const Set &set)
Checks whether subset is a subset of set.
Definition: fn.hpp:406
T(x)
SmallBitset least_subset(SmallBitset S)
Returns the least subset of a given set, i.e. the set represented by the lowest 1 bit.
Definition: ADT.hpp:267
and
Definition: enum_ops.hpp:12
void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
Definition: fn.hpp:442
SmallBitset next_subset(SmallBitset subset, SmallBitset set)
Returns the next subset of a given subset and `set.
Definition: ADT.hpp:270
STL namespace.
Enumerate all subsets of size k based on superset of size n.
Definition: ADT.hpp:830
static GospersHack enumerate_from(SmallBitset set, uint64_t n)
Create an instance of GospersHack that enumerates all remaining subsets of a set of n elements,...
Definition: ADT.hpp:849
static GospersHack enumerate_all(uint64_t k, uint64_t n)
Create an instance of GospersHack that enumerates all subsets of size k of a set of n elements.
Definition: ADT.hpp:839
SmallBitset operator*() const
Returns the current subset.
Definition: ADT.hpp:881
GospersHack & operator++()
Advance to the next subset.
Definition: ADT.hpp:859
uint64_t limit_
Definition: ADT.hpp:833
SmallBitset set_
Definition: ADT.hpp:832
A proxy to access single elements in SmallBitset.
Definition: ADT.hpp:32
Proxy & operator=(bool val)
Definition: ADT.hpp:48
std::size_t offset_
Definition: ADT.hpp:39
std::conditional_t< Is_Const, const SmallBitset &, SmallBitset & > reference_type
Definition: ADT.hpp:36
reference_type S_
Definition: ADT.hpp:38
Proxy & operator=(const Proxy &other)
Definition: ADT.hpp:50
static constexpr bool Is_Const
Definition: ADT.hpp:33
Proxy(reference_type S, std::size_t offset)
Definition: ADT.hpp:42
SmallBitset as_set() const
Definition: ADT.hpp:81
bool operator!=(iterator other) const
Definition: ADT.hpp:68
std::size_t operator*() const
Definition: ADT.hpp:80
iterator(uint64_t bits)
Definition: ADT.hpp:65
iterator & operator++()
Definition: ADT.hpp:70
bool operator==(iterator other) const
Definition: ADT.hpp:67
iterator operator++(int)
Definition: ADT.hpp:78
reverse_iterator & operator++()
Definition: ADT.hpp:101
bool operator!=(reverse_iterator other) const
Definition: ADT.hpp:99
std::size_t operator*() const
Definition: ADT.hpp:104
SmallBitset as_set() const
Definition: ADT.hpp:109
bool operator==(reverse_iterator other) const
Definition: ADT.hpp:98
reverse_iterator(uint64_t bits)
Definition: ADT.hpp:96
reverse_iterator operator++(int)
Definition: ADT.hpp:102
Implements a small and efficient set over integers in the range of 0 to 63 (including).
Definition: ADT.hpp:26
bool is_singleton() const
Definition: ADT.hpp:165
void print_fixed_length(std::ostream &out, std::size_t size) const
Print a textual representation of this with size bits to out.
Definition: ADT.hpp:256
SmallBitset hi() const
Returns the highest set bit as a SmallBitset.
Definition: ADT.hpp:168
void dump() const
Definition: ADT.cpp:8
Proxy< true > operator()(std::size_t offset) const
Returns the offset-th bit.
Definition: ADT.hpp:131
constexpr std::size_t capacity()
Returns the maximum capacity.
Definition: ADT.hpp:159
friend SmallBitset operator|(SmallBitset left, SmallBitset right)
Returns the union of left and right, i.e. left ∪ right.
Definition: ADT.hpp:219
M_LCOV_EXCL_START friend std::ostream & operator<<(std::ostream &out, SmallBitset s)
Write a textual representation of s to out.
Definition: ADT.hpp:249
SmallBitset(uint64_t bits)
Definition: ADT.hpp:114
auto rend() const
Definition: ADT.hpp:180
SmallBitset mask_to_lo() const
Returns a mask up to and including the lowest set bit.
Definition: ADT.hpp:197
bool operator!=(SmallBitset other) const
Definition: ADT.hpp:188
auto cend() const
Definition: ADT.hpp:176
auto rbegin() const
Definition: ADT.hpp:178
Proxy< false > at(std::size_t offset)
Returns a proxy to the bit at offset offset.
Definition: ADT.hpp:152
SmallBitset operator~() const
Inverts all bits in the bitset.
Definition: ADT.hpp:191
friend SmallBitset operator-(SmallBitset left, SmallBitset right)
Returns the set where the elements of right have been subtracted from left, i.e. left - right.
Definition: ADT.hpp:223
friend SmallBitset operator&(SmallBitset left, SmallBitset right)
Returns the intersection of left and right, i.e. left ∩ right.
Definition: ADT.hpp:221
SmallBitset & operator++()
Treat this SmallBitset as an element of the power set of 2^n bits, where n is the number of bits that...
Definition: ADT.hpp:232
SmallBitset & operator|=(SmallBitset other)
Definition: ADT.hpp:225
static SmallBitset All(std::size_t n)
Factory method for creating a SmallBitset with first n bits set.
Definition: ADT.hpp:117
auto cbegin() const
Definition: ADT.hpp:174
SmallBitset & operator&=(SmallBitset other)
Definition: ADT.hpp:226
std::size_t size() const
Returns the number of elements in this SmallBitset.
Definition: ADT.hpp:161
Proxy< true > at(std::size_t offset) const
Returns a proxy to the bit at offset offset.
Definition: ADT.hpp:144
friend SmallBitset subtract(SmallBitset left, SmallBitset right)
Returns the set where the elements of right have been subtracted from left, i.e. left - right.
Definition: ADT.hpp:217
bool empty() const
Returns true if there are no elements in this SmallBitset.
Definition: ADT.hpp:163
auto end() const
Definition: ADT.hpp:175
auto crbegin() const
Definition: ADT.hpp:179
friend SmallBitset intersect(SmallBitset left, SmallBitset right)
Returns the intersection of left and right, i.e. left ∩ right.
Definition: ADT.hpp:215
Proxy< false > operator()(std::size_t offset)
Returns the offset-th bit.
Definition: ADT.hpp:134
static SmallBitset Singleton(std::size_t n)
Factory method for creating a Singleton Smallbitset with n -th bit set.
Definition: ADT.hpp:125
SmallBitset operator--(int)
Treat this SmallBitset as an element of the power set of 2^n bits, where n is the number of bits that...
Definition: ADT.hpp:245
auto begin() const
Definition: ADT.hpp:173
Proxy< false > operator[](std::size_t offset)
Returns the offset-th bit.
Definition: ADT.hpp:140
auto crend() const
Definition: ADT.hpp:181
Proxy< true > operator[](std::size_t offset) const
Returns the offset-th bit.
Definition: ADT.hpp:137
SmallBitset & operator--()
Treat this SmallBitset as an element of the power set of 2^n bits, where n is the number of bits that...
Definition: ADT.hpp:241
bool operator==(SmallBitset other) const
Definition: ADT.hpp:187
uint64_t bits_
the bit vector representing the set
Definition: ADT.hpp:57
friend SmallBitset unify(SmallBitset left, SmallBitset right)
Returns the union of left and right, i.e. left ∪ right.
Definition: ADT.hpp:213
SmallBitset operator++(int)
Treat this SmallBitset as an element of the power set of 2^n bits, where n is the number of bits that...
Definition: ADT.hpp:236
SmallBitset singleton_to_lo_mask() const
Converts a singleton set to a mask up to – but not including – the single, set bit.
Definition: ADT.hpp:207
SmallBitset & operator-=(SmallBitset other)
Definition: ADT.hpp:227
static constexpr std::size_t CAPACITY
the maximum capacity of a SmallBitset
Definition: ADT.hpp:27
bool is_subset(SmallBitset other) const
Returns true if the set represented by this is a subset of other, i.e. this ⊆ other.
Definition: ADT.hpp:194
This class efficiently enumerates all subsets of a given size.
Definition: ADT.hpp:886
SmallBitset operator*() const
Definition: ADT.hpp:903
SubsetEnumerator & operator++()
Definition: ADT.hpp:901
GospersHack GH_
‍used to enumerate the power set of numbers 0 to n-1
Definition: ADT.hpp:891
SubsetEnumerator(SmallBitset set, uint64_t size)
Definition: ADT.hpp:894
SmallBitset set_
‍the set to compute the power set of
Definition: ADT.hpp:889
std::bidirectional_iterator_tag iterator_category
Definition: ADT.hpp:417
the_iterator operator++(int)
Definition: ADT.hpp:438
the_iterator(node_type *node, std::uintptr_t prev)
Definition: ADT.hpp:428
the_iterator & operator--()
Definition: ADT.hpp:440
the_iterator operator--(int)
Definition: ADT.hpp:448
reference operator*() const
Definition: ADT.hpp:450
the_iterator & operator++()
Definition: ADT.hpp:430
bool operator==(const the_iterator &other) const
Definition: ADT.hpp:453
std::ptrdiff_t difference_type
Definition: ADT.hpp:419
bool operator!=(const the_iterator &other) const
Definition: ADT.hpp:456
std::conditional_t< Is_Const, const T &, T & > reference
Definition: ADT.hpp:421
static constexpr bool Is_Const
Definition: ADT.hpp:415
Implements a doubly-linked list with an overhead of just a single pointer per element.
Definition: ADT.hpp:385
const_reference_type front() const
Definition: ADT.hpp:503
Allocator allocator_type
Definition: ADT.hpp:388
const_iterator crend() const
Definition: ADT.hpp:520
void push_back(const value_type &value)
Definition: ADT.hpp:560
size_type size_
‍the number of elements/nodes in the list
Definition: ADT.hpp:408
node_type * allocate_node()
Definition: ADT.hpp:660
allocator_type & get_allocator() const noexcept
Definition: ADT.hpp:499
doubly_linked_list(const doubly_linked_list &other)
Definition: ADT.hpp:491
doubly_linked_list(InputIt begin, InputIt end, allocator_type &&allocator=allocator_type())
Definition: ADT.hpp:482
iterator rend()
Definition: ADT.hpp:516
M_LCOV_EXCL_START friend std::ostream & operator<<(std::ostream &out, const doubly_linked_list &L)
Definition: ADT.hpp:634
iterator rbegin()
Definition: ADT.hpp:515
iterator insert(const_iterator pos, size_type count, const value_type &value)
Definition: ADT.hpp:567
const_iterator rend() const
Definition: ADT.hpp:518
iterator erase(iterator pos)
Definition: ADT.hpp:591
const_iterator begin() const
Definition: ADT.hpp:510
the_iterator< true > const_iterator
Definition: ADT.hpp:463
value_type pop_back()
Definition: ADT.hpp:611
void deallocate_node(node_type *ptr)
Definition: ADT.hpp:661
iterator erase(const_iterator pos)
Definition: ADT.hpp:609
const_iterator rbegin() const
Definition: ADT.hpp:517
reference_type front()
Definition: ADT.hpp:502
friend void swap(doubly_linked_list &first, doubly_linked_list &second)
Definition: ADT.hpp:465
doubly_linked_list(A &&allocator)
Definition: ADT.hpp:477
const_iterator cend() const
Definition: ADT.hpp:513
size_type size() const
Definition: ADT.hpp:524
iterator begin()
Definition: ADT.hpp:508
node_type * tail_
‍points to the last node
Definition: ADT.hpp:406
const_reference_type back() const
Definition: ADT.hpp:505
iterator insert(const_iterator pos, const value_type &value)
Definition: ADT.hpp:565
doubly_linked_list & operator=(doubly_linked_list other)
Definition: ADT.hpp:497
void push_front(const value_type &value)
Definition: ADT.hpp:562
iterator insert(const_iterator pos, value_type &&value)
Definition: ADT.hpp:566
void push_front(value_type &&value)
Definition: ADT.hpp:563
const T & const_reference_type
Definition: ADT.hpp:391
doubly_linked_list(doubly_linked_list &&other)
Definition: ADT.hpp:495
size_type max_size() const
Definition: ADT.hpp:525
iterator emplace(const_iterator pos, Args &&... args)
Definition: ADT.hpp:529
void push_back(value_type &&value)
Definition: ADT.hpp:561
iterator end()
Definition: ADT.hpp:509
friend std::string to_string(const doubly_linked_list &L)
Definition: ADT.hpp:649
reference_type back()
Definition: ADT.hpp:504
node_type * head_
‍points to the first node
Definition: ADT.hpp:404
iterator insert(const_iterator pos, std::initializer_list< value_type > ilist)
Definition: ADT.hpp:587
bool empty() const
Definition: ADT.hpp:523
const_iterator end() const
Definition: ADT.hpp:511
value_type pop_front()
Definition: ADT.hpp:618
const_iterator crbegin() const
Definition: ADT.hpp:519
const_iterator cbegin() const
Definition: ADT.hpp:512
reference_type emplace_back(Args &&... args)
Definition: ADT.hpp:549
void dump() const
Definition: ADT.hpp:656
reference_type emplace_front(Args &&... args)
Definition: ADT.hpp:555
std::size_t size_type
Definition: ADT.hpp:387
the_iterator< false > iterator
Definition: ADT.hpp:462
iterator insert(const_iterator pos, InputIt first, InputIt last)
Definition: ADT.hpp:575
void dump(std::ostream &out) const
Definition: ADT.hpp:655
allocator_type allocator_
‍the memory allocator
Definition: ADT.hpp:401
Implements an array of dynamic but fixed size.
Definition: ADT.hpp:278
value_type & at(std::size_t pos)
Returns a reference to the element at position pos.
Definition: ADT.hpp:348
const_iterator end() const
Definition: ADT.hpp:357
dyn_array(dyn_array &&)=default
iterator end()
Definition: ADT.hpp:355
std::size_t size_
Definition: ADT.hpp:286
value_type & operator[](std::size_t pos)
Returns a reference to the element at position pos.
Definition: ADT.hpp:335
bool operator!=(const dyn_array &other) const
Returns false iff the contents of this and other are equal, that is, they have the same number of ele...
Definition: ADT.hpp:376
const value_type * const_iterator
Definition: ADT.hpp:282
const value_type & at(std::size_t pos) const
Returns a reference to the element at position pos.
Definition: ADT.hpp:341
const value_type * data() const
Returns a pointer to the beginning of the array.
Definition: ADT.hpp:324
value_type * iterator
Definition: ADT.hpp:281
dyn_array & operator=(dyn_array &&)=default
std::unique_ptr< value_type[]> arr_
Definition: ADT.hpp:285
dyn_array(const dyn_array &other)
Copy-constructs an array.
Definition: ADT.hpp:310
dyn_array(std::size_t size)
Constructs an array of size size.
Definition: ADT.hpp:293
iterator begin()
Definition: ADT.hpp:354
const value_type & operator[](std::size_t pos) const
Returns a reference to the element at position pos.
Definition: ADT.hpp:329
const_iterator cend() const
Definition: ADT.hpp:359
std::size_t size_type
Definition: ADT.hpp:280
size_type size() const
Returns the size of this array, i.e.
Definition: ADT.hpp:321
T value_type
Definition: ADT.hpp:279
value_type * data()
Returns a pointer to the beginning of the array.
Definition: ADT.hpp:326
dyn_array()
Constructs an array of size 0.
Definition: ADT.hpp:290
const_iterator begin() const
Definition: ADT.hpp:356
dyn_array(InputIt begin, InputIt end)
Constructs an array with the elements in range [begin, end).
Definition: ADT.hpp:301
bool operator==(const dyn_array &other) const
Returns true iff the contents of this and other are equal, that is, they have the same number of elem...
Definition: ADT.hpp:363
const_iterator cbegin() const
Definition: ADT.hpp:358
Signals that an index-based or key-based access was out of range.
Definition: exception.hpp:43
std::conditional_t< OwnsProjection, projection_type, const projection_type & > project_
Definition: ADT.hpp:714
bool operator==(projecting_iterator other) const
Definition: ADT.hpp:720
std::function< ReturnType &(It)> projection_type
Definition: ADT.hpp:710
projecting_iterator(It it, const projection_type &project)
Definition: ADT.hpp:718
bool operator!=(projecting_iterator other) const
Definition: ADT.hpp:723
difference_type operator-(projecting_iterator other) const
Definition: ADT.hpp:736
projecting_iterator(It it, projection_type project)
Definition: ADT.hpp:717
std::reverse_iterator< It > crend() const
Definition: ADT.hpp:691
It iterator_type
Definition: ADT.hpp:667
std::reverse_iterator< It > rbegin() const
Definition: ADT.hpp:688
bool empty() const
Definition: ADT.hpp:680
std::size_t size() const
Definition: ADT.hpp:681
It cbegin() const
Definition: ADT.hpp:685
range< std::reverse_iterator< It > > reverse() const
Returns this range reversed.
Definition: ADT.hpp:694
It cend() const
Definition: ADT.hpp:686
std::reverse_iterator< It > rend() const
Definition: ADT.hpp:689
It begin() const
Definition: ADT.hpp:683
range()
Definition: ADT.hpp:677
range(It begin, It end)
Definition: ADT.hpp:678
std::reverse_iterator< It > crbegin() const
Definition: ADT.hpp:690
It begin_
Definition: ADT.hpp:674
It end() const
Definition: ADT.hpp:684
A sorted list of elements.
Definition: ADT.hpp:784
bool contains(const T &value) const
Returns true iff this sorted_vector contains an element that is equal to value.
Definition: ADT.hpp:811
vector_type v_
the internal container of elements
Definition: ADT.hpp:791
auto end() const
Definition: ADT.hpp:799
auto cbegin() const
Definition: ADT.hpp:800
std::vector< T > vector_type
the type of the internal container of elements
Definition: ADT.hpp:785
auto begin() const
Definition: ADT.hpp:798
void insert(InsertIt first, InsertIt last)
Inserts elements in the range from first (including) to last (excluding) into this `sorted_vector.
Definition: ADT.hpp:821
sorted_vector(Compare comp=Compare())
Definition: ADT.hpp:794
auto reserve(size_type new_cap)
Reserves space for new_cap elements in this sorted_vector.
Definition: ADT.hpp:808
auto empty() const
Returns true iff the sorted_vector has no elements.
Definition: ADT.hpp:804
typename vector_type::size_type size_type
Definition: ADT.hpp:787
auto begin()
Definition: ADT.hpp:796
auto cend() const
Definition: ADT.hpp:801
auto insert(T value)
Inserts value into this sorted_vector.
Definition: ADT.hpp:817
auto size() const
Returns the number of elements in this sorted_vector.
Definition: ADT.hpp:806
Compare comp_
Definition: ADT.hpp:790
auto end()
Definition: ADT.hpp:797
view(It begin, It end, Fn &&fn)
Definition: ADT.hpp:769
view(range< It > range, Fn &&fn)
Definition: ADT.hpp:767
projecting_iterator_type begin() const
Definition: ADT.hpp:771
std::function< ReturnType &(It)> projection_type
Definition: ADT.hpp:756
view(range< It > range, projection_type project)
Definition: ADT.hpp:764
view(It begin, It end, projection_type project)
Definition: ADT.hpp:765
projection_type project_
Definition: ADT.hpp:761
projecting_iterator_type end() const
Definition: ADT.hpp:772
Definition: ADT.hpp:750