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

PeterCDMcLean / BitLib / 15696616722

17 Jun 2025 02:29AM UTC coverage: 54.11% (+0.6%) from 53.519%
15696616722

Pull #17

github

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

10137 of 18710 branches covered (54.18%)

Branch coverage included in aggregate %.

212 of 251 new or added lines in 13 files covered. (84.46%)

214 existing lines in 11 files now uncovered.

6062 of 11227 relevant lines covered (53.99%)

7736453.1 hits per line

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

88.24
/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{} {}
16✔
86

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

91
  template <std::integral U>
92
  constexpr bit_array(const U& integral) {
80✔
93
    this->from_integral(integral);
80✔
94
  }
80✔
95

96
  constexpr bit_array(const bit_array<T, N, W>& other) noexcept
1✔
97
      : storage(other.storage) {}
2✔
98

99
  constexpr bit_array(const bit_array<T, N, W>&& other) noexcept
1✔
100
      : storage(other.storage) {}
2✔
101

102
  constexpr bit_array(const bit_sized_range auto& other) {
4✔
103
    if (other.size() != this->size()) [[unlikely]] {
4✔
104
      throw std::invalid_argument("other bit_range contains an invalid number of bits for bit_array.");
2✔
105
    }
1✔
106
    ::bit::copy(other.begin(), other.end(), this->begin());
2✔
107
  };
2✔
108

109
  constexpr bit_array(const std::initializer_list<value_type> init)
8✔
110
    requires(!std::is_same_v<value_type, word_type>)
111
  {
8✔
112
    if (init.size() != bitsof(*this)) [[unlikely]] {
16!
113
      throw std::invalid_argument("initialize_list contains an invalid number of bits for bit_array.");
2✔
114
    }
1✔
115
    std::copy(init.begin(), init.end(), this->begin());
14✔
116
  }
14✔
117

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

125
  constexpr bit_array(const std::initializer_list<word_type> init) : storage{} {
126
    // Make sure we handle the case where init.size() != Words
127
    auto it = init.begin();
128
    for (size_type i = 0; i < std::min(Words(N), init.size()); ++i, ++it) {
129
      storage[i] = *it;
130
    }
131
  }
132

133
  constexpr bit_array(const std::string_view s)
2✔
134
    requires(std::is_same_v<value_type, bit_value>)
135
  {
2✔
136
    if (bitsof(*this) != static_cast<size_t>(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] {
4!
137
      throw std::invalid_argument("String contains an invalid number of bits for bit_array.");
2✔
138
    };
1✔
139
    size_type i = 0;
2✔
140
    for (char c : s) {
27!
141
      if (c == '0') {
26!
142
        begin()[i++] = bit0;
10✔
143
      } else if (c == '1') {
16!
144
        begin()[i++] = bit1;
12✔
145
      }
6✔
146
    }
13✔
147
  }
2✔
148

149
  ~bit_array() = default;
150
  /*
151
    * Assignment
152
    */
153
  constexpr bit_array& operator=(const bit_array<T, N, W, Policy>& other) = default;
154

155
  constexpr bit_array& operator=(const bit_sized_range auto& other) {
156
    if (other.size() != this->size()) [[unlikely]] {
157
      throw std::invalid_argument("other bit_sized_range contains an invalid number of bits for bit_array.");
158
    }
159
    ::bit::copy(other.begin(), other.end(), this->begin());
160
    return *this;
161
  };
162

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

168
  constexpr word_type* data() noexcept {
2✔
169
    return size() ? storage.data() : nullptr;
3!
170
  }
1✔
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 {
426✔
180
    return iterator(storage.begin());
426✔
181
  }
213✔
182

183
  constexpr const_iterator begin() const noexcept {
160✔
184
    return const_iterator(storage.begin());
160✔
185
  }
80✔
186

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

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

201
  constexpr operator bit_value() const noexcept
2✔
202
    requires(std::is_same_v<value_type, bit_value> && N == 1)
203
  {
2✔
204
    return this->begin()[0];
4✔
205
  }
2✔
206
};
207

208
static_assert(bit_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_range concept!");
209
static_assert(bit_sized_range<bit_array<bit_value, 11>>, "bit_array does not satisfy bit_sized_range concept!");
210
#ifdef CONTIGUOUS_RANGE
211
static_assert(bit_contiguous_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_range concept!");
212
static_assert(bit_contiguous_sized_range<bit_array<11>>, "bit_array does not satisfy bit_contiguous_sized_range concept!");
213
#endif
214

215
#if 0
216
// Class Template Argument Deduction
217
// CTAD guide for the constructor taking a word_type&,
218
// deducing Extent as bitsof<word_type>().
219
template <typename word_type>
220
bit_array(word_type&) -> bit_array<word_type, bitsof<word_type>()>;
221
template <typename word_type>
222
bit_array(word_type*) -> bit_array<word_type, bitsof<word_type>()>;
223

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

232
}  // namespace bit
233

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