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