51 int64_t InlineBufferCapacity = 64,
59 static constexpr int64_t required_ints_for_bits(
const int64_t number_of_bits)
64 static constexpr int64_t IntsInInlineBuffer = required_ints_for_bits(InlineBufferCapacity);
66 static constexpr int64_t AllocationAlignment =
alignof(
BitInt);
87 BitVector(Allocator allocator = {})
noexcept : allocator_(allocator)
89 data_ = inline_buffer_;
91 capacity_in_bits_ = BitsInInlineBuffer;
99 const int64_t ints_to_copy = required_ints_for_bits(span.
size());
100 if (span.
size() <= BitsInInlineBuffer) {
102 data_ = inline_buffer_;
103 capacity_in_bits_ = BitsInInlineBuffer;
107 data_ =
static_cast<BitInt *
>(
108 allocator_.allocate(ints_to_copy *
sizeof(
BitInt), AllocationAlignment, __func__));
109 capacity_in_bits_ = ints_to_copy *
BitsPerInt;
111 size_in_bits_ = span.
size();
117 allocator_ = other.allocator_;
122 if (other.is_inline()) {
126 int64_t ints_to_copy = IntsInInlineBuffer;
127 if constexpr (IntsInInlineBuffer > 8) {
129 ints_to_copy = other.used_ints_amount();
131 data_ = inline_buffer_;
138 size_in_bits_ = other.size_in_bits_;
139 capacity_in_bits_ = other.capacity_in_bits_;
142 other.data_ = other.inline_buffer_;
143 other.size_in_bits_ = 0;
144 other.capacity_in_bits_ = BitsInInlineBuffer;
153 this->
resize(size_in_bits, value);
168 if (!this->is_inline()) {
169 allocator_.deallocate(data_);
198 return size_in_bits_;
206 return capacity_in_bits_;
211 return size_in_bits_ == 0;
231 return {data_, index};
241 return {data_, index};
254 this->ensure_space_for_one();
267 return {data_, size_in_bits_};
277 return {data_, size_in_bits_};
287 const int64_t old_size_in_bits = size_in_bits_;
288 if (new_size_in_bits > old_size_in_bits) {
289 this->
reserve(new_size_in_bits);
291 size_in_bits_ = new_size_in_bits;
292 if (old_size_in_bits < new_size_in_bits) {
312 this->realloc_to_at_least(new_capacity_in_bits);
330 capacity_in_bits_ = 0;
331 if (!this->is_inline()) {
332 allocator_.deallocate(data_);
334 data_ = inline_buffer_;
338 void ensure_space_for_one()
340 if (
UNLIKELY(size_in_bits_ >= capacity_in_bits_)) {
341 this->realloc_to_at_least(size_in_bits_ + 1);
346 const BitInt initial_value_for_new_ints = 0)
348 if (capacity_in_bits_ >= min_capacity_in_bits) {
352 const int64_t min_capacity_in_ints = this->required_ints_for_bits(min_capacity_in_bits);
355 const int64_t min_new_capacity_in_ints = 2 * this->required_ints_for_bits(capacity_in_bits_);
357 const int64_t new_capacity_in_ints = std::max(min_capacity_in_ints, min_new_capacity_in_ints);
358 const int64_t ints_to_copy = this->used_ints_amount();
361 allocator_.allocate(new_capacity_in_ints *
sizeof(
BitInt), AllocationAlignment, __func__));
367 new_data + ints_to_copy, new_capacity_in_ints - ints_to_copy, initial_value_for_new_ints);
369 if (!this->is_inline()) {
370 allocator_.deallocate(data_);
374 capacity_in_bits_ = new_capacity_in_ints *
BitsPerInt;
377 bool is_inline()
const
379 return data_ == inline_buffer_;
382 int64_t used_ints_amount()
const
384 return this->required_ints_for_bits(size_in_bits_);
388template<
int64_t InlineBufferCapacity,
typename Allocator>
394template<
int64_t InlineBufferCapacity,
typename Allocator>
403using bits::BitVector;
#define BLI_NO_UNIQUE_ADDRESS
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
constexpr int64_t size() const
const BitInt * data() const
MutableBitIterator begin()
BitVector(const int64_t size_in_bits, const bool value=false, Allocator allocator={})
void resize(const int64_t new_size_in_bits, const bool value=false)
MutableBitRef operator[](const int64_t index)
BitVector(const Span< bool > values, Allocator allocator={})
BitIterator begin() const
void reserve(const int new_capacity_in_bits)
void append(const bool value)
BitVector(const BoundedBitSpan span)
BitVector(Allocator allocator={}) noexcept
BitVector & operator=(BitVector &&other)
BitVector & operator=(const BitVector &other)
BitVector(BitVector &&other) noexcept
BitVector(NoExceptConstructor, Allocator allocator={}) noexcept
void fill(const bool value)
IndexRange index_range() const
BitVector(const BitVector &other)
const BitInt * data() const
BitRef operator[](const int64_t index) const
bool or_bools_into_bits(Span< bool > bools, MutableBitSpan r_bits, int64_t allowed_overshoot=0)
static constexpr int64_t BitsPerInt
T to_best_bit_span(const T &data)
Container & copy_assign_container(Container &dst, const Container &src)
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
void uninitialized_fill_n(T *dst, int64_t n, const T &value)
void uninitialized_copy_n(const T *src, int64_t n, T *dst)