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

PeterCDMcLean / BitLib / 15696998807

17 Jun 2025 02:58AM UTC coverage: 54.11% (+0.6%) from 53.519%
15696998807

push

github

web-flow
Truncation policy (#17)

* Add draft policies for integer conversion

* Add allocator to Policy. Use policy to construct from integral

* Add convenience conversion pathway for literal -> bit_value

* Add algorithm accumulate and utility to_string

* template keyword only necessary if actually passing template args

* Better UX for accumulate policy

* small tweaks to to_string

* Add static_assert error to bit_literal.

* Consolidate from_integral code

* Fix accumulate, get_word doesn't mask

10137 of 18710 branches covered (54.18%)

Branch coverage included in aggregate %.

212 of 251 new or added lines in 13 files covered. (84.46%)

214 existing lines in 11 files now uncovered.

6062 of 11227 relevant lines covered (53.99%)

7736453.1 hits per line

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

57.79
/include/bitlib/bit-algorithms/accumulate.hpp
1
// ================================= BIT_ARRAY_REF =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        accumulate.hpp
4
// Description: Implementation of accumulate
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9

10
#ifndef _BIT_ACCUMULATE_HPP_INCLUDED
11
#define _BIT_ACCUMULATE_HPP_INCLUDED
12

13
#include "bitlib/bit-iterator/bit_iterator.hpp"
14
#include "bitlib/bit-iterator/bit_details.hpp"
15

16
namespace bit {
17

18
namespace policy {
19
struct AccumulateInitialSubword {
20
  static constexpr bool initial_sub_word = true;
21
};
22

23
struct AccumulateNoInitialSubword {
24
  static constexpr bool initial_sub_word = false;
25
};
26
}  // namespace policy
27

28
template <bool forward, bool initial_sub_word, typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
29
constexpr auto accumulate(
4✔
30
    bit_iterator<RandomAccessIt> first,
31
    bit_iterator<RandomAccessIt> last,
32
    T acc,
33
    BinaryOperation binary_op,
34
    BinaryOperationSubword binary_op_subword) {
4✔
35
  using word_type = typename bit_iterator<RandomAccessIt>::word_type;
4✔
36
  using size_type = typename bit_iterator<RandomAccessIt>::size_type;
4✔
37
  constexpr size_type digits = bitsof<word_type>();
8✔
38

39

40
  size_type total_bits_to_op = distance(first, last);
8✔
41
  bool keep_going = true;;
8✔
42
  if constexpr (initial_sub_word) {
43
    size_type sub_digits;
44
    if constexpr (forward) {
45
      sub_digits = std::min(digits - first.position(), total_bits_to_op);
46
      if (sub_digits != 0) {
47
        acc = binary_op_subword(std::move(acc), get_masked_word<word_type>(first, sub_digits), sub_digits);
48
        advance(first, digits - first.position());
49
      }
50
    } else {
51
      sub_digits = std::min(last.position(), total_bits_to_op);
52
      if (sub_digits != 0) {
53
        advance(last, -sub_digits);
54
        acc = binary_op_subword(std::move(acc), get_masked_word<word_type>(last, sub_digits), sub_digits);
55
      }
56
    }
57
    total_bits_to_op -= sub_digits;
58
  }
59

60
  const size_type whole_words_to_op = total_bits_to_op / digits;
8✔
61
  const size_type remaining_bits_to_op = total_bits_to_op % digits;
8✔
62

63
  for (size_t i = 0; i < whole_words_to_op; i ++) {
12!
64
    if constexpr (forward) {
2✔
65
      acc = binary_op(std::move(acc), get_word<word_type>(first));
4✔
66
      advance(first, digits);
4✔
67
    } else {
68
      advance(last, -digits);
69
      acc = binary_op(std::move(acc), get_word<word_type>(last));
70
    }
71
  }
2✔
72
  if (remaining_bits_to_op > 0) {
8!
73
    if constexpr (forward) {
2✔
74
      acc = binary_op_subword(std::move(acc), get_masked_word<word_type>(first, remaining_bits_to_op), remaining_bits_to_op);
4✔
75
    } else {
76
      advance(last, -remaining_bits_to_op);
77
      acc = binary_op_subword(std::move(acc), get_masked_word<word_type>(last, remaining_bits_to_op), remaining_bits_to_op);
78
    }
79
  }
2✔
80

81
  return acc;
12✔
82
}
4✔
83

84
template <bool forward, bool initial_sub_word, typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
85
constexpr auto accumulate_while(
4✔
86
    bit_iterator<RandomAccessIt> first,
87
    bit_iterator<RandomAccessIt> last,
88
    T acc,
89
    BinaryOperation binary_op,
90
    BinaryOperationSubword binary_op_subword) {
4✔
91
  using word_type = typename bit_iterator<RandomAccessIt>::word_type;
4✔
92
  using size_type = typename bit_iterator<RandomAccessIt>::size_type;
4✔
93
  using difference_type = typename bit_iterator<RandomAccessIt>::difference_type;
4✔
94
  constexpr size_type digits = bitsof<word_type>();
8✔
95

96
  size_type total_bits_to_op = distance(first, last);
8✔
97
  size_type whole_words_to_op = total_bits_to_op / digits;
8✔
98

99
  bool keep_going = true;;
8✔
100
  if constexpr (initial_sub_word) {
4✔
101
    if (whole_words_to_op > 1) {
8!
102
      size_type sub_digits;
1✔
103
      if constexpr (forward) {
104
        sub_digits = std::min(digits - first.position(), total_bits_to_op);
105
        if (sub_digits != 0) {
106
          std::tie(keep_going, acc) = binary_op_subword(std::move(acc), get_masked_word<word_type>(first, sub_digits), sub_digits);
107
          advance(first, digits - first.position());
108
        }
109
      } else {
1✔
110
        sub_digits = std::min(last.position(), total_bits_to_op);
2✔
111
        if (sub_digits != 0) {
2!
NEW
112
          advance(last, -sub_digits);
×
NEW
113
          std::tie(keep_going, acc) = binary_op_subword(std::move(acc), get_masked_word<word_type>(first, sub_digits), sub_digits);
×
NEW
114
        }
115
      }
1✔
116
      total_bits_to_op -= sub_digits;
2✔
117
      if (!keep_going) {
2!
NEW
118
        return acc; // Stop early if the operation indicates to stop
×
NEW
119
      }
120
    }
1✔
121
  }
4✔
122

123
  whole_words_to_op = total_bits_to_op / digits;
8✔
124
  const size_type remaining_bits_to_op = total_bits_to_op % digits;
8✔
125

126
  for (size_type i = 0; i < whole_words_to_op; i ++) {
12!
127
    if constexpr (forward) {
128
      std::tie(keep_going, acc) = binary_op(std::move(acc), get_word<word_type>(first));
129
      advance(first, digits);
130
    } else {
4✔
131
      advance(last, -digits);
8✔
132
      std::tie(keep_going, acc) = binary_op(std::move(acc), get_word<word_type>(last));
8✔
133
    }
4✔
134
    if (!keep_going) {
8!
135
      return acc; // Stop early if the operation indicates to stop
4✔
136
    }
2✔
137
  }
4✔
138
  if (remaining_bits_to_op > 0) {
4!
139
    if constexpr (forward) {
140
      std::tie(std::ignore, acc) = binary_op_subword(std::move(acc), get_masked_word<word_type>(first, remaining_bits_to_op), remaining_bits_to_op);
141
    } else {
1✔
142
      advance(last, -remaining_bits_to_op);
2✔
143
      std::tie(std::ignore, acc) = binary_op_subword(std::move(acc), get_masked_word<word_type>(last, remaining_bits_to_op), remaining_bits_to_op);
2✔
144
    }
1✔
145
  }
1✔
146

147
  return acc;
4✔
148
}
4✔
149

150
// Requires BinaryOperation to have a third but defaulted argument
151
template <typename RandomAccessIt, typename T, typename BinaryOperation>
152
constexpr auto accumulate(
153
    const bit_iterator<RandomAccessIt>& first,
154
    const bit_iterator<RandomAccessIt>& last,
155
    const T& acc,
156
    BinaryOperation binary_op) {
157
  return accumulate<true, true>(first, last, acc, binary_op, binary_op);
158
}
159

160
template <typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
161
constexpr auto accumulate(
162
    const bit_iterator<RandomAccessIt>& first,
163
    const bit_iterator<RandomAccessIt>& last,
164
    const T& acc,
165
    BinaryOperation binary_op,
166
    BinaryOperationSubword binary_op_subword) {
167
  return accumulate<true, true>(first, last, acc, binary_op, binary_op_subword);
168
}
169

170
// Requires BinaryOperation to have a third but defaulted argument
171
template <typename RandomAccessIt, typename T, typename BinaryOperation>
172
constexpr auto accumulate_while(
173
    const bit_iterator<RandomAccessIt>& first,
174
    const bit_iterator<RandomAccessIt>& last,
175
    const T& acc,
176
    BinaryOperation binary_op) {
177
  return accumulate_while<true, true>(first, last, acc, binary_op, binary_op);
178
}
179

180
template <typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
181
constexpr auto accumulate_while(
182
    const bit_iterator<RandomAccessIt>& first,
183
    const bit_iterator<RandomAccessIt>& last,
184
    const T& acc,
185
    BinaryOperation binary_op,
186
    BinaryOperationSubword binary_op_subword) {
187
  return accumulate_while<true, true>(first, last, acc, binary_op, binary_op_subword);
188
}
189

190
// Requires BinaryOperation to have a third but defaulted argument
191
template <typename RandomAccessIt, typename T, typename BinaryOperation>
192
constexpr auto accumulate_backward_while(
193
    const bit_iterator<RandomAccessIt>& first,
194
    const bit_iterator<RandomAccessIt>& last,
195
    const T& acc,
196
    BinaryOperation binary_op) {
197
  return accumulate_while<false, true>(first, last, acc, binary_op, binary_op);
198
}
199

200
template <typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
201
constexpr auto accumulate_backward_while(
4✔
202
    const bit_iterator<RandomAccessIt>& first,
203
    const bit_iterator<RandomAccessIt>& last,
204
    const T& acc,
205
    BinaryOperation binary_op,
206
    BinaryOperationSubword binary_op_subword) {
4✔
207
  return accumulate_while<false, true>(first, last, acc, binary_op, binary_op_subword);
12✔
208
}
4✔
209

210
// Requires BinaryOperation to have a third but defaulted argument
211
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation>
212
constexpr auto accumulate(
4✔
213
    Policy,
214
    const bit_iterator<RandomAccessIt>& first,
215
    const bit_iterator<RandomAccessIt>& last,
216
    const T& acc,
217
    BinaryOperation binary_op) {
4✔
218
  return accumulate<true, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op);
12✔
219
}
4✔
220

221
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
222
constexpr auto accumulate(
223
    Policy,
224
    const bit_iterator<RandomAccessIt>& first,
225
    const bit_iterator<RandomAccessIt>& last,
226
    const T& acc,
227
    BinaryOperation binary_op,
228
    BinaryOperationSubword binary_op_subword) {
229
  return accumulate<true, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op_subword);
230
}
231

