• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PeterCDMcLean / BitLib / 14950244216

10 May 2025 11:50PM UTC coverage: 96.875% (-0.2%) from 97.036%
14950244216

Pull #8

github

web-flow
Merge ac41f7e7e into a837637fd
Pull Request #8: Common bit array base

161 of 169 new or added lines in 5 files covered. (95.27%)

2 existing lines in 2 files now uncovered.

1302 of 1344 relevant lines covered (96.88%)

16284812.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/include/bitlib/bit-containers/bit_array.hpp
1
// ================================= BIT_ARRAY =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        bit_array.hpp
4
// Description: Implementation of bit_array
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9
#ifndef _BIT_ARRAY_HPP_INCLUDED
10
#define _BIT_ARRAY_HPP_INCLUDED
11
// ========================================================================== //
12

13
// ================================ PREAMBLE ================================ //
14
// C++ standard library
15
#include <algorithm>
16
#include <bit>
17
#include <cmath>
18
#include <cstring>  // memcpy
19
#include <span>
20
#include <string>
21
#include <type_traits>
22
#include <vector>
23

24
// Project sources
25
#include "bitlib/bit-algorithms/bit_algorithm.hpp"
26
#include "bitlib/bit-containers/bit_array_base.hpp"
27
#include "bitlib/bit-containers/bit_bitsof.hpp"
28
#include "bitlib/bit-containers/bit_span.hpp"
29
#include "bitlib/bit-iterator/bit.hpp"
30

