-
Notifications
You must be signed in to change notification settings - Fork 2
/
reverse.hpp
129 lines (114 loc) · 4.38 KB
/
reverse.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// =============================== reverse.hpp ================================= //
// Project: The Experimental Bit Algorithms Library
// Name: copy.hpp
// Description: Implementation of reverse
// Creator: Vincent Reverdy
// Contributor: Vincent Reverdy [2019]
// License: BSD 3-Clause License
// ========================================================================== //
#ifndef _REVERSE_HPP_INCLUDED
#define _REVERSE_HPP_INCLUDED
#pragma once
// ========================================================================== //
// ================================ PREAMBLE ================================ //
// C++ standard library
// Project sources
#include "bit.hpp"
// Third-party libraries
// Miscellaneous
namespace bit {
// ========================================================================== //
// --------------------------- Reverse Algorithms --------------------------- //
// Status: complete
template <class BidirIt>
constexpr void reverse(
bit_iterator<BidirIt> first,
bit_iterator<BidirIt> last
)
{
// Assertions
_assert_range_viability(first, last);
// Types and constants
using word_type = typename bit_iterator<BidirIt>::word_type;
using size_type = typename bit_iterator<BidirIt>::size_type;
constexpr size_type digits = binary_digits<word_type>::value;
// Initialization
const bool is_first_aligned = first.position() == 0;
const bool is_last_aligned = last.position() == 0;
size_type gap = (digits - last.position()) * !is_last_aligned;
auto it = first.base();
word_type first_value = {};
word_type last_value = {};
// Reverse when bit iterators are aligned
if (is_first_aligned && is_last_aligned) {
std::reverse(first.base(), last.base());
for (; it != last.base(); ++it) {
*it = _bitswap(*it);
}
// Reverse when bit iterators do not belong to the same underlying word
} else if (first.base() != last.base()) {
// Save first and last element
first_value = *first.base();
last_value = *std::prev(last.base(), is_last_aligned);
// Reverse the underlying sequence
std::reverse(first.base(), std::next(last.base(), !is_last_aligned));
// Bitswap every element of the underlying sequence
for (it = first.base(); it != std::next(last.base(), !is_last_aligned); ++it) {
*it = _bitswap(*it);
}
// Shift the underlying sequence to the left
if (first.position() < gap) {
gap = gap - first.position();
shift_left(
bit_iterator(first.base()),
bit_iterator(std::next(last.base())),
gap);
it = first.base();
// Shift the underlying sequence to the right
} else if (first.position() > gap) {
gap = first.position() - gap;
shift_right(
bit_iterator(first.base()),
bit_iterator(std::next(last.base(), !is_last_aligned)),
gap);
it = first.base();
}
// Blend bits of the first element
if (!is_first_aligned) {
*first.base() = _bitblend<word_type>(
first_value,
*first.base(),
first.position(),
digits - first.position()
);
}
// Blend bits of the last element
if (!is_last_aligned) {
*last.base() = _bitblend<word_type>(
*last.base(),
last_value,
last.position(),
digits - last.position()
);
}
// Reverse when bit iterators belong to the same underlying word
} else {
*it = _bitblend<word_type>(
*it,
_bitswap<word_type>(*it >> first.position()) >> gap,
first.position(),
last.position() - first.position()
);
}
}
// Status: to do
template <class ExecutionPolicy, class BidirIt>
void reverse(ExecutionPolicy&& policy, bit_iterator<BidirIt> first,
bit_iterator<BidirIt> last) {
(policy, first, last);
}
// -------------------------------------------------------------------------- //
// ========================================================================== //
} // namespace bit
#endif // _REVERSE_HPP_INCLUDED
// ========================================================================== //