232
// Requires BinaryOperation to have a third but defaulted argument
233
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation>
234
constexpr auto accumulate_while(
235
    Policy,
236
    const bit_iterator<RandomAccessIt>& first,
237
    const bit_iterator<RandomAccessIt>& last,
238
    const T& acc,
239
    BinaryOperation binary_op) {
240
  return accumulate_while<true, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op);
241
}
242

243
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
244
constexpr auto accumulate_while(
245
    Policy,
246
    const bit_iterator<RandomAccessIt>& first,
247
    const bit_iterator<RandomAccessIt>& last,
248
    const T& acc,
249
    BinaryOperation binary_op,
250
    BinaryOperationSubword binary_op_subword) {
251
  return accumulate_while<true, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op_subword);
252
}
253

254
// Requires BinaryOperation to have a third but defaulted argument
255
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation>
256
constexpr auto accumulate_backward_while(
257
    Policy,
258
    const bit_iterator<RandomAccessIt>& first,
259
    const bit_iterator<RandomAccessIt>& last,
260
    const T& acc,
261
    BinaryOperation binary_op) {
262
  return accumulate_while<false, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op);
263
}
264

265
template <typename Policy, typename RandomAccessIt, typename T, typename BinaryOperation, typename BinaryOperationSubword>
266
constexpr auto accumulate_backward_while(
267
    Policy,
268
    const bit_iterator<RandomAccessIt>& first,
269
    const bit_iterator<RandomAccessIt>& last,
270
    const T& acc,
271
    BinaryOperation binary_op,
272
    BinaryOperationSubword binary_op_subword) {
273
  return accumulate_while<false, Policy::initial_sub_word>(first, last, acc, binary_op, binary_op_subword);
274
}
275

276
} // namespace bit
277

278
#endif  // _BIT_ACCUMULATE_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

© 2026 Coveralls, Inc