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

PeterCDMcLean / BitLib / 16780993828

06 Aug 2025 03:13PM UTC coverage: 71.949% (-2.8%) from 74.757%
16780993828

Pull #28

github

web-flow
Merge 77a02a220 into 61746a6ab
Pull Request #28: Use upload / download action instead of cache

3451 of 5352 branches covered (64.48%)

Branch coverage included in aggregate %.

2438 of 2833 relevant lines covered (86.06%)

16239128.44 hits per line

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

82.42
/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{} {}
16✔
102

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

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

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

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

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

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

129
  constexpr array(const std::initializer_list<value_type> init)
130
    requires(!std::is_same_v<value_type, word_type>)
131
      : base() {
8✔
132
    if (init.size() != bitsof(*this)) [[unlikely]] {
8!
133
      throw std::invalid_argument("initialize_list contains an invalid number of bits for array.");
1✔
134
    }
1✔
135
    std::copy(init.begin(), init.end(), this->begin());
7✔
136
  }
7✔
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)
154
    requires(std::is_same_v<value_type, bit_value>)
155
      : base() {
2✔
156
    if (bitsof(*this) != static_cast<size_t>(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] {
2!
157
      throw std::invalid_argument("String contains an invalid number of bits for array.");
1✔
158
    };
1✔
159
    size_type i = 0;
1✔
160
    for (char c : s) {
13!
161
      if (c == '0') {
13!
162
        begin()[i++] = bit0;
5✔
163
      } else if (c == '1') {
8!
164
        begin()[i++] = bit1;
6✔
165
      }
6✔
166
    }
13✔
167
  }
1✔
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 {
2✔
184
    std::copy(other.storage.begin(), other.storage.end(), storage.begin());
2✔
185
    return *this;
2✔
186
  }
2✔
187

188
  constexpr word_type* data() noexcept {
1✔
189
    return size() ? storage.data() : nullptr;
1!
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 {
258✔
200
    return iterator(storage.begin());
258✔
201
  }
258✔
202

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

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

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

221
  constexpr operator bit_value() const noexcept
222
    requires(std::is_same_v<value_type, bit_value> && N == 1)
223
  {
2✔
224
    return this->begin()[0];
2✔
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