Vcsn  2.5
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 
50  template <typename Container, typename Predicate>
51  void erase_if(Container& c, const Predicate& p)
52  {
53  using std::begin;
54  using std::end;
55  for (auto i = begin(c); i != end(c); /* nothing. */)
56  {
57  if (p(*i))
58  i = c.erase(i);
59  else
60  ++i;
61  }
62  }
63 
64 
66  template <typename Container>
67  typename Container::value_type
68  front(const Container& container)
69  {
70  using std::begin;
71  using std::end;
72  auto i = begin(container);
73  assert(i != end(container));
74  return *i;
75  }
76 
78  template <typename Iterator, typename Pred, typename Less>
79  boost::iterator_range<Iterator>
80  initial_sorted_range(Iterator begin, Iterator end,
81  Pred pred, Less less)
82  {
83  if (pred(*begin))
84  for (auto i = begin;; ++i)
85  {
86  auto next = std::next(i);
87  if (next == end
88  || !pred(*next)
89  || less(*next, *i))
90  return {begin, next};
91  }
92  else
93  return {end, end};
94  }
95 
100  template <typename Container, typename Compare>
101  bool is_sorted_forward(const Container& container, Compare comp)
102  {
103  auto i = std::begin(container);
104  auto end = std::end(container);
105  if (i != end)
106  {
107  auto prev = *i;
108  for (++i; i != end; ++i)
109  if (comp(prev, *i))
110  prev = *i;
111  else
112  return false;
113  }
114  return true;
115  }
116 
123  template <typename InputIt1, typename InputIt2, class Compare>
124  int lexicographical_cmp(InputIt1 first1, InputIt1 last1,
125  InputIt2 first2, InputIt2 last2,
126  Compare comp)
127  {
128  for ( ; first1 != last1 && first2 != last2; ++first1, ++first2)
129  if (auto res = comp(*first1, *first2))
130  return res;
131  // f1 == l1 && f2 != l2 -> -1
132  // f1 == l1 && f2 == l2 -> 0
133  // f1 != l1 && f2 == l2 -> +1
134  return (first1 != last1) - (first2 != last2);
135  }
136 
141  template <typename Cont1, typename Cont2, typename Compare>
142  int
143  lexicographical_cmp(const Cont1& cont1,
144  const Cont2& cont2,
145  Compare comp)
146  {
147  // FIXME: clang 3.5 does not feature cbegin/cend.
148  using std::begin;
149  using std::end;
150  return lexicographical_cmp(begin(cont1), end(cont1),
151  begin(cont2), end(cont2),
152  comp);
153  }
154 
157  template <typename Container>
158  typename Container::value_type
159  max_forward(const Container& container)
160  {
161  auto i = std::begin(container);
162  auto end = std::end(container);
163  assert(i != end);
164  if (i != end)
165  {
166  auto res = *i;
167  for (++i; i != end; ++i)
168  if (res < *i)
169  res = *i;
170  return res;
171  }
172  abort();
173  }
174 
175  // Boost 1.49 does not have boost/algorithm/cxx11/none_of.hpp and the like.
176  template <typename Range, typename Predicate>
177  bool none_of(const Range &r, Predicate p)
178  {
179  using std::begin;
180  using std::end;
181  return std::none_of(begin(r), end(r), p);
182  }
183 
184  // Not in Boost 1.49.
185  template <typename Range, typename Value>
186  bool none_of_equal(const Range &r, const Value& value)
187  {
188  return none_of(r, [&value](const Value& v) { return v == value; });
189  }
190 
191 
194  template <typename Container, typename Fun>
195  auto transform(const Container& c, Fun&& fun)
196  {
197  using value_t = decltype(std::forward<Fun>(fun)(*begin(c)));
198  auto res = std::vector<value_t>(c.size());
199  std::transform(begin(c), end(c), begin(res), std::forward<Fun>(fun));
200  return res;
201  }
202  }
203 
205  template <typename Container,
206  // SFINAE.
207  typename = typename Container::value_type>
208  Container
209  set_difference(const Container& s1, const Container& s2)
210  {
211  auto res = Container{s1.key_comp(), s1.get_allocator()};
212  auto i = std::insert_iterator<Container>{res, res.begin()};
213  boost::set_difference(s1, s2, i, s1.key_comp());
214  return res;
215  }
216 
218  template <typename Container,
219  // SFINAE.
220  typename = typename Container::value_type>
221  Container
222  set_intersection(const Container& s1, const Container& s2)
223  {
224  auto res = Container{s1.key_comp(), s1.get_allocator()};
225  auto i = std::insert_iterator<Container>{res, res.begin()};
226  boost::set_intersection(s1, s2, i, s1.key_comp());
227  return res;
228  }
229 
231  template <typename Container>
232  bool
233  same_domain(const Container& x, const Container& y)
234  {
235  if (x.size() == y.size())
236  {
237  using std::begin; using std::end;
238  for (auto xi = begin(x), xend = end(x), yi = begin(y);
239  xi != xend;
240  ++xi, ++yi)
241  if (x.key_comp()(xi->first, yi->first)
242  || x.key_comp()(yi->first, xi->first))
243  return false;
244  return true;
245  }
246  else
247  return false;
248  }
249 
251  template <typename Container,
252  // SFINAE.
253  typename = typename Container::value_type>
254  Container
255  set_union(const Container& s1, const Container& s2)
256  {
257  auto res = Container{s1.key_comp(), s1.get_allocator()};
258  auto i = std::insert_iterator<Container>{res, res.begin()};
259  boost::set_union(s1, s2, i, s1.key_comp());
260  return res;
261  }
262 }
Container::value_type front(const Container &container)
The first member of this Container.
Definition: algorithm.hh:68
bool same_domain(const Container &x, const Container &y)
Check that two associative containers have the same keys.
Definition: algorithm.hh:233
void erase_if(Container &c, const Predicate &p)
Definition: algorithm.hh:51
bool any_of(const Range &r, Predicate p)
Definition: algorithm.hh:16
Definition: a-star.hh:8
return res
Definition: multiply.hh:398
bool any_of(const Range &r)
Definition: algorithm.hh:24
Container set_union(const Container &s1, const Container &s2)
The union of two sets.
Definition: algorithm.hh:255
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:195
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:80
bool none_of(const Range &r, Predicate p)
Definition: algorithm.hh:177
int lexicographical_cmp(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp)
Lexicographical three-way comparison between two ranges.
Definition: algorithm.hh:124
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
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:101
Container::value_type back(const Container &container)
The last member of this Container.
Definition: algorithm.hh:37
Container set_difference(const Container &s1, const Container &s2)
The set of members of s1 that are not members of s2.
Definition: algorithm.hh:209
bool none_of_equal(const Range &r, const Value &value)
Definition: algorithm.hh:186
Functor to compare Values of ValueSets.
Definition: functional.hh:91
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:159
Container set_intersection(const Container &s1, const Container &s2)
The intersection of two sets.
Definition: algorithm.hh:222