]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // Copyright Louis Dionne 2013-2017 |
7c673cae FG |
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 | template <typename T, typename = std::enable_if_t< | |
27 | !hana::Constant<T>::value | |
28 | >> | |
29 | constexpr T sqrt(T x) { | |
30 | T inf = 0, sup = (x == 1 ? 1 : x/2); | |
31 | while (!((sup - inf) <= 1 || ((sup*sup <= x) && ((sup+1)*(sup+1) > x)))) { | |
32 | T mid = (inf + sup) / 2; | |
33 | bool take_inf = mid*mid > x ? 1 : 0; | |
34 | inf = take_inf ? inf : mid; | |
35 | sup = take_inf ? mid : sup; | |
36 | } | |
37 | ||
38 | return sup*sup <= x ? sup : inf; | |
39 | } | |
40 | ||
41 | template <typename T, typename = std::enable_if_t< | |
42 | hana::Constant<T>::value | |
43 | >> | |
44 | constexpr auto sqrt(T const&) { | |
45 | return hana::integral_c<typename T::value_type, sqrt(T::value)>; | |
46 | } | |
47 | ||
48 | ||
49 | namespace then { | |
50 | namespace mpl = boost::mpl; | |
51 | ||
52 | template <typename N> | |
53 | struct sqrt | |
54 | : mpl::integral_c<typename N::value_type, ::sqrt(N::value)> | |
55 | { }; | |
56 | ||
57 | template <typename X, typename Y> | |
58 | struct point { | |
59 | using x = X; | |
60 | using y = Y; | |
61 | }; | |
62 | ||
63 | //! [distance-mpl] | |
64 | template <typename P1, typename P2> | |
65 | struct distance { | |
66 | using xs = typename mpl::minus<typename P1::x, | |
67 | typename P2::x>::type; | |
68 | using ys = typename mpl::minus<typename P1::y, | |
69 | typename P2::y>::type; | |
70 | using type = typename sqrt< | |
71 | typename mpl::plus< | |
72 | typename mpl::multiplies<xs, xs>::type, | |
73 | typename mpl::multiplies<ys, ys>::type | |
74 | >::type | |
75 | >::type; | |
76 | }; | |
77 | ||
78 | static_assert(mpl::equal_to< | |
79 | distance<point<mpl::int_<3>, mpl::int_<5>>, | |
80 | point<mpl::int_<7>, mpl::int_<2>>>::type, | |
81 | mpl::int_<5> | |
82 | >::value, ""); | |
83 | //! [distance-mpl] | |
84 | } | |
85 | ||
86 | ||
87 | namespace now { | |
88 | namespace hana = boost::hana; | |
89 | using namespace hana::literals; | |
90 | ||
91 | template <typename X, typename Y> | |
92 | struct _point { | |
93 | X x; | |
94 | Y y; | |
95 | }; | |
96 | template <typename X, typename Y> | |
97 | constexpr _point<X, Y> point(X x, Y y) { return {x, y}; } | |
98 | ||
99 | //! [distance-hana] | |
100 | template <typename P1, typename P2> | |
101 | constexpr auto distance(P1 p1, P2 p2) { | |
102 | auto xs = p1.x - p2.x; | |
103 | auto ys = p1.y - p2.y; | |
104 | return sqrt(xs*xs + ys*ys); | |
105 | } | |
106 | ||
107 | BOOST_HANA_CONSTANT_CHECK(distance(point(3_c, 5_c), point(7_c, 2_c)) == 5_c); | |
108 | //! [distance-hana] | |
109 | ||
110 | void test() { | |
111 | ||
112 | //! [distance-dynamic] | |
113 | auto p1 = point(3, 5); // dynamic values now | |
114 | auto p2 = point(7, 2); // | |
115 | BOOST_HANA_RUNTIME_CHECK(distance(p1, p2) == 5); // same function works! | |
116 | //! [distance-dynamic] | |
117 | ||
118 | } | |
119 | } | |
120 | ||
121 | ||
122 | int main() { | |
123 | now::test(); | |
124 | } |