17ec681f3Smrg//
27ec681f3Smrg// Copyright 2013 Francisco Jerez
37ec681f3Smrg//
47ec681f3Smrg// Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg// copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg// to deal in the Software without restriction, including without limitation
77ec681f3Smrg// the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg// and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg// Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg//
117ec681f3Smrg// The above copyright notice and this permission notice shall be included in
127ec681f3Smrg// all copies or substantial portions of the Software.
137ec681f3Smrg//
147ec681f3Smrg// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157ec681f3Smrg// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167ec681f3Smrg// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
177ec681f3Smrg// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
187ec681f3Smrg// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
197ec681f3Smrg// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
207ec681f3Smrg// OTHER DEALINGS IN THE SOFTWARE.
217ec681f3Smrg//
227ec681f3Smrg
237ec681f3Smrg#ifndef CLOVER_UTIL_FUNCTIONAL_HPP
247ec681f3Smrg#define CLOVER_UTIL_FUNCTIONAL_HPP
257ec681f3Smrg
267ec681f3Smrg#include <type_traits>
277ec681f3Smrg
287ec681f3Smrgnamespace clover {
297ec681f3Smrg   struct identity {
307ec681f3Smrg      template<typename T>
317ec681f3Smrg      typename std::remove_reference<T>::type
327ec681f3Smrg      operator()(T &&x) const {
337ec681f3Smrg         return x;
347ec681f3Smrg      }
357ec681f3Smrg   };
367ec681f3Smrg
377ec681f3Smrg   struct plus {
387ec681f3Smrg      template<typename T, typename S>
397ec681f3Smrg      typename std::common_type<T, S>::type
407ec681f3Smrg      operator()(T x, S y) const {
417ec681f3Smrg         return x + y;
427ec681f3Smrg      }
437ec681f3Smrg   };
447ec681f3Smrg
457ec681f3Smrg   struct minus {
467ec681f3Smrg      template<typename T, typename S>
477ec681f3Smrg      typename std::common_type<T, S>::type
487ec681f3Smrg      operator()(T x, S y) const {
497ec681f3Smrg         return x - y;
507ec681f3Smrg      }
517ec681f3Smrg   };
527ec681f3Smrg
537ec681f3Smrg   struct negate {
547ec681f3Smrg      template<typename T>
557ec681f3Smrg      T
567ec681f3Smrg      operator()(T x) const {
577ec681f3Smrg         return -x;
587ec681f3Smrg      }
597ec681f3Smrg   };
607ec681f3Smrg
617ec681f3Smrg   struct multiplies {
627ec681f3Smrg      template<typename T, typename S>
637ec681f3Smrg      typename std::common_type<T, S>::type
647ec681f3Smrg      operator()(T x, S y) const {
657ec681f3Smrg         return x * y;
667ec681f3Smrg      }
677ec681f3Smrg   };
687ec681f3Smrg
697ec681f3Smrg   struct divides {
707ec681f3Smrg      template<typename T, typename S>
717ec681f3Smrg      typename std::common_type<T, S>::type
727ec681f3Smrg      operator()(T x, S y) const {
737ec681f3Smrg         return x / y;
747ec681f3Smrg      }
757ec681f3Smrg   };
767ec681f3Smrg
777ec681f3Smrg   struct modulus {
787ec681f3Smrg      template<typename T, typename S>
797ec681f3Smrg      typename std::common_type<T, S>::type
807ec681f3Smrg      operator()(T x, S y) const {
817ec681f3Smrg         return x % y;
827ec681f3Smrg      }
837ec681f3Smrg   };
847ec681f3Smrg
857ec681f3Smrg   struct minimum {
867ec681f3Smrg      template<typename T>
877ec681f3Smrg      T
887ec681f3Smrg      operator()(T x) const {
897ec681f3Smrg         return x;
907ec681f3Smrg      }
917ec681f3Smrg
927ec681f3Smrg      template<typename T, typename... Ts>
937ec681f3Smrg      T
947ec681f3Smrg      operator()(T x, Ts... xs) const {
957ec681f3Smrg         T y = minimum()(xs...);
967ec681f3Smrg         return x < y ? x : y;
977ec681f3Smrg      }
987ec681f3Smrg   };
997ec681f3Smrg
1007ec681f3Smrg   struct maximum {
1017ec681f3Smrg      template<typename T>
1027ec681f3Smrg      T
1037ec681f3Smrg      operator()(T x) const {
1047ec681f3Smrg         return x;
1057ec681f3Smrg      }
1067ec681f3Smrg
1077ec681f3Smrg      template<typename T, typename... Ts>
1087ec681f3Smrg      T
1097ec681f3Smrg      operator()(T x, Ts... xs) const {
1107ec681f3Smrg         T y = maximum()(xs...);
1117ec681f3Smrg         return x < y ? y : x;
1127ec681f3Smrg      }
1137ec681f3Smrg   };
1147ec681f3Smrg
1157ec681f3Smrg   struct preincs {
1167ec681f3Smrg      template<typename T>
1177ec681f3Smrg      T &
1187ec681f3Smrg      operator()(T &x) const {
1197ec681f3Smrg         return ++x;
1207ec681f3Smrg      }
1217ec681f3Smrg   };
1227ec681f3Smrg
1237ec681f3Smrg   struct predecs {
1247ec681f3Smrg      template<typename T>
1257ec681f3Smrg      T &
1267ec681f3Smrg      operator()(T &x) const {
1277ec681f3Smrg         return --x;
1287ec681f3Smrg      }
1297ec681f3Smrg   };
1307ec681f3Smrg
1317ec681f3Smrg   template<typename T>
1327ec681f3Smrg   class multiplies_by_t {
1337ec681f3Smrg   public:
1347ec681f3Smrg      multiplies_by_t(T x) : x(x) {
1357ec681f3Smrg      }
1367ec681f3Smrg
1377ec681f3Smrg      template<typename S>
1387ec681f3Smrg      typename std::common_type<T, S>::type
1397ec681f3Smrg      operator()(S y) const {
1407ec681f3Smrg         return x * y;
1417ec681f3Smrg      }
1427ec681f3Smrg
1437ec681f3Smrg   private:
1447ec681f3Smrg      T x;
1457ec681f3Smrg   };
1467ec681f3Smrg
1477ec681f3Smrg   template<typename T>
1487ec681f3Smrg   multiplies_by_t<T>
1497ec681f3Smrg   multiplies_by(T x) {
1507ec681f3Smrg      return { x };
1517ec681f3Smrg   }
1527ec681f3Smrg
1537ec681f3Smrg   template<typename T>
1547ec681f3Smrg   class preincs_by_t {
1557ec681f3Smrg   public:
1567ec681f3Smrg      preincs_by_t(T n) : n(n) {
1577ec681f3Smrg      }
1587ec681f3Smrg
1597ec681f3Smrg      template<typename S>
1607ec681f3Smrg      S &
1617ec681f3Smrg      operator()(S &x) const {
1627ec681f3Smrg         return x += n;
1637ec681f3Smrg      }
1647ec681f3Smrg
1657ec681f3Smrg   private:
1667ec681f3Smrg      T n;
1677ec681f3Smrg   };
1687ec681f3Smrg
1697ec681f3Smrg   template<typename T>
1707ec681f3Smrg   preincs_by_t<T>
1717ec681f3Smrg   preincs_by(T n) {
1727ec681f3Smrg      return { n };
1737ec681f3Smrg   }
1747ec681f3Smrg
1757ec681f3Smrg   template<typename T>
1767ec681f3Smrg   class predecs_by_t {
1777ec681f3Smrg   public:
1787ec681f3Smrg      predecs_by_t(T n) : n(n) {
1797ec681f3Smrg      }
1807ec681f3Smrg
1817ec681f3Smrg      template<typename S>
1827ec681f3Smrg      S &
1837ec681f3Smrg      operator()(S &x) const {
1847ec681f3Smrg         return x -= n;
1857ec681f3Smrg      }
1867ec681f3Smrg
1877ec681f3Smrg   private:
1887ec681f3Smrg      T n;
1897ec681f3Smrg   };
1907ec681f3Smrg
1917ec681f3Smrg   template<typename T>
1927ec681f3Smrg   predecs_by_t<T>
1937ec681f3Smrg   predecs_by(T n) {
1947ec681f3Smrg      return { n };
1957ec681f3Smrg   }
1967ec681f3Smrg
1977ec681f3Smrg   struct greater {
1987ec681f3Smrg      template<typename T, typename S>
1997ec681f3Smrg      bool
2007ec681f3Smrg      operator()(T x, S y) const {
2017ec681f3Smrg         return x > y;
2027ec681f3Smrg      }
2037ec681f3Smrg   };
2047ec681f3Smrg
2057ec681f3Smrg   struct evals {
2067ec681f3Smrg      template<typename T>
2077ec681f3Smrg      auto
2087ec681f3Smrg      operator()(T &&x) const -> decltype(x()) {
2097ec681f3Smrg         return x();
2107ec681f3Smrg      }
2117ec681f3Smrg   };
2127ec681f3Smrg
2137ec681f3Smrg   struct derefs {
2147ec681f3Smrg      template<typename T>
2157ec681f3Smrg      auto
2167ec681f3Smrg      operator()(T &&x) const -> decltype(*x) {
2177ec681f3Smrg         return *x;
2187ec681f3Smrg      }
2197ec681f3Smrg   };
2207ec681f3Smrg
2217ec681f3Smrg   struct addresses {
2227ec681f3Smrg      template<typename T>
2237ec681f3Smrg      T *
2247ec681f3Smrg      operator()(T &x) const {
2257ec681f3Smrg         return &x;
2267ec681f3Smrg      }
2277ec681f3Smrg
2287ec681f3Smrg      template<typename T>
2297ec681f3Smrg      T *
2307ec681f3Smrg      operator()(std::reference_wrapper<T> x) const {
2317ec681f3Smrg         return &x.get();
2327ec681f3Smrg      }
2337ec681f3Smrg   };
2347ec681f3Smrg
2357ec681f3Smrg   struct begins {
2367ec681f3Smrg      template<typename T>
2377ec681f3Smrg      auto
2387ec681f3Smrg      operator()(T &x) const -> decltype(x.begin()) {
2397ec681f3Smrg         return x.begin();
2407ec681f3Smrg      }
2417ec681f3Smrg   };
2427ec681f3Smrg
2437ec681f3Smrg   struct ends {
2447ec681f3Smrg      template<typename T>
2457ec681f3Smrg      auto
2467ec681f3Smrg      operator()(T &x) const -> decltype(x.end()) {
2477ec681f3Smrg         return x.end();
2487ec681f3Smrg      }
2497ec681f3Smrg   };
2507ec681f3Smrg
2517ec681f3Smrg   struct sizes {
2527ec681f3Smrg      template<typename T>
2537ec681f3Smrg      auto
2547ec681f3Smrg      operator()(T &x) const -> decltype(x.size()) {
2557ec681f3Smrg         return x.size();
2567ec681f3Smrg      }
2577ec681f3Smrg   };
2587ec681f3Smrg
2597ec681f3Smrg   template<typename T>
2607ec681f3Smrg   class advances_by_t {
2617ec681f3Smrg   public:
2627ec681f3Smrg      advances_by_t(T n) : n(n) {
2637ec681f3Smrg      }
2647ec681f3Smrg
2657ec681f3Smrg      template<typename S>
2667ec681f3Smrg      S
2677ec681f3Smrg      operator()(S &&it) const {
2687ec681f3Smrg         std::advance(it, n);
2697ec681f3Smrg         return std::forward<S>(it);
2707ec681f3Smrg      }
2717ec681f3Smrg
2727ec681f3Smrg   private:
2737ec681f3Smrg      T n;
2747ec681f3Smrg   };
2757ec681f3Smrg
2767ec681f3Smrg   template<typename T>
2777ec681f3Smrg   advances_by_t<T>
2787ec681f3Smrg   advances_by(T n) {
2797ec681f3Smrg      return { n };
2807ec681f3Smrg   }
2817ec681f3Smrg
2827ec681f3Smrg   struct zips {
2837ec681f3Smrg      template<typename... Ts>
2847ec681f3Smrg      std::tuple<Ts...>
2857ec681f3Smrg      operator()(Ts &&... xs) const {
2867ec681f3Smrg         return std::tuple<Ts...>(std::forward<Ts>(xs)...);
2877ec681f3Smrg      }
2887ec681f3Smrg   };
2897ec681f3Smrg
2907ec681f3Smrg   struct is_zero {
2917ec681f3Smrg      template<typename T>
2927ec681f3Smrg      bool
2937ec681f3Smrg      operator()(const T &x) const {
2947ec681f3Smrg         return x == 0;
2957ec681f3Smrg      }
2967ec681f3Smrg   };
2977ec681f3Smrg
2987ec681f3Smrg   struct keys {
2997ec681f3Smrg      template<typename P>
3007ec681f3Smrg      auto
3017ec681f3Smrg      operator()(P &&p) const -> decltype(std::get<0>(std::forward<P>(p))) {
3027ec681f3Smrg         return std::get<0>(std::forward<P>(p));
3037ec681f3Smrg      }
3047ec681f3Smrg   };
3057ec681f3Smrg
3067ec681f3Smrg   struct values {
3077ec681f3Smrg      template<typename P>
3087ec681f3Smrg      auto
3097ec681f3Smrg      operator()(P &&p) const -> decltype(std::get<1>(std::forward<P>(p))) {
3107ec681f3Smrg         return std::get<1>(std::forward<P>(p));
3117ec681f3Smrg      }
3127ec681f3Smrg   };
3137ec681f3Smrg
3147ec681f3Smrg   template<typename T>
3157ec681f3Smrg   class equals_t {
3167ec681f3Smrg   public:
3177ec681f3Smrg      equals_t(T &&x) : x(x) {}
3187ec681f3Smrg
3197ec681f3Smrg      template<typename S>
3207ec681f3Smrg      bool
3217ec681f3Smrg      operator()(S &&y) const {
3227ec681f3Smrg         return x == y;
3237ec681f3Smrg      }
3247ec681f3Smrg
3257ec681f3Smrg   private:
3267ec681f3Smrg      T x;
3277ec681f3Smrg   };
3287ec681f3Smrg
3297ec681f3Smrg   template<typename T>
3307ec681f3Smrg   equals_t<T>
3317ec681f3Smrg   equals(T &&x) {
3327ec681f3Smrg      return { std::forward<T>(x) };
3337ec681f3Smrg   }
3347ec681f3Smrg
3357ec681f3Smrg   class name_equals {
3367ec681f3Smrg   public:
3377ec681f3Smrg      name_equals(const std::string &name) : name(name) {
3387ec681f3Smrg      }
3397ec681f3Smrg
3407ec681f3Smrg      template<typename T>
3417ec681f3Smrg      bool
3427ec681f3Smrg      operator()(const T &x) const {
3437ec681f3Smrg         return std::string(x.name.begin(), x.name.end()) == name;
3447ec681f3Smrg      }
3457ec681f3Smrg
3467ec681f3Smrg   private:
3477ec681f3Smrg      const std::string &name;
3487ec681f3Smrg   };
3497ec681f3Smrg
3507ec681f3Smrg   template<typename T>
3517ec681f3Smrg   class key_equals_t {
3527ec681f3Smrg   public:
3537ec681f3Smrg      key_equals_t(T &&x) : x(x) {
3547ec681f3Smrg      }
3557ec681f3Smrg
3567ec681f3Smrg      template<typename P>
3577ec681f3Smrg      bool
3587ec681f3Smrg      operator()(const P &p) const {
3597ec681f3Smrg         return p.first == x;
3607ec681f3Smrg      }
3617ec681f3Smrg
3627ec681f3Smrg   private:
3637ec681f3Smrg      T x;
3647ec681f3Smrg   };
3657ec681f3Smrg
3667ec681f3Smrg   template<typename T>
3677ec681f3Smrg   key_equals_t<T>
3687ec681f3Smrg   key_equals(T &&x) {
3697ec681f3Smrg      return { std::forward<T>(x) };
3707ec681f3Smrg   }
3717ec681f3Smrg
3727ec681f3Smrg   template<typename T>
3737ec681f3Smrg   class type_equals_t {
3747ec681f3Smrg   public:
3757ec681f3Smrg      type_equals_t(T type) : type(type) {
3767ec681f3Smrg      }
3777ec681f3Smrg
3787ec681f3Smrg      template<typename S>
3797ec681f3Smrg      bool
3807ec681f3Smrg      operator()(const S &x) const {
3817ec681f3Smrg         return x.type == type;
3827ec681f3Smrg      }
3837ec681f3Smrg
3847ec681f3Smrg   private:
3857ec681f3Smrg      T type;
3867ec681f3Smrg   };
3877ec681f3Smrg
3887ec681f3Smrg   template<typename T>
3897ec681f3Smrg   type_equals_t<T>
3907ec681f3Smrg   type_equals(T x) {
3917ec681f3Smrg      return { x };
3927ec681f3Smrg   }
3937ec681f3Smrg
3947ec681f3Smrg   template<typename T>
3957ec681f3Smrg   class id_type_equals_t {
3967ec681f3Smrg   public:
3977ec681f3Smrg      id_type_equals_t(const uint32_t id, T t) :
3987ec681f3Smrg         id(id), type(t) {
3997ec681f3Smrg      }
4007ec681f3Smrg
4017ec681f3Smrg      template<typename X>
4027ec681f3Smrg      bool
4037ec681f3Smrg      operator()(const X &x) const {
4047ec681f3Smrg         return id == x.id && type(x);
4057ec681f3Smrg      }
4067ec681f3Smrg
4077ec681f3Smrg   private:
4087ec681f3Smrg      const uint32_t id;
4097ec681f3Smrg      type_equals_t<T> type;
4107ec681f3Smrg   };
4117ec681f3Smrg
4127ec681f3Smrg   template<typename T>
4137ec681f3Smrg   id_type_equals_t<T>
4147ec681f3Smrg   id_type_equals(const uint32_t id, T x) {
4157ec681f3Smrg      return { id, x };
4167ec681f3Smrg   }
4177ec681f3Smrg
4187ec681f3Smrg   struct interval_overlaps {
4197ec681f3Smrg      template<typename T>
4207ec681f3Smrg      bool
4217ec681f3Smrg      operator()(T x0, T x1, T y0, T y1) {
4227ec681f3Smrg         return ((x0 <= y0 && y0 < x1) ||
4237ec681f3Smrg                 (y0 <= x0 && x0 < y1));
4247ec681f3Smrg      }
4257ec681f3Smrg   };
4267ec681f3Smrg}
4277ec681f3Smrg
4287ec681f3Smrg#endif
429