Imported Upstream version 1.64.0
[platform/upstream/boost.git] / libs / hana / example / cppcon_2014 / matrix / matrix.hpp
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 #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