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

PeterCDMcLean / BitLib / 15668442123

15 Jun 2025 11:21PM UTC coverage: 54.204% (+0.7%) from 53.519%
15668442123

Pull #17

github

web-flow
Merge 91a9e717f into 0f0b787a1
Pull Request #17: Truncation policy

10212 of 18774 branches covered (54.39%)

Branch coverage included in aggregate %.

177 of 216 new or added lines in 12 files covered. (81.94%)

214 existing lines in 11 files now uncovered.

6035 of 11200 relevant lines covered (53.88%)

7755103.91 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 <span>
19
#include <string>
20
#include <type_traits>
21
#include <vector>
22

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

32
namespace bit {
33
// ========================================================================== //
34

35
namespace detail {
36

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

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

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

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

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

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

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

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

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

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

96
  template <std::integral U>
97
  constexpr bit_array(const U& integral) {
98
    if constexpr (bits < bitsof<U>) {
99
      Policy::truncation::template from_integral<U, N>(*this, integral);
100
    } else {
101
      bit_pointer<U> integral_ptr(&integral);
102
      ::bit::copy(integral_ptr, integral_ptr + bitsof<U>(), begin());
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