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

PeterCDMcLean / BitLib / 16781103655

06 Aug 2025 03:17PM UTC coverage: 74.757%. Remained the same
16781103655

push

github

web-flow
Use upload / download action instead of cache (#28)

* Use upload / download action instead of cache

* Try without single quotes

* Rerun base_ref build if possible

3451 of 5352 branches covered (64.48%)

Branch coverage included in aggregate %.

2555 of 2682 relevant lines covered (95.26%)

29850565.99 hits per line

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

86.96
/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-iterator/bit.hpp"
29
#include "bitlib/bit_concepts.hpp"
30

31
namespace bit {
32

33
template <typename T = bit_value,
34
          std::size_t N = std::dynamic_extent,
35
          typename W = std::conditional_t<
36
              std::is_same_v<T, bit_value>,
37
              std::conditional_t<
38
                  (N == std::dynamic_extent),
39
                  std::uintptr_t,
40
                  ceil_integral<N>>,
41
              T>,
42
          typename Policy = policy::typical<std::remove_cvref_t<W>>>
43
class array;
44

45
template <std::size_t N = std::dynamic_extent,
46
          typename W = std::conditional_t<
47
              (N == std::dynamic_extent),
48
              std::uintptr_t,
49
              ceil_integral<N>>,
50
          typename Policy = policy::typical<std::remove_cvref_t<W>>>
51
using bit_array = array<bit_value, N, W, Policy>;
52

53
namespace detail {
54

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

58
template <typename value_type, typename word_type, std::size_t N>
59
struct array_iterator_types {
60
  using iterator = typename std::conditional<std::is_same_v<value_type, bit_value>,
61
                                             bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>,
62
                                             typename std::array<word_type, Words<value_type, word_type, N>()>::iterator>::type;
63

64
  using const_iterator = typename std::conditional<std::is_same_v<value_type, bit_value>,
65
                                                   bit_iterator<typename std::array<word_type, Words<value_type, word_type, N>()>::const_iterator>,
66
                                                   typename std::array<const word_type, Words<value_type, word_type, N>()>::const_iterator>::type;
67
};
68
}  // namespace detail
69

70
template <typename T, std::size_t N, typename W, typename Policy>
71
class array : public array_base<array<T, N, W, Policy>, T, N, W, false, Policy, detail::array_iterator_types<T, W, N>> {
72
 public:
73
  using base = array_base<array<T, N, W, Policy>, T, N, W, false, Policy, detail::array_iterator_types<T, W, N>>;
74
  using base::end;
75
  using base::size;
76
  using typename base::const_iterator;
77
  using typename base::const_pointer;
78
  using typename base::const_reference;
79
  using typename base::difference_type;
80
  using typename base::iterator;
81
  using typename base::pointer;
82
  using typename base::reference;
83
  using typename base::size_type;
84
  using typename base::value_type;
85
  using typename base::word_type;
86

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

89
 protected:
90
  static constexpr std::size_t Words(std::size_t size_) {
91
    return (size_ * bitsof<value_type>() + bitsof<word_type>() - 1) / bitsof<word_type>();
92
  }
93

94
 private:
95
  std::array<word_type, Words(N)> storage;
96

97
 public:
98
  /*
99
  * Constructors, copies and moves...
100
  */
101
  constexpr array() noexcept : storage{} {}
18✔
102

103
  constexpr array(value_type bit_val) {
9✔
104
    this->fill(bit_val);
6✔
105
  }
6✔
106

107
  constexpr array(detail::uninitialized_t, const size_t& size) {
12✔
108
    assert(size == N);
8!
109
  }
8✔
110

111
  template <std::integral U>
112
  constexpr array(const U& integral) {
189✔
113
    this->from_integral(integral);
126✔
114
  }
126✔
115

116
  constexpr array(const array<T, N, W, Policy>& other) noexcept
14✔
117
      : base(), storage(other.storage) {}
28✔
118

119
  constexpr array(const array<T, N, W, Policy>&& other) noexcept
1✔
120
      : base(), storage(other.storage) {}
2✔
121

122
  constexpr array(const bit_sized_range auto& other) : base() {
6✔
123
    if (other.size() != this->size()) [[unlikely]] {
4✔
124
      throw std::invalid_argument("other bit_range contains an invalid number of bits for array.");
2✔
125
    }
1✔
126
    ::bit::copy(other.begin(), other.end(), this->begin());
2✔
127
  };
2✔
128

129
  constexpr array(const std::initializer_list<value_type> init)
8✔
130
    requires(!std::is_same_v<value_type, word_type>)
131
      : base() {
16✔
132
    if (init.size() != bitsof(*this)) [[unlikely]] {
16!
133
      throw std::invalid_argument("initialize_list contains an invalid number of bits for array.");
2✔
134
    }
1✔
135
    std::copy(init.begin(), init.end(), this->begin());
14✔
136
  }
14✔
137

138
  constexpr array(const std::initializer_list<bool> init) : base() {
139
    if (init.size() != bitsof(*this)) [[unlikely]] {
140
      throw std::invalid_argument("initialize_list contains an invalid number of bits for array.");
141
    }
142
    std::copy(init.begin(), init.end(), this->begin());
143
  }
144

145
  constexpr array(const std::initializer_list<word_type> init) : base(), storage{} {
146
    // Make sure we handle the case where init.size() != Words
147
    auto it = init.begin();
148
    for (size_type i = 0; i < std::min(Words(N), init.size()); ++i, ++it) {
149
      storage[i] = *it;
150
    }
151
  }
152

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

169
  ~array() = default;
170
  /*
171
    * Assignment
172
    */
173
  constexpr array& operator=(const array<T, N, W, Policy>& other) = default;
174

175
  constexpr array& operator=(const bit_sized_range auto& other) {
176
    if (other.size() != this->size()) [[unlikely]] {
177
      throw std::invalid_argument("other bit_sized_range contains an invalid number of bits for array.");
178
    }
179
    ::bit::copy(other.begin(), other.end(), this->begin());
180
    return *this;
181
  };
182

183
  constexpr array& operator=(array<T, N, W, Policy>&& other) noexcept {
4✔
184
    std::copy(other.storage.begin(), other.storage.end(), storage.begin());
4✔
185
    return *this;
4✔
186
  }
2✔
187

188
  constexpr word_type* data() noexcept {
2✔
189
    return size() ? storage.data() : nullptr;
3!
190
  }
1✔
191

192
  constexpr const word_type* data() const noexcept {
193
    return size() ? storage.data() : nullptr;
194
  }
195

196
  /*
197
    * Iterators
198
    */
199
  constexpr iterator begin() noexcept {
516✔
200
    return iterator(storage.begin());
516✔
201
  }
258✔
202

203
  constexpr const_iterator begin() const noexcept {
256✔
204
    return const_iterator(storage.begin());
256✔
205
  }
128✔
206

207
  /*
208
    * Capacity
209
    */
210
  constexpr size_type size() const noexcept {
260✔
211
    return N;
260✔
212
  }
130✔
213

214
  /*
215
    * Operations
216
    */
217
  constexpr void swap(array<T, N, W, Policy>& other) noexcept {
2✔
218
    std::swap(this->storage, other.storage);
2✔
219
  }
2✔
220

221
  constexpr operator bit_value() const noexcept
2✔
222
    requires(std::is_same_v<value_type, bit_value> && N == 1)
223
  {
2✔
224
    return this->begin()[0];
4✔
225
  }
2✔
226
};
227

228
static_assert(bit_range<bit_array<11>>, "array does not satisfy bit_range concept!");
229
static_assert(bit_sized_range<bit_array<11>>, "array does not satisfy bit_sized_range concept!");
230
#ifdef CONTIGUOUS_RANGE
231
static_assert(bit_contiguous_range<array<11>>, "array does not satisfy bit_contiguous_range concept!");
232
static_assert(bit_contiguous_sized_range<array<11>>, "array does not satisfy bit_contiguous_sized_range concept!");
233
#endif
234

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

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

252
}  // namespace bit
253

254
#endif  // _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