preCICE v3.2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
algorithm.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <fmt/ostream.h>
6#include <functional>
7#include <iterator>
8#include <set>
9#include <type_traits>
10#include <utility>
11
12namespace precice::utils {
13
32template <class InputIt1, class InputIt2, class OutputIt>
33void set_intersection_indices(InputIt1 ref1, InputIt1 first1, InputIt1 last1,
34 InputIt2 first2, InputIt2 last2, OutputIt d_first)
35{
36 while (first1 != last1 && first2 != last2) {
37 if (*first1 < *first2) {
38 ++first1;
39 } else {
40 if (!(*first2 < *first1)) {
41 *d_first++ = std::distance(ref1, first1++); // *first1 and *first2 are equivalent.
42 }
43 ++first2;
44 }
45 }
46}
47
49template <typename... Elements>
50auto make_array(Elements &&...elements) -> std::array<typename std::common_type<Elements...>::type, sizeof...(Elements)>
51{
52 return {std::forward<Elements>(elements)...};
53}
54
62template <typename Container, typename BinaryPredicate = std::equal_to<typename Container::value_type>>
63bool unique_elements(const Container &c, BinaryPredicate p = {})
64{
65 // This algorithm runs on small containers, so the O(n^2) does not hurt.
66 auto cbegin = c.begin();
67 auto cend = c.end();
68 // An empty set has unique elements
69 if (cbegin == cend) {
70 return true;
71 }
72 auto cstart = cbegin + 1;
73 for (; cstart < cend; ++cbegin, ++cstart) {
74 if (std::find_if(cstart, cend,
75 [&p, cbegin](const typename Container::value_type &v) -> bool {
76 return p(*cbegin, v);
77 }) != cend) {
78 return false;
79 }
80 }
81 return true;
82}
83
91template <class InputIter, class ElementType>
92void intersperse(InputIter first, InputIter last, const ElementType &elem, std::ostream &out)
93{
94 if (first == last)
95 return;
96
97 out << *first++;
98 for (; first != last; ++first) {
99 out << elem << *first;
100 }
101}
102
106template <class InputIt1, class InputIt2>
108mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
109{
110 while (first1 != last1 && first2 != last2 && *first1 == *first2) {
111 ++first1, ++first2;
112 }
113 return std::make_pair(first1, first2);
114}
115
117template <typename InputIter>
121 InputIter begin;
122 InputIter end;
123
124 RangePreview(Size n, InputIter begin, InputIter end)
125 : n(n), begin(begin), end(end) {}
126
127 void print(std::ostream &out) const
128 {
129 if (begin == end) {
130 out << "<Empty Range>";
131 return;
132 }
133
134 out << '[';
135
136 if (n == 0) {
137 out << " ... ";
138 } else {
139 auto dist = std::distance(begin, end);
140 const std::string sep{", "};
141 if (dist <= n * 2) {
142 intersperse(begin, end, sep, out);
143 } else {
144 auto last1 = begin;
145 std::advance(last1, n);
146 intersperse(begin, last1, sep, out);
147 out << sep << "... " << sep;
148 auto first2 = begin;
149 std::advance(first2, dist - n);
150 intersperse(first2, end, sep, out);
151 }
152 }
153
154 auto mm = std::minmax_element(begin, end);
155 out << "] min:" << *mm.first << " max:" << *mm.second;
156 }
157};
158
160template <typename Iter>
162{
163 rp.print(out);
164 return out;
165}
166
171template <typename Range, typename Iter = typename Range::const_iterator, typename Size = typename std::iterator_traits<Iter>::difference_type>
172const RangePreview<Iter> previewRange(Size n, const Range &range)
173{
174 return {n, std::begin(range), std::end(range)};
175}
176
178template <typename T, typename Index, size_t n>
180{
181 static_assert(n > 0, "Reordering nothing is pointless");
182 std::array<T, n> reordered;
183 for (std::size_t i = 0; i < n; ++i) {
184 reordered[i] = elements[order[i]];
185 }
186 return reordered;
187}
188
189template <class InputIt, class Size, class InOutIt>
190void add_n(InputIt first, Size count, InOutIt result)
191{
192 std::transform(first, std::next(first, count), result, result, std::plus{});
193}
194
196template <class InputIt, class Unary>
197void for_each_unique(InputIt first, InputIt last, Unary func)
198{
199 using Inner = std::remove_cv_t<std::remove_reference_t<decltype(*first)>>;
200 std::set<Inner> seen;
201 std::for_each(first, last, [&seen, &func](const auto &elem) {
202 if (seen.count(elem) == 0) {
203 seen.insert(elem);
204 func(elem);
205 }
206 });
207}
208
210template <class InputIt, class Predicate>
211std::pair<InputIt, InputIt> find_first_range(InputIt first, InputIt last, Predicate p)
212{
213 auto firstMatch = std::find_if(first, last, p);
214 if (firstMatch == last) { // nothing found
215 return {last, last};
216 }
217 auto trailing = firstMatch;
218 auto next = std::next(firstMatch);
219 while (next != last && p(*next)) {
220 ++trailing;
221 ++next;
222 }
223 return {firstMatch, trailing};
224}
225
226} // namespace precice::utils
227
228template <typename Iter>
229struct fmt::formatter<precice::utils::RangePreview<Iter>> : ostream_formatter {
230};
std::ostream & out
T advance(T... args)
T begin(T... args)
T count(T... args)
T distance(T... args)
T end(T... args)
T find_if(T... args)
T for_each(T... args)
T make_pair(T... args)
T make_unique(T... args)
T minmax_element(T... args)
contains precice-related utilities.
auto reorder_array(const std::array< Index, n > &order, const std::array< T, n > &elements) -> std::array< T, n >
Reorders an array given an array of unique indices.
void add_n(InputIt first, Size count, InOutIt result)
void for_each_unique(InputIt first, InputIt last, Unary func)
Calls each value in the range of [first, last[ exactly once.
std::pair< InputIt, InputIt > find_first_range(InputIt first, InputIt last, Predicate p)
Finds the first range in [first, last[ that fulfills a predicate.
void intersperse(InputIter first, InputIter last, const ElementType &elem, std::ostream &out)
Definition algorithm.hpp:92
const RangePreview< Iter > previewRange(Size n, const Range &range)
bool unique_elements(const Container &c, BinaryPredicate p={})
Definition algorithm.hpp:63
std::ostream & operator<<(std::ostream &out, const RangePreview< Iter > &rp)
Allows streaming of RangePreview objects.
auto make_array(Elements &&...elements) -> std::array< typename std::common_type< Elements... >::type, sizeof...(Elements)>
Function that generates an array from given elements.
Definition algorithm.hpp:50
void set_intersection_indices(InputIt1 ref1, InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first)
This function is by and large the same as std::set_intersection(). The only difference is that we don...
Definition algorithm.hpp:33
std::pair< InputIt1, InputIt2 > mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
Main namespace of the precice library.
T next(T... args)
The RangePreview object used as a lazy proxy struct for proviewing the content of a Range.
typename std::iterator_traits< InputIter >::difference_type Size
RangePreview(Size n, InputIter begin, InputIter end)
void print(std::ostream &out) const
T transform(T... args)