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