ORIGINAL
Loading...
Searching...
No Matches
bitSet.h
Go to the documentation of this file.
1#ifndef BITSET_H
2#define BITSET_H
3
4#include "array.h"
5#include "couple.h"
6#include "iterationStream.h"
7
8
9namespace original {
28 template<typename ALLOC = allocator<bool>>
29 class bitSet final : public baseArray<bool, ALLOC>, public iterationStream<bool, bitSet<ALLOC>>{
33 using underlying_type = u_integer;
34
40 using rebind_alloc_underlying = ALLOC::template rebind_alloc<underlying_type>;
41
42 static constexpr integer BLOCK_MAX_SIZE = sizeof(underlying_type) * 8;
43
49
50 u_integer size_;
51
58 void bitsetInit(u_integer size);
59
66 [[nodiscard]] static bool getBitFromBlock(underlying_type block_value, integer bit);
67
74 [[nodiscard]] static underlying_type setBitFromBlock(underlying_type block_value, integer bit);
75
82 [[nodiscard]] static underlying_type clearBitFromBlock(underlying_type block_value, integer bit);
83
90 [[nodiscard]] static underlying_type clearHigherBitsFromBlock(underlying_type block_value, integer bit);
91
95 void clearRedundantBits();
96
103 [[nodiscard]] bool getBit(integer bit, integer block) const;
104
110 void setBit(integer bit, integer block);
111
117 void clearBit(integer bit, integer block);
118
125 void writeBit(integer bit, integer block, bool value);
126
132 static couple<u_integer, integer> toInnerIdx(integer index);
133
140 static integer toOuterIdx(u_integer cur_block, integer cur_bit);
141
142 public:
143
151 class Iterator final : public baseIterator<bool> {
152 mutable integer cur_bit;
153 mutable integer cur_block;
154 mutable underlying_type* block_;
155 const bitSet* container_;
156
164 explicit Iterator(integer bit, integer block, underlying_type* block_p, const bitSet* container);
165
171 bool equalPtr(const iterator *other) const override;
172
173 public:
174 friend class bitSet;
175
180 Iterator* clone() const override;
181
186 [[nodiscard]] bool hasNext() const override;
187
192 [[nodiscard]] bool hasPrev() const override;
193
199 bool atPrev(const iterator *other) const override;
200
206 bool atNext(const iterator *other) const override;
207
211 void next() const override;
212
216 void prev() const override;
217
222 Iterator* getPrev() const override;
223
228 Iterator* getNext() const override;
229
234 void operator+=(integer steps) const override;
235
240 void operator-=(integer steps) const override;
241
247 integer operator-(const iterator& other) const override;
248
253 bool& get() override;
254
259 [[nodiscard]] std::string className() const override;
260
265 [[nodiscard]] bool get() const override;
266
271 void set(const bool &data) override;
272
277 [[nodiscard]] bool isValid() const override;
278 };
279
287 explicit bitSet(u_integer size, ALLOC allocator = ALLOC{});
288
293 bitSet(const std::initializer_list<bool>& lst);
294
301 bitSet(const bitSet& other);
302
310 bitSet& operator=(const bitSet& other);
311
319 bitSet(bitSet&& other) noexcept;
320
329 bitSet& operator=(bitSet&& other) noexcept;
330
337 void swap(bitSet& other) noexcept;
338
343 [[nodiscard]] u_integer count() const;
344
351
356 [[nodiscard]] u_integer size() const override;
357
362 [[nodiscard]] Iterator* begins() const override;
363
368 [[nodiscard]] Iterator* ends() const override;
369
375 [[nodiscard]] bool get(integer index) const override;
376
382 bool& operator[](integer index) override;
383
389 void set(integer index, const bool &e) override;
390
396 [[nodiscard]] u_integer indexOf(const bool &e) const override;
397
398 ~bitSet() override = default;
399
405 bitSet& operator&=(const bitSet& other);
406
412 bitSet& operator|=(const bitSet& other);
413
419 bitSet& operator^=(const bitSet& other);
420
425 [[nodiscard]] std::string className() const override;
426
432 template<typename Callback = transform<bool>>
433 void forEach(Callback operation = Callback{}) = delete;
434
441 template<typename ALLOC_>
443
450 template<typename ALLOC_>
452
459 template<typename ALLOC_>
461
467 template<typename ALLOC_>
469 };
470
478 template<typename ALLOC_>
480
488 template<typename ALLOC_>
490
498 template<typename ALLOC_>
500
507 template<typename ALLOC_>
509}
510
511namespace std {
518 template<typename ALLOC>
519 void swap(original::bitSet<ALLOC>& lhs, original::bitSet<ALLOC>& rhs) noexcept; // NOLINT
520}
521
522 template<typename ALLOC>
523 auto original::bitSet<ALLOC>::bitsetInit(const u_integer size) -> void
524 {
525 this->map = array<underlying_type, rebind_alloc_underlying>((size + BLOCK_MAX_SIZE - 1) / BLOCK_MAX_SIZE, rebind_alloc_underlying{});
526 this->size_ = size;
527 }
528
529 template<typename ALLOC>
530 auto original::bitSet<ALLOC>::getBitFromBlock(const underlying_type block_value, const integer bit) -> bool {
531 return block_value & underlying_type{1} << bit;
532 }
533
534 template<typename ALLOC>
535 auto original::bitSet<ALLOC>::setBitFromBlock(const underlying_type block_value, const integer bit) -> underlying_type {
536 return block_value | underlying_type{1} << bit;
537 }
538
539 template<typename ALLOC>
540 auto original::bitSet<ALLOC>::clearBitFromBlock(const underlying_type block_value, const integer bit) -> underlying_type {
541 return block_value & ~(underlying_type{1} << bit);
542 }
543
544 template<typename ALLOC>
545 auto original::bitSet<ALLOC>::clearHigherBitsFromBlock(const underlying_type block_value, const integer bit) -> underlying_type
546 {
547 return block_value & (underlying_type{1} << (bit + 1)) - underlying_type{1};
548 }
549
550 template<typename ALLOC>
552 {
553 this->map.set(-1, clearHigherBitsFromBlock(this->map.get(-1), toInnerIdx(this->size() - 1).second()));
554 }
555
556 template<typename ALLOC>
557 auto original::bitSet<ALLOC>::getBit(const integer bit, const integer block) const -> bool {
558 return getBitFromBlock(this->map.get(block), bit);
559 }
560
561 template<typename ALLOC>
562 auto original::bitSet<ALLOC>::setBit(const integer bit, const integer block) -> void {
563 this->map.set(block, setBitFromBlock(this->map.get(block), bit));
564 }
565
566 template<typename ALLOC>
567 auto original::bitSet<ALLOC>::clearBit(const integer bit, const integer block) -> void {
568 this->map.set(block, clearBitFromBlock(this->map.get(block), bit));
569 }
570
571 template<typename ALLOC>
572 auto original::bitSet<ALLOC>::writeBit(const integer bit, const integer block, const bool value) -> void {
573 value ? this->setBit(bit, block) : this->clearBit(bit, block);
574 }
575
576 template<typename ALLOC>
577 auto original::bitSet<ALLOC>::toInnerIdx(const integer index) -> couple<u_integer, integer> {
578 return {static_cast<u_integer>(index / BLOCK_MAX_SIZE), index % BLOCK_MAX_SIZE};
579 }
580
581 template<typename ALLOC>
582 auto original::bitSet<ALLOC>::toOuterIdx(const u_integer cur_block, const integer cur_bit) -> integer
583 {
584 return cur_block * BLOCK_MAX_SIZE + cur_bit;
585 }
586
587 template<typename ALLOC>
588 original::bitSet<ALLOC>::Iterator::Iterator(const integer bit, const integer block, underlying_type* block_p, const bitSet* container)
589 : cur_bit(bit), cur_block(block), block_(block_p), container_(container) {}
590
591 template<typename ALLOC>
592 auto original::bitSet<ALLOC>::Iterator::equalPtr(const iterator *other) const -> bool {
593 auto* other_it = dynamic_cast<const Iterator*>(other);
594 return other_it != nullptr
595 && this->cur_bit == other_it->cur_bit
596 && this->cur_block == other_it->cur_block;
597 }
598
599 template<typename ALLOC>
601 return new Iterator(*this);
602 }
603
604 template<typename ALLOC>
606 return toOuterIdx(this->cur_block, this->cur_bit) < this->container_->size() - 1;
607 }
608
609 template<typename ALLOC>
611 return toOuterIdx(this->cur_block, this->cur_bit) > 0;
612 }
613
614 template<typename ALLOC>
616 auto* other_it = dynamic_cast<const Iterator*>(other);
617 if (other_it == nullptr)
618 return false;
619 return this->operator-(*other_it) == -1;
620 }
621
622 template<typename ALLOC>
624 auto* other_it = dynamic_cast<const Iterator*>(other);
625 if (other_it == nullptr)
626 return false;
627 return this->operator-(*other_it) == 1;
628 }
629
630 template<typename ALLOC>
632 this->operator+=(1);
633 }
634
635 template<typename ALLOC>
637 this->operator-=(1);
638 }
639
640 template<typename ALLOC>
642 if (!this->isValid()) throw outOfBoundError();
643 auto* it = this->clone();
644 it->prev();
645 return it;
646 }
647
648 template<typename ALLOC>
650 if (!this->isValid()) throw outOfBoundError();
651 auto* it = this->clone();
652 it->next();
653 return it;
654 }
655
656 template<typename ALLOC>
658 {
659 auto new_idx = toInnerIdx(toOuterIdx(this->cur_block, this->cur_bit) + steps);
660 this->cur_block = new_idx.first();
661 this->cur_bit = new_idx.second();
662 }
663
664 template<typename ALLOC>
666 {
667 auto new_idx = toInnerIdx(toOuterIdx(this->cur_block, this->cur_bit) - steps);
668 this->cur_block = new_idx.first();
669 this->cur_bit = new_idx.second();
670 }
671
672 template<typename ALLOC>
674 auto* other_it = dynamic_cast<const Iterator*>(&other);
675 if (other_it == nullptr)
676 return this > &other ?
677 (std::numeric_limits<integer>::max)() :
678 (std::numeric_limits<integer>::min)();
679 if (this->container_ != other_it->container_)
680 return this->container_ > other_it->container_ ?
681 (std::numeric_limits<integer>::max)() :
682 (std::numeric_limits<integer>::min)();
683
684 return toOuterIdx(this->cur_block, this->cur_bit) - toOuterIdx(other_it->cur_block, other_it->cur_bit);
685 }
686
687 template<typename ALLOC>
691
692 template<typename ALLOC>
694 return "bitSet::Iterator";
695 }
696
697 template<typename ALLOC>
699 {
700 if (!this->isValid()) throw outOfBoundError();
701 return getBitFromBlock(*this->block_, this->cur_bit);
702 }
703
704 template<typename ALLOC>
705 auto original::bitSet<ALLOC>::Iterator::set(const bool &data) -> void {
706 if (!this->isValid()) throw outOfBoundError();
707 *this->block_ = data ?
708 setBitFromBlock(*this->block_, this->cur_bit) : clearBitFromBlock(*this->block_, this->cur_bit);
709 }
710
711 template<typename ALLOC>
713 const auto outer = toOuterIdx(this->cur_block, this->cur_bit);
714 return outer >= 0 && outer < this->container_->size();
715 }
716
717 template<typename ALLOC>
719 : baseArray<bool, ALLOC>(std::move(allocator)), size_() {
720 this->bitsetInit(size);
721 }
722
723 template<typename ALLOC>
724 original::bitSet<ALLOC>::bitSet(const std::initializer_list<bool>& lst) : bitSet(lst.size()) {
725 u_integer i = 0;
726 for (const auto& e : lst) {
727 auto idx = toInnerIdx(i);
728 this->writeBit(idx.second(), idx.first(), e);
729 i += 1;
730 }
731 }
732
733 template<typename ALLOC>
735 this->operator=(other);
736 }
737
738 template<typename ALLOC>
740 if (this == &other) return *this;
741 this->map = other.map;
742 this->size_ = other.size_;
743 if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
744 this->allocator = other.allocator;
745 }
746 return *this;
747 }
748
749 template<typename ALLOC>
751 {
752 this->operator=(std::move(other));
753 }
754
755 template<typename ALLOC>
757 {
758 if (this == &other)
759 return *this;
760
761 this->map = std::move(other.map);
762 this->size_ = other.size_;
763 if constexpr (ALLOC::propagate_on_container_move_assignment::value){
764 this->allocator = other.allocator;
765 }
766 other.bitsetInit(0);
767 return *this;
768 }
769
770 template <typename ALLOC>
772 {
773 if (this == &other)
774 return;
775
776 std::swap(this->size_, other.size_);
777 std::swap(this->map, other.map);
778 if constexpr (ALLOC::propagate_on_container_swap::value) {
779 std::swap(this->allocator, other.allocator);
780 }
781 }
782
783 template<typename ALLOC>
785 u_integer count = 0;
786 for (const auto& e : this->map) {
787 auto n = e;
788 while (n) {
789 n &= n - 1;
790 count += 1;
791 }
792 }
793 return count;
794 }
795
796 template<typename ALLOC>
798 if (this->size() == new_size) {
799 return *this;
800 }
801
802 auto nb = bitSet(new_size);
803 const u_integer blocks_min = minimum(nb.map.size(),
804 this->map.size());
805 for (u_integer i = 0; i < blocks_min; i++) {
806 nb.map.set(i, this->map.get(i));
807 }
808 nb.clearRedundantBits();
809 return nb;
810 }
811
812 template<typename ALLOC>
814 {
815 return this->size_;
816 }
817
818 template<typename ALLOC>
820 return new Iterator(0, 0, &this->map.data(), this);
821 }
822
823 template<typename ALLOC>
825 return new Iterator(toInnerIdx(this->size() - 1).second(), this->map.size() - 1,
826 &this->map.data() + this->map.size() - 1, this);
827 }
828
829 template<typename ALLOC>
830 auto original::bitSet<ALLOC>::get(integer index) const -> bool {
831 if (this->indexOutOfBound(index)) throw outOfBoundError();
832 index = this->parseNegIndex(index);
833 auto idx = toInnerIdx(index);
834 return this->getBit(idx.second(), idx.first());
835 }
836
837 template<typename ALLOC>
841
842 template<typename ALLOC>
843 auto original::bitSet<ALLOC>::set(integer index, const bool &e) -> void {
844 if (this->indexOutOfBound(index)) throw outOfBoundError();
845 index = this->parseNegIndex(index);
846 auto idx = toInnerIdx(index);
847 this->writeBit(idx.second(), idx.first(), e);
848 }
849
850 template<typename ALLOC>
851 auto original::bitSet<ALLOC>::indexOf(const bool &e) const -> u_integer {
852 for (u_integer i = 0; i < this->size(); i++) {
853 if (auto idx = toInnerIdx(i);
854 e == this->getBit(idx.second(), idx.first())) {
855 return i;
856 }
857 }
858 return this->size();
859 }
860
861 template<typename ALLOC>
863 if (this->size() != other.size()) {
864 const auto resized = other.resize(this->size());
865 for (u_integer i = 0; i < this->map.size(); i++) {
866 this->map.set(i, this->map.get(i) & resized.map.get(i));
867 }
868 }else {
869 for (u_integer i = 0; i < this->map.size(); i++) {
870 this->map.set(i, this->map.get(i) & other.map.get(i));
871 }
872 }
873 return *this;
874 }
875
876 template<typename ALLOC>
878 if (this->size() != other.size()) {
879 const auto resized = other.resize(this->size());
880 for (u_integer i = 0; i < this->map.size(); i++) {
881 this->map.set(i, this->map.get(i) | resized.map.get(i));
882 }
883 }else {
884 for (u_integer i = 0; i < this->map.size(); i++) {
885 this->map.set(i, this->map.get(i) | other.map.get(i));
886 }
887 }
888 return *this;
889 }
890
891 template<typename ALLOC>
893 if (this->size() != other.size()) {
894 const auto resized = other.resize(this->size());
895 for (u_integer i = 0; i < this->map.size(); i++) {
896 this->map.set(i, this->map.get(i) ^ resized.map.get(i));
897 }
898 }else {
899 for (u_integer i = 0; i < this->map.size(); i++) {
900 this->map.set(i, this->map.get(i) ^ other.map.get(i));
901 }
902 }
903 return *this;
904 }
905
906 template<typename ALLOC>
908 return "bitSet";
909 }
910
911 template<typename ALLOC_>
913 bitSet bs{lbs};
914 bs &= rbs;
915 return bs;
916 }
917
918 template<typename ALLOC_>
919 auto original::operator|(const bitSet<ALLOC_> &lbs, const bitSet<ALLOC_> &rbs) -> bitSet<ALLOC_> {
920 bitSet bs{lbs};
921 bs |= rbs;
922 return bs;
923 }
924
925 template<typename ALLOC_>
926 auto original::operator^(const bitSet<ALLOC_> &lbs, const bitSet<ALLOC_> &rbs) -> bitSet<ALLOC_> {
927 bitSet bs{lbs};
928 bs ^= rbs;
929 return bs;
930 }
931
932 template<typename ALLOC_>
933 auto original::operator~(const bitSet<ALLOC_> &bs) -> bitSet<ALLOC_> {
934 bitSet nbs(bs);
935 for (u_integer i = 0; i < nbs.map.size(); i++) {
936 nbs.map.set(i, ~nbs.map.get(i));
937 }
938 nbs.clearRedundantBits();
939 return nbs;
940 }
941
942 template <typename ALLOC>
944 {
945 lhs.swap(rhs);
946 }
947
948#endif //BITSET_H
Provides the array class for a fixed-size container with random access.
Default memory allocator using allocators utilities.
Definition allocator.h:153
void swap(autoPtr &other) noexcept
Swaps the reference counters between two autoPtr instances.
Definition autoPtr.h:703
const TYPE * get() const
Get managed pointer const version.
Definition autoPtr.h:629
Base class for fixed-size serial containers.
Definition baseArray.h:43
A base class for basic iterators.
Definition iterator.h:296
An iterator for traversing the bits in a bitSet.
Definition bitSet.h:151
bool hasPrev() const override
Checks if there is a previous element.
Definition bitSet.h:610
bool hasNext() const override
Checks if there is a next element.
Definition bitSet.h:605
Iterator * getPrev() const override
Gets the previous iterator.
Definition bitSet.h:641
bool atNext(const iterator *other) const override
Checks if the iterator is at the next element.
Definition bitSet.h:623
bool & get() override
Gets the value of the current bit.
Definition bitSet.h:688
void next() const override
Moves the iterator to the next element.
Definition bitSet.h:631
Iterator * clone() const override
Clones the iterator.
Definition bitSet.h:600
bool atPrev(const iterator *other) const override
Checks if the iterator is at the previous element.
Definition bitSet.h:615
std::string className() const override
Returns the class name of this iterator.
Definition bitSet.h:693
void operator+=(integer steps) const override
Advances the iterator by the given number of steps.
Definition bitSet.h:657
void operator-=(integer steps) const override
Moves the iterator backward by the given number of steps.
Definition bitSet.h:665
void set(const bool &data) override
Sets the value of the current bit.
Definition bitSet.h:705
void prev() const override
Moves the iterator to the previous element.
Definition bitSet.h:636
bool isValid() const override
Checks if the iterator is valid.
Definition bitSet.h:712
Iterator * getNext() const override
Gets the next iterator.
Definition bitSet.h:649
A class representing a set of bits, offering functionality to manipulate and query individual bits.
Definition bitSet.h:29
Iterator * begins() const override
Gets the iterator to the beginning of the bitSet.
Definition bitSet.h:819
friend bitSet< ALLOC_ > operator^(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Performs a bitwise XOR operation between two bitSets.
bitSet & operator|=(const bitSet &other)
Performs a bitwise OR operation between two bitSets.
Definition bitSet.h:877
u_integer indexOf(const bool &e) const override
Finds the index of the first occurrence of a specific value.
Definition bitSet.h:851
bitSet & operator&=(const bitSet &other)
Performs a bitwise AND operation between two bitSets.
Definition bitSet.h:862
bitSet(u_integer size, ALLOC allocator=ALLOC{})
Constructs a bitSet with the given size.
Definition bitSet.h:718
Iterator * ends() const override
Gets the iterator to the end of the bitSet.
Definition bitSet.h:824
bool & operator[](integer index) override
Gets the reference of a specific bit by index.
Definition bitSet.h:838
void set(integer index, const bool &e) override
Sets the value of a specific bit by index.
Definition bitSet.h:843
bitSet & operator^=(const bitSet &other)
Performs a bitwise XOR operation between two bitSets.
Definition bitSet.h:892
u_integer size() const override
Gets the size of the bitSet.
Definition bitSet.h:813
void swap(bitSet &other) noexcept
Swaps the contents of this bitSet with another.
Definition bitSet.h:771
bitSet resize(u_integer new_size) const
Resizes the bitSet to the given size.
Definition bitSet.h:797
bool get(integer index) const override
Gets the value of a specific bit by index.
Definition bitSet.h:830
friend bitSet< ALLOC_ > operator&(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Performs a bitwise AND operation between two bitSets.
void forEach(Callback operation=Callback{})=delete
Deleted forEach method to prevent misuse.
u_integer count() const
Counts the number of bits set to true.
Definition bitSet.h:784
friend bitSet< ALLOC_ > operator~(const bitSet< ALLOC_ > &bs)
Performs a bitwise NOT operation on a bitSet.
friend bitSet< ALLOC_ > operator|(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Performs a bitwise OR operation between two bitSets.
std::string className() const override
Gets the class name for the bitSet.
Definition bitSet.h:907
bitSet & operator=(const bitSet &other)
Copy assignment operator.
Definition bitSet.h:739
Abstract base class for containers.
Definition container.h:26
A stream class that allows iteration, comparison, hashing and printing.
Definition iterationStream.h:60
Base iterator interface that supports common operations for iteration.
Definition iterator.h:37
friend iterator< T > * operator-(const iterator< T > &it, integer steps)
Subtracts a number of steps from the iterator's current position and returns a new iterator.
Abstract base class for key-value mapping containers.
Definition map.h:49
Exception for container index out-of-range errors.
Definition error.h:192
Unique ownership smart pointer with move semantics.
Definition ownerPtr.h:37
Abstract base class for unique element containers.
Definition set.h:44
Exception for unimplemented method calls.
Definition error.h:271
Generic pair container implementation.
Provides functionality for an iteration stream with comparison, hashing and printing.
Main namespace for the project Original.
Definition algorithms.h:21
auto operator-(const iterator< T > &it, integer steps) -> iterator< T > *
Subtracts a number of steps from the iterator's current position and returns a new iterator.
bitSet< ALLOC_ > operator^(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Bitwise XOR operator for two bitSets.
bitSet< ALLOC_ > operator~(const bitSet< ALLOC_ > &bs)
Bitwise NOT operator for a bitSet.
TYPE minimum(TYPE a, TYPE b)
Returns the smaller of two given values.
bitSet< ALLOC_ > operator&(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Bitwise AND operator for two bitSets.
bitSet< ALLOC_ > operator|(const bitSet< ALLOC_ > &lbs, const bitSet< ALLOC_ > &rbs)
Bitwise OR operator for two bitSets.
auto count()
Creates a count pipe operation.
Definition generators.h:957
Standard namespace extensions for original::alternative.
Definition allocator.h:351
void swap(original::objPoolAllocator< TYPE > &lhs, original::objPoolAllocator< TYPE > &rhs) noexcept
Specialization of std::swap for objPoolAllocator.
Definition allocator.h:635