• 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

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 <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_bitsof.hpp"
26
#include "bitlib/bit-containers/bit_policy.hpp"
27
#include "bitlib/bit-containers/bit_span.hpp"
28
#include "bitlib/bit-iterator/bit.hpp"
29

30
namespace bit {
31

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

210
    return integral;
4✔
211
  }
2✔
212

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

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

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

268
}  // namespace bit
269

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