matrix.hpp 3.4 KB

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