]>
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 | ||
92f5a8d4 | 26 | namespace support { |
7c673cae FG |
27 | template <typename T, typename = std::enable_if_t< |
28 | !hana::Constant<T>::value | |
29 | >> | |
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 | >> | |
45 | constexpr auto sqrt(T const&) { | |
46 | return hana::integral_c<typename T::value_type, sqrt(T::value)>; | |
47 | } | |
92f5a8d4 | 48 | } // end namespace support |
7c673cae FG |
49 | |
50 | ||
51 | namespace then { | |
52 | namespace mpl = boost::mpl; | |
53 | ||
54 | template <typename N> | |
55 | struct sqrt | |
92f5a8d4 | 56 | : mpl::integral_c<typename N::value_type, support::sqrt(N::value)> |
7c673cae FG |
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> | |
99 | constexpr _point<X, Y> point(X x, Y y) { return {x, y}; } | |
100 | ||
92f5a8d4 TL |
101 | using support::sqrt; // avoid conflicts with ::sqrt |
102 | ||
7c673cae FG |
103 | //! [distance-hana] |
104 | template <typename P1, typename 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 | ||
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 | ||
126 | int main() { | |
127 | now::test(); | |
128 | } |