cgv
Loading...
Searching...
No Matches
algorithm.h
1#pragma once
2
3#include <algorithm>
4#include <numeric>
5#include <string>
6#include <utility>
7#include <vector>
8
9namespace cgv {
10namespace utils {
11
13template <class T1 = void, class T2 = void>
14struct get_first {
15 constexpr T1 operator()(const std::pair<T1, T2>& pair) const {
16 return pair.first;
17 }
18};
19
21template <>
22struct get_first<void, void> {
23 template <class T1, class T2>
24 constexpr auto operator()(const std::pair<T1, T2>& pair) const
25 -> decltype(static_cast<const T1&>(pair.first)) {
26 return static_cast<const T1&>(pair.first);
27 }
28};
29
31template <class T1 = void, class T2 = void>
32struct get_second {
33 constexpr T2 operator()(const std::pair<T1, T2>& pair) const {
34 return pair.second;
35 }
36};
37
39template <>
40struct get_second<void, void> {
41 template <class T1, class T2>
42 constexpr auto operator()(const std::pair<T1, T2>& pair) const
43 -> decltype(static_cast<const T2&>(pair.second)) {
44 return static_cast<const T2&>(pair.second);
45 }
46};
47
56template<typename ForwardIt, typename T>
57T min_value(ForwardIt first, ForwardIt last, T fallback) {
58 auto it = std::min_element(first, last);
59 return it != last ? static_cast<T>(*it) : fallback;
60}
61
72template<typename ForwardIt, typename UnaryOp, typename T>
73T min_value(ForwardIt first, ForwardIt last, UnaryOp operation, T fallback) {
74 auto it = std::min_element(first, last, [&operation](const auto& left, const auto& right) {
75 return operation(left) < operation(right);
76 });
77 return it != last ? static_cast<T>(operation(*it)) : fallback;
78}
79
88template<typename ForwardIt, typename T>
89T max_value(ForwardIt first, ForwardIt last, T fallback) {
90 auto it = std::max_element(first, last);
91 return it != last ? static_cast<T>(*it) : fallback;
92}
93
104template<typename ForwardIt, typename UnaryOp, typename T>
105T max_value(ForwardIt first, ForwardIt last, UnaryOp operation, T fallback) {
106 auto it = std::max_element(first, last, [&operation](const auto& left, const auto& right) {
107 return operation(left) < operation(right);
108 });
109 return it != last ? static_cast<T>(operation(*it)) : fallback;
110}
111
122template <class InputIt, class UnaryOp>
123std::string transform_join(const InputIt first, const InputIt last, UnaryOp operation, const std::string& separator, bool trailing_separator = false) {
124 std::string res = "";
125 if(last > first) {
126 for(auto curr = first; curr != last; ++curr) {
127 res += operation(*curr);
128 if(last - curr > 1 || trailing_separator)
129 res += separator;
130 }
131 }
132 return res;
133}
134
145template <class InputIt>
146std::string join(const InputIt first, const InputIt last, const std::string& separator, bool trailing_separator = false) {
147 return transform_join(first, last, [](const auto& val) { return to_string(val); }, separator, trailing_separator);
148}
149
160template<class InputIt, class OutputIt>
161OutputIt pair_adjacent(const InputIt first, const InputIt last, OutputIt d_first) {
162 if(std::distance(first, last) > 1) {
163 return std::transform(first, std::prev(last), std::next(first), d_first, [](const auto& a, const auto& b) {
164 return std::make_pair(a, b);
165 });
166 }
167 return d_first;
168}
169
178template<class InputIt>
179std::vector<std::pair<typename InputIt::value_type, typename InputIt::value_type>> pair_adjacent(const InputIt first, const InputIt last) {
180 std::vector<std::pair<typename InputIt::value_type, typename InputIt::value_type>> res;
181 pair_adjacent(first, last, std::back_inserter(res));
182 return res;
183}
184
198template<typename InputIt1, typename InputIt2, typename OutputIt>
199OutputIt zip(const InputIt1 first1, const InputIt1 last1, const InputIt2 first2, OutputIt d_first) {
200 return std::transform(first1, last1, first2, d_first, [](const auto& a, const auto& b) {
201 return std::make_pair(a, b);
202 });
203}
204
216template<typename InputIt1, typename InputIt2>
217std::vector<std::pair<typename InputIt1::value_type, typename InputIt2::value_type>> zip(const InputIt1 first1, const InputIt1 last1, const InputIt2 first2) {
218 std::vector<std::pair<typename InputIt1::value_type, typename InputIt2::value_type>> res;
219 zip(first1, last1, first2, std::back_inserter(res));
220 return res;
221}
222
231template<typename ParamT = float, typename OutputIt>
232void subdivision_sequence(OutputIt output_first, ParamT start, ParamT stop, size_t n) {
233 if(n == 1) {
234 *output_first = ParamT(0.5) * (start + stop);
235 ++output_first;
236 } else if(n > 1) {
237 const ParamT size = stop - start;
238 const ParamT step = size / static_cast<ParamT>(n - 1);
239 for(size_t i = 0; i < n; ++i) {
240 ParamT t = start + step * static_cast<ParamT>(i);
241 *output_first = t;
242 ++output_first;
243 }
244 }
245}
246
253template<typename ParamT>
254std::vector<ParamT> subdivision_sequence(ParamT start, ParamT stop, size_t n) {
255 std::vector<ParamT> out;
256 out.reserve(n);
257 cgv::utils::subdivision_sequence(std::back_inserter(out), start, stop, n);
258 return out;
259}
260
267template<class InputIt>
268std::vector<size_t> generate_index_sequence(const InputIt first, const InputIt last) {
269 std::vector<size_t> indices(static_cast<size_t>(std::distance(first, last)));
270 std::iota(indices.begin(), indices.end(), 0);
271 return indices;
272}
273
281template<class RandomIt>
282std::vector<size_t> sort_indices(const RandomIt first, const RandomIt last) {
283 std::vector<size_t> indices = generate_index_sequence(first, last);
284 std::sort(indices.begin(), indices.end(), [first](size_t i1, size_t i2) {
285 return first[i1] < first[i2];
286 });
287 return indices;
288}
289
297template<class RandomIt>
298std::vector<size_t> stable_sort_indices(const RandomIt first, const RandomIt last) {
299 std::vector<size_t> indices = generate_index_sequence(first, last);
300 std::stable_sort(indices.begin(), indices.end(), [first](size_t i1, size_t i2) {
301 return first[i1] < first[i2];
302 });
303 return indices;
304}
305
316template<class RandomIt, class Compare>
317std::vector<size_t> sort_indices(const RandomIt first, const RandomIt last, Compare comp) {
318 std::vector<size_t> indices = generate_index_sequence(first, last);
319 std::sort(indices.begin(), indices.end(), [first, &comp](size_t i1, size_t i2) {
320 return comp(first[i1], first[i2]);
321 });
322 return indices;
323}
324
335template<class RandomIt, class Compare>
336std::vector<size_t> stable_sort_indices(const RandomIt first, const RandomIt last, Compare comp) {
337 std::vector<size_t> indices = generate_index_sequence(first, last);
338 std::stable_sort(indices.begin(), indices.end(), [first, &comp](size_t i1, size_t i2) {
339 return comp(first[i1], first[i2]);
340 });
341 return indices;
342}
343
344} // namespace utils
345} // namespace cgv
std::string join(const InputIt first, const InputIt last, const std::string &separator, bool trailing_separator=false)
Concatenate elements in the range [first, last) to a std::string.
Definition algorithm.h:146
std::vector< size_t > generate_index_sequence(const InputIt first, const InputIt last)
Return a sequence of monotonically increasing values from 0 to n = distance(first,...
Definition algorithm.h:268
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
std::string transform_join(const InputIt first, const InputIt last, UnaryOp operation, const std::string &separator, bool trailing_separator=false)
Transform elements in the range [first, last) and concatenate them to a std::string.
Definition algorithm.h:123
std::vector< size_t > sort_indices(const RandomIt first, const RandomIt last)
Return a sequence of indices corresponding to the sorted order of values in [first,...
Definition algorithm.h:282
OutputIt zip(const InputIt1 first1, const InputIt1 last1, const InputIt2 first2, OutputIt d_first)
Zip two sequences together to form a single sequene of pairs and store the results in an output range...
Definition algorithm.h:199
std::vector< size_t > stable_sort_indices(const RandomIt first, const RandomIt last)
Return a sequence of indices corresponding to the sorted order of values in [first,...
Definition algorithm.h:298
T min_value(ForwardIt first, ForwardIt last, T fallback)
Find the minimum value in the range [first, last) or return fallback if the range is empty.
Definition algorithm.h:57
void subdivision_sequence(OutputIt output_first, ParamT start, ParamT stop, size_t n)
Generate a sequence of n uniformly-spaced values in [start,stop] and store the result in an output ra...
Definition algorithm.h:232
OutputIt pair_adjacent(const InputIt first, const InputIt last, OutputIt d_first)
Transform the elements in the range [first, last) to adjacent pairs and store the results in an outpu...
Definition algorithm.h:161
T max_value(ForwardIt first, ForwardIt last, T fallback)
Find the maximum value in the range [first, last) or return fallback if the range is empty.
Definition algorithm.h:89
this header is dependency free
Definition print.h:11
Return std::pair::first.
Definition algorithm.h:14
Return std::pair::second.
Definition algorithm.h:32