1 /* Copyright (c) 1997-2021
2    Ewgenij Gawrilow, Michael Joswig, and the polymake team
3    Technische Universität Berlin, Germany
4    https://polymake.org
5 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version: http://www.gnu.org/licenses/gpl.txt.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 --------------------------------------------------------------------------------
16 */
17 
18 #pragma once
19 /** @file Set.h
20     @brief Implementation of pm::Set class
21 */
22 
23 
24 
25 #include "polymake/internal/AVL.h"
26 #include "polymake/internal/tree_containers.h"
27 #include "polymake/internal/shared_object.h"
28 #include "polymake/internal/converters.h"
29 #include "polymake/IndexedSubset.h"
30 #include "polymake/SelectedSubset.h"
31 
32 namespace pm {
33 
34 template <typename SetRef, cmp_value direction>
35 class TruncatedSet
36    : public GenericSet< TruncatedSet<SetRef,direction>,
37                         typename deref<SetRef>::type::element_type, typename deref<SetRef>::type::element_comparator > {
38 public:
39    using value_type = typename container_traits<SetRef>::value_type;
40    using const_reference = typename container_traits<SetRef>::const_reference;
41    using reference = const_reference;
42    using container_category = bidirectional_iterator_tag;
43 protected:
44    using alias_t = alias<SetRef>;
45    alias_t set;
46    value_type limit;
47 
48    decltype(auto) get_set() const { return *set; }
49 public:
50    template <typename Arg, typename = std::enable_if_t<std::is_constructible<alias_t, Arg>::value>>
51    TruncatedSet(Arg&& set_arg, const value_type& lim_arg)
52       : set(std::forward<Arg>(set_arg))
53       , limit(lim_arg) {}
54 
55    decltype(auto) get_comparator() const { return get_set().get_comparator(); }
56 
57 protected:
58    using set_iterator = typename container_traits<SetRef>::const_iterator;
59    using set_reverse_iterator = typename container_traits<SetRef>::const_reverse_iterator;
60    using trunc_base = std::conditional_t<direction==cmp_lt, set_iterator, set_reverse_iterator>;
61    using range_base = std::conditional_t<direction==cmp_gt, set_iterator, set_reverse_iterator>;
62 
63    class predicate {
64       value_type limit;
65       typename deref<SetRef>::type::element_comparator cmp;
66    public:
67       typedef value_type argument_type;
68       typedef bool result_type;
69 
70       predicate(const value_type& lim_arg=value_type()) : limit(lim_arg) {}
71 
72       result_type operator() (const value_type& i) const
73       {
74          return cmp(i, limit)==direction;
75       }
76    };
77 
78    using trunc_it = input_truncator<trunc_base, predicate>;
79    using range_it = std::conditional_t<check_iterator_feature<range_base, end_sensitive>::value, range_base, iterator_range<range_base>>;
80 
81 public:
82    using iterator = std::conditional_t<direction==cmp_lt, trunc_it, range_it>;
83    using const_iterator = iterator ;
84    using reverse_iterator = std::conditional_t<direction==cmp_gt, trunc_it, range_it>;
85    using const_reverse_iterator = reverse_iterator;
86 protected:
87    template <typename TEnd_sensitive>
88    iterator begin_impl(int_constant<cmp_lt>, TEnd_sensitive) const
89    {
90       return iterator(get_set().begin(), predicate(limit));
91    }
92    iterator end_impl(int_constant<cmp_lt>) const
93    {
94       return iterator(get_set().find_nearest(limit, polymake::operations::ge()), predicate(limit));
95    }
96    reverse_iterator rbegin_impl(int_constant<cmp_lt>, std::false_type) const
97    {
98       return reverse_iterator(get_set().find_nearest(limit, polymake::operations::lt()), get_set().rend());
99    }
100    reverse_iterator rbegin_impl(int_constant<cmp_lt>, std::true_type) const
101    {
102       return set_reverse_iterator(get_set().find_nearest(limit, polymake::operations::lt()));
103    }
104    reverse_iterator rend_impl(int_constant<cmp_lt>) const
105    {
106       return get_set().rend();
107    }
108    iterator begin_impl(int_constant<cmp_gt>, std::false_type) const
109    {
110       return iterator(get_set().find_nearest(limit, polymake::operations::gt()), get_set().end());
111    }
112    iterator begin_impl(int_constant<cmp_gt>, std::true_type) const
113    {
114       return get_set().find_nearest(limit, polymake::operations::gt());
115    }
116    iterator end_impl(int_constant<cmp_gt>) const
117    {
118       return get_set().end();
119    }
120    template <typename TEnd_sensitive>
121    reverse_iterator rbegin_impl(int_constant<cmp_gt>, TEnd_sensitive) const
122    {
123       return reverse_iterator(get_set().rbegin(), predicate(limit));
124    }
125    reverse_iterator rend_impl(int_constant<cmp_gt>) const
126    {
127       return get_set().find_nearest(limit, polymake::operations::le());
128    }
129 public:
130    iterator begin() const { return begin_impl(int_constant<direction>(), bool_constant<check_iterator_feature<range_base, end_sensitive>::value>()); }
131    iterator end() const { return end_impl(int_constant<direction>()); }
132    reverse_iterator rbegin() const { return rbegin_impl(int_constant<direction>(), bool_constant<check_iterator_feature<range_base, end_sensitive>::value>()); }
133    reverse_iterator rend() const { return rend_impl(int_constant<direction>()); }
134 
135    reference front() const { return *begin(); }
136    reference back() const { return *rbegin(); }
137 
138    /// the size of the set
139    Int size() const { return count_it(begin()); }
140    /// true if the set is empty
141    bool empty() const { return begin().at_end(); }
142 };
143 
144 template <typename SetRef, cmp_value direction>
145 struct spec_object_traits< TruncatedSet<SetRef, direction> >
146    : spec_object_traits<is_container> {
147    static constexpr bool is_temporary = true, is_always_const = is_effectively_const<SetRef>::value;
148 };
149 
150 // to be used as callback in AVL::Tree::insert()
151 struct element_seen_op {
152    mutable bool seen;
153    element_seen_op() : seen(false) {}
154 
155    template <typename Key>
156    void operator() (const Key&, const nothing&) const { seen=true; }
157 
158    operator bool () const { return seen; }
159 };
160 
161 /// @ref generic "Generic type" for ordered mutable sets
162 template <typename TSet, typename E = typename TSet::element_type, typename Comparator = typename TSet::element_comparator>
163 class GenericMutableSet
164    : public GenericSet<TSet, E, Comparator> {
165    template <typename, typename, typename> friend class GenericMutableSet;
166 protected:
167    GenericMutableSet() = default;
168    GenericMutableSet(const GenericMutableSet&) = default;
169    using generic_mutable_type = GenericMutableSet;
170 public:
171    using typename GenericSet<TSet, E, Comparator>::top_type;
172 
173    template <typename Right>
174    using is_compatible_element = typename mlist_and<is_lossless_convertible<Right, E>, are_comparable_via<E, Right, Comparator>>::type;
175 
176    template <typename Right, bool is_set = is_generic_set<Right>::value>
177    struct is_compatible_set : std::false_type {};
178 
179    template <typename Right>
180    struct is_compatible_set<Right, true> : mlist_and<is_compatible_element<typename Right::element_type>, std::is_same<Comparator, typename Right::element_comparator>>::type {};
181 
182 protected:
183    template <typename TSet2>
184    void plus_seek(const TSet2& s)
185    {
186       for (auto e2 = entire(s); !e2.at_end(); ++e2)
187          this->top().insert(*e2);
188    }
189 
190    template <typename TSet2>
191    void plus_seq(const TSet2& s)
192    {
193       const Comparator& cmp_op = this->top().get_comparator();
194       auto e1 = entire(this->top());
195       auto e2 = entire(s);
196       while (!e1.at_end() && !e2.at_end()) {
197          switch (cmp_op(*e1,*e2)) {
198          case cmp_eq: ++e2;
199          case cmp_lt: ++e1; break;
200          case cmp_gt: this->top().insert(e1,*e2); ++e2;
201          }
202       }
203       for (; !e2.at_end(); ++e2) this->top().insert(e1,*e2);
204    }
205 
206    template <typename TSet2, typename E2>
207    void plus_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::true_type)
208    {
209       if (size_estimator<top_type, unwary_t<TSet2>>::seek_cheaper_than_sequential(this->top(), s.top()))
210          plus_seek(s.top());
211       else
212          plus_seq(s.top());
213    }
214 
215    template <typename TSet2, typename E2>
216    void plus_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::false_type)
217    {
218       plus_seq(s.top());
219    }
220 
221    template <typename Right>
222    void plus_element_impl(const Right& x, std::true_type)
223    {
224       this->top().insert(x);
225    }
226 
227    template <typename Right>
228    void plus_element_impl(const Right& x, std::false_type)
229    {
230       plus_seq(scalar2set(x));
231    }
232 
233    template <typename TSet2>
234    void minus_seek(const TSet2& s)
235    {
236       for (auto e2=entire(s); !e2.at_end(); ++e2)
237          this->top().erase(*e2);
238    }
239 
240    template <typename TSet2>
241    void minus_seq(const TSet2& s)
242    {
243       const Comparator& cmp_op=this->top().get_comparator();
244       auto e1 = entire(this->top());
245       auto e2 = entire(s);
246       while (!e1.at_end() && !e2.at_end()) {
247          switch (cmp_op(*e1,*e2)) {
248          case cmp_lt: ++e1; break;
249          case cmp_eq: this->top().erase(e1++);
250          case cmp_gt: ++e2;
251          }
252       }
253    }
254 
255    template <typename TSet2, typename E2>
256    void minus_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::true_type)
257    {
258       if (size_estimator<top_type, unwary_t<TSet2>>::seek_cheaper_than_sequential(this->top(), s.top()))
259          minus_seek(s.top());
260       else
261          minus_seq(s.top());
262    }
263 
264    template <typename TSet2, typename E2>
265    void minus_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::false_type)
266    {
267       minus_seq(s.top());
268    }
269 
270    template <typename Right>
271    void minus_element_impl(const Right& x, std::true_type)
272    {
273       this->top().erase(x);
274    }
275 
276    template <typename Right>
277    void minus_element_impl(const Right& x, std::false_type)
278    {
279       minus_seq(scalar2set(x));
280    }
281 
282    template <typename TSet2>
283    void xor_seek(const TSet2& s)
284    {
285       for (auto e2=entire(s); !e2.at_end(); ++e2)
286          this->top().toggle(*e2);
287    }
288 
289    template <typename TSet2>
290    void xor_seq(const TSet2& s)
291    {
292       const Comparator& cmp_op = this->top().get_comparator();
293       auto e1 = entire(this->top());
294       auto e2 = entire(s);
295       while (!e1.at_end() && !e2.at_end()) {
296          switch (cmp_op(*e1,*e2)) {
297          case cmp_lt:  ++e1;  break;
298          case cmp_eq: this->top().erase(e1++);  ++e2;  break;
299          case cmp_gt: this->top().insert(e1,*e2);  ++e2;
300          }
301       }
302       for (; !e2.at_end(); ++e2) this->top().insert(e1,*e2);
303    }
304 
305    template <typename TSet2, typename E2>
306    void xor_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::true_type)
307    {
308       if (size_estimator<top_type, unwary_t<TSet2>>::seek_cheaper_than_sequential(this->top(), s.top()))
309          xor_seek(s.top());
310       else
311          xor_seq(s.top());
312    }
313 
314    template <typename TSet2, typename E2>
315    void xor_set_impl(const GenericSet<TSet2, E2, Comparator>& s, std::false_type)
316    {
317       xor_seq(s.top());
318    }
319 
320    template <typename Right>
321    void xor_element_impl(const Right& x, std::true_type)
322    {
323       this->top().toggle(x);
324    }
325 
326    template <typename Right>
327    void xor_element_impl(const Right& x, std::false_type)
328    {
329       xor_seq(scalar2set(x));
330    }
331 
332    template <typename TSet2, typename E2>
333    constexpr bool trivial_assignment(const GenericSet<TSet2, E2, Comparator>&) const { return false; }
334 
335    constexpr bool trivial_assignment(const GenericMutableSet& s) const { return this==&s; }
336 
337    template <typename TSet2, typename E2, typename DiffConsumer>
338    void assign(const GenericSet<TSet2, E2, Comparator>& s, DiffConsumer diff)
339    {
340       const Comparator& cmp_op=this->top().get_comparator();
341       auto dst = entire(this->top());
342       auto src = entire(s.top());
343       int state = (dst.at_end() ? 0 : zipper_first) + (src.at_end() ? 0 : zipper_second);
344       while (state >= zipper_both) {
345          switch (cmp_op(*dst, *src)) {
346          case cmp_lt:
347             if (!is_instance_of<DiffConsumer, black_hole>::value) *diff++=*dst;
348             this->top().erase(dst++);
349             if (dst.at_end()) state -= zipper_first;
350             break;
351          case cmp_eq:
352             ++dst;
353             if (dst.at_end()) state -= zipper_first;
354             ++src;
355             if (src.at_end()) state -= zipper_second;
356             break;
357          case cmp_gt:
358             if (!is_instance_of<DiffConsumer, black_hole>::value) *diff++=*src;
359             this->top().insert(dst, *src);  ++src;
360             if (src.at_end()) state -= zipper_second;
361          }
362       }
363       if (state & zipper_first) {
364          do {
365             if (!is_instance_of<DiffConsumer, black_hole>::value) *diff++=*dst;
366             this->top().erase(dst++);
367          }
368          while (!dst.at_end());
369       } else if (state) {
370          do {
371             if (!is_instance_of<DiffConsumer, black_hole>::value) *diff++=*src;
372             this->top().insert(dst, *src);  ++src;
373          } while (!src.at_end());
374       }
375    }
376 
377    template <typename TSet2, typename E2>
378    void assign(const GenericSet<TSet2, E2, Comparator>& s)
379    {
380       assign(s, black_hole<E>());
381    }
382 
383 public:
384    top_type& operator= (const GenericMutableSet& s)
385    {
386       if (!this->trivial_assignment(s)) this->top().assign(s);
387       return this->top();
388    }
389 
390    template <typename TSet2, typename E2,
391              typename = std::enable_if_t<can_initialize<E2, E>::value>>
392    top_type& operator= (const GenericSet<TSet2, E2, Comparator>& other)
393    {
394       this->top().assign(other);
395       return this->top();
396    }
397 
398    template <typename E2,
399              typename = std::enable_if_t<can_initialize<E2, E>::value>>
400    top_type& operator= (std::initializer_list<E2> l)
401    {
402       this->top().clear();
403       this->top().insert_from(entire(l));
404       return this->top();
405    }
406 
407    template <typename TSet2>
408    void swap(GenericMutableSet<TSet2, E, Comparator>& s)
409    {
410       if (trivial_assignment(s)) return;
411       const Comparator& cmp_op = this->top().get_comparator();
412       auto e1 = entire(this->top());
413       auto e2 = entire(s.top());
414       int state = (e1.at_end() ? 0 : zipper_first) + (e2.at_end() ? 0 : zipper_second);
415       while (state >= zipper_both) {
416          switch (cmp_op(*e1,*e2)) {
417          case cmp_lt:
418             s.top().insert(e2, e1.index());
419             this->top().erase(e1++);
420             if (e1.at_end()) state -= zipper_first;
421             break;
422          case cmp_gt:
423             this->top().insert(e1, e2.index());
424             s.top().erase(e2++);
425             if (e2.at_end()) state -= zipper_second;
426             break;
427          case cmp_eq:
428             ++e1;
429             if (e1.at_end()) state -= zipper_first;
430             ++e2;
431             if (e2.at_end()) state -= zipper_second;
432          }
433       }
434       if (state & zipper_first) {
435          do {
436             s.top().insert(e2, e1.index());
437             this->top().erase(e1++);
438          } while (!e1.at_end());
439       } else if (state) {
440          do {
441             this->top().insert(e1, e2.index());
442             s.top().erase(e2++);
443          } while (!e2.at_end());
444       }
445    }
446 
447    /// %Set union
448    template <typename Right>
449    std::enable_if_t<is_compatible_set<Right>::value, top_type&>
450    operator+= (const Right& x)
451    {
452       plus_set_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
453       return this->top();
454    }
455 
456    template <typename Right>
457    std::enable_if_t<is_compatible_element<Right>::value, top_type&>
458    operator+= (const Right& x)
459    {
460       plus_element_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
461       return this->top();
462    }
463 
464    /// Add to the set, report true if existed formerly.
465    template <typename Right>
466    std::enable_if_t<is_compatible_element<Right>::value, bool> collect(const Right& x)
467    {
468       element_seen_op seen;
469       this->top().insert(x, nothing(), seen);
470       return seen;
471    }
472 
473    /// %Set difference
474    template <typename Right>
475    std::enable_if_t<is_compatible_set<Right>::value, top_type&>
476    operator-= (const Right& x)
477    {
478       minus_set_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
479       return this->top();
480    }
481 
482    template <typename Right>
483    std::enable_if_t<is_compatible_element<Right>::value, top_type&>
484    operator-= (const Right& x)
485    {
486       minus_element_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
487       return this->top();
488    }
489 
490    /// %Set intersection
491    template <typename Right>
492    std::enable_if_t<is_compatible_set<Right>::value, top_type&>
493    operator*= (const Right& x)
494    {
495       const Comparator& cmp_op = this->top().get_comparator();
496       auto e1 = entire(this->top());
497       auto e2 = entire(x.top());
498       while (!e1.at_end() && !e2.at_end()) {
499          switch (cmp_op(*e1,*e2)) {
500          case cmp_lt: this->top().erase(e1++); break;
501          case cmp_eq: ++e1;
502          case cmp_gt: ++e2;
503          }
504       }
505       while (!e1.at_end()) this->top().erase(e1++);
506       return this->top();
507    }
508 
509    /// Symmetrical difference
510    template <typename Right>
511    std::enable_if_t<is_compatible_set<Right>::value, top_type&>
512    operator^= (const Right& x)
513    {
514       xor_set_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
515       return this->top();
516    }
517 
518    template <typename Right>
519    std::enable_if_t<is_compatible_element<Right>::value, top_type&>
520    operator^= (const Right& x)
521    {
522       xor_element_impl(x, is_derived_from_instance_of<top_type, modified_tree>());
523       return this->top();
524    }
525 
526    /// Compute the symmetrical difference and make *this equal to s
527    template <typename Right>
528    std::enable_if_t<is_compatible_set<Right>::value, Set<E, Comparator>>
529    extract_symdif(const Right& x)
530    {
531       Set<E, Comparator> result;
532       assign(x, std::back_inserter(result));
533       return result;
534    }
535 
536    auto operator<< (const E& upper_limit) const
537    {
538       return TruncatedSet<const top_type&, cmp_lt>(this->top(), upper_limit);
539    }
540 
541    auto operator>> (const E& lower_limit) const
542    {
543       return TruncatedSet<const top_type&, cmp_gt>(this->top(), lower_limit);
544    }
545 
546    top_type& operator<<= (const E& upper_limit)
547    {
548       const Comparator& cmp_op=this->top().get_comparator();
549       auto it=entire<reversed>(this->top());
550       while (!it.at_end() && cmp_op(*it,upper_limit)>=cmp_eq)
551          this->top().erase(it++);
552       return this->top();
553    }
554 
555    top_type& operator>>= (const E& lower_limit)
556    {
557       const Comparator& cmp_op=this->top().get_comparator();
558       auto it=entire(this->top());
559       while (!it.at_end() && cmp_op(*it,lower_limit)<=cmp_eq)
560          this->top().erase(it++);
561       return this->top();
562    }
563 
564    template <typename TSet2>
565    top_type& select(const GenericSet<TSet2>& selector)
566    {
567       auto e1=entire(this->top());
568       typename unwary_t<TSet2>::element_type cur(0);
569       for (auto s=entire(selector.top()); !s.at_end(); ++s) {
570          for (; cur < *s; ++cur) this->top().erase(e1++);
571          ++e1; ++cur;
572       }
573       while (!e1.at_end()) this->top().erase(e1++);
574       return this->top();
575    }
576 
577    template <typename TSet2>
578    top_type& select(const Complement<TSet2>& selector)
579    {
580       auto e1=entire(this->top());
581       typename TSet2::element_type cur(0);
582       for (auto s=entire(selector.base()); !s.at_end(); ++s) {
583          for (; cur < *s; ++cur) ++e1;
584          this->top().erase(e1++); ++cur;
585       }
586       return this->top();
587    }
588 
589    template <typename Result>
590    struct rebind_generic {
591       typedef GenericMutableSet<Result, E, Comparator> type;
592    };
593 
594 }; // end class GenericMutableSet
595 
596 /** @class Set
597     @brief An associative container based on a balanced binary search (%AVL) tree.
598     @c Comparator is a functor defining a total ordering on the element value domain.
599     In most cases, the default choice (lexicographical order) will suffice for your needs.
600 
601     The data tree is attached to the Set object via a @ref refcounting "smart pointer".
602     Arithmetic operations for sets are listed at @ref genericSets "operations".
603     <br>The following standard functions for sets are also implemented:<br>
604     <code>
605        contains(); empty(); size();
606     </code>
607 */
608 
609 template <typename E, typename Comparator>
610 class Set
611    : public modified_tree< Set<E, Comparator>,
612                            mlist< ContainerTag< AVL::tree<typename AVL::single_key_traits<E, nothing, Comparator>::type> >,
613                                   OperationTag< BuildUnary<AVL::node_accessor> > > >
614    , public GenericMutableSet< Set<E, Comparator>, E, Comparator > {
615 protected:
616    using tree_type = AVL::tree<typename AVL::single_key_traits<E, nothing, Comparator>::type>;
617    shared_object<tree_type, AliasHandlerTag<shared_alias_handler>> tree;
618 
619    friend Set& make_mutable_alias(Set& alias, Set& owner)
620    {
621       alias.tree.make_mutable_alias(owner.tree);
622       return alias;
623    }
624 public:
625    tree_type& get_container() { return *tree; }
626    const tree_type& get_container() const { return *tree; }
627 
628    /// Create an empty set.
629    Set() {}
630 
631    /// Create an empty set with a non-default Comparator
632    explicit Set(const Comparator& cmp_arg)
633       : tree(cmp_arg) {}
634 
635    /// Create a Set from an iterator
636    template <typename Iterator>
637    Set(Iterator&& src, Iterator&& end,
638        std::enable_if_t<assess_iterator_value<Iterator, can_initialize, E>::value, std::nullptr_t> =nullptr)
639    {
640       insert_from(make_iterator_range(std::forward<Iterator>(src), std::forward<Iterator>(end)));
641    }
642 
643    template <typename Iterator>
644    explicit Set(Iterator&& src,
645                 std::enable_if_t<assess_iterator<Iterator, check_iterator_feature, end_sensitive>::value &&
646                                  assess_iterator_value<Iterator, can_initialize, E>::value,
647                                  std::nullptr_t> = nullptr)
648    {
649       insert_from(ensure_private_mutable(std::forward<Iterator>(src)));
650    }
651 
652    /// Copy of a disguised Set object.
653    Set(const GenericSet<Set, E, Comparator>& s)
654       : tree(s.top().tree) {}
655 
656    /// Copy of an abstract set of the same element type.
657    template <typename Set2>
658    Set(const GenericSet<Set2, E, Comparator>& s)
659       : tree(entire(s.top())) {}
660 
661    /// Copy of an abstract set with element conversion.
662    template <typename Set2, typename E2, typename Comparator2, typename = std::enable_if_t<can_initialize<E2, E>::value>>
663    explicit Set(const GenericSet<Set2, E2, Comparator2>& s)
664       : tree(entire(attach_converter<E>(s.top()))) {}
665 
666    template <typename E2, typename = std::enable_if_t<can_initialize<E2, E>::value>>
667    Set(std::initializer_list<E2> l)
668    {
669       insert_from(entire(l));
670    }
671 
672    template <typename Container>
673    explicit Set(const Container& src,
674                 std::enable_if_t<isomorphic_to_container_of<Container, E, is_set>::value, std::nullptr_t> = nullptr)
675    {
676       insert_from(entire(src));
677    }
678 
679    Set& operator= (const Set& other) { assign(other); return *this; }
680    using Set::generic_mutable_type::operator=;
681 
682    /// Make the set empty.
683    void clear() { tree.apply(shared_clear()); }
684 
685    /// for compatibility with Bitset
686    void resize(Int) {}
687 
688    /** @brief Swap the content with another Set.
689        @param s the other Set
690    */
691    void swap(Set& s) { tree.swap(s.tree); }
692 
693    friend void relocate(Set* from, Set* to)
694    {
695       relocate(&from->tree, &to->tree);
696    }
697 
698 #if POLYMAKE_DEBUG
699    void check(const char* label) const { tree->check(label); }
700    void tree_dump() const { tree->dump(); }
701 #endif
702 
703    Set& operator<<= (const E& upper_limit)
704    {
705       if (tree.is_shared())
706          *this=*this << upper_limit;
707       else
708          Set::generic_mutable_type::operator<<=(upper_limit);
709       return *this;
710    }
711 
712    Set& operator>>= (const E& lower_limit)
713    {
714       if (tree.is_shared())
715          *this=*this >> lower_limit;
716       else
717          Set::generic_mutable_type::operator>>=(lower_limit);
718       return *this;
719    }
720 
721    template <typename Set2>
722    Set& select(const GenericSet<Set2>& selector)
723    {
724       if (tree.is_shared())
725          *this=Set(entire(pm::select(const_cast<const Set&>(*this), selector.top())));
726       else
727          Set::generic_mutable_type::select(selector);
728       return *this;
729    }
730 
731    template <typename Set2>
732    Set& select(const Complement<Set2>& selector)
733    {
734       if (tree.is_shared())
735          *this=Set(entire(pm::select(const_cast<const Set&>(*this), selector)));
736       else
737          Set::generic_mutable_type::select(selector);
738       return *this;
739    }
740 
741    /// Return the (pointwise) image of this under a permutation.
742    template <typename Permutation>
743    Set copy_permuted(const Permutation& perm) const
744    {
745       Set result;
746       for (auto p = entire<indexed>(perm);  !p.at_end();  ++p)
747          if (this->exists(*p)) result.tree->push_back(p.index());
748       return result;
749    }
750 
751    /// Return the (pointwise) image of this under the inverse of a given permutation.
752    template <typename Permutation>
753    Set copy_permuted_inv(const Permutation& perm) const
754    {
755       const Set result(pm::select(perm, *this));
756       return result;
757    }
758 
759 protected:
760    template <typename, typename, typename> friend class GenericMutableSet;
761 
762    void assign(const GenericSet<Set>& s) { tree=s.top().tree; }
763 
764    template <typename Set2, typename E2>
765    void assign(const GenericSet<Set2, E2, Comparator>& s)
766    {
767       if (tree.is_shared()) {
768          assign(Set(s));
769       } else {
770          tree->assign(entire(s.top()));
771       }
772    }
773 
774    /// Insert elements from a sequence, coming in any order.
775    template <typename Iterator>
776    void insert_from(Iterator&& src)
777    {
778       tree_type* t=tree.get();
779       for (; !src.at_end(); ++src)
780          t->insert(*src);
781    }
782 };
783 
784 template <typename E, typename Comparator, typename Permutation>
785 Set<E,Comparator> permuted(const Set<E,Comparator>& s, const Permutation& perm)
786 {
787    return s.copy_permuted(perm);
788 }
789 
790 template <typename E, typename Comparator, typename Permutation>
791 Set<E,Comparator> permuted_inv(const Set<E,Comparator>& s, const Permutation& perm)
792 {
793    return s.copy_permuted_inv(perm);
794 }
795 
796 // FIXME: temporary hack until all Vector<Set> disappear from atint
797 template <typename E, typename Comparator>
798 struct spec_object_traits<Set<E, Comparator>> : spec_object_traits<is_container> {
799    static const Set<E, Comparator>& zero()
800    {
801       static const Set<E, Comparator> z{};
802       return z;
803    }
804 };
805 
806 } // end namespace pm
807 
808 namespace polymake {
809    using pm::Set;
810 }
811 
812 namespace std {
813    template <typename Set1, typename Set2, typename E, typename Comparator>
814    void swap(pm::GenericMutableSet<Set1,E,Comparator>& s1, pm::GenericMutableSet<Set2,E,Comparator>& s2)
815    {
816       s1.top().swap(s2.top());
817    }
818 
819    template <typename E, typename Comparator>
820    void swap(pm::Set<E,Comparator>& s1, pm::Set<E,Comparator>& s2) { s1.swap(s2); }
821 }
822 
823 
824 // Local Variables:
825 // mode:C++
826 // c-basic-offset:3
827 // indent-tabs-mode:nil
828 // End:
829