• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
You are now the owner of this repo.

PeterCDMcLean / BitLib / 14949319596

10 May 2025 09:32PM UTC coverage: 96.898% (-0.1%) from 97.036%
14949319596

Pull #8

github

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

171 of 179 new or added lines in 5 files covered. (95.53%)

1 existing line in 1 file now uncovered.

1312 of 1354 relevant lines covered (96.9%)

16164538.6 hits per line

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

94.44
/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 typename base::const_iterator;
58
  using typename base::const_pointer;
59
  using typename base::const_reference;
60
  using typename base::difference_type;
61
  using typename base::iterator;
62
  using typename base::pointer;
63
  using typename base::reference;
64
  using typename base::size_type;
65
  using typename base::value_type;
66
  using typename base::word_type;
67

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

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

75
 private:
76
  static constexpr std::size_t Words_ = Words(N);
77
  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);
78

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

183
  constexpr iterator end() noexcept {
15✔
184
    return begin() + size();
15✔
185
  }
186

187
  constexpr const_iterator begin() const noexcept {
13✔
188
    return const_iterator(storage.begin());
13✔
189
  }
190

191
  constexpr const_iterator end() const noexcept {
11✔
192
    return const_iterator(storage.begin()) + size();
11✔
193
  }
194

195
  constexpr const_iterator cbegin() const noexcept {
196
    return const_iterator(storage.begin());
197
  }
198

199
  constexpr const_iterator cend() const noexcept {
200
    return const_iterator(storage.begin()) + size();
201
  }
202

203
  /*
204
    * Capacity
205
    */
206
  constexpr size_type size() const noexcept {
91✔
207
    return N;
91✔
208
  }
209

210
  /*
211
    * Operations
212
    */
213
  constexpr void swap(bit_array<T, N, V, W>& other) noexcept {
1✔
214
    std::swap(this->storage, other.storage);
1✔
215
  }
1✔
216

217
  template <std::integral U>
218
  explicit constexpr operator U() const noexcept
219
    requires(bitsof<U>() >= (bitsof<T>() * N))
220
  {
221
    return base::operator U();
222
  }
223
};
224

225
static_assert(bit_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_range concept!");
226
static_assert(bit_sized_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_sized_range concept!");
227
#ifdef CONTIGUOUS_RANGE
228
static_assert(bit_contiguous_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_range concept!");
229
static_assert(bit_contiguous_sized_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_sized_range concept!");
230
#endif
231

232
#if 0
233
// Class Template Argument Deduction
234
// CTAD guide for the constructor taking a word_type&,
235
// deducing Extent as bitsof<word_type>().
236
template <typename word_type>
237
bit_array(word_type&) -> bit_array<word_type, bitsof<word_type>()>;
238
template <typename word_type>
239
bit_array(word_type*) -> bit_array<word_type, bitsof<word_type>()>;
240

241
// CTAD guide for the constructor taking a word_type* and a size,
242
// which should always be used when Extent is std::dynamic_extent.
243
template <typename word_type>
244
bit_array(word_type&, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
245
template <typename word_type>
246
bit_array(word_type*, std::size_t) -> bit_array<word_type, std::dynamic_extent>;
247
#endif
248

249
}  // namespace bit
250

251
#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