• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 
5 #ifndef TEST_SUPPORT_NUMERIC_HPP
6 #define TEST_SUPPORT_NUMERIC_HPP
7 
8 #include <boost/hana/core/tag_of.hpp>
9 #include <boost/hana/eval.hpp>
10 #include <boost/hana/fwd/div.hpp>
11 #include <boost/hana/fwd/equal.hpp>
12 #include <boost/hana/fwd/eval_if.hpp>
13 #include <boost/hana/fwd/less.hpp>
14 #include <boost/hana/fwd/minus.hpp>
15 #include <boost/hana/fwd/mod.hpp>
16 #include <boost/hana/fwd/mult.hpp>
17 #include <boost/hana/fwd/negate.hpp>
18 #include <boost/hana/fwd/not.hpp>
19 #include <boost/hana/fwd/one.hpp>
20 #include <boost/hana/fwd/plus.hpp>
21 #include <boost/hana/fwd/while.hpp>
22 #include <boost/hana/fwd/zero.hpp>
23 
24 
25 struct numeric_type {
numeric_typenumeric_type26     constexpr explicit numeric_type(int v) : value(v) { }
27     int value;
operator intnumeric_type28     constexpr operator int() const { return value; }
29 };
30 
31 using Numeric = boost::hana::tag_of_t<numeric_type>;
32 
33 struct numeric_t {
operator ()numeric_t34     constexpr numeric_type operator()(int x) const {
35         return numeric_type{x};
36     }
37 };
38 constexpr numeric_t numeric{};
39 
40 
41 namespace boost { namespace hana {
42     //////////////////////////////////////////////////////////////////////////
43     // Comparable
44     //////////////////////////////////////////////////////////////////////////
45     template <>
46     struct equal_impl<Numeric, Numeric> {
47         template <typename X, typename Y>
applyboost::hana::equal_impl48         static constexpr auto apply(X x, Y y)
49         { return numeric(x.value == y.value); }
50     };
51 
52     //////////////////////////////////////////////////////////////////////////
53     // Orderable
54     //////////////////////////////////////////////////////////////////////////
55     template <>
56     struct less_impl<Numeric, Numeric> {
57         template <typename X, typename Y>
applyboost::hana::less_impl58         static constexpr auto apply(X x, Y y) {
59             // Workaround a _weird_ GCC bug:
60             // error: parse error in template argument list
61             //      bool cmp = (x.value < y.value);
62             //                    ^
63             int xv = x.value, yv = y.value;
64             return numeric(xv < yv);
65         }
66     };
67 
68     //////////////////////////////////////////////////////////////////////////
69     // Logical
70     //////////////////////////////////////////////////////////////////////////
71     template <>
72     struct eval_if_impl<Numeric> {
73         template <typename C, typename T, typename E>
applyboost::hana::eval_if_impl74         static constexpr auto apply(C const& c, T&& t, E&& e) {
75             return c.value ? hana::eval(static_cast<T&&>(t))
76                            : hana::eval(static_cast<E&&>(e));
77         }
78     };
79 
80     template <>
81     struct not_impl<Numeric> {
82         template <typename X>
applyboost::hana::not_impl83         static constexpr auto apply(X x)
84         { return numeric(!x.value); }
85     };
86 
87     template <>
88     struct while_impl<Numeric> {
89         template <typename Pred, typename State, typename F>
applyboost::hana::while_impl90         static constexpr auto apply(Pred pred, State state, F f)
91             -> decltype(true ? f(state) : state)
92         {
93             if (pred(state))
94                 return hana::while_(pred, f(state), f);
95             else
96                 return state;
97         }
98     };
99 
100     //////////////////////////////////////////////////////////////////////////
101     // Monoid
102     //////////////////////////////////////////////////////////////////////////
103     template <>
104     struct plus_impl<Numeric, Numeric> {
105         template <typename X, typename Y>
applyboost::hana::plus_impl106         static constexpr auto apply(X x, Y y)
107         { return numeric(x.value + y.value); }
108     };
109 
110     template <>
111     struct zero_impl<Numeric> {
applyboost::hana::zero_impl112         static constexpr auto apply()
113         { return numeric(0); }
114     };
115 
116     //////////////////////////////////////////////////////////////////////////
117     // Group
118     //
119     // Define either one to select which MCD is used:
120     //  BOOST_HANA_TEST_GROUP_NEGATE_MCD
121     //  BOOST_HANA_TEST_GROUP_MINUS_MCD
122     //
123     // If neither is defined, the MCD used is unspecified.
124     //////////////////////////////////////////////////////////////////////////
125 #if defined(BOOST_HANA_TEST_GROUP_NEGATE_MCD)
126     template <>
127     struct negate_impl<Numeric> {
128         template <typename X>
applyboost::hana::negate_impl129         static constexpr auto apply(X x)
130         { return numeric(-x.value); }
131     };
132 #else
133     template <>
134     struct minus_impl<Numeric, Numeric> {
135         template <typename X, typename Y>
applyboost::hana::minus_impl136         static constexpr auto apply(X x, Y y)
137         { return numeric(x.value - y.value); }
138     };
139 #endif
140 
141     //////////////////////////////////////////////////////////////////////////
142     // Ring
143     //////////////////////////////////////////////////////////////////////////
144     template <>
145     struct mult_impl<Numeric, Numeric> {
146         template <typename X, typename Y>
applyboost::hana::mult_impl147         static constexpr auto apply(X x, Y y)
148         { return numeric(x.value * y.value); }
149     };
150 
151     template <>
152     struct one_impl<Numeric> {
applyboost::hana::one_impl153         static constexpr auto apply()
154         { return numeric(1); }
155     };
156 
157     //////////////////////////////////////////////////////////////////////////
158     // EuclideanRing
159     //////////////////////////////////////////////////////////////////////////
160     template <>
161     struct div_impl<Numeric, Numeric> {
162         template <typename X, typename Y>
applyboost::hana::div_impl163         static constexpr auto apply(X x, Y y)
164         { return numeric(x.value / y.value); }
165     };
166 
167     template <>
168     struct mod_impl<Numeric, Numeric> {
169         template <typename X, typename Y>
applyboost::hana::mod_impl170         static constexpr auto apply(X x, Y y)
171         { return numeric(x.value % y.value); }
172     };
173 }} // end namespace boost::hana
174 
175 #endif //! TEST_SUPPORT_NUMERIC_HPP
176