-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathpartition.hpp
148 lines (129 loc) · 3.68 KB
/
partition.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* @file partition.hpp
* @brief
* @date 2020-07-22
* @author Peter
* @copyright
* Peter of [ThinkSpirit Laboratory](http://thinkspirit.org/)
* of [Nanjing University of Information Science & Technology](http://www.nuist.edu.cn/)
* all rights reserved
*/
#ifndef KERBAL_ALGORITHM_PARTITION_HPP
#define KERBAL_ALGORITHM_PARTITION_HPP
#include <kerbal/algorithm/querier/find_if.hpp>
#include <kerbal/algorithm/querier/find_if_not.hpp>
#include <kerbal/algorithm/swap.hpp>
#include <kerbal/compatibility/constexpr.hpp>
#include <kerbal/iterator/iterator.hpp>
#include <kerbal/iterator/iterator_traits.hpp>
namespace kerbal
{
namespace algorithm
{
namespace detail
{
template <typename ForwardIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
ForwardIterator
partition(
ForwardIterator first, ForwardIterator last,
UnaryPredicate pred, std::forward_iterator_tag
)
{
first = kerbal::algorithm::find_if_not(first, last, pred);
if (first != last) {
ForwardIterator adv(kerbal::iterator::next(first));
while (adv != last) {
if (pred(*adv)) {
kerbal::algorithm::iter_swap(first, adv);
++first;
}
++adv;
}
}
return first;
}
template <typename BidirectionalIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
bool partition_move_first_iter(
BidirectionalIterator &first, BidirectionalIterator &last,
UnaryPredicate &pred, std::bidirectional_iterator_tag
)
{
while (first != last) {
if (pred(*first)) {
++first;
} else {
return false;
}
}
return true;
}
template <typename BidirectionalIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
bool partition_move_last_iter(
BidirectionalIterator &first, BidirectionalIterator &last,
UnaryPredicate &pred, std::bidirectional_iterator_tag
)
{
while (first != last) {
if (pred(*last)) {
return false;
} else {
--last;
}
}
return true;
}
template <typename BidirectionalIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
BidirectionalIterator
partition(
BidirectionalIterator first, BidirectionalIterator last,
UnaryPredicate pred, std::bidirectional_iterator_tag
)
{
while (true) {
if (kerbal::algorithm::detail::partition_move_first_iter(
first, last, pred,
kerbal::iterator::iterator_category(first))
) {
return first;
}
--last;
if (kerbal::algorithm::detail::partition_move_last_iter(
first, last, pred,
kerbal::iterator::iterator_category(first))
) {
return first;
}
kerbal::algorithm::iter_swap(first, last);
++first;
}
}
} // namespace detail
template <typename ForwardIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
ForwardIterator partition(ForwardIterator first, ForwardIterator last, UnaryPredicate pred)
{
return kerbal::algorithm::detail::partition(
first, last, pred,
kerbal::iterator::iterator_category(first)
);
}
template <typename InputIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
InputIterator is_partitioned_until(InputIterator first, InputIterator last, UnaryPredicate pred)
{
first = kerbal::algorithm::find_if_not(first, last, pred);
return kerbal::algorithm::find_if(first, last, pred);
}
template <typename InputIterator, typename UnaryPredicate>
KERBAL_CONSTEXPR14
bool is_partitioned(InputIterator first, InputIterator last, UnaryPredicate pred)
{
return static_cast<bool>(kerbal::algorithm::is_partitioned_until(first, last, pred) == last);
}
} // namespace algorithm
} // namespace kerbal
#endif // KERBAL_ALGORITHM_PARTITION_HPP