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