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

PeterCDMcLean / BitLib / 16544577083

26 Jul 2025 10:39PM UTC coverage: 76.997% (-1.5%) from 78.485%
16544577083

Pull #18

github

web-flow
Merge 4bac8f49d into 079daa142
Pull Request #18: From string

3414 of 5100 branches covered (66.94%)

Branch coverage included in aggregate %.

264 of 313 new or added lines in 12 files covered. (84.35%)

30 existing lines in 2 files now uncovered.

2494 of 2573 relevant lines covered (96.93%)

31115123.0 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
  requires(
36
      (std::is_same_v<std::remove_cvref_t<std::iter_value_t<RandomAccessItIn>>,
37
                      std::remove_cvref_t<std::iter_value_t<RandomAccessItOut>>>))
38
constexpr bit_iterator<RandomAccessItOut> transform(
1,021✔
39
    bit_iterator<RandomAccessItIn> first,
40
    bit_iterator<RandomAccessItIn> last,
41
    bit_iterator<RandomAccessItOut> d_first,
42
    UnaryOperation unary_op) {
1,021✔
43
  using word_type = typename bit_iterator<RandomAccessItIn>::word_type;
1,021✔
44
  using size_type = typename bit_iterator<RandomAccessItIn>::size_type;
1,021✔
45
  constexpr size_type digits = binary_digits<word_type>::value;
2,042✔
46

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

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

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

101
                bool out_is_aligned = is_aligned(&*it, 64);
102

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

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

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

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

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

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

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

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

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

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

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

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

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

316

317
// ========================================================================== //
318
} // namespace bit
319

320
#endif // _TRANSFORM_HPP_INCLUDED
321
// ========================================================================== //
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