numeric.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. #ifndef TEST_SUPPORT_NUMERIC_HPP
  5. #define TEST_SUPPORT_NUMERIC_HPP
  6. #include <boost/hana/core/tag_of.hpp>
  7. #include <boost/hana/eval.hpp>
  8. #include <boost/hana/fwd/div.hpp>
  9. #include <boost/hana/fwd/equal.hpp>
  10. #include <boost/hana/fwd/eval_if.hpp>
  11. #include <boost/hana/fwd/less.hpp>
  12. #include <boost/hana/fwd/minus.hpp>
  13. #include <boost/hana/fwd/mod.hpp>
  14. #include <boost/hana/fwd/mult.hpp>
  15. #include <boost/hana/fwd/negate.hpp>
  16. #include <boost/hana/fwd/not.hpp>
  17. #include <boost/hana/fwd/one.hpp>
  18. #include <boost/hana/fwd/plus.hpp>
  19. #include <boost/hana/fwd/while.hpp>
  20. #include <boost/hana/fwd/zero.hpp>
  21. struct numeric_type {
  22. constexpr explicit numeric_type(int v) : value(v) { }
  23. int value;
  24. constexpr operator int() const { return value; }
  25. };
  26. using Numeric = boost::hana::tag_of_t<numeric_type>;
  27. struct numeric_t {
  28. constexpr numeric_type operator()(int x) const {
  29. return numeric_type{x};
  30. }
  31. };
  32. constexpr numeric_t numeric{};
  33. namespace boost { namespace hana {
  34. //////////////////////////////////////////////////////////////////////////
  35. // Comparable
  36. //////////////////////////////////////////////////////////////////////////
  37. template <>
  38. struct equal_impl<Numeric, Numeric> {
  39. template <typename X, typename Y>
  40. static constexpr auto apply(X x, Y y)
  41. { return numeric(x.value == y.value); }
  42. };
  43. //////////////////////////////////////////////////////////////////////////
  44. // Orderable
  45. //////////////////////////////////////////////////////////////////////////
  46. template <>
  47. struct less_impl<Numeric, Numeric> {
  48. template <typename X, typename Y>
  49. static constexpr auto apply(X x, Y y) {
  50. // Workaround a _weird_ GCC bug:
  51. // error: parse error in template argument list
  52. // bool cmp = (x.value < y.value);
  53. // ^
  54. int xv = x.value, yv = y.value;
  55. return numeric(xv < yv);
  56. }
  57. };
  58. //////////////////////////////////////////////////////////////////////////
  59. // Logical
  60. //////////////////////////////////////////////////////////////////////////
  61. template <>
  62. struct eval_if_impl<Numeric> {
  63. template <typename C, typename T, typename E>
  64. static constexpr auto apply(C const& c, T&& t, E&& e) {
  65. return c.value ? hana::eval(static_cast<T&&>(t))
  66. : hana::eval(static_cast<E&&>(e));
  67. }
  68. };
  69. template <>
  70. struct not_impl<Numeric> {
  71. template <typename X>
  72. static constexpr auto apply(X x)
  73. { return numeric(!x.value); }
  74. };
  75. template <>
  76. struct while_impl<Numeric> {
  77. template <typename Pred, typename State, typename F>
  78. static constexpr auto apply(Pred pred, State state, F f)
  79. -> decltype(true ? f(state) : state)
  80. {
  81. if (pred(state))
  82. return hana::while_(pred, f(state), f);
  83. else
  84. return state;
  85. }
  86. };
  87. //////////////////////////////////////////////////////////////////////////
  88. // Monoid
  89. //////////////////////////////////////////////////////////////////////////
  90. template <>
  91. struct plus_impl<Numeric, Numeric> {
  92. template <typename X, typename Y>
  93. static constexpr auto apply(X x, Y y)
  94. { return numeric(x.value + y.value); }
  95. };
  96. template <>
  97. struct zero_impl<Numeric> {
  98. static constexpr auto apply()
  99. { return numeric(0); }
  100. };
  101. //////////////////////////////////////////////////////////////////////////
  102. // Group
  103. //
  104. // Define either one to select which MCD is used:
  105. // BOOST_HANA_TEST_GROUP_NEGATE_MCD
  106. // BOOST_HANA_TEST_GROUP_MINUS_MCD
  107. //
  108. // If neither is defined, the MCD used is unspecified.
  109. //////////////////////////////////////////////////////////////////////////
  110. #if defined(BOOST_HANA_TEST_GROUP_NEGATE_MCD)
  111. template <>
  112. struct negate_impl<Numeric> {
  113. template <typename X>
  114. static constexpr auto apply(X x)
  115. { return numeric(-x.value); }
  116. };
  117. #else
  118. template <>
  119. struct minus_impl<Numeric, Numeric> {
  120. template <typename X, typename Y>
  121. static constexpr auto apply(X x, Y y)
  122. { return numeric(x.value - y.value); }
  123. };
  124. #endif
  125. //////////////////////////////////////////////////////////////////////////
  126. // Ring
  127. //////////////////////////////////////////////////////////////////////////
  128. template <>
  129. struct mult_impl<Numeric, Numeric> {
  130. template <typename X, typename Y>
  131. static constexpr auto apply(X x, Y y)
  132. { return numeric(x.value * y.value); }
  133. };
  134. template <>
  135. struct one_impl<Numeric> {
  136. static constexpr auto apply()
  137. { return numeric(1); }
  138. };
  139. //////////////////////////////////////////////////////////////////////////
  140. // EuclideanRing
  141. //////////////////////////////////////////////////////////////////////////
  142. template <>
  143. struct div_impl<Numeric, Numeric> {
  144. template <typename X, typename Y>
  145. static constexpr auto apply(X x, Y y)
  146. { return numeric(x.value / y.value); }
  147. };
  148. template <>
  149. struct mod_impl<Numeric, Numeric> {
  150. template <typename X, typename Y>
  151. static constexpr auto apply(X x, Y y)
  152. { return numeric(x.value % y.value); }
  153. };
  154. }} // end namespace boost::hana
  155. #endif //! TEST_SUPPORT_NUMERIC_HPP