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_; ncolumnscppcon::matrix_type37 constexpr auto ncolumns() const 38 { return boost::hana::length(boost::hana::front(rows_)); } 39 nrowscppcon::matrix_type40 constexpr auto nrows() const 41 { return boost::hana::length(rows_); } 42 sizecppcon::matrix_type43 constexpr auto size() const 44 { return nrows() * ncolumns(); } 45 46 template <typename I, typename J> atcppcon::matrix_type47 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( __anonfc11f17b0102(auto const& row) 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 111