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

PeterCDMcLean / BitLib / 15113635153

19 May 2025 12:58PM UTC coverage: 96.707% (+46.8%) from 49.868%
15113635153

Pull #11

github

web-flow
Merge 1adbb07aa into 9126838eb
Pull Request #11: Bitwise operators in bit_array_base

128 of 129 new or added lines in 4 files covered. (99.22%)

20 existing lines in 5 files now uncovered.

1439 of 1488 relevant lines covered (96.71%)

14708883.99 hits per line

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

98.68
/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_span.hpp"
28
#include "bitlib/bit-iterator/bit.hpp"
29

30
namespace bit {
31

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

35
template <typename T,
36
          std::size_t N,
37
          std::align_val_t V,
38
          typename W>
39
class bit_array;
40
// ========================================================================== //
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 It The iterator type for the derived class
52
 * @tparam CIt The const_iterator type for the derived class
53
 */
54
template <typename Derived, typename T, size_t N, typename W, typename It, typename CIt>
55
class bit_array_base {
56
 protected:
57
  constexpr Derived& derived() noexcept {
1,460✔
58
    return static_cast<Derived&>(*this);
1,460✔
59
  }
60

61
  constexpr const Derived& derived() const noexcept {
115✔
62
    return static_cast<const Derived&>(*this);
115✔
63
  }
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 = It;
75
  using const_iterator = CIt;
76

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

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

86
  constexpr reference at(size_type pos) {
13✔
87
    if (pos < derived().size()) {
13✔
88
      return derived().begin()[pos];
20✔
89
    } else {
90
      throw std::out_of_range("Position is out of range");
3✔
91
    }
92
  }
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() {
3✔
103
    return derived().begin()[0];
6✔
104
  }
105

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

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

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

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

122
  constexpr const_iterator end() const noexcept {
45✔
123
    return const_iterator(derived().begin()) + derived().size();
45✔
124
  }
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 {
4✔
136
    return 0 == derived().size();
4✔
137
  }
138

139
  constexpr size_type max_size() const noexcept {
1✔
140
    return derived().size();
1✔
141
  }
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>(&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 {
8✔
174
    return bit_array_ref<bit_value, word_type>(&this->at(offset), right - offset);
8✔
175
  }
176

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

182
  /**
183
   * @brief Explicit conversion to integral types
184
   */
185
  template <std::integral U>
186
  explicit constexpr operator U() const noexcept {
2✔
187
    assert(derived().size() <= bitsof<U>());
2✔
188
    U integral;
2✔
189
    bit_span<uint8_t, bitsof<U>()> integral_ref(reinterpret_cast<uint8_t*>(&integral));
2✔
190
    copy(derived().begin(), derived().begin() + bitsof<U>(), integral_ref.begin());
2✔
191
    if constexpr (std::is_signed_v<U>) {
192
      ::bit::fill(integral_ref.begin() + derived().size(), integral_ref.end(), integral_ref[bitsof<U>() - 1]);
193
    } else {
194
      ::bit::fill(integral_ref.begin() + derived().size(), integral_ref.end(), bit0);
2✔
195
    }
196
    return integral;
2✔
197
  }
198

199
  using compatible_bitarray = bit_array<value_type, N, std::align_val_t(alignof(word_type)), word_type>;
200

201
  constexpr compatible_bitarray operator~() {
2✔
202
    compatible_bitarray result(derived().size());
2✔
203
    transform(derived().begin(), derived().end(), result.begin(), [](const word_type& bits) -> word_type { return ~bits; });
8✔
204
    return result;
4✔
UNCOV
205
  }
×
206

207
  //TODO: This should take a const bit_sized_range, but
208
  //      transform has problems with incompatible
209
  //      const/non-const word_type iterators
210
  constexpr compatible_bitarray operator|(const bit_sized_range auto& other) const {
1✔
211
    assert(other.size() == derived().size());
1✔
212
    compatible_bitarray result(derived().size());
1✔
213
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
214
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
8✔
215
    return result;
2✔
216
  }
217
  constexpr Derived& operator|=(bit_sized_range auto& other) {
1✔
218
    assert(other.size() == derived().size());
1✔
219
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
220
              [](const word_type& a, const word_type& b) -> word_type { return a | b; });
8✔
221
    return derived();
2✔
222
  }
223
  constexpr compatible_bitarray operator&(const bit_sized_range auto& other) const {
1✔
224
    assert(other.size() == derived().size());
1✔
225
    compatible_bitarray result(derived().size());
1✔
226
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
227
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
8✔
228
    return result;
2✔
229
  }
230
  constexpr Derived& operator&=(bit_sized_range auto& other) {
1✔
231
    assert(other.size() == derived().size());
1✔
232
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
233
              [](const word_type& a, const word_type& b) -> word_type { return a & b; });
8✔
234
    return derived();
2✔
235
  }
236
  constexpr compatible_bitarray operator^(const bit_sized_range auto& other) const {
1✔
237
    assert(other.size() == derived().size());
1✔
238
    compatible_bitarray result(derived().size());
1✔
239
    transform(derived().begin(), derived().end(), other.begin(), result.begin(),
1✔
240
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
8✔
241
    return result;
2✔
242
  }
243
  constexpr Derived& operator^=(bit_sized_range auto& other) {
1✔
244
    assert(other.size() == derived().size());
1✔
245
    transform(derived().begin(), derived().end(), other.begin(), derived().begin(),
1✔
246
              [](const word_type& a, const word_type& b) -> word_type { return a ^ b; });
8✔
247
    return derived();
2✔
248
  }
249
};
250
constexpr bool operator==(const bit_sized_range auto& lhs, const bit_sized_range auto& rhs) {
33✔
251
  if (lhs.size() != rhs.size()) {
33✔
252
    return false;
2✔
253
  }
254
  return ::bit::equal(lhs.begin(), lhs.end(), rhs.begin());
31✔
255
}
256

257
}  // namespace bit
258

259
#endif  // _BIT_ARRAY_BASE_HPP_INCLUDED
260
        // ========================================================================== //
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