• 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

84.08
/include/bitlib/bit-containers/bit_array_base.hpp
1
// ================================= BIT_ARRAY_BASE =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        bit_array_base.hpp
4
// Description: Base implementation for bit_array variants
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9
#ifndef _BIT_ARRAY_BASE_HPP_INCLUDED
10
#define _BIT_ARRAY_BASE_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_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

31
namespace bit {
32

33
template <typename T, typename W, typename Policy>
34
class bit_array_ref;
35

36
template <typename T,
37
          std::size_t N,
38
          typename W,
39
          typename Policy>
40
class bit_array;
41

42
/**
43
 * @brief Base class template for bit_array implementations
44
 *
45
 * This is a CRTP (Curiously Recurring Template Pattern) base class that provides
46
 * common functionality for bit_array variants.
47
 *
48
 * @tparam Derived The derived class (CRTP pattern)
49
 * @tparam T The value type (typically bit_value)
50
 * @tparam W The word type used for storage
51
 * @tparam N The size of the bit array, or std::dynamic_extent for dynamic size
52
 * @tparam Policy The policy for integral conversion (default is typical)
53
 * @tparam Iterators A struct that provides iterator and const_iterator types
54
 */
55
template <typename Derived, typename T, size_t N, typename W, typename Policy, typename Iterators>
56
class bit_array_base {
57
 protected:
58
  constexpr Derived& derived() noexcept {
3,363✔
59
    return static_cast<Derived&>(*this);
3,363✔
60
  }
1,940✔
61

62
  constexpr const Derived& derived() const noexcept {
246✔
63
    return static_cast<const Derived&>(*this);
246✔
64
  }
123✔
65

66
 public:
67
  using word_type = W;
68
  using value_type = T;
69
  using size_type = std::size_t;
70
  using difference_type = std::ptrdiff_t;
71
  using reference = typename std::conditional<std::is_same_v<T, bit_value>, bit_reference<word_type&>, T&>::type;
72
  using const_reference = typename std::conditional<std::is_same_v<T, bit_value>, const bit_reference<const word_type&>, const T&>::type;
73
  using pointer = typename std::conditional<std::is_same_v<T, bit_value>, bit_pointer<word_type>, T&>::type;
74
  using const_pointer = const pointer;
75
  using iterator = Iterators::iterator;
76
  using const_iterator = Iterators::const_iterator;
77

78
  // Element access
79
  constexpr reference operator[](size_type pos) {
2,849✔
80
    return derived().begin()[pos];
4,015✔
81
  }
1,683✔
82

83
  constexpr const_reference operator[](size_type pos) const {
84
    return derived().begin()[pos];
85
  }
86

87
  constexpr reference at(size_type pos) {
26✔
88
    if (pos < derived().size()) {
26!
89
      return derived().begin()[pos];
30✔
90
    } else {
10✔
91
      throw std::out_of_range("Position is out of range");
6✔
92
    }
3✔
93
  }
13✔
94

95
  constexpr const_reference at(size_type pos) const {
96
    if (pos < derived().size()) {
97
      return derived().begin()[pos];
98
    } else {
99
      throw std::out_of_range("Position is out of range");
100
    }
101
  }
102

103
  constexpr reference front() {
6✔
104
    return derived().begin()[0];
9✔
105
  }
3✔
106

107
  constexpr const_reference front() const {
108
    return derived().begin()[0];
109
  }
110

111
  constexpr reference back() {
6✔
112
    return derived().begin()[derived().size() - 1];
9✔
113
  }
3✔
114

115
  constexpr const_reference back() const {
116
    return derived().begin()[derived().size() - 1];
117
  }
118

119
  constexpr iterator end() noexcept {
128✔
120
    return derived().begin() + derived().size();
128✔
121
  }
64✔
122

123
  constexpr const_iterator end() const noexcept {
98✔
124
    return const_iterator(derived().begin()) + derived().size();
98✔
125
  }
49✔
126

127
  constexpr const_iterator cbegin() const noexcept {
128
    return const_iterator(derived().begin());
129
  }
130

131
  constexpr const_iterator cend() const noexcept {
132
    return const_iterator(derived().end());
133
  }
134

135
  // Capacity
136
  constexpr bool empty() const noexcept {
8✔
137
    return 0 == derived().size();
8✔
138
  }
4✔
139

140
  constexpr size_type max_size() const noexcept {
2✔
141
    return derived().size();
2✔
142
  }
1✔
143

144
  // String representation
145
  constexpr std::string debug_string() const {
146
    return debug_string(derived().begin(), derived().end());
147
  }
148

149
  constexpr std::string debug_string(const_iterator first, const_iterator last) const {
150
    std::string ret = "";
151
    auto position = 0;
152
    for (auto it = first; it != last; ++it) {
153
      if (position % bitsof<word_type>() == 0 && position != 0) {
154
        ret += " ";
155
      } else if (position % 8 == 0 && position != 0) {
156
        ret += '.';
157
      }
158
      ret += *it == bit1 ? '1' : '0';
159
      ++position;
160
    }
161
    return ret;
162
  }
163

164
  /**
165
   * @brief Slice operations - returns a bit_array_ref
166
   */
167
  constexpr auto operator()(size_type offset, size_type right) const noexcept {
168
    return bit_array_ref<bit_value, const word_type, Policy>(&this->at(offset), right - offset);
169
  }
170

171
  /**
172
   * @brief Slice operations - returns a bit_array_ref
173
   */
174
  constexpr auto operator()(size_type offset, size_type right) noexcept {
16✔
175
    return bit_array_ref<bit_value, word_type, Policy>(&this->at(offset), right - offset);
16✔
176
  }
8✔
177

178
  // Common operations
179
  constexpr void fill(value_type bit_val) noexcept {
76✔
180
    std::fill(derived().begin(), derived().end(), bit_val);
76✔
181
  }
76✔
182

183
  /**
184
   * @brief Explicit conversion to integral types
185
   */
186
  template <std::integral U>
187
  explicit constexpr operator U() const noexcept {
4✔
188
    assert(derived().size() <= bitsof<U>());
4!
189
    U integral;
4✔
190

191
    if constexpr (N == std::dynamic_extent) {
2✔
192
      if (derived().size() > bitsof<U>()) {
4!
NEW
193
        Policy::truncation::template to_integral<U, N>(derived(), integral);
×
194
      } else {
2✔
195
        ::bit::copy(derived().begin(), end(), bit_pointer<U>(&integral));
4✔
196
      }
2✔
197
      if (derived().size() < bitsof<U>()) {
4!
NEW
198
        Policy::extension::template to_integral<U, N>(derived(), integral);
×
NEW
199
      }
200
    } else {
201
      if constexpr (N > bitsof<U>()) {
202
        Policy::truncation::template to_integral<U, N>(derived(), integral);
203
      } else {
204
        ::bit::copy(derived().begin(), end(), bit_pointer<U>(&integral));
205
      }
206
      if constexpr (N < bitsof<U>()) {
207
        Policy::extension::template to_integral<U, N>(derived(), integral);
208
      }
209
    }
210

211
    return integral;
4✔
212
  }
2✔
213

214
  using compatible_bitarray = bit_array<value_type, N, word_type, Policy>;
215

216
  constexpr compatible_bitarray operator~() {
4✔
217
    compatible_bitarray result(derived().size());
6✔
218
    transform(derived().begin(), derived().end(), result.begin(), [](const word_type& bits) -> word_type { return ~bits; });
8✔
219
    return result;
6✔
220
  }
2✔
221

222
  constexpr compatible_bitarray operator|(const bit_sized_range auto& other) const {
2✔
223
    assert(other.size() == derived().size());
2!
224
    compatible_bitarray result(derived().size());
2✔
225
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
2✔
226
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
3✔
227
    return result;
3✔
228
  }
1✔
229
  constexpr Derived& operator|=(bit_sized_range auto& other) {
2✔
230
    assert(other.size() == derived().size());
2!
231
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
2✔
232
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
3✔
233
    return derived();
3✔
234
  }
1✔
235
  constexpr compatible_bitarray operator&(const bit_sized_range auto& other) const {
2✔
236
    assert(other.size() == derived().size());
2!
237
    compatible_bitarray result(derived().size());
2✔
238
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
2✔
239
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
3✔
240
    return result;
3✔
241
  }
1✔
242
  constexpr Derived& operator&=(bit_sized_range auto& other) {
2✔
243
    assert(other.size() == derived().size());
2!
244
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
2✔
245
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
3✔
246
    return derived();
3✔
247
  }
1✔
248
  constexpr compatible_bitarray operator^(const bit_sized_range auto& other) const {
2✔
249
    assert(other.size() == derived().size());
2!
250
    compatible_bitarray result(derived().size());
2✔
251
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
2✔
252
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
3✔
253
    return result;
3✔
254
  }
1✔
255
  constexpr Derived& operator^=(bit_sized_range auto& other) {
2✔
256
    assert(other.size() == derived().size());
2!
257
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
2✔
258
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
3✔
259
    return derived();
3✔
260
  }
1✔
261
};
262
constexpr bool operator==(const bit_sized_range auto& lhs, const bit_sized_range auto& rhs) {
56✔
263
  if (lhs.size() != rhs.size()) {
56!
264
    return false;
4✔
265
  }
2✔
266
  return ::bit::equal(lhs.begin(), lhs.end(), rhs.begin());
52✔
267
}
28✔
268

269
}  // namespace bit
270

271
#endif  // _BIT_ARRAY_BASE_HPP_INCLUDED
272
        // ========================================================================== //
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