31
namespace bit {
32
// ========================================================================== //
33

34
namespace detail {
35

36
template <typename value_type, typename word_type, std::size_t N>
37
constexpr size_t Words() { return (N * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>(); }
38

39
template <typename value_type, typename word_type, std::size_t N>
40
using bit_array_d_it = typename std::conditional<std::is_same_v<value_type, bit_value>,
41
                                                 bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>,
42
                                                 typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>::type;
43

44
template <typename value_type, typename word_type, std::size_t N>
45
using bit_array_d_cit = typename std::conditional<std::is_same_v<value_type, bit_value>,
46
                                                  bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::const_iterator>,
47
                                                  typename std::array<const word_type, Words<value_type, word_type, N>()>::const_iterator>::type;
48
}  // namespace detail
49

50
template <typename T = bit_value,
51
          std::size_t N = std::dynamic_extent,
52
          std::align_val_t V = std::align_val_t(alignof(T)),
53
          typename W = std::conditional_t<std::is_same_v<T, bit_value>, uint8_t, T>>
54
class bit_array : public bit_array_base<bit_array<T, N, V, W>, T, W, detail::bit_array_d_it<T, W, N>, detail::bit_array_d_cit<T, W, N>> {
55
 public:
56
  using base = bit_array_base<bit_array<T, N, V, W>, T, W, detail::bit_array_d_it<T, W, N>, detail::bit_array_d_cit<T, W, N>>;
57
  using base::end;
58
  using typename base::const_iterator;
59
  using typename base::const_pointer;
60
  using typename base::const_reference;
61
  using typename base::difference_type;
62
  using typename base::iterator;
63
  using typename base::pointer;
64
  using typename base::reference;
65
  using typename base::size_type;
66
  using typename base::value_type;
67
  using typename base::word_type;
68

69
  static constexpr std::size_t bits = N * bitsof<T>();
70

71
 protected:
72
  static constexpr std::size_t Words(std::size_t size_) {
73
    return (size_ * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>();
74
  }
75

76
 private:
77
  static constexpr std::size_t Words_ = Words(N);
78
  static constexpr std::size_t AlignedWords = (((Words_ * sizeof(word_type) + static_cast<size_t>(V) - 1) & ~(static_cast<size_t>(V) - 1)) + sizeof(word_type) - 1) / sizeof(word_type);
79

80
  alignas(static_cast<size_t>(V)) std::array<word_type, AlignedWords> storage;
81

82
 public:
83
  /*
84
  * Constructors, copies and moves...
85
  */
86
  constexpr bit_array() noexcept : storage{} {}
2✔
87

88
  constexpr bit_array(value_type bit_val) : storage{} {
89
    this->fill(bit_val);
90
  }
91

92
  template <std::integral U>
93
  constexpr bit_array(const U& integral)
94
    requires(bitsof<U>() <= bits)
95
  {
96
    std::memcpy(&storage[0], &integral, sizeof(integral));
97

98
    bool sign_extend = false;
99
    if constexpr (std::is_signed_v<U>) {
100
      sign_extend = (integral & (1 << (bitsof<U>() - 1))) ? true : false;
101
    }
102
    if (sign_extend) {
103
      for (auto it = begin() + bitsof<U>(); it != end(); ++it) {
104
        *it = bit1;
105
      }
106
    } else {
107
      for (auto it = begin() + bitsof<U>(); it != end(); ++it) {
108
        *it = bit0;
109
      }
110
    }
111
  }
112

113
  constexpr bit_array(const bit_array<T, N, V, W>& other) = default;
114

115
  constexpr bit_array(const bit_array<T, N, V, W>&& other) noexcept
1✔
116
      : storage(other.storage) {}
1✔
117

118
  constexpr bit_array(const std::initializer_list<value_type> init)
6✔
119
    requires(!std::is_same_v<value_type, word_type>)
120
  {
121
    if (init.size() != bitsof(*this)) [[unlikely]] {
6✔
NEW
122
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
×
123
    }
124
    std::copy(init.begin(), init.end(), this->begin());
6✔
125
  }
6✔
126

127
  constexpr bit_array(const std::initializer_list<bool> init) {
128
    if (init.size() != bitsof(*this)) [[unlikely]] {
129
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
130
    }
131
    std::copy(init.begin(), init.end(), this->begin());
132
  }
133

134
  constexpr bit_array(const std::initializer_list<word_type> init) : storage{} {
135
    // Make sure we handle the case where init.size() != Words
136
    auto it = init.begin();
137
    for (size_type i = 0; i < std::min(AlignedWords, init.size()); ++i, ++it) {
138
      storage[i] = *it;
139
    }
140
  }
141

142
  constexpr bit_array(const std::string_view s)
1✔
143
    requires(std::is_same_v<value_type, bit_value>)
144
  {
145
    if (bitsof(*this) != static_cast<size_t>(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] {
1✔
NEW
146
      throw std::invalid_argument("String contains an invalid number of bits for bit_array.");
×
147
    };
148
    size_type i = 0;
1✔
149
    for (char c : s) {
14✔
150
      if (c == '0') {
13✔
151
        begin()[i++] = bit0;
5✔
152
      } else if (c == '1') {
8✔
153
        begin()[i++] = bit1;
6✔
154
      }
155
    }
156
  }
1✔
157

158
  ~bit_array() = default;
159
  /*
160
    * Assignment
161
    */
162
  constexpr bit_array& operator=(const bit_array<T, N, V, W>& other) = default;
163

164
  constexpr bit_array& operator=(bit_array<T, N, V, W>&& other) noexcept {
1✔
165
    std::copy(other.storage.begin(), other.storage.end(), storage.begin());
1✔
166
    return *this;
1✔
167
  }
168

169
  constexpr word_type* data() noexcept {
1✔
170
    return size() ? storage.data() : nullptr;
2✔
171
  }
172

173
  constexpr const word_type* data() const noexcept {
174
    return size() ? storage.data() : nullptr;
175
  }
176

177
  /*
178
    * Iterators
179
    */
180
  constexpr iterator begin() noexcept {
121✔
181
    return iterator(storage.begin());
121✔
182
  }
183

184
  constexpr const_iterator begin() const noexcept {
24✔
185
    return const_iterator(storage.begin());
24✔
186
  }
187

188
  /*
189
    * Capacity
190
    */
191
  constexpr size_type size() const noexcept {
91✔
192
    return N;
91✔
193
  }
194

195
  /*
196
    * Operations
197
    */
198
  constexpr void swap(bit_array<T, N, V, W>& other) noexcept {
1✔
199
    std::swap(this->storage, other.storage);
1✔
200
  }
1✔
201
};
202

203
static_assert(bit_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_range concept!");
204
static_assert(bit_sized_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_sized_range concept!");
205
#ifdef CONTIGUOUS_RANGE
206
static_assert(bit_contiguous_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_range concept!");
207
static_assert(bit_contiguous_sized_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_sized_range concept!");
208
#endif
209

210
#if 0
211
// Class Template Argument Deduction
212
// CTAD guide for the constructor taking a word_type&,
213
// deducing Extent as bitsof<word_type>().
214
template <typename word_type>
215
bit_array(word_type&) -> bit_array<word_type, bitsof<word_type>()>;
216
template <typename word_type>
217
bit_array(word_type*) -> bit_array<word_type, bitsof<word_type>()>;
218

219
// CTAD guide for the constructor taking a word_type* and a size,
220
// which should always be used when Extent is std::dynamic_extent.
221
template <typename word_type>
222
bit_array(word_type&, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
223
template <typename word_type>
224
bit_array(word_type*, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
225
#endif
226

227
}  // namespace bit
228

229
#endif  // _BIT_ARRAY_HPP_INCLUDED
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc