1//
2// Copyright 2013 Francisco Jerez
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20// OTHER DEALINGS IN THE SOFTWARE.
21//
22
23#ifndef CLOVER_UTIL_FUNCTIONAL_HPP
24#define CLOVER_UTIL_FUNCTIONAL_HPP
25
26#include <type_traits>
27
28namespace clover {
29   struct identity {
30      template<typename T>
31      typename std::remove_reference<T>::type
32      operator()(T &&x) const {
33         return x;
34      }
35   };
36
37   struct plus {
38      template<typename T, typename S>
39      typename std::common_type<T, S>::type
40      operator()(T x, S y) const {
41         return x + y;
42      }
43   };
44
45   struct minus {
46      template<typename T, typename S>
47      typename std::common_type<T, S>::type
48      operator()(T x, S y) const {
49         return x - y;
50      }
51   };
52
53   struct negate {
54      template<typename T>
55      T
56      operator()(T x) const {
57         return -x;
58      }
59   };
60
61   struct multiplies {
62      template<typename T, typename S>
63      typename std::common_type<T, S>::type
64      operator()(T x, S y) const {
65         return x * y;
66      }
67   };
68
69   struct divides {
70      template<typename T, typename S>
71      typename std::common_type<T, S>::type
72      operator()(T x, S y) const {
73         return x / y;
74      }
75   };
76
77   struct modulus {
78      template<typename T, typename S>
79      typename std::common_type<T, S>::type
80      operator()(T x, S y) const {
81         return x % y;
82      }
83   };
84
85   struct minimum {
86      template<typename T>
87      T
88      operator()(T x) const {
89         return x;
90      }
91
92      template<typename T, typename... Ts>
93      T
94      operator()(T x, Ts... xs) const {
95         T y = minimum()(xs...);
96         return x < y ? x : y;
97      }
98   };
99
100   struct maximum {
101      template<typename T>
102      T
103      operator()(T x) const {
104         return x;
105      }
106
107      template<typename T, typename... Ts>
108      T
109      operator()(T x, Ts... xs) const {
110         T y = maximum()(xs...);
111         return x < y ? y : x;
112      }
113   };
114
115   struct preincs {
116      template<typename T>
117      T &
118      operator()(T &x) const {
119         return ++x;
120      }
121   };
122
123   struct predecs {
124      template<typename T>
125      T &
126      operator()(T &x) const {
127         return --x;
128      }
129   };
130
131   template<typename T>
132   class multiplies_by_t {
133   public:
134      multiplies_by_t(T x) : x(x) {
135      }
136
137      template<typename S>
138      typename std::common_type<T, S>::type
139      operator()(S y) const {
140         return x * y;
141      }
142
143   private:
144      T x;
145   };
146
147   template<typename T>
148   multiplies_by_t<T>
149   multiplies_by(T x) {
150      return { x };
151   }
152
153   template<typename T>
154   class preincs_by_t {
155   public:
156      preincs_by_t(T n) : n(n) {
157      }
158
159      template<typename S>
160      S &
161      operator()(S &x) const {
162         return x += n;
163      }
164
165   private:
166      T n;
167   };
168
169   template<typename T>
170   preincs_by_t<T>
171   preincs_by(T n) {
172      return { n };
173   }
174
175   template<typename T>
176   class predecs_by_t {
177   public:
178      predecs_by_t(T n) : n(n) {
179      }
180
181      template<typename S>
182      S &
183      operator()(S &x) const {
184         return x -= n;
185      }
186
187   private:
188      T n;
189   };
190
191   template<typename T>
192   predecs_by_t<T>
193   predecs_by(T n) {
194      return { n };
195   }
196
197   struct greater {
198      template<typename T, typename S>
199      bool
200      operator()(T x, S y) const {
201         return x > y;
202      }
203   };
204
205   struct evals {
206      template<typename T>
207      auto
208      operator()(T &&x) const -> decltype(x()) {
209         return x();
210      }
211   };
212
213   struct derefs {
214      template<typename T>
215      auto
216      operator()(T &&x) const -> decltype(*x) {
217         return *x;
218      }
219   };
220
221   struct addresses {
222      template<typename T>
223      T *
224      operator()(T &x) const {
225         return &x;
226      }
227
228      template<typename T>
229      T *
230      operator()(std::reference_wrapper<T> x) const {
231         return &x.get();
232      }
233   };
234
235   struct begins {
236      template<typename T>
237      auto
238      operator()(T &x) const -> decltype(x.begin()) {
239         return x.begin();
240      }
241   };
242
243   struct ends {
244      template<typename T>
245      auto
246      operator()(T &x) const -> decltype(x.end()) {
247         return x.end();
248      }
249   };
250
251   struct sizes {
252      template<typename T>
253      auto
254      operator()(T &x) const -> decltype(x.size()) {
255         return x.size();
256      }
257   };
258
259   template<typename T>
260   class advances_by_t {
261   public:
262      advances_by_t(T n) : n(n) {
263      }
264
265      template<typename S>
266      S
267      operator()(S &&it) const {
268         std::advance(it, n);
269         return it;
270      }
271
272   private:
273      T n;
274   };
275
276   template<typename T>
277   advances_by_t<T>
278   advances_by(T n) {
279      return { n };
280   }
281
282   struct zips {
283      template<typename... Ts>
284      std::tuple<Ts...>
285      operator()(Ts &&... xs) const {
286         return std::tuple<Ts...>(std::forward<Ts>(xs)...);
287      }
288   };
289
290   struct is_zero {
291      template<typename T>
292      bool
293      operator()(const T &x) const {
294         return x == 0;
295      }
296   };
297
298   struct keys {
299      template<typename P>
300      auto
301      operator()(P &&p) const -> decltype(std::get<0>(std::forward<P>(p))) {
302         return std::get<0>(std::forward<P>(p));
303      }
304   };
305
306   struct values {
307      template<typename P>
308      auto
309      operator()(P &&p) const -> decltype(std::get<1>(std::forward<P>(p))) {
310         return std::get<1>(std::forward<P>(p));
311      }
312   };
313
314   template<typename T>
315   class equals_t {
316   public:
317      equals_t(T &&x) : x(x) {}
318
319      template<typename S>
320      bool
321      operator()(S &&y) const {
322         return x == y;
323      }
324
325   private:
326      T x;
327   };
328
329   template<typename T>
330   equals_t<T>
331   equals(T &&x) {
332      return { std::forward<T>(x) };
333   }
334
335   class name_equals {
336   public:
337      name_equals(const std::string &name) : name(name) {
338      }
339
340      template<typename T>
341      bool
342      operator()(const T &x) const {
343         return std::string(x.name.begin(), x.name.end()) == name;
344      }
345
346   private:
347      const std::string &name;
348   };
349
350   template<typename T>
351   class key_equals_t {
352   public:
353      key_equals_t(T &&x) : x(x) {
354      }
355
356      template<typename P>
357      bool
358      operator()(const P &p) const {
359         return p.first == x;
360      }
361
362   private:
363      T x;
364   };
365
366   template<typename T>
367   key_equals_t<T>
368   key_equals(T &&x) {
369      return { std::forward<T>(x) };
370   }
371
372   template<typename T>
373   class type_equals_t {
374   public:
375      type_equals_t(T type) : type(type) {
376      }
377
378      template<typename S>
379      bool
380      operator()(const S &x) const {
381         return x.type == type;
382      }
383
384   private:
385      T type;
386   };
387
388   template<typename T>
389   type_equals_t<T>
390   type_equals(T x) {
391      return { x };
392   }
393
394   struct interval_overlaps {
395      template<typename T>
396      bool
397      operator()(T x0, T x1, T y0, T y1) {
398         return ((x0 <= y0 && y0 < x1) ||
399                 (y0 <= x0 && x0 < y1));
400      }
401   };
402}
403
404#endif
405