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)
5 #ifndef TEST_SUPPORT_NUMERIC_HPP
6 #define TEST_SUPPORT_NUMERIC_HPP
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>
26 constexpr explicit numeric_type(int v) : value(v) { }
28 constexpr operator int() const { return value; }
31 using Numeric = boost::hana::tag_of_t<numeric_type>;
34 constexpr numeric_type operator()(int x) const {
35 return numeric_type{x};
38 constexpr numeric_t numeric{};
41 namespace boost { namespace hana {
42 //////////////////////////////////////////////////////////////////////////
44 //////////////////////////////////////////////////////////////////////////
46 struct equal_impl<Numeric, Numeric> {
47 template <typename X, typename Y>
48 static constexpr auto apply(X x, Y y)
49 { return numeric(x.value == y.value); }
52 //////////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////////
56 struct less_impl<Numeric, Numeric> {
57 template <typename X, typename Y>
58 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);
63 int xv = x.value, yv = y.value;
64 return numeric(xv < yv);
68 //////////////////////////////////////////////////////////////////////////
70 //////////////////////////////////////////////////////////////////////////
72 struct eval_if_impl<Numeric> {
73 template <typename C, typename T, typename E>
74 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));
81 struct not_impl<Numeric> {
83 static constexpr auto apply(X x)
84 { return numeric(!x.value); }
88 struct while_impl<Numeric> {
89 template <typename Pred, typename State, typename F>
90 static constexpr auto apply(Pred pred, State state, F f)
91 -> decltype(true ? f(state) : state)
94 return hana::while_(pred, f(state), f);
100 //////////////////////////////////////////////////////////////////////////
102 //////////////////////////////////////////////////////////////////////////
104 struct plus_impl<Numeric, Numeric> {
105 template <typename X, typename Y>
106 static constexpr auto apply(X x, Y y)
107 { return numeric(x.value + y.value); }
111 struct zero_impl<Numeric> {
112 static constexpr auto apply()
113 { return numeric(0); }
116 //////////////////////////////////////////////////////////////////////////
119 // Define either one to select which MCD is used:
120 // BOOST_HANA_TEST_GROUP_NEGATE_MCD
121 // BOOST_HANA_TEST_GROUP_MINUS_MCD
123 // If neither is defined, the MCD used is unspecified.
124 //////////////////////////////////////////////////////////////////////////
125 #if defined(BOOST_HANA_TEST_GROUP_NEGATE_MCD)
127 struct negate_impl<Numeric> {
128 template <typename X>
129 static constexpr auto apply(X x)
130 { return numeric(-x.value); }
134 struct minus_impl<Numeric, Numeric> {
135 template <typename X, typename Y>
136 static constexpr auto apply(X x, Y y)
137 { return numeric(x.value - y.value); }
141 //////////////////////////////////////////////////////////////////////////
143 //////////////////////////////////////////////////////////////////////////
145 struct mult_impl<Numeric, Numeric> {
146 template <typename X, typename Y>
147 static constexpr auto apply(X x, Y y)
148 { return numeric(x.value * y.value); }
152 struct one_impl<Numeric> {
153 static constexpr auto apply()
154 { return numeric(1); }
157 //////////////////////////////////////////////////////////////////////////
159 //////////////////////////////////////////////////////////////////////////
161 struct div_impl<Numeric, Numeric> {
162 template <typename X, typename Y>
163 static constexpr auto apply(X x, Y y)
164 { return numeric(x.value / y.value); }
168 struct mod_impl<Numeric, Numeric> {
169 template <typename X, typename Y>
170 static constexpr auto apply(X x, Y y)
171 { return numeric(x.value % y.value); }
173 }} // end namespace boost::hana
175 #endif //! TEST_SUPPORT_NUMERIC_HPP