]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Louis Dionne 2013-2016 |
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 | #ifndef BOOST_HANA_EXAMPLE_CPPCON_2014_MATRIX_MATRIX_HPP | |
6 | #define BOOST_HANA_EXAMPLE_CPPCON_2014_MATRIX_MATRIX_HPP | |
7 | ||
8 | #include <boost/hana/all_of.hpp> | |
9 | #include <boost/hana/assert.hpp> | |
10 | #include <boost/hana/at.hpp> | |
11 | #include <boost/hana/drop_front.hpp> | |
12 | #include <boost/hana/front.hpp> | |
13 | #include <boost/hana/functional/on.hpp> | |
14 | #include <boost/hana/functional/partial.hpp> | |
15 | #include <boost/hana/fuse.hpp> | |
16 | #include <boost/hana/length.hpp> | |
17 | #include <boost/hana/mult.hpp> | |
18 | #include <boost/hana/sum.hpp> | |
19 | #include <boost/hana/tuple.hpp> | |
20 | #include <boost/hana/unpack.hpp> | |
21 | #include <boost/hana/value.hpp> | |
22 | #include <boost/hana/zip.hpp> | |
23 | #include <boost/hana/zip_with.hpp> | |
24 | ||
25 | #include <utility> | |
26 | ||
27 | ||
28 | namespace cppcon { | |
29 | template <unsigned Rows, unsigned Columns> | |
30 | struct Matrix { }; | |
31 | ||
32 | template <unsigned Rows, unsigned Columns, typename Storage> | |
33 | struct matrix_type { | |
34 | using hana_tag = Matrix<Rows, Columns>; | |
35 | ||
36 | Storage rows_; | |
37 | constexpr auto ncolumns() const | |
38 | { return boost::hana::length(boost::hana::front(rows_)); } | |
39 | ||
40 | constexpr auto nrows() const | |
41 | { return boost::hana::length(rows_); } | |
42 | ||
43 | constexpr auto size() const | |
44 | { return nrows() * ncolumns(); } | |
45 | ||
46 | template <typename I, typename J> | |
47 | constexpr decltype(auto) at(I i, J j) const | |
48 | { return boost::hana::at(boost::hana::at(rows_, i), j); } | |
49 | }; | |
50 | ||
51 | auto row = boost::hana::make_tuple; | |
52 | ||
53 | auto matrix = [](auto&& ...rows) -> decltype(auto) { | |
54 | namespace hana = boost::hana; | |
55 | auto storage = hana::make_tuple(std::forward<decltype(rows)>(rows)...); | |
56 | auto ncolumns = hana::length(hana::front(storage)); | |
57 | BOOST_HANA_CONSTANT_CHECK( | |
58 | hana::all_of(hana::drop_front(storage), [&](auto const& row) { | |
59 | return hana::length(row) == ncolumns; | |
60 | }) | |
61 | ); | |
62 | ||
63 | return matrix_type< | |
64 | sizeof...(rows), hana::value(ncolumns), decltype(storage) | |
65 | >{std::move(storage)}; | |
66 | }; | |
67 | ||
68 | auto vector = boost::hana::on(matrix, row); | |
69 | ||
70 | ||
71 | // More operations | |
72 | auto rows = [](auto&& m) -> decltype(auto) { | |
73 | return std::forward<decltype(m)>(m).rows_; | |
74 | }; | |
75 | ||
76 | auto transpose = [](auto&& m) -> decltype(auto) { | |
77 | return boost::hana::unpack( | |
78 | boost::hana::fuse(boost::hana::zip)(rows(std::forward<decltype(m)>(m))), | |
79 | matrix | |
80 | ); | |
81 | }; | |
82 | ||
83 | auto columns = [](auto&& m) -> decltype(auto) { | |
84 | return rows(transpose(std::forward<decltype(m)>(m))); | |
85 | }; | |
86 | ||
87 | auto element_wise = [](auto&& f) -> decltype(auto) { | |
88 | namespace hana = boost::hana; | |
89 | return [f(std::forward<decltype(f)>(f))](auto&& ...m) -> decltype(auto) { | |
90 | return hana::unpack( | |
91 | hana::zip_with(hana::partial(hana::zip_with, f), | |
92 | rows(std::forward<decltype(m)>(m))... | |
93 | ), | |
94 | matrix | |
95 | ); | |
96 | }; | |
97 | }; | |
98 | ||
99 | namespace detail { | |
100 | auto tuple_scalar_product = [](auto&& u, auto&& v) -> decltype(auto) { | |
101 | namespace hana = boost::hana; | |
102 | return hana::sum<>(hana::zip_with(hana::mult, | |
103 | std::forward<decltype(u)>(u), | |
104 | std::forward<decltype(v)>(v) | |
105 | )); | |
106 | }; | |
107 | } | |
108 | } // end namespace cppcon | |
109 | ||
110 | #endif // !BOOST_HANA_EXAMPLE_CPPCON_2014_MATRIX_MATRIX_HPP |