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 
28 namespace clover {
29    struct identity {
30       template<typename T>
31       typename std::remove_reference<T>::type
operator ()clover::identity32       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
operator ()clover::plus40       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
operator ()clover::minus48       operator()(T x, S y) const {
49          return x - y;
50       }
51    };
52 
53    struct negate {
54       template<typename T>
55       T
operator ()clover::negate56       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
operator ()clover::multiplies64       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
operator ()clover::divides72       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
operator ()clover::modulus80       operator()(T x, S y) const {
81          return x % y;
82       }
83    };
84 
85    struct minimum {
86       template<typename T>
87       T
operator ()clover::minimum88       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
operator ()clover::maximum103       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 &
operator ()clover::preincs118       operator()(T &x) const {
119          return ++x;
120       }
121    };
122 
123    struct predecs {
124       template<typename T>
125       T &
operator ()clover::predecs126       operator()(T &x) const {
127          return --x;
128       }
129    };
130 
131    template<typename T>
132    class multiplies_by_t {
133    public:
multiplies_by_t(T x)134       multiplies_by_t(T x) : x(x) {
135       }
136 
137       template<typename S>
138       typename std::common_type<T, S>::type
operator ()(S y) const139       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>
multiplies_by(T x)149    multiplies_by(T x) {
150       return { x };
151    }
152 
153    template<typename T>
154    class preincs_by_t {
155    public:
preincs_by_t(T n)156       preincs_by_t(T n) : n(n) {
157       }
158 
159       template<typename S>
160       S &
operator ()(S & x) const161       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>
preincs_by(T n)171    preincs_by(T n) {
172       return { n };
173    }
174 
175    template<typename T>
176    class predecs_by_t {
177    public:
predecs_by_t(T n)178       predecs_by_t(T n) : n(n) {
179       }
180 
181       template<typename S>
182       S &
operator ()(S & x) const183       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>
predecs_by(T n)193    predecs_by(T n) {
194       return { n };
195    }
196 
197    struct greater {
198       template<typename T, typename S>
199       bool
operator ()clover::greater200       operator()(T x, S y) const {
201          return x > y;
202       }
203    };
204 
205    struct evals {
206       template<typename T>
207       auto
operator ()clover::evals208       operator()(T &&x) const -> decltype(x()) {
209          return x();
210       }
211    };
212 
213    struct derefs {
214       template<typename T>
215       auto
operator ()clover::derefs216       operator()(T &&x) const -> decltype(*x) {
217          return *x;
218       }
219    };
220 
221    struct addresses {
222       template<typename T>
223       T *
operator ()clover::addresses224       operator()(T &x) const {
225          return &x;
226       }
227 
228       template<typename T>
229       T *
operator ()clover::addresses230       operator()(std::reference_wrapper<T> x) const {
231          return &x.get();
232       }
233    };
234 
235    struct begins {
236       template<typename T>
237       auto
operator ()clover::begins238       operator()(T &x) const -> decltype(x.begin()) {
239          return x.begin();
240       }
241    };
242 
243    struct ends {
244       template<typename T>
245       auto
operator ()clover::ends246       operator()(T &x) const -> decltype(x.end()) {
247          return x.end();
248       }
249    };
250 
251    struct sizes {
252       template<typename T>
253       auto
operator ()clover::sizes254       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:
advances_by_t(T n)262       advances_by_t(T n) : n(n) {
263       }
264 
265       template<typename S>
266       S
operator ()(S && it) const267       operator()(S &&it) const {
268          std::advance(it, n);
269          return std::forward<S>(it);
270       }
271 
272    private:
273       T n;
274    };
275 
276    template<typename T>
277    advances_by_t<T>
advances_by(T n)278    advances_by(T n) {
279       return { n };
280    }
281 
282    struct zips {
283       template<typename... Ts>
284       std::tuple<Ts...>
operator ()clover::zips285       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
operator ()clover::is_zero293       operator()(const T &x) const {
294          return x == 0;
295       }
296    };
297 
298    struct keys {
299       template<typename P>
300       auto
operator ()clover::keys301       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
operator ()clover::values309       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:
equals_t(T && x)317       equals_t(T &&x) : x(x) {}
318 
319       template<typename S>
320       bool
operator ()(S && y) const321       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>
equals(T && x)331    equals(T &&x) {
332       return { std::forward<T>(x) };
333    }
334 
335    class name_equals {
336    public:
name_equals(const std::string & name)337       name_equals(const std::string &name) : name(name) {
338       }
339 
340       template<typename T>
341       bool
operator ()(const T & x) const342       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:
key_equals_t(T && x)353       key_equals_t(T &&x) : x(x) {
354       }
355 
356       template<typename P>
357       bool
operator ()(const P & p) const358       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>
key_equals(T && x)368    key_equals(T &&x) {
369       return { std::forward<T>(x) };
370    }
371 
372    template<typename T>
373    class type_equals_t {
374    public:
type_equals_t(T type)375       type_equals_t(T type) : type(type) {
376       }
377 
378       template<typename S>
379       bool
operator ()(const S & x) const380       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>
type_equals(T x)390    type_equals(T x) {
391       return { x };
392    }
393 
394    template<typename T>
395    class id_type_equals_t {
396    public:
id_type_equals_t(const uint32_t id,T t)397       id_type_equals_t(const uint32_t id, T t) :
398          id(id), type(t) {
399       }
400 
401       template<typename X>
402       bool
operator ()(const X & x) const403       operator()(const X &x) const {
404          return id == x.id && type(x);
405       }
406 
407    private:
408       const uint32_t id;
409       type_equals_t<T> type;
410    };
411 
412    template<typename T>
413    id_type_equals_t<T>
id_type_equals(const uint32_t id,T x)414    id_type_equals(const uint32_t id, T x) {
415       return { id, x };
416    }
417 
418    struct interval_overlaps {
419       template<typename T>
420       bool
operator ()clover::interval_overlaps421       operator()(T x0, T x1, T y0, T y1) {
422          return ((x0 <= y0 && y0 < x1) ||
423                  (y0 <= x0 && x0 < y1));
424       }
425    };
426 }
427 
428 #endif
429