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

PeterCDMcLean / BitLib / 15658468082

15 Jun 2025 02:19AM UTC coverage: 54.19% (+0.7%) from 53.519%
15658468082

Pull #17

github

web-flow
Merge 9f7c4d06e into 0f0b787a1
Pull Request #17: Truncation policy

10212 of 18780 branches covered (54.38%)

Branch coverage included in aggregate %.

179 of 225 new or added lines in 12 files covered. (79.56%)

214 existing lines in 11 files now uncovered.

6037 of 11205 relevant lines covered (53.88%)

7751643.37 hits per line

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

86.52
/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_policy.hpp"
29
#include "bitlib/bit-containers/bit_span.hpp"
30
#include "bitlib/bit-iterator/bit.hpp"
31
#include "bitlib/bit_concepts.hpp"
32

33
namespace bit {
34
// ========================================================================== //
35

36
namespace detail {
37

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

41
template <typename value_type, typename word_type, std::size_t N>
42
struct bit_array_iterator_types {
43
  using iterator = typename std::conditional<std::is_same_v<value_type, bit_value>,
44
                                             bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>,
45
                                             typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>::type;
46

47
  using const_iterator = typename std::conditional<std::is_same_v<value_type, bit_value>,
48
                                                   bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::const_iterator>,
49
                                                   typename std::array<const word_type, Words<value_type, word_type, N>()>::const_iterator>::type;
50
};
51
}  // namespace detail
52

53
template <typename T = bit_value,
54
          std::size_t N = std::dynamic_extent,
55
          typename W = std::conditional_t<(N == std::dynamic_extent), std::uintptr_t, ceil_integral<N>>,
56
          typename Policy = policy::typical<W>>
57
class bit_array : public bit_array_base<bit_array<T, N, W>, T, N, W, Policy, detail::bit_array_iterator_types<T, W, N>> {
58
 public:
59
  using base = bit_array_base<bit_array<T, N, W>, T, N, W, Policy, detail::bit_array_iterator_types<T, W, N>>;
60
  using base::end;
61
  using typename base::const_iterator;
62
  using typename base::const_pointer;
63
  using typename base::const_reference;
64
  using typename base::difference_type;
65
  using typename base::iterator;
66
  using typename base::pointer;
67
  using typename base::reference;
68
  using typename base::size_type;
69
  using typename base::value_type;
70
  using typename base::word_type;
71

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

74
 protected:
UNCOV
75
  static constexpr std::size_t Words(std::size_t size_) {
UNCOV
76
    return (size_ * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>();
UNCOV
77
  }
78

79
 private:
80
  std::array<word_type, Words(N)> storage;
81

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

88
  /*This constructor is purely to simplify some corners of the API*/
89
  constexpr bit_array(size_type size) noexcept : storage{} {
12✔
90
    assert(size == N);
8!
91
  }
8✔
92

93
  constexpr bit_array(value_type bit_val) {
6✔
94
    this->fill(bit_val);
6✔
95
  }
6✔
96

97
  template <std::integral U>
98
  constexpr bit_array(const U& integral) {
99
    if constexpr (bits < bitsof<U>) {
100
      Policy::truncation::template from_integral<U, N>(*this, integral);
101
    } else {
102
      std::memcpy(&storage[0], &integral, sizeof(integral));
103
    }
104
    if constexpr (bitsof<U>() < bits) {
105
      Policy::extension::template from_integral<U, N>(*this, integral, detail::uninitialized);
106
    }
107
  }
108

109
  constexpr bit_array(const bit_array<T, N, W>& other) noexcept
1✔
110
      : storage(other.storage) {}
2✔
111

112
  constexpr bit_array(const bit_array<T, N, W>&& other) noexcept
1✔
113
      : storage(other.storage) {}
38✔
114

115
  constexpr bit_array(const bit_sized_range auto& other) {
4✔
116
    if (other.size() != this->size()) [[unlikely]] {
4✔
117
      throw std::invalid_argument("other bit_range contains an invalid number of bits for bit_array.");
2✔
118
    }
1✔
119
    ::bit::copy(other.begin(), other.end(), this->begin());
2✔
120
  };
2✔
121

122
  constexpr bit_array(const std::initializer_list<value_type> init)
8✔
123
    requires(!std::is_same_v<value_type, word_type>)
124
  {
8✔
125
    if (init.size() != bitsof(*this)) [[unlikely]] {
16!
126
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
2✔
127
    }
1✔
128
    std::copy(init.begin(), init.end(), this->begin());
14✔
129
  }
14✔
130

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

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

146
  constexpr bit_array(const std::string_view s)
2✔
147
    requires(std::is_same_v<value_type, bit_value>)
148
  {
2✔
149
    if (bitsof(*this) != static_cast<size_t>(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] {
4!
150
      throw std::invalid_argument("String contains an invalid number of bits for bit_array.");
2✔
151
    };
1✔
152
    size_type i = 0;
2✔
153
    for (char c : s) {
27!
154
      if (c == '0') {
26!
155
        begin()[i++] = bit0;
10✔
156
      } else if (c == '1') {
16!
157
        begin()[i++] = bit1;
12✔
158
      }
6✔
159
    }
13✔
160
  }
2✔
161

162
  ~bit_array() = default;
163
  /*
164
    * Assignment
165
    */
166
  constexpr bit_array& operator=(const bit_array<T, N, W, Policy>& other) = default;
167

168
  constexpr bit_array& operator=(const bit_sized_range auto& other) {
169
    if (other.size() != this->size()) [[unlikely]] {
170
      throw std::invalid_argument("other bit_sized_range contains an invalid number of bits for bit_array.");
171
    }
172
    ::bit::copy(other.begin(), other.end(), this->begin());
173
    return *this;
174
  };
175

176
  constexpr bit_array& operator=(bit_array<T, N, W, Policy>&& other) noexcept {
4✔
177
    std::copy(other.storage.begin(), other.storage.end(), storage.begin());
4✔
178
    return *this;
4✔
179
  }
2✔
180

181
  constexpr word_type* data() noexcept {
2✔
182
    return size() ? storage.data() : nullptr;
3!
183
  }
1✔
184

185
  constexpr const word_type* data() const noexcept {
186
    return size() ? storage.data() : nullptr;
187
  }
188

189
  /*
190
    * Iterators
191
    */
192
  constexpr iterator begin() noexcept {
1,303✔
193
    return iterator(storage.begin());
1,303✔
194
  }
910✔
195

196
  constexpr const_iterator begin() const noexcept {
168✔
197
    return const_iterator(storage.begin());
168✔
198
  }
84✔
199

200
  /*
201
    * Capacity
202
    */
203
  constexpr size_type size() const noexcept {
1,364✔
204
    return N;
1,364✔
205
  }
954✔
206

207
  /*
208
    * Operations
209
    */
210
  constexpr void swap(bit_array<T, N, W>& other) noexcept {
2✔
211
    std::swap(this->storage, other.storage);
2✔
212
  }
2✔
213

214
  constexpr operator bit_value() const noexcept
2✔
215
    requires(std::is_same_v<value_type, bit_value> && N == 1)
216
  {
2✔
217
    return this->begin()[0];
4✔
218
  }
2✔
219
};
220

221
static_assert(bit_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_range concept!");
222
static_assert(bit_sized_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_sized_range concept!");
223
#ifdef CONTIGUOUS_RANGE
224
static_assert(bit_contiguous_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_range concept!");
225
static_assert(bit_contiguous_sized_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_sized_range concept!");
226
#endif
227

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

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

245
}  // namespace bit
246

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