aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
sequence_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
51
52// to ease IDE parser
54
55namespace gum {
56
57 // returns the size of the sequence
58 template < typename Key, bool Gen >
60 return _h_.size();
61 }
62
63 // return true if empty
64 template < typename Key, bool Gen >
66 return _h_.empty();
67 }
68
69 // returns the size of the sequence
70 template < typename Key >
72 return _h_.size();
73 }
74
75 // return true if empty
76 template < typename Key >
77 bool SequenceImplementation< Key, true >::empty() const noexcept {
78 return _h_.empty();
79 }
80
81 // ===========================================================================
82 // class SequenceIteratorSafe
83 // ===========================================================================
84
85 // default constructor
86 template < typename Key >
87 template < bool Gen >
89 Idx pos) noexcept :
90 _seq_{
91 reinterpret_cast< const SequenceImplementation< Key, std::is_scalar_v< Key > >* >(&seq)} {
92 GUM_CONSTRUCTOR(SequenceIteratorSafe);
93
94 if (pos > _seq_->size()) _iterator_ = _seq_->size(); // make the iterator point to end
95 else _iterator_ = pos;
96 }
97
98 // default constructor
99 template < typename Key >
101 _seq_{
102 reinterpret_cast< const SequenceImplementation< Key, std::is_scalar_v< Key > >* >(&seq)} {
103 GUM_CONSTRUCTOR(SequenceIteratorSafe);
104
105 if (pos > _seq_->size()) _iterator_ = _seq_->size(); // make the iterator point to end
106 else _iterator_ = pos;
107 }
108
109 // copy constructor
110 template < typename Key >
112 const SequenceIteratorSafe< Key >& source) noexcept :
113 _iterator_{source._iterator_}, _seq_{source._seq_} {
114 GUM_CONS_CPY(SequenceIteratorSafe);
115 }
116
117 // move constructor
118 template < typename Key >
119 SequenceIteratorSafe< Key >::SequenceIteratorSafe(SequenceIteratorSafe< Key >&& source) noexcept :
120 _iterator_{source._iterator_}, _seq_{source._seq_} {
121 GUM_CONS_MOV(SequenceIteratorSafe);
122 }
123
124 // destructor
125 template < typename Key >
129
130 // copy operator
131 template < typename Key >
132 SequenceIteratorSafe< Key >&
133 SequenceIteratorSafe< Key >::operator=(const SequenceIteratorSafe< Key >& source) noexcept
134 = default;
135
136 // move operator
137 template < typename Key >
138 SequenceIteratorSafe< Key >&
139 SequenceIteratorSafe< Key >::operator=(SequenceIteratorSafe< Key >&& source) noexcept {
140 _iterator_ = source._iterator_;
141 _seq_ = source._seq_;
142 return *this;
143 }
144
145 // point the iterator to the next value in the sequence
146 template < typename Key >
147 SequenceIteratorSafe< Key >& SequenceIteratorSafe< Key >::operator++() noexcept {
148 if (_iterator_ < _seq_->size()) ++_iterator_;
149 else _iterator_ = _seq_->size();
150
151 return *this;
152 }
153
154 // point the iterator to the preceding value in the sequence
155 template < typename Key >
156 SequenceIteratorSafe< Key >& SequenceIteratorSafe< Key >::operator--() noexcept {
157 if (_iterator_ != std::numeric_limits< Idx >::max()) --_iterator_;
158
159 return *this;
160 }
161
162 // makes the iterator point to i elements further in the sequence
163 template < typename Key >
164 SequenceIteratorSafe< Key >& SequenceIteratorSafe< Key >::operator+=(Size nb) noexcept {
165 if (_iterator_ == std::numeric_limits< Idx >::max()) return *this;
166 _iterator_ += nb;
167 if (_iterator_ > _seq_->size()) _iterator_ = _seq_->size();
168
169 return *this;
170 }
171
172 // makes the iterator point to i elements further in the sequence
173 template < typename Key >
174 SequenceIteratorSafe< Key >& SequenceIteratorSafe< Key >::operator-=(Size nb) noexcept {
175 if (_iterator_ == std::numeric_limits< Idx >::max()) return *this;
176 _iterator_ -= nb;
177 if (_iterator_ > _seq_->size()) _iterator_ = std::numeric_limits< Idx >::max();
178
179 return *this;
180 }
181
182 // returns a new iterator
183 template < typename Key >
184 SequenceIteratorSafe< Key > SequenceIteratorSafe< Key >::operator+(Size nb) noexcept {
185 return SequenceIteratorSafe< Key >{*this} += nb;
186 }
188 // returns a new iterator
189 template < typename Key >
190 SequenceIteratorSafe< Key > SequenceIteratorSafe< Key >::operator-(Size nb) noexcept {
191 return SequenceIteratorSafe< Key >{*this} -= nb;
192 }
194 // checks whether two iterators are pointing to the same element
195 template < typename Key >
197 const SequenceIteratorSafe< Key >& source) const noexcept {
198 if (_seq_->empty()) return true; // all iterators are the same if seq is empty
200 if ((_iterator_ != source._iterator_) || (_seq_ != source._seq_)) return false;
201
202 return true;
203 }
204
205 // checks whether two iterators are pointing to different elements
206 template < typename Key >
208 const SequenceIteratorSafe< Key >& source) const noexcept {
209 return !operator==(source);
210 }
212 // returns the position of the iterator in the sequence
213 template < typename Key >
215 if (_iterator_ >= _seq_->size()) {
216 GUM_ERROR(UndefinedIteratorValue, "iterator is end() or rend()")
218
219 return _iterator_;
220 }
221
222 // the iterator points to the posth element (0 = beginning of the sequence).
223 template < typename Key >
225 if (pos > _seq_->size()) _iterator_ = _seq_->size();
226 else _iterator_ = pos;
227 }
228
229 // the iterator points to the posth element (0 = beginning of the sequence).
230 template < typename Key >
232 _iterator_ = std::numeric_limits< Idx >::max();
233 }
234
235 // the iterator points to the posth element (0 = beginning of the sequence).
236 template < typename Key >
238 _iterator_ = _seq_->size();
239 }
240
241 // returns the value pointed to by the iterator
242 template < typename Key >
244 return Getter::op_star(_seq_->_v_[pos()]);
245 }
246
247 // dereferences the value pointed to by the iterator
248 template < typename Key >
250 return Getter::op_arrow(_seq_->_v_[pos()]);
252
253 // ===========================================================================
254 // === NON SCALAR GUM SEQUENCE IMPLEMENTATION ===
255 // ===========================================================================
256
257 // updates const iterators
258 template < typename Key, bool Gen >
260 _end_safe_._setAtEnd_();
261 }
262
263 // clear the sequence
264 template < typename Key, bool Gen >
266 _h_.clear();
267 _v_.clear();
268 _update_end_();
269 }
270
271 // clears the current sequence and fill it with copies the element of aSeq
272 template < typename Key, bool Gen >
274 clear();
275
276 for (Size i = 0; i < aSeq.size(); ++i) {
277 Key& new_key = const_cast< Key& >(_h_.insert(*(aSeq._v_[i]), i).first);
278 _v_.push_back(&new_key);
279 }
280
281 _update_end_();
282 }
283
284 // Default constructor
285 template < typename Key, bool Gen >
287 _h_(size_param), _end_safe_{*this}, _rend_safe_{*this} {
288 GUM_CONSTRUCTOR(SequenceImplementation);
289 _rend_safe_._setAtRend_();
290 _update_end_();
291 }
292
293 // initializer list constructor
294 template < typename Key, bool Gen >
296 _end_safe_{*this}, _rend_safe_{*this} {
297 GUM_CONSTRUCTOR(SequenceImplementation);
298 _rend_safe_._setAtRend_();
299 for (const auto& elt: list) {
300 insert(elt); // performs the _update_end_ ()
301 }
302 }
303
304 // copy constructor
305 template < typename Key, bool Gen >
307 const SequenceImplementation< Key, Gen >& aSeq) : _end_safe_{*this}, _rend_safe_{*this} {
308 GUM_CONS_CPY(SequenceImplementation);
309 _rend_safe_._setAtRend_();
310 _copy_(aSeq); // performs the _update_end_ ()
311 }
312
313 // move constructor
314 template < typename Key, bool Gen >
317 _h_(std::move(aSeq._h_)), _v_(std::move(aSeq._v_)), _end_safe_{*this}, _rend_safe_{*this} {
318 GUM_CONS_MOV(SequenceImplementation);
319 _rend_safe_._setAtRend_();
320 _update_end_();
321 }
322
323 // destructor
324 template < typename Key, bool Gen >
328
329 // copy operator
330 template < typename Key, bool Gen >
333 // avoid self assignment
334 if (&aSeq != this) {
335 _copy_(aSeq); // performs the _update_end_ ()
336 }
337
338 return *this;
340
341 // move operator
342 template < typename Key, bool Gen >
345 // avoid self assignment
346 if (&aSeq != this) {
347 _h_ = std::move(aSeq._h_);
348 _v_ = std::move(aSeq._v_);
350 }
351
352 return *this;
353 }
354
355 // check the existence of k in the sequence
356 template < typename Key, bool Gen >
358 return _h_.exists(k);
359 }
361 // returns a pointer to the position of k, or nullptr if not found
362 template < typename Key, bool Gen >
364 return _h_.tryGet(k);
365 }
366
367 // insert an element at the end of the sequence
368 template < typename Key, bool Gen >
370 // k will be added at the end. Insert the new key into the hashtable
371 Key& new_key = const_cast< Key& >(_h_.insert(k, _h_.size()).first);
372 try {
373 _v_.push_back(&new_key);
374 } catch (...) {
375 _h_.erase(new_key);
376 throw;
377 }
378 _update_end_();
379 }
380
381 // insert an element at the end of the sequence
382 template < typename Key, bool Gen >
384 // k will be added at the end. Insert the new key into the hashtable
385 Key& new_key = const_cast< Key& >(_h_.insert(std::move(k), _h_.size()).first);
386 try {
387 _v_.push_back(&new_key);
388 } catch (...) {
389 _h_.erase(new_key);
390 throw;
391 }
392 _update_end_();
394
395 // emplace a new element in the sequence
396 template < typename Key, bool Gen >
397 template < typename... Args >
399 Key key(std::forward< Args >(args)...);
400 Key& new_key = const_cast< Key& >(_h_.insert(std::move(key), _h_.size()).first);
401 try {
402 _v_.push_back(&new_key);
403 } catch (...) {
404 _h_.erase(new_key);
405 throw;
406 }
407 _update_end_();
408 }
409
410 // insert k in the sequence (synonym for insert)
411 template < typename Key, bool Gen >
412 SequenceImplementation< Key, Gen >& SequenceImplementation< Key, Gen >::operator<<(const Key& k) {
413 insert(k);
414 return *this;
415 }
416
417 // insert k in the sequence (synonym for insert)
418 template < typename Key, bool Gen >
420 insert(std::move(k));
421 return *this;
422 }
424 // remove an element from the sequence
425 template < typename Key, bool Gen >
427 // get the position of the element to remove
428 auto p = _h_.tryGet(k);
429 if (!p) return;
430 Idx pos = *p;
431
432 // erase the element
433 _v_.erase(_v_.begin() + pos);
434 for (Idx i = pos, nb_elts = _h_.size() - 1; i < nb_elts; ++i) {
435 --_h_[*(_v_[i])];
436 }
437 _h_.erase(k);
438
439 _update_end_();
440 }
441
442 // remove from the sequence the element pointed to by the iterator
443 template < typename Key, bool Gen >
445 if (iter.pos() >= size()) return;
446
447 // erase the element
448 Idx pos = iter.pos();
449 Key* key = _v_[pos];
450 _v_.erase(_v_.begin() + pos);
451
452 for (Idx i = pos, nb_elts = _h_.size() - 1; i < nb_elts; ++i) {
453 --_h_[*(_v_[i])];
454 }
455 _h_.erase(*key);
456
457 _update_end_();
458 }
460 // remove k in the sequence (synonym for erase)
461 template < typename Key, bool Gen >
467 // returns the object at position i ( first elt = index 0 )
468 template < typename Key, bool Gen >
470 if (i >= _h_.size()) {
471 GUM_ERROR(OutOfBounds, "index " << i << " for a sequence of size" << _h_.size())
472 }
474 return *(_v_[i]);
475 }
476
477 // returns the element at position i (synonym for atPos)
478 template < typename Key, bool Gen >
480 return atPos(i);
481 }
482
483 // returns the position of the object passed in argument (if it exists)
484 template < typename Key, bool Gen >
486 return _h_[key];
487 }
488
489 // inserts and returns the object at the pos i
490 template < typename Key, bool Gen >
492 if (i >= _h_.size()) { GUM_ERROR(NotFound, "index too large") }
494 Key& new_key = const_cast< Key& >(_h_.insert(newKey, i).first);
495 _h_.erase(*(_v_[i]));
496 _v_[i] = &new_key;
497 }
498
499 // inserts and returns the object at the pos i
500 template < typename Key, bool Gen >
502 if (i >= _h_.size()) { GUM_ERROR(NotFound, "index too large") }
503
504 Key& new_key = const_cast< Key& >(_h_.insert(std::move(newKey), i).first);
505 _h_.erase(*(_v_[i]));
506 _v_[i] = &new_key;
507 }
508
509 // replace two elements in the sequence
510 template < typename Key, bool Gen >
512 if (i == j) return;
513
514 Key& ki = const_cast< Key& >(atPos(i));
515 Key& kj = const_cast< Key& >(atPos(j));
516
517 _h_[ki] = j;
518 _h_[kj] = i;
519
520 _v_[i] = &kj;
521 _v_[j] = &ki;
522 }
523
524 // returns the first element
525 template < typename Key, bool Gen >
527 return atPos(0);
528 }
529
530 // returns the last element
531 template < typename Key, bool Gen >
533 return atPos(size() - 1);
534 }
535
536 // Print a sequence
537 template < typename Key, bool Gen >
539 std::stringstream stream;
540 stream << "[";
541
542 if (!_h_.empty()) {
543 stream << "0:" << *_v_[0];
544
545 for (Idx i = 1; i < _h_.size(); ++i) {
546 stream << std::format(" - {}:", i) << *_v_[i];
547 }
548 }
549
550 stream << "]";
551
552 return stream.str();
553 }
554
555 // returns true if the content of k equals that of *this
556 template < typename Key, bool Gen >
558 const SequenceImplementation< Key, Gen >& k) const {
559 if (size() != k.size()) return false;
560 else {
561 for (Idx i = 0; i < size(); ++i)
562 if (*_v_[i] != *(k._v_[i])) return false;
563 }
564
565 return true;
566 }
567
568 // returns true if the content of k is different from that of *this
569 template < typename Key, bool Gen >
574
575 // a << operator for displaying the content of the Sequence
576 template < typename Key, bool Gen >
577 std::ostream& operator<<(std::ostream& stream, const SequenceImplementation< Key, Gen >& seq) {
578 stream << seq.toString();
579 return stream;
580 }
581
582 // returns the safe begin iterator
583 template < typename Key, bool Gen >
587
588 // returns the safe end iterator
589 template < typename Key, bool Gen >
593
594 // return an iterator pointing to the last element
595 template < typename Key, bool Gen >
598 it._setPos_(size() - 1);
599 return it;
600 }
601
602 // returns an iterator pointing just before the first element
603 template < typename Key, bool Gen >
607
608 // returns the unsafe begin iterator
609 template < typename Key, bool Gen >
610 SequenceIterator< Key > SequenceImplementation< Key, Gen >::begin() const {
611 return SequenceIterator< Key >{*this};
612 }
613
614 // returns the unsafe end iterator
615 template < typename Key, bool Gen >
616 const SequenceIterator< Key >& SequenceImplementation< Key, Gen >::end() const noexcept {
617 return _end_safe_;
618 }
619
620 // return an iterator pointing to the last element
621 template < typename Key, bool Gen >
622 SequenceIterator< Key > SequenceImplementation< Key, Gen >::rbegin() const {
623 SequenceIterator< Key > it{*this};
624 it._setPos_(size() - 1);
625 return it;
626 }
627
628 // returns an iterator pointing just before the first element
629 template < typename Key, bool Gen >
630 const SequenceIterator< Key >& SequenceImplementation< Key, Gen >::rend() const noexcept {
631 return _rend_safe_;
632 }
633
634 // modifies the size of the internal structures of the sequence
635 template < typename Key, bool Gen >
637 if (new_size < _h_.size()) return;
638
639 _h_.resize(new_size);
640 _v_.reserve(new_size);
641 }
642
643 // ===========================================================================
644 // === SCALAR GUM SEQUENCE IMPLEMENTATION ===
645 // ===========================================================================
646
647 // updates the end iterators
648 template < typename Key >
650 _end_safe_._setAtEnd_();
651 }
652
653 // clear the sequence
654 template < typename Key >
656 _h_.clear();
657 _v_.clear();
658 _update_end_();
659 }
660
661 // clears the current sequence and fill it with copies the element of aSeq
662 template < typename Key >
663 void
665 clear();
666
667 for (Size i = 0; i < aSeq.size(); ++i) {
668 _h_.insert(aSeq._v_[i], i);
669 _v_.push_back(aSeq._v_[i]);
670 }
671
672 _update_end_();
673 }
674
675 // Default constructor
676 template < typename Key >
678 _h_(size_param), _end_safe_{*this}, _rend_safe_{*this} {
679 GUM_CONSTRUCTOR(SequenceImplementation);
680 _rend_safe_._setAtRend_();
681 _end_safe_._setAtEnd_();
682 }
683
684 // initializer list constructor
685 template < typename Key >
686 SequenceImplementation< Key, true >::SequenceImplementation(std::initializer_list< Key > list) :
687 _end_safe_{*this}, _rend_safe_{*this} {
688 GUM_CONSTRUCTOR(SequenceImplementation);
689 _rend_safe_._setAtRend_();
690 for (const auto& elt: list) {
691 insert(elt);
692 }
693 }
694
695 // copy constructor
696 template < typename Key >
699 _h_(aSeq._h_), _v_(aSeq._v_), _end_safe_{*this}, _rend_safe_{*this} {
700 GUM_CONS_CPY(SequenceImplementation);
701 _rend_safe_._setAtRend_();
702 _end_safe_._setAtEnd_();
703 }
704
705 // move constructor
706 template < typename Key >
709 _h_(std::move(aSeq._h_)), _v_(std::move(aSeq._v_)), _end_safe_{*this}, _rend_safe_{*this} {
710 GUM_CONS_MOV(SequenceImplementation);
711 _rend_safe_._setAtRend_();
712 _end_safe_._setAtEnd_();
713 }
714
715 // destructor
716 template < typename Key >
718 GUM_DESTRUCTOR(SequenceImplementation);
719 }
720
721 // copy operator
722 template < typename Key >
725 // avoid self assignment
726 if (&aSeq != this) { _copy_(aSeq); }
727
728 return *this;
729 }
730
731 // move operator
732 template < typename Key >
735 // avoid self assignment
736 if (&aSeq != this) {
737 _h_ = std::move(aSeq._h_);
738 _v_ = std::move(aSeq._v_);
739 _update_end_();
740 }
741
742 return *this;
743 }
744
745 // check the existence of k in the sequence
746 template < typename Key >
748 return _h_.exists(k);
749 }
750
751 // returns a pointer to the position of k, or nullptr if not found
752 template < typename Key >
754 return _h_.tryGet(k);
755 }
756
757 // insert an element at the end of the sequence
758 template < typename Key >
760 // k will be added at the end. Insert the new key into the hashtable
761 Key& new_key = const_cast< Key& >(_h_.insert(k, _h_.size()).first);
762 try {
763 _v_.push_back(new_key);
764 } catch (...) {
765 _h_.erase(new_key);
766 throw;
767 }
768 _update_end_();
769 }
770
771 // emplace a new element in the sequence
772 template < typename Key >
773 template < typename... Args >
775 Key key(std::forward< Args >(args)...);
776 Key& new_key = const_cast< Key& >(_h_.insert(std::move(key), _h_.size()).first);
777 try {
778 _v_.push_back(new_key);
779 } catch (...) { _h_.erase(new_key); }
780 _update_end_();
781 }
782
783 // insert k in the sequence (synonym for insert)
784 template < typename Key >
786 insert(k);
787 return *this;
788 }
789
790 // remove an element from the sequence
791 template < typename Key >
793 // get the position of the element to remove
794 auto p = _h_.tryGet(k);
795 if (!p) return;
796 Idx pos = *p;
797
798 // erase the element
799 _v_.erase(_v_.begin() + pos);
800 for (Idx i = pos, nb_elts = _h_.size() - 1; i < nb_elts; ++i) {
801 --_h_[_v_[i]];
802 }
803 _h_.erase(k);
804
805 _update_end_();
806 }
807
808 // remove from the sequence the element pointed to by the iterator
809 template < typename Key >
810 void SequenceImplementation< Key, true >::erase(const iterator_safe& iter) {
811 if (iter.pos() >= size()) return;
812
813 // erase the element
814 Idx pos = iter.pos();
815 Key key = _v_[pos];
816 _v_.erase(_v_.begin() + pos);
817
818 for (Idx i = pos, nb_elts = _h_.size() - 1; i < nb_elts; ++i) {
819 --_h_[_v_[i]];
820 }
821 _h_.erase(key);
822
823 _update_end_();
824 }
825
826 // remove k in the sequence (synonym for erase)
827 template < typename Key >
829 erase(k);
830 return *this;
831 }
832
833 // returns the object at position i
834 template < typename Key >
836 if (i >= _h_.size()) { GUM_ERROR(NotFound, "not enough elements in the sequence") }
837
838 return _v_[i];
839 }
840
841 // returns the element at position i (synonym for atPos)
842 template < typename Key >
844 return atPos(i);
845 }
846
847 // returns the position of the object passed in argument (if it exists)
848 template < typename Key >
850 return _h_[key];
851 }
852
853 // sets the object at position i
854 template < typename Key >
856 if (i >= _h_.size()) { GUM_ERROR(NotFound, "index too large") }
857
858 _h_.insert(newKey, i);
859 _h_.erase(_v_[i]);
860 _v_[i] = newKey;
861 }
862
863 // replace two elements in the sequence
864 template < typename Key >
866 if (i == j) return;
867
868 Key ki = atPos(i);
869 Key kj = atPos(j);
870
871 _h_[ki] = j;
872 _h_[kj] = i;
873
874 _v_[i] = kj;
875 _v_[j] = ki;
876 }
877
878 // returns the first element
879 template < typename Key >
881 return atPos(0);
882 }
883
884 // returns the last element
885 template < typename Key >
887 return atPos(size() - 1);
888 }
889
890 // Print a sequence
891 template < typename Key >
893 std::stringstream stream;
894 stream << "[";
895
896 if (!_h_.empty()) {
897 stream << "0:" << _v_[0];
898
899 for (Idx i = 1; i < _h_.size(); ++i) {
900 stream << std::format(" - {}:", i) << _v_[i];
901 }
902 }
903
904 stream << "]";
905
906 return stream.str();
907 }
908
909 // returns true if the content of k equals that of *this
910 template < typename Key >
913 if (size() != k.size()) return false;
914 else {
915 for (Idx i = 0; i < size(); ++i)
916 if (_v_[i] != k._v_[i]) return false;
917 }
918
919 return true;
920 }
921
922 // returns true if the content of k is different from that of *this
923 template < typename Key >
926 return !operator==(k);
927 }
928
929 // a << operator for displaying the content of the Sequence
930 template < typename Key >
931 std::ostream& operator<<(std::ostream& stream, const SequenceImplementation< Key, true >& seq) {
932 stream << seq.toString();
933 return stream;
934 }
935
936 // returns the safe begin iterator
937 template < typename Key >
938 SequenceIteratorSafe< Key > SequenceImplementation< Key, true >::beginSafe() const {
939 return SequenceIteratorSafe< Key >{*this};
940 }
941
942 // return the safe end iterator
943 template < typename Key >
945 return _end_safe_;
946 }
947
948 // return an iterator pointing to the last element
949 template < typename Key >
952 it._setPos_(size() - 1);
953 return it;
954 }
955
956 // returns an iterator pointing just before the first element
957 template < typename Key >
960 return _rend_safe_;
961 }
962
963 // returns the unsafe begin iterator
964 template < typename Key >
965 SequenceIterator< Key > SequenceImplementation< Key, true >::begin() const {
966 return SequenceIterator< Key >{*this};
967 }
968
969 // return the unsafe end iterator
970 template < typename Key >
971 const SequenceIterator< Key >& SequenceImplementation< Key, true >::end() const noexcept {
972 return _end_safe_;
973 }
974
975 // return an unsafe iterator pointing to the last element
976 template < typename Key >
977 SequenceIterator< Key > SequenceImplementation< Key, true >::rbegin() const {
978 SequenceIterator< Key > it{*this};
979 it._setPos_(size() - 1);
980 return it;
981 }
982
983 // returns an unsafe iterator pointing just before the first element
984 template < typename Key >
985 const SequenceIterator< Key >& SequenceImplementation< Key, true >::rend() const noexcept {
986 return _rend_safe_;
987 }
988
989 // modifies the size of the internal structures of the sequence
990 template < typename Key >
992 if (new_size < _h_.size()) return;
993
994 _h_.resize(new_size);
995 _v_.reserve(new_size);
996 }
997
998 // ===========================================================================
999 // Sequence
1000 // ===========================================================================
1001
1002 // Default constructor
1003 template < typename Key >
1005 SequenceImplementation< Key, std::is_scalar< Key >::value >(size_param) {
1006 GUM_CONSTRUCTOR(Sequence);
1007 }
1008
1009 // initializer list constructor
1010 template < typename Key >
1011 Sequence< Key >::Sequence(std::initializer_list< Key > list) :
1012 SequenceImplementation< Key, std::is_scalar< Key >::value >(list) {
1013 // for debugging purposes
1014 GUM_CONSTRUCTOR(Sequence);
1015 }
1016
1017 // copy constructor
1018 template < typename Key >
1020 SequenceImplementation< Key, std::is_scalar< Key >::value >(aSeq) {
1021 // for debugging purposes
1022 GUM_CONS_CPY(Sequence);
1024
1025 // move constructor
1026 template < typename Key >
1028 SequenceImplementation< Key, std::is_scalar< Key >::value >(std::move(aSeq)) {
1029 // for debugging purposes
1030 GUM_CONS_MOV(Sequence);
1031 }
1032
1033 // destructor
1034 template < typename Key >
1036 // for debugging purposes
1037 GUM_DESTRUCTOR(Sequence);
1038 }
1039
1040 // copy operator
1041 template < typename Key >
1044 return *this;
1045 }
1046
1047 // move operator
1048 template < typename Key >
1050 Implementation::operator=(std::move(aSeq));
1051 return *this;
1052 }
1053
1054 // returns the set difference : this \ seq
1055 template < typename Key >
1057 Set< Key > res;
1058
1059 for (iterator iter = this->begin(); iter != this->end(); ++iter) {
1060 if (!seq.exists(*iter)) res << *iter;
1061 }
1063 return res;
1064 }
1065
1066 // a << operator for displaying the content of the Sequence
1067 template < typename Key >
1068 std::ostream& operator<<(std::ostream& stream, const Sequence< Key >& seq) {
1069 stream << seq.toString();
1070 return stream;
1071 }
1072
1073 template < bool gen >
1074 template < typename Key >
1075 const Key& SequenceIteratorGet< gen >::op_star(const Key* x) {
1076 return *x;
1077 }
1078
1079 template < bool gen >
1080 template < typename Key >
1081 const Key* SequenceIteratorGet< gen >::op_arrow(const Key* x) {
1082 return x;
1084
1085 template < typename Key >
1086 const Key& SequenceIteratorGet< true >::op_star(const Key& x) {
1087 return x;
1088 }
1089
1090 template < typename Key >
1091 const Key* SequenceIteratorGet< true >::op_arrow(const Key& x) {
1092 return &x;
1093 }
1094
1095} /* namespace gum */
Exception : the element we looked for cannot be found.
Exception : out of bound.
The internal class for storing (ordered) sequences of objects.
Definition sequence.h:109
std::string toString() const
Displays the content of the sequence.
const Key & atPos(Idx i) const
Returns the object at the pos i.
SequenceIteratorSafe< Key > iterator_safe
Types for STL compliance.
Definition sequence.h:128
optional_ref< const Idx > tryPos(const Key &k) const
Returns a pointer to the position of k in the sequence, or nullptr if k is not found.
iterator begin() const
Returns an unsafe begin iterator.
std::vector< Key * > _v_
The set of the elements stored into the sequence.
Definition sequence.h:502
SequenceImplementation< Key, Gen > & operator<<(const Key &k)
Insert k at the end of the sequence (synonym for insert).
const iterator & end() const noexcept
Returns the unsafe end iterator.
iterator_safe beginSafe() const
Returns a safe begin iterator.
const iterator & rend() const noexcept
Returns the unsafe rend iterator.
const Key & front() const
Returns the first element of the element.
void insert(const Key &k)
Insert an element at the end of the sequence.
bool operator==(const SequenceImplementation< Key, Gen > &k) const
Returns true if the content of k equals that of *this.
void erase(const Key &k)
Remove an element from the sequence.
void resize(Size new_size)
Modifies the size of the internal structures of the sequence.
void emplace(Args &&... args)
Emplace a new element in the sequence.
const Key & back() const
Returns the last element of the sequence.
bool empty() const noexcept
Return true if empty.
SequenceImplementation< Key, Gen > & operator>>(const Key &k)
Remove k in the sequence (synonym for erase).
iterator rbegin() const
Returns an unsafe rbegin iterator.
bool exists(const Key &k) const
Check the existence of k in the sequence.
~SequenceImplementation() noexcept
Class destructor.
const iterator_safe & rendSafe() const noexcept
Returns the safe rend iterator.
void setAtPos(Idx i, const Key &newKey)
Change the value.
SequenceImplementation< Key, Gen > & operator=(const SequenceImplementation< Key, Gen > &aSeq)
Copy operator.
SequenceIteratorSafe< Key > _end_safe_
Stores the end iterator for fast access.
Definition sequence.h:509
void _update_end_() noexcept
A method to update the end iterator after changes in the sequence.
void _copy_(const SequenceImplementation< Key, Gen > &aSeq)
Clears the current sequence and fill it with copies the element of aSeq.
iterator_safe rbeginSafe() const
Returns a safe rbegin iterator.
const Key & operator[](Idx i) const
Returns the element at position i (synonym for atPos).
friend class SequenceIteratorSafe< Key >
Friends to speed up access.
Definition sequence.h:112
void swap(Idx i, Idx j)
Swap index.
const iterator_safe & endSafe() const noexcept
Returns the safe end iterator.
void clear()
Clear the sequence.
Size size() const noexcept
Returns the size of the sequence.
HashTable< Key, Idx > _h_
Keep track of the position of the element in v (for fast retrieval).
Definition sequence.h:499
SequenceImplementation(Size size_param=HashTableConst::default_size)
Default constructor.
bool operator!=(const SequenceImplementation< Key, Gen > &k) const
Returns true if the content of k is different from that of *this.
Safe iterators for Sequence.
Definition sequence.h:1148
void _setAtRend_() noexcept
The iterator points to rend.
bool operator!=(const SequenceIteratorSafe< Key > &source) const noexcept
Checks whether two iterators are pointing to different elements.
SequenceIteratorSafe()=delete
Constructor, always give a valid iterator (even if pos too large).
SequenceIteratorSafe< Key > & operator++() noexcept
Point the iterator to the next value in the sequence.
void _setPos_(Idx pos) noexcept
The iterator points to the posth element (0 = beginning of the sequence).
const Key * operator->() const
Returns the value pointed to by the iterator (works only for non-scalars).
Idx _iterator_
The index in the sequence's vector where the iterator is pointing.
Definition sequence.h:1354
SequenceIteratorSafe< Key > operator+(Size nb) noexcept
Returns a new iterator.
SequenceIteratorSafe(const SequenceImplementation< Key, Gen > &seq, Idx pos=0) noexcept
Constructor, always give a valid iterator (even if pos too large).
SequenceIteratorSafe< Key > & operator--() noexcept
Point the iterator to the preceding value in the sequence.
void _setAtEnd_() noexcept
The iterator points to the end (which is pos size()-1).
SequenceIteratorSafe< Key > & operator-=(Size nb) noexcept
Makes the iterator point to i elements further in the sequence.
bool operator==(const SequenceIteratorSafe< Key > &source) const noexcept
Checks whether two iterators are pointing to the same elements.
~SequenceIteratorSafe() noexcept
Class destructor.
SequenceIteratorSafe< Key > & operator=(const SequenceIteratorSafe< Key > &source) noexcept
Copy operator.
const Key & operator*() const
Returns the value pointed to by the iterator.
SequenceIteratorSafe< Key > operator-(Size nb) noexcept
Returns a new iterator.
const SequenceImplementation< Key, std::is_scalar_v< Key > > * _seq_
The sequence pointed to by the iterator (by default, key is a scalar).
Definition sequence.h:1357
SequenceIteratorSafe< Key > & operator+=(Size nb) noexcept
Makes the iterator point to i elements further in the sequence.
Idx pos() const
Returns the position of the iterator in the sequence.
friend class SequenceImplementation
Friend to speed up access.
Definition sequence.h:1151
The generic class for storing (ordered) sequences of objects.
Definition sequence.h:994
Sequence(Size size_param=HashTableConst::default_size)
Default constructor.
Sequence< Key > & operator=(const Sequence< Key > &aSeq)
Copy operator.
~Sequence() noexcept
Class destructor.
SequenceIterator< Key > iterator
Types for STL compliance.
Definition sequence.h:1005
Set< Key > diffSet(const Sequence< Key > &seq) const
Difference between two sequences as a Set<Key> = this \ seq.
Representation of a set.
Definition set.h:129
Exception : generic error on iterator.
A lightweight wrapper around a pointer providing an optional-like API for references (not supported b...
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
bool operator==(const HashTableIteratorSafe< Key, Val > &from) const noexcept
Checks whether two iterators are pointing toward equal elements.
STL namespace.
Header file of gum::Sequence, a class for storing (ordered) sequences of objects.