123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- // Copyright Louis Dionne 2013-2017
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- #ifndef TEST_SUPPORT_NUMERIC_HPP
- #define TEST_SUPPORT_NUMERIC_HPP
- #include <boost/hana/core/tag_of.hpp>
- #include <boost/hana/eval.hpp>
- #include <boost/hana/fwd/div.hpp>
- #include <boost/hana/fwd/equal.hpp>
- #include <boost/hana/fwd/eval_if.hpp>
- #include <boost/hana/fwd/less.hpp>
- #include <boost/hana/fwd/minus.hpp>
- #include <boost/hana/fwd/mod.hpp>
- #include <boost/hana/fwd/mult.hpp>
- #include <boost/hana/fwd/negate.hpp>
- #include <boost/hana/fwd/not.hpp>
- #include <boost/hana/fwd/one.hpp>
- #include <boost/hana/fwd/plus.hpp>
- #include <boost/hana/fwd/while.hpp>
- #include <boost/hana/fwd/zero.hpp>
- struct numeric_type {
- constexpr explicit numeric_type(int v) : value(v) { }
- int value;
- constexpr operator int() const { return value; }
- };
- using Numeric = boost::hana::tag_of_t<numeric_type>;
- struct numeric_t {
- constexpr numeric_type operator()(int x) const {
- return numeric_type{x};
- }
- };
- constexpr numeric_t numeric{};
- namespace boost { namespace hana {
- //////////////////////////////////////////////////////////////////////////
- // Comparable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct equal_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value == y.value); }
- };
- //////////////////////////////////////////////////////////////////////////
- // Orderable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct less_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y) {
- // Workaround a _weird_ GCC bug:
- // error: parse error in template argument list
- // bool cmp = (x.value < y.value);
- // ^
- int xv = x.value, yv = y.value;
- return numeric(xv < yv);
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Logical
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct eval_if_impl<Numeric> {
- template <typename C, typename T, typename E>
- static constexpr auto apply(C const& c, T&& t, E&& e) {
- return c.value ? hana::eval(static_cast<T&&>(t))
- : hana::eval(static_cast<E&&>(e));
- }
- };
- template <>
- struct not_impl<Numeric> {
- template <typename X>
- static constexpr auto apply(X x)
- { return numeric(!x.value); }
- };
- template <>
- struct while_impl<Numeric> {
- template <typename Pred, typename State, typename F>
- static constexpr auto apply(Pred pred, State state, F f)
- -> decltype(true ? f(state) : state)
- {
- if (pred(state))
- return hana::while_(pred, f(state), f);
- else
- return state;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Monoid
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct plus_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value + y.value); }
- };
- template <>
- struct zero_impl<Numeric> {
- static constexpr auto apply()
- { return numeric(0); }
- };
- //////////////////////////////////////////////////////////////////////////
- // Group
- //
- // Define either one to select which MCD is used:
- // BOOST_HANA_TEST_GROUP_NEGATE_MCD
- // BOOST_HANA_TEST_GROUP_MINUS_MCD
- //
- // If neither is defined, the MCD used is unspecified.
- //////////////////////////////////////////////////////////////////////////
- #if defined(BOOST_HANA_TEST_GROUP_NEGATE_MCD)
- template <>
- struct negate_impl<Numeric> {
- template <typename X>
- static constexpr auto apply(X x)
- { return numeric(-x.value); }
- };
- #else
- template <>
- struct minus_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value - y.value); }
- };
- #endif
- //////////////////////////////////////////////////////////////////////////
- // Ring
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct mult_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value * y.value); }
- };
- template <>
- struct one_impl<Numeric> {
- static constexpr auto apply()
- { return numeric(1); }
- };
- //////////////////////////////////////////////////////////////////////////
- // EuclideanRing
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct div_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value / y.value); }
- };
- template <>
- struct mod_impl<Numeric, Numeric> {
- template <typename X, typename Y>
- static constexpr auto apply(X x, Y y)
- { return numeric(x.value % y.value); }
- };
- }} // end namespace boost::hana
- #endif //! TEST_SUPPORT_NUMERIC_HPP
|