integral.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. #include <boost/mpl/equal_to.hpp>
  5. #include <boost/mpl/int.hpp>
  6. #include <boost/mpl/integral_c.hpp>
  7. #include <boost/mpl/minus.hpp>
  8. #include <boost/mpl/multiplies.hpp>
  9. #include <boost/mpl/pair.hpp>
  10. #include <boost/mpl/plus.hpp>
  11. #include <boost/hana/assert.hpp>
  12. #include <boost/hana/concept/constant.hpp>
  13. #include <boost/hana/equal.hpp>
  14. #include <boost/hana/integral_constant.hpp>
  15. #include <boost/hana/minus.hpp>
  16. #include <boost/hana/mult.hpp>
  17. #include <boost/hana/pair.hpp>
  18. #include <boost/hana/plus.hpp>
  19. #include <type_traits>
  20. namespace hana = boost::hana;
  21. namespace support {
  22. template <typename T, typename = std::enable_if_t<
  23. !hana::Constant<T>::value
  24. >>
  25. constexpr T sqrt(T x) {
  26. T inf = 0, sup = (x == 1 ? 1 : x/2);
  27. while (!((sup - inf) <= 1 || ((sup*sup <= x) && ((sup+1)*(sup+1) > x)))) {
  28. T mid = (inf + sup) / 2;
  29. bool take_inf = mid*mid > x ? 1 : 0;
  30. inf = take_inf ? inf : mid;
  31. sup = take_inf ? mid : sup;
  32. }
  33. return sup*sup <= x ? sup : inf;
  34. }
  35. template <typename T, typename = std::enable_if_t<
  36. hana::Constant<T>::value
  37. >>
  38. constexpr auto sqrt(T const&) {
  39. return hana::integral_c<typename T::value_type, sqrt(T::value)>;
  40. }
  41. } // end namespace support
  42. namespace then {
  43. namespace mpl = boost::mpl;
  44. template <typename N>
  45. struct sqrt
  46. : mpl::integral_c<typename N::value_type, support::sqrt(N::value)>
  47. { };
  48. template <typename X, typename Y>
  49. struct point {
  50. using x = X;
  51. using y = Y;
  52. };
  53. //! [distance-mpl]
  54. template <typename P1, typename P2>
  55. struct distance {
  56. using xs = typename mpl::minus<typename P1::x,
  57. typename P2::x>::type;
  58. using ys = typename mpl::minus<typename P1::y,
  59. typename P2::y>::type;
  60. using type = typename sqrt<
  61. typename mpl::plus<
  62. typename mpl::multiplies<xs, xs>::type,
  63. typename mpl::multiplies<ys, ys>::type
  64. >::type
  65. >::type;
  66. };
  67. static_assert(mpl::equal_to<
  68. distance<point<mpl::int_<3>, mpl::int_<5>>,
  69. point<mpl::int_<7>, mpl::int_<2>>>::type,
  70. mpl::int_<5>
  71. >::value, "");
  72. //! [distance-mpl]
  73. }
  74. namespace now {
  75. namespace hana = boost::hana;
  76. using namespace hana::literals;
  77. template <typename X, typename Y>
  78. struct _point {
  79. X x;
  80. Y y;
  81. };
  82. template <typename X, typename Y>
  83. constexpr _point<X, Y> point(X x, Y y) { return {x, y}; }
  84. using support::sqrt; // avoid conflicts with ::sqrt
  85. //! [distance-hana]
  86. template <typename P1, typename P2>
  87. constexpr auto distance(P1 p1, P2 p2) {
  88. auto xs = p1.x - p2.x;
  89. auto ys = p1.y - p2.y;
  90. return sqrt(xs*xs + ys*ys);
  91. }
  92. BOOST_HANA_CONSTANT_CHECK(distance(point(3_c, 5_c), point(7_c, 2_c)) == 5_c);
  93. //! [distance-hana]
  94. void test() {
  95. //! [distance-dynamic]
  96. auto p1 = point(3, 5); // dynamic values now
  97. auto p2 = point(7, 2); //
  98. BOOST_HANA_RUNTIME_CHECK(distance(p1, p2) == 5); // same function works!
  99. //! [distance-dynamic]
  100. }
  101. }
  102. int main() {
  103. now::test();
  104. }