sparrow 2.2.1
C++20 idiomatic APIs for the Apache Arrow Columnar Format
Loading...
Searching...
No Matches
dynamic_bitset.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <type_traits>
18
22
23namespace sparrow
24{
55 template <std::integral T>
56 class dynamic_bitset : public dynamic_bitset_base<buffer<T>>
57 {
58 public:
59
62 using default_allocator = typename storage_type::default_allocator;
66
88 template <std::ranges::input_range R, allocator A>
89 requires std::convertible_to<std::ranges::range_value_t<R>, value_type>
90 constexpr explicit dynamic_bitset(const R& r, const A& a)
91 : dynamic_bitset(std::ranges::size(r), true, a)
92 {
93 std::size_t i = 0;
94 for (auto value : r)
95 {
96 if (!value)
97 {
98 this->set(i, false);
99 }
100 i++;
101 }
102 }
103
110 template <typename A>
111 requires(not std::same_as<A, dynamic_bitset<T>> and allocator<A>)
112 constexpr dynamic_bitset(const A& a);
113
122 template <allocator A>
123 constexpr explicit dynamic_bitset(size_type n, const A& a);
124
134 template <allocator A>
135 constexpr dynamic_bitset(size_type n, value_type v, const A& a);
136
153 template <allocator A>
154 constexpr dynamic_bitset(block_type* p, size_type n, const A& a);
155
171 template <allocator A>
172 constexpr dynamic_bitset(block_type* p, size_type n, size_type offset, const A& a);
173
191 template <allocator A>
193
205
219
220 constexpr ~dynamic_bitset() = default;
221 constexpr dynamic_bitset(const dynamic_bitset&) = default;
222 constexpr dynamic_bitset(dynamic_bitset&&) noexcept = default;
223
224 template <allocator A>
225 constexpr dynamic_bitset(const dynamic_bitset& rhs, const A& a);
226
227 template <allocator A>
228 constexpr dynamic_bitset(dynamic_bitset&& rhs, const A& a);
229
230 constexpr dynamic_bitset& operator=(const dynamic_bitset&) = default;
231 constexpr dynamic_bitset& operator=(dynamic_bitset&&) noexcept = default;
232
244 [[nodiscard]] constexpr dynamic_bitset slice(size_type start, size_type length) const;
245
256 [[nodiscard]] constexpr dynamic_bitset slice(size_type start) const;
257
258 // Inherit container-like operations from base class
259 using base_type::clear;
260 using base_type::emplace;
261 using base_type::erase;
262 using base_type::insert;
263 using base_type::pop_back;
264 using base_type::push_back;
265 using base_type::resize;
266 };
267
268 template <std::integral T>
269 template <class A>
270 requires(not std::same_as<A, dynamic_bitset<T>> and allocator<A>)
271 constexpr dynamic_bitset<T>::dynamic_bitset(const A& a)
272 : base_type(storage_type(a), 0u)
273 {
275 }
276
277 template <std::integral T>
278 template <allocator A>
280 : dynamic_bitset(n, false, a)
281 {
283 }
284
285 template <std::integral T>
286 template <allocator A>
288 : base_type(
289 storage_type(this->compute_block_count(n), value ? block_type(~block_type(0)) : block_type(0), a),
290 n,
291 0,
292 value ? 0u : n
293 )
294 {
296 }
297
298 template <std::integral T>
299 template <allocator A>
301 : base_type(storage_type(p, p != nullptr ? this->compute_block_count(n) : 0, a), n)
302 {
304 }
305
306 template <std::integral T>
307 template <allocator A>
313
314 template <std::integral T>
315 template <allocator A>
316 constexpr dynamic_bitset<
322
323 template <std::integral T>
329
330 template <std::integral T>
336
337 template <std::integral T>
338 template <allocator A>
339 constexpr dynamic_bitset<T>::dynamic_bitset(const dynamic_bitset& rhs, const A& a)
340 : base_type(storage_type(rhs, a))
341 {
342 }
343
344 template <std::integral T>
345 template <allocator A>
347 : base_type(storage_type(std::move(rhs), a))
348 {
349 }
350
351 template <std::integral T>
352 constexpr auto dynamic_bitset<T>::slice(size_type start, size_type length) const -> dynamic_bitset
353 {
354 if (start + length > this->size())
355 {
356 throw std::out_of_range("slice: start + length exceeds bitset size");
357 }
358
359 sparrow::buffer<T> buffer_copy = this->buffer();
360
361 return dynamic_bitset<T>(std::move(buffer_copy), length, this->offset() + start);
362 }
363
364 template <std::integral T>
365 constexpr auto dynamic_bitset<T>::slice(size_type start) const -> dynamic_bitset
366 {
367 if (start > this->size())
368 {
369 throw std::out_of_range("slice: start exceeds bitset size");
370 }
371
372 return slice(start, this->size() - start);
373 }
374
389
390 namespace detail
391 {
393
394 inline validity_bitmap ensure_validity_bitmap_impl(std::size_t size, const validity_bitmap& bitmap)
395 {
396 if (bitmap.size() == 0)
397 {
398 return {size, true, bitmap.buffer().get_allocator()};
399 }
400 return bitmap; // copy
401 }
402
404 {
405 if (bitmap.size() == 0)
406 {
407 bitmap.resize(size, true);
408 }
409 return std::move(bitmap);
410 }
411
412 // range of booleans
413 template <std::ranges::input_range R>
414 requires(std::same_as<std::ranges::range_value_t<R>, bool>)
415 validity_bitmap ensure_validity_bitmap_impl(std::size_t size, R&& range)
416 {
417 SPARROW_ASSERT_TRUE(size == range_size(range) || range_size(range) == 0);
419 std::size_t i = 0;
420 for (auto value : range)
421 {
422 if (!value)
423 {
424 bitmap.set(i, false);
425 }
426 i++;
427 }
428 return bitmap;
429 }
430
431 // range of indices / integers (but not booleans)
432 template <std::ranges::input_range R>
433 requires(
434 std::unsigned_integral<std::ranges::range_value_t<R>>
435 && !std::same_as<std::ranges::range_value_t<R>, bool>
436 && !std::same_as<std::decay_t<R>, validity_bitmap>
437 )
438 validity_bitmap ensure_validity_bitmap_impl(std::size_t size, R&& range_of_indices)
439 {
441 for (auto index : range_of_indices)
442 {
443 bitmap.set(index, false);
444 }
445 return bitmap;
446 }
447 } // namespace detail
448
462 template <class T>
463 concept validity_bitmap_input = (std::same_as<T, validity_bitmap> || std::same_as<T, const validity_bitmap&>
464 || (std::ranges::input_range<T>
465 && std::same_as<std::ranges::range_value_t<T>, bool>)
466 || (std::ranges::input_range<T>
467 && std::unsigned_integral<std::ranges::range_value_t<T>>) )
468 && (!std::same_as<std::remove_cvref_t<T>, std::string>
469 && !std::same_as<std::remove_cvref_t<T>, std::string_view>
470 && !std::same_as<std::decay_t<T>, const char*>);
471
502 template <validity_bitmap_input R>
503 validity_bitmap ensure_validity_bitmap(std::size_t size, R&& validity_input)
504 {
505 return detail::ensure_validity_bitmap_impl(size, std::forward<R>(validity_input));
506 }
507
508} // namespace sparrow
Object that owns a piece of contiguous memory.
Definition buffer.hpp:131
typename storage_type_without_cvrefpointer::value_type block_type
constexpr void set(size_type pos, value_type value)
static constexpr size_type compute_block_count(size_type bits_count) noexcept
constexpr size_type size() const noexcept
constexpr const storage_type_without_cvrefpointer & buffer() const noexcept
typename storage_type_without_cvrefpointer::size_type size_type
constexpr dynamic_bitset_base(storage_type buffer, size_type size)
constexpr size_type null_count() const noexcept
constexpr size_type offset() const noexcept
A dynamic size sequence of bits with efficient storage and manipulation operations.
constexpr dynamic_bitset(dynamic_bitset &&) noexcept=default
typename storage_type::default_allocator default_allocator
Type of default allocator.
constexpr void resize(size_type n, value_type b=false)
constexpr iterator erase(const_iterator pos)
constexpr void clear() noexcept
constexpr iterator insert(const_iterator pos, value_type value)
constexpr dynamic_bitset(storage_type &&buf, size_type size, size_type offset)
Constructs a bitset by taking ownership of a storage buffer.
constexpr dynamic_bitset(size_type n, const A &a)
Constructs a bitset with n bits, all initialized to false.
constexpr dynamic_bitset(size_type n, value_type v, const A &a)
Constructs a bitset with n bits, all initialized to the specified value.
typename base_type::block_type block_type
Type of each storage block (same as T)
constexpr dynamic_bitset(const dynamic_bitset &)=default
constexpr dynamic_bitset(block_type *p, size_type n, const A &a)
Constructs a bitset using existing memory.
constexpr iterator emplace(const_iterator pos, value_type value)
constexpr void push_back(value_type value)
constexpr dynamic_bitset slice(size_type start, size_type length) const
constexpr dynamic_bitset(storage_type &&buf, size_type size, size_type offset, size_type null_count)
Constructs a bitset by taking ownership of a storage buffer with null count.
constexpr dynamic_bitset(block_type *p, size_type n, size_type offset, size_type null_count, const A &a)
Constructs a bitset using existing memory with offset and null count tracking.
constexpr dynamic_bitset(block_type *p, size_type n, size_type offset, const A &a)
Constructs a bitset using existing memory with null count tracking.
dynamic_bitset_base< buffer< T > > base_type
Base class type.
typename base_type::storage_type storage_type
Underlying storage container type.
typename base_type::value_type value_type
Type of individual bit values (bool)
typename base_type::size_type size_type
Type used for sizes and indices.
constexpr ~dynamic_bitset()=default
constexpr dynamic_bitset(const R &r, const A &a)
Constructs a dynamic_bitset from an input range of convertible values.
constexpr dynamic_bitset(const A &a)
Default constructor.
Concept defining valid input types for validity bitmap creation.
#define SPARROW_ASSERT_TRUE(expr__)
sparrow::validity_bitmap validity_bitmap
validity_bitmap ensure_validity_bitmap_impl(std::size_t size, const validity_bitmap &bitmap)
constexpr std::size_t range_size(R &&r)
Definition ranges.hpp:35
dynamic_bitset< std::uint8_t > validity_bitmap
Type alias for a validity bitmap using 8-bit storage blocks.
validity_bitmap ensure_validity_bitmap(std::size_t size, R &&validity_input)
Ensures a validity bitmap of the specified size from various input types.
Extensions to the C++ standard library.