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

PeterCDMcLean / BitLib / 16535147226

26 Jul 2025 02:33AM UTC coverage: 77.05% (-1.4%) from 78.485%
16535147226

Pull #18

github

web-flow
Merge 3dbf7bd55 into 079daa142
Pull Request #18: From string

3406 of 5080 branches covered (67.05%)

Branch coverage included in aggregate %.

248 of 295 new or added lines in 12 files covered. (84.07%)

30 existing lines in 2 files now uncovered.

2476 of 2554 relevant lines covered (96.95%)

31346596.33 hits per line

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

75.8
/include/bitlib/bit-algorithms/transform.hpp
1
// =============================== TRANSFORM =============================== //
2
// Project: The Experimental Bit Algorithms Library
3
// Name: transform.hpp
4
// Description: bit_iterator overloads for std::transform
5
// License: BSD 3-Clause License
6
// ========================================================================== //
7
#ifndef _TRANSFORM_HPP_INCLUDED
8
#define _TRANSFORM_HPP_INCLUDED
9
// ========================================================================== //
10

11
// ============================== PREAMBLE ================================== //
12
// C++ standard library
13
#include <functional>
14
#include <type_traits>
15
// Project sources
16
#include "bitlib/bit-iterator/bit.hpp"
17
// Third-party libraries
18
// Miscellaneous
19

20
namespace bit {
21
// ========================================================================== //
22

23

24

25
//template <class RandomAccessIt, class WordType>
26
//constexpr bit_iterator<RandomAccessIt> transform(
27
        //bit_iterator<RandomAccessIt> first,
28
        //bit_iterator<RandomAccessIt> last,
29
        //bit_iterator<RandomAccessIt> d_first,
30
        //std::bit_or<WordType>) {
31

32
    //return d_first;
33
//}
34
template <class RandomAccessItIn, class RandomAccessItOut, class UnaryOperation>
35
constexpr bit_iterator<RandomAccessItOut> transform(
1,021✔
36
    bit_iterator<RandomAccessItIn> first,
37
    bit_iterator<RandomAccessItIn> last,
38
    bit_iterator<RandomAccessItOut> d_first,
39
    UnaryOperation unary_op) {
1,021✔
40
  using word_type = typename bit_iterator<RandomAccessItIn>::word_type;
1,021✔
41
  using size_type = typename bit_iterator<RandomAccessItIn>::size_type;
1,021✔
42
  constexpr size_type digits = binary_digits<word_type>::value;
2,042✔
43

44
  // Assertions
45
  _assert_range_viability(first, last);
2,042✔
46
  if (first == last) {
2,042!
47
    return d_first;
139✔
48
  }
40✔
49

50
  // Initialization
51
  const bool is_d_first_aligned = d_first.position() == 0;
1,903✔
52
  size_type total_bits_to_op = distance(first, last);
1,903✔
53
  size_type remaining_bits_to_op = total_bits_to_op;
1,903✔
54
  auto it = d_first.base();
1,903✔
55

56
  // d_first is not aligned. Copy partial word to align it
57
  if (!is_d_first_aligned) {
1,903!
58
    size_type partial_bits_to_op = ::std::min(
1,372✔
59
        remaining_bits_to_op,
655✔
60
        digits - d_first.position());
2,089✔
61
    word_type result;
655✔
62
    if constexpr (std::is_invocable_v<UnaryOperation, word_type, size_type>) {
655✔
NEW
63
      result = unary_op(
×
NEW
64
          static_cast<word_type>(
NEW
65
              get_masked_word<word_type>(first, partial_bits_to_op)
×
NEW
66
              << static_cast<word_type>(d_first.position())),
×
NEW
67
          partial_bits_to_op);
68
    } else {
655✔
69
      result = unary_op(
1,372✔
70
          static_cast<word_type>(
2,017✔
71
              get_masked_word<word_type>(first, partial_bits_to_op)
1,372✔
72
              << static_cast<word_type>(d_first.position())));
1,372✔
73
    }
655✔
74
    *it = _bitblend(
1,372✔
75
        *it,
1,372✔
76
        result,
655✔
77
        static_cast<word_type>(d_first.position()),
1,372✔
78
        static_cast<word_type>(partial_bits_to_op));
655✔
79
    remaining_bits_to_op -= partial_bits_to_op;
1,372✔
80
    advance(first, partial_bits_to_op);
1,372✔
81
    it++;
1,372✔
82
  }
655✔
83
  auto firstIt = first.base();
1,903✔
84
  if (remaining_bits_to_op > 0) {
1,903!
85
    const bool is_first_aligned = first.position() == 0;
1,474✔
86
    //size_type words_to_op = ::std::ceil(remaining_bits_to_op / static_cast<float>(digits));
87
    // d_first will be aligned at this point
88
    if (is_first_aligned && remaining_bits_to_op > digits) {
1,474!
89
      auto N = ::std::distance(firstIt, last.base());
800✔
90
#ifdef BITLIB_HWY
91
            if constexpr (std::is_same_v<UnaryOperation, std::bit_not<word_type>>)
92
            {
93
                // Align to 64 bit boundary
94
                for (; firstIt != last.base() && !is_aligned(&*firstIt, 64); firstIt++, it++) {
95
                    *it = unary_op(*firstIt);
96
                }
97

98
                bool out_is_aligned = is_aligned(&*it, 64);
99

100
                constexpr hn::ScalableTag<word_type> d;
101
                for (; std::distance(firstIt, last.base()) >= hn::Lanes(d); firstIt += hn::Lanes(d), it += hn::Lanes(d))
102
                {
103
                    const auto v = hn::Not(hn::Load(d, &*firstIt));
104
                    if (out_is_aligned)
105
                    {
106
                        hn::Store(v, d, &*it);
107
                    } else {
108
                        hn::StoreU(v, d, &*it);
109
                    }
110
                }
111
            }
112
#endif
113
            size_t std_dist = ::std::distance(firstIt, last.base());
800✔
114
            for (auto in_it = firstIt; in_it != last.base(); std::advance(in_it, 1), std::advance(it, 1)) {
918,914!
115
              if constexpr (std::is_invocable_v<UnaryOperation, word_type, size_type>) {
459,029✔
NEW
116
                *it = unary_op(*in_it, digits);
×
117
              } else {
459,029✔
118
                *it = unary_op(*in_it);
918,114✔
119
              }
459,029✔
120
            }
459,029✔
121
            //it = std::transform(firstIt, last.base(), it, unary_op);
122
            firstIt += std_dist;
800✔
123
            first = bit_iterator<RandomAccessItIn>(firstIt);
800✔
124
            remaining_bits_to_op -= digits * N;
800✔
125
    } else {
800✔
126
      while (remaining_bits_to_op >= digits) {
701!
127
        if constexpr (std::is_invocable_v<UnaryOperation, word_type, size_type>) {
13✔
128
          *it = unary_op(get_word<word_type>(first, digits), digits);
12✔
129
        } else {
7✔
130
          *it = unary_op(get_word<word_type>(first, digits));
15✔
131
        }
7✔
132

133
        remaining_bits_to_op -= digits;
27✔
134
        it++;
27✔
135
        advance(first, digits);
27✔
136
      }
13✔
137
    }
364✔
138
        if (remaining_bits_to_op > 0) {
1,474!
139
          word_type result;
714✔
140
          if constexpr (std::is_invocable_v<UnaryOperation, word_type, size_type>) {
714✔
141
            result = unary_op(get_masked_word<word_type>(first, remaining_bits_to_op), remaining_bits_to_op);
10✔
142
          } else {
709✔
143
            result = unary_op(get_masked_word<word_type>(first, remaining_bits_to_op));
1,413✔
144
          }
709✔
145
          *it = _bitblend(
1,962✔
146
              *it,
1,416✔
147
              result,
714✔
148
              _mask<word_type>(remaining_bits_to_op));
884✔
149
        }
714✔
150
  }
741✔
151
    return d_first + total_bits_to_op;
1,903✔
152
}
1,021✔
153

154
template <class RandomAccessItIn, class RandomAccessItOut, class BinaryOperation>
155
constexpr bit_iterator<RandomAccessItOut> transform(
1,014✔
156
    bit_iterator<RandomAccessItIn> first1,
157
    bit_iterator<RandomAccessItIn> last1,
158
    bit_iterator<RandomAccessItIn> first2,
159
    bit_iterator<RandomAccessItOut> d_first,
160
    BinaryOperation binary_op) {
1,014✔
161
  using word_type = typename bit_iterator<RandomAccessItIn>::word_type;
1,014✔
162
  using size_type = typename bit_iterator<RandomAccessItIn>::size_type;
1,014✔
163
  constexpr size_type digits = binary_digits<word_type>::value;
2,028✔
164

165
  // Assertions
166
  _assert_range_viability(first1, last1);
2,028✔
167
  if (first1 == last1) {
2,028!
168
    return d_first;
140✔
169
  }
53✔
170

171
  // Initialization
172
  const bool is_d_first_aligned = d_first.position() == 0;
1,888✔
173
  size_type total_bits_to_op = distance(first1, last1);
1,888✔
174
  size_type remaining_bits_to_op = total_bits_to_op;
1,888✔
175
  auto it = d_first.base();
1,888✔
176

177
  // d_first is not aligned. Copy partial word to align it
178
  if (!is_d_first_aligned) {
1,888!
179
    size_type partial_bits_to_op = ::std::min(
1,863✔
180
        remaining_bits_to_op,
950✔
181
        digits - d_first.position());
2,776✔
182
    *it = _bitblend(
2,641✔
183
        *it,
1,863✔
184
        binary_op(
1,127✔
185
            static_cast<word_type>(
2,993✔
186
                get_masked_word<word_type>(first1, partial_bits_to_op)
1,863✔
187
                << static_cast<word_type>(d_first.position())),
2,122✔
188
            static_cast<word_type>(
2,993✔
189
                get_masked_word<word_type>(first2, partial_bits_to_op)
1,863✔
190
                << static_cast<word_type>(d_first.position()))),
2,122✔
191
        static_cast<word_type>(d_first.position()),
1,863✔
192
        static_cast<word_type>(partial_bits_to_op));
950✔
193
    remaining_bits_to_op -= partial_bits_to_op;
1,863✔
194
    advance(first1, partial_bits_to_op);
1,863✔
195
    advance(first2, partial_bits_to_op);
1,863✔
196
    it++;
1,863✔
197
  }
950✔
198
  if (remaining_bits_to_op > 0) {
1,888!
199
    const bool is_first1_aligned = first1.position() == 0;
1,312✔
200
    const bool is_first2_aligned = first2.position() == 0;
1,312✔
201
    //size_type words_to_op = ::std::ceil(remaining_bits_to_op / static_cast<float>(digits));
202
    // d_first will be aligned at this point
203
    if (is_first1_aligned && is_first2_aligned && remaining_bits_to_op > digits) {
1,312!
204
      auto N = ::std::distance(first1.base(), last1.base());
780✔
205
      it = std::transform(first1.base(), last1.base(), first2.base(), it, binary_op);
780✔
206
      first1 += digits * N;
780✔
207
      first2 += digits * N;
780✔
208
      remaining_bits_to_op -= digits * N;
780✔
209
    } else {
780✔
210
      while (remaining_bits_to_op >= digits) {
558✔
211
        *it = binary_op(
26✔
212
            get_word<word_type>(first1, digits),
38✔
213
            get_word<word_type>(first2, digits));
38✔
214
        remaining_bits_to_op -= digits;
26✔
215
        it++;
26✔
216
        advance(first1, digits);
26✔
217
        advance(first2, digits);
26✔
218
      }
14✔
219
    }
279✔
220
    if (remaining_bits_to_op > 0) {
1,312!
221
      *it = _bitblend(
2,286✔
222
          *it,
1,266✔
223
          binary_op(
769✔
224
              get_masked_word<word_type>(first1, remaining_bits_to_op),
1,882✔
225
              get_masked_word<word_type>(first2, remaining_bits_to_op)),
1,882✔
226
          _mask<word_type>(remaining_bits_to_op));
769✔
227
    }
650✔
228
  }
675✔
229
  return d_first + total_bits_to_op;
1,888✔
230
}
1,014✔
231

232
//template <class RandomAccessIt1, class RandomAccessIt2, class RandomAccessIt3, class BinaryOperation>
233
//constexpr bit_iterator<RandomAccessIt> transform_word(bit_iterator<RandomAccessIt1> first,
234
    //bit_iterator<RandomAccessIt1> last, bit_iterator<RandomAccessIt2> first2,
235
    //bit_iterator<RandomAccessIt> d_first, BinaryOperation binary_op) {
236
    //// Assertions
237
     //_assert_range_viability(first, last);
238

239
    //// Types and constants
240
    //using word_type1    = typename bit_iterator<RandomAccessIt1>::word_type;
241
    //using word_type2    = typename bit_iterator<RandomAccessIt2>::word_type;
242
    //using word_type_out = typename bit_iterator<RandomAccessIt>::word_type;
243
    //using size_type1    = typename bit_iterator<RandomAccessIt1>::size_type;
244
    //using size_type2    = typename bit_iterator<RandomAccessIt2>::size_type;
245
    //using size_type_out = typename bit_iterator<RandomAccessIt>::size_type;
246
    //constexpr size_type1 digits1     = binary_digits<word_type1>::value;
247
    //constexpr size_type2 digits2     = binary_digits<word_type2>::value;
248
    //constexpr size_type_out digits_out  = binary_digits<word_type_out>::value;
249

250
    //// This is just for now. Perhaps later we can expand to different word sizes
251
    //assert(digits1 == digits2);
252
    //assert(digits2 == digits_out);
253
    //using word_type = word_type1;
254
    //using size_type = size_type1;
255
    //constexpr size_type digits = digits1;
256

257
    //if (is_within<digits>(first, last)) {
258
        //word_type d = distance(first, last);
259
        //write_word(
260
            //binary_op(
261
                //get_word(first, d),
262
                //get_word(first2, d)
263
            //),
264
            //d_first,
265
            //d
266
        //);
267
        //return next(d_first, d);
268
    //}
269

270
    //RandomAccessIt1 it1    = first.base();
271
    //if (first.position() != 0) {
272
        //word_type d = digits - first.position();
273
        //write_word(
274
            //binary_op(
275
                //static_cast<word_type>(*first.base() >> first.position()),
276
                //get_word(first2, d)
277
            //),
278
            //d_first,
279
            //d
280
        //);
281
        //++it1;
282
        //advance(first2, d);
283
        //advance(d_first, d);
284
    //}
285

286
    //while (it1 != last1.base()) {
287
        //write_word(
288
            //binary_op(
289
                //*it1++,
290
                //get_word<word_type>(first2)
291
            //),
292
            //d_first,
293
            //(word_type)digits
294
        //);
295
        //advance(d_first, digits);
296
        //advance(first2, digits);
297
    //}
298

299
    //if (last1.position() != 0) {
300
        //write_word(
301
            //binary_op(
302
                //*it1,
303
                //get_word(first2, last1.position())
304
            //),
305
            //d_first,
306
            //static_cast<word_type>(last1.position())
307
        //);
308
        //advance(d_first, last1.position());
309
    //}
310
    //return d_first;
311
//}
312

313

314
// ========================================================================== //
315
} // namespace bit
316

317
#endif // _TRANSFORM_HPP_INCLUDED
318
// ========================================================================== //
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