LIEF: Library to Instrument Executable Formats Version 1.0.0
Loading...
Searching...
No Matches
algorithms.h
Go to the documentation of this file.
1/*
2 * Frozen
3 * Copyright 2016 QuarksLab
4 *
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
20 * under the License.
21 */
22
23#ifndef FROZEN_LETITGO_BITS_ALGORITHMS_H
24#define FROZEN_LETITGO_BITS_ALGORITHMS_H
25
27
28#include <limits>
29#include <tuple>
30
31namespace frozen {
32
33namespace bits {
34
35auto constexpr next_highest_power_of_two(std::size_t v) {
36 // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
37 constexpr auto trip_count = std::numeric_limits<decltype(v)>::digits;
38 v--;
39 for(std::size_t i = 1; i < trip_count; i <<= 1)
40 v |= v >> i;
41 v++;
42 return v;
43}
44
45template<class T>
46auto constexpr log(T v) {
47 std::size_t n = 0;
48 while (v > 1) {
49 n += 1;
50 v >>= 1;
51 }
52 return n;
53}
54
55constexpr std::size_t bit_weight(std::size_t n) {
56 return (n <= 8*sizeof(unsigned int))
57 + (n <= 8*sizeof(unsigned long))
58 + (n <= 8*sizeof(unsigned long long))
59 + (n <= 128);
60}
61
62unsigned int select_uint_least(std::integral_constant<std::size_t, 4>);
63unsigned long select_uint_least(std::integral_constant<std::size_t, 3>);
64unsigned long long select_uint_least(std::integral_constant<std::size_t, 2>);
65template<std::size_t N>
66unsigned long long select_uint_least(std::integral_constant<std::size_t, N>) {
67 static_assert(N < 2, "unsupported type size");
68 return {};
69}
70
71
72template<std::size_t N>
73using select_uint_least_t = decltype(select_uint_least(std::integral_constant<std::size_t, bit_weight(N)>()));
74
75template <typename Iter, typename Compare>
76constexpr auto min_element(Iter begin, const Iter end,
77 Compare const &compare) {
78 auto result = begin;
79 while (begin != end) {
80 if (compare(*begin, *result)) {
81 result = begin;
82 }
83 ++begin;
84 }
85 return result;
86}
87
88template <class T>
89constexpr void cswap(T &a, T &b) {
90 auto tmp = a;
91 a = b;
92 b = tmp;
93}
94
95template <class T, class U>
96constexpr void cswap(std::pair<T, U> & a, std::pair<T, U> & b) {
97 cswap(a.first, b.first);
98 cswap(a.second, b.second);
99}
100
101template <class... Tys, std::size_t... Is>
102constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b, std::index_sequence<Is...>) {
103 using swallow = int[];
104 (void) swallow{(cswap(std::get<Is>(a), std::get<Is>(b)), 0)...};
105}
106
107template <class... Tys>
108constexpr void cswap(std::tuple<Tys...> &a, std::tuple<Tys...> &b) {
109 cswap(a, b, std::make_index_sequence<sizeof...(Tys)>());
110}
111
112template <typename Iter>
113constexpr void iter_swap(Iter a, Iter b) {
114 cswap(*a, *b);
115}
116
117template <typename Iterator, class Compare>
118constexpr Iterator partition(Iterator left, Iterator right, Compare const &compare) {
119 auto pivot = left + (right - left) / 2;
120 iter_swap(right, pivot);
121 pivot = right;
122 for (auto it = left; 0 < right - it; ++it) {
123 if (compare(*it, *pivot)) {
124 iter_swap(it, left);
125 left++;
126 }
127 }
128 iter_swap(pivot, left);
129 pivot = left;
130 return pivot;
131}
132
133template <typename Iterator, class Compare>
134constexpr void quicksort(Iterator left, Iterator right, Compare const &compare) {
135 while (0 < right - left) {
136 auto new_pivot = bits::partition(left, right, compare);
137 quicksort(left, new_pivot, compare);
138 left = new_pivot + 1;
139 }
140}
141
142template <typename Container, class Compare>
143constexpr Container quicksort(Container const &array,
144 Compare const &compare) {
145 Container res = array;
146 quicksort(res.begin(), res.end() - 1, compare);
147 return res;
148}
149
150template <class T, class Compare> struct LowerBound {
151 T const &value_;
152 Compare const &compare_;
153 constexpr LowerBound(T const &value, Compare const &compare)
154 : value_(value), compare_(compare) {}
155
156 template <class ForwardIt>
157 inline constexpr ForwardIt doit_fast(ForwardIt first,
158 std::integral_constant<std::size_t, 0>) {
159 return first;
160 }
161
162 template <class ForwardIt, std::size_t N>
163 inline constexpr ForwardIt doit_fast(ForwardIt first,
164 std::integral_constant<std::size_t, N>) {
165 auto constexpr step = N / 2;
166 static_assert(N/2 == N - N / 2 - 1, "power of two minus 1");
167 auto it = first + step;
168 auto next_it = compare_(*it, value_) ? it + 1 : first;
169 return doit_fast(next_it, std::integral_constant<std::size_t, N / 2>{});
170 }
171
172 template <class ForwardIt, std::size_t N>
173 inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, true>) {
174 return doit_fast(first, std::integral_constant<std::size_t, N>{});
175 }
176
177 template <class ForwardIt, std::size_t N>
178 inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, N>, std::integral_constant<bool, false>) {
179 auto constexpr next_power = next_highest_power_of_two(N);
180 auto constexpr next_start = next_power / 2 - 1;
181 auto it = first + next_start;
182 if (compare_(*it, value_)) {
183 auto constexpr next = N - next_start - 1;
184 return doitfirst(it + 1, std::integral_constant<std::size_t, next>{}, std::integral_constant<bool, next_highest_power_of_two(next) - 1 == next>{});
185 }
186 else
187 return doit_fast(first, std::integral_constant<std::size_t, next_start>{});
188 }
189
190 template <class ForwardIt>
191 inline constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant<std::size_t, 1>, std::integral_constant<bool, false>) {
192 return doit_fast(first, std::integral_constant<std::size_t, 1>{});
193 }
194};
195
196template <std::size_t N, class ForwardIt, class T, class Compare>
197constexpr ForwardIt lower_bound(ForwardIt first, const T &value, Compare const &compare) {
198 return LowerBound<T, Compare>{value, compare}.doitfirst(first, std::integral_constant<std::size_t, N>{}, std::integral_constant<bool, next_highest_power_of_two(N) - 1 == N>{});
199}
200
201template <std::size_t N, class Compare, class ForwardIt, class T>
202constexpr bool binary_search(ForwardIt first, const T &value,
203 Compare const &compare) {
204 ForwardIt where = lower_bound<N>(first, value, compare);
205 return (!(where == first + N) && !(compare(value, *where)));
206}
207
208
209template<class InputIt1, class InputIt2>
210constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
211{
212 for (; first1 != last1; ++first1, ++first2) {
213 if (!(*first1 == *first2)) {
214 return false;
215 }
216 }
217 return true;
218}
219
220template<class InputIt1, class InputIt2>
221constexpr bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
222{
223 for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
224 if (*first1 < *first2)
225 return true;
226 if (*first2 < *first1)
227 return false;
228 }
229 return (first1 == last1) && (first2 != last2);
230}
231
232} // namespace bits
233} // namespace frozen
234
235#endif
Definition algorithms.h:33
constexpr auto min_element(Iter begin, const Iter end, Compare const &compare)
Definition algorithms.h:76
constexpr void iter_swap(Iter a, Iter b)
Definition algorithms.h:113
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition algorithms.h:210
unsigned int select_uint_least(std::integral_constant< std::size_t, 4 >)
constexpr ForwardIt lower_bound(ForwardIt first, const T &value, Compare const &compare)
Definition algorithms.h:197
constexpr Iterator partition(Iterator left, Iterator right, Compare const &compare)
Definition algorithms.h:118
auto constexpr log(T v)
Definition algorithms.h:46
auto constexpr next_highest_power_of_two(std::size_t v)
Definition algorithms.h:35
constexpr std::size_t bit_weight(std::size_t n)
Definition algorithms.h:55
constexpr void cswap(T &a, T &b)
Definition algorithms.h:89
decltype(select_uint_least(std::integral_constant< std::size_t, bit_weight(N)>())) select_uint_least_t
Definition algorithms.h:73
constexpr void quicksort(Iterator left, Iterator right, Compare const &compare)
Definition algorithms.h:134
constexpr bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
Definition algorithms.h:221
constexpr bool binary_search(ForwardIt first, const T &value, Compare const &compare)
Definition algorithms.h:202
Definition algorithm.h:30
Definition algorithms.h:150
T const & value_
Definition algorithms.h:151
constexpr ForwardIt doit_fast(ForwardIt first, std::integral_constant< std::size_t, N >)
Definition algorithms.h:163
constexpr ForwardIt doit_fast(ForwardIt first, std::integral_constant< std::size_t, 0 >)
Definition algorithms.h:157
constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant< std::size_t, N >, std::integral_constant< bool, true >)
Definition algorithms.h:173
Compare const & compare_
Definition algorithms.h:152
constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant< std::size_t, 1 >, std::integral_constant< bool, false >)
Definition algorithms.h:191
constexpr LowerBound(T const &value, Compare const &compare)
Definition algorithms.h:153
constexpr ForwardIt doitfirst(ForwardIt first, std::integral_constant< std::size_t, N >, std::integral_constant< bool, false >)
Definition algorithms.h:178