Vcsn  2.8
Be Rational
algorithm.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <iterator> // next
5 #include <vector>
6 
7 #include <boost/range/algorithm/set_algorithm.hpp>
8 #include <boost/range/iterator_range_core.hpp>
9 
10 namespace vcsn
11 {
12  namespace detail
13  {
14  // Not in Boost 1.49.
15  template <typename Range, typename Predicate>
16  bool any_of(const Range &r, Predicate p)
17  {
18  using std::begin;
19  using std::end;
20  return std::any_of(begin(r), end(r), p);
21  }
22 
23  template <typename Range>
24  bool any_of(const Range &r)
25  {
26  using std::begin;
27  using std::end;
28  return std::any_of(begin(r), end(r),
29  [](const auto& p) -> bool { return p; });
30  }
31 
35  template <typename Container>
36  typename Container::value_type
37  back(const Container& container)
38  {
39  using std::begin;
40  using std::end;
41  auto i = begin(container);
42  auto iend = end(container);
43  assert(i != iend);
44  auto res = *i;
45  for (++i; i != iend; ++i)
46  res = *i;
47  return res;
48  }
49 
54  template <typename Container, typename Predicate>
55  void erase_if(Container& c, Predicate p)
56  {
57  using std::begin;
58  using std::end;
59  for (auto i = begin(c); i != end(c); /* nothing. */)
60  {
61  if (p(*i))
62  i = c.erase(i);
63  else
64  ++i;
65  }
66  }
67 
68 
70  template <typename Container>
71  typename Container::value_type
72  front(const Container& container)
73  {
74  using std::begin;
75  using std::end;
76  auto i = begin(container);
77  assert(i != end(container));
78  return *i;
79  }
80 
82  template <typename Iterator, typename Pred, typename Less>
83  boost::iterator_range<Iterator>
84  initial_sorted_range(Iterator begin, Iterator end,
85  Pred pred, Less less)
86  {
87  if (pred(*begin))
88  for (auto i = begin;; ++i)
89  {
90  auto next = std::next(i);
91  if (next == end
92  || !pred(*next)
93  || less(*next, *i))
94  return {begin, next};
95  }
96  else
97  return {end, end};
98  }
99 
104  template <typename Container, typename Compare>
105  bool is_sorted_forward(const Container& container, Compare comp)
106  {
107  auto i = std::begin(container);
108  auto end = std::end(container);
109  if (i != end)
110  {
111  auto prev = *i;
112  for (++i; i != end; ++i)
113  if (comp(prev, *i))
114  prev = *i;
115  else
116  return false;
117  }
118  return true;
119  }
120 
127  template <typename InputIt1, typename InputIt2, class Compare>
128  int lexicographical_cmp(InputIt1 first1, InputIt1 last1,
129  InputIt2 first2, InputIt2 last2,
130  Compare comp)
131  {
132  for ( ; first1 != last1 && first2 != last2; ++first1, ++first2)
133  if (auto res = comp(*first1, *first2))
134  return res;
135  // f1 == l1 && f2 != l2 -> -1
136  // f1 == l1 && f2 == l2 -> 0
137  // f1 != l1 && f2 == l2 -> +1
138  return (first1 != last1) - (first2 != last2);
139  }
140 
145  template <typename Cont1, typename Cont2, typename Compare>
146  int
147  lexicographical_cmp(const Cont1& cont1,
148  const Cont2& cont2,
149  Compare comp)
150  {
151  // FIXME: clang 3.5 does not feature cbegin/cend.
152  using std::begin;
153  using std::end;
154  return lexicographical_cmp(begin(cont1), end(cont1),
155  begin(cont2), end(cont2),
156  comp);
157  }
158 
161  template <typename Container>
162  typename Container::value_type
163  max_forward(const Container& container)
164  {
165  auto i = std::begin(container);
166  auto end = std::end(container);
167  assert(i != end);
168  auto res = *i;
169  for (++i; i != end; ++i)
170  if (res < *i)
171  res = *i;
172  return res;
173  }
174 
177  template <typename Container, typename Comp>
178  typename Container::value_type
179  min_forward(const Container& container, Comp comp)
180  {
181  auto i = std::begin(container);
182  auto end = std::end(container);
183  assert(i != end);
184  auto res = *i;
185  for (++i; i != end; ++i)
186  if (comp(*i, res))
187  res = *i;
188  return res;
189  }
190 
191  // Boost 1.49 does not have boost/algorithm/cxx11/none_of.hpp and the like.
192  template <typename Range, typename Predicate>
193  bool none_of(const Range &r, Predicate p)
194  {
195  using std::begin;
196  using std::end;
197  return std::none_of(begin(r), end(r), p);
198  }
199 
200  // Not in Boost 1.49.
201  template <typename Range, typename Value>
202  bool none_of_equal(const Range &r, const Value& value)
203  {
204  return none_of(r, [&value](const Value& v) { return v == value; });
205  }
206 
207 
210  template <typename Container, typename Fun>
211  auto transform(const Container& c, Fun&& fun)
212  {
213  using value_t = decltype(std::forward<Fun>(fun)(*begin(c)));
214  auto res = std::vector<value_t>(c.size());
215  std::transform(begin(c), end(c), begin(res), std::forward<Fun>(fun));
216  return res;
217  }
218  }
219 
221  template <typename Container,
222  // SFINAE.
223  typename = typename Container::value_type>
224  Container
225  set_difference(const Container& s1, const Container& s2)
226  {
227  auto res = Container{s1.key_comp(), s1.get_allocator()};
228  auto i = std::insert_iterator<Container>{res, res.begin()};
229  boost::set_difference(s1, s2, i, s1.key_comp());
230  return res;
231  }
232 
234  template <typename Container,
235  // SFINAE.
236  typename = typename Container::value_type>
237  Container
238  set_intersection(const Container& s1, const Container& s2)
239  {
240  auto res = Container{s1.key_comp(), s1.get_allocator()};
241  auto i = std::insert_iterator<Container>{res, res.begin()};
242  boost::set_intersection(s1, s2, i, s1.key_comp());
243  return res;
244  }
245 
247  template <typename Container>
248  bool
249  same_domain(const Container& x, const Container& y)
250  {
251  if (x.size() == y.size())
252  {
253  using std::begin; using std::end;
254  for (auto xi = begin(x), xend = end(x), yi = begin(y);
255  xi != xend;
256  ++xi, ++yi)
257  if (x.key_comp()(xi->first, yi->first)
258  || x.key_comp()(yi->first, xi->first))
259  return false;
260  return true;
261  }
262  else
263  return false;
264  }
265 
267  template <typename Container,
268  // SFINAE.
269  typename = typename Container::value_type>
270  Container
271  set_union(const Container& s1, const Container& s2)
272  {
273  auto res = Container{s1.key_comp(), s1.get_allocator()};
274  auto i = std::insert_iterator<Container>{res, res.begin()};
275  boost::set_union(s1, s2, i, s1.key_comp());
276  return res;
277  }
278 }
bool any_of(const Range &r, Predicate p)
Definition: algorithm.hh:16
int lexicographical_cmp(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp)
Lexicographical three-way comparison between two ranges.
Definition: algorithm.hh:128
bool any_of(const Range &r)
Definition: algorithm.hh:24
boost::iterator_range< Iterator > initial_sorted_range(Iterator begin, Iterator end, Pred pred, Less less)
The longest initial range of elements matching the predicate.
Definition: algorithm.hh:84
bool same_domain(const Container &x, const Container &y)
Check that two associative containers have the same keys.
Definition: algorithm.hh:249
Container::value_type min_forward(const Container &container, Comp comp)
Same as *std::max_element, but works with an input iterator, not just a forward iterator.
Definition: algorithm.hh:179
bool none_of(const Range &r, Predicate p)
Definition: algorithm.hh:193
Container::value_type back(const Container &container)
The last member of this Container.
Definition: algorithm.hh:37
auto transform(const Container &c, Fun &&fun)
Map a unary function on a container of values, and return the vector the results. ...
Definition: algorithm.hh:211
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
Container::value_type max_forward(const Container &container)
Same as *std::max_element, but works with an input iterator, not just a forward iterator.
Definition: algorithm.hh:163
void erase_if(Container &c, Predicate p)
In place removal of entries matching the predicate.
Definition: algorithm.hh:55
Definition: a-star.hh:8
Container set_intersection(const Container &s1, const Container &s2)
The intersection of two sets.
Definition: algorithm.hh:238
Container::value_type front(const Container &container)
The first member of this Container.
Definition: algorithm.hh:72
bool none_of_equal(const Range &r, const Value &value)
Definition: algorithm.hh:202
Container set_union(const Container &s1, const Container &s2)
The union of two sets.
Definition: algorithm.hh:271
Functor to compare Values of ValueSets.
Definition: functional.hh:91
bool is_sorted_forward(const Container &container, Compare comp)
Same as std::is_sorted, but works with an input iterator, not just a forward iterator.
Definition: algorithm.hh:105
return res
Definition: multiply.hh:399
Container set_difference(const Container &s1, const Container &s2)
The set of members of s1 that are not members of s2.
Definition: algorithm.hh:225