diff options
Diffstat (limited to 'include/mm/view.hpp')
-rw-r--r-- | include/mm/view.hpp | 134 |
1 files changed, 90 insertions, 44 deletions
diff --git a/include/mm/view.hpp b/include/mm/view.hpp index 910c16a..e701a78 100644 --- a/include/mm/view.hpp +++ b/include/mm/view.hpp @@ -1,66 +1,112 @@ #pragma once -#include <mmmatrix.hpp> +#include "mm/mmmatrix.hpp" +#include <variant> +#include <tuple> +#include <type_traits> +#include <functional> -namespace mm::alg { - template < - template<typename, std::size_t, std::size_t> typename Matrix, - typename T, std::size_t Rows, std::size_t Cols - > - struct visitor - { - using type = T; +namespace mm { + + namespace algorithm { + // does nothing + struct visit + { + visit() = default; - // copy constructible - visitor(const visitor& other) = default; + template<typename Matrix> + void operator()(Matrix& m) {} + }; - T& operator()(const Matrix<T, Rows, Cols>& m, index row, index col) { - return m.at(row, col); - } + struct transpose : public visit + { + /// does not work with non-square matrices + template<typename Matrix> + void operator()(Matrix& m) { + static_assert(Matrix::rows == Matrix::cols); + // naiive impl + for (index r = 0; r < m.rows / 2; r++) + for (index c = 0; c < m.cols; c++) + if (c != r) + std::swap(m.at(r, c), m.at(c, r)); + } + }; - const T& operator()(const Matrix<T, Rows, Cols>& m, index row, index col) { - return operator()(m, row, col); - } - }; + /// algorithm aliases + using tr = transpose; + } + + /// namespace alias + namespace alg = algorithm; - template < - template<typename, std::size_t, std::size_t> typename Matrix, - typename T, std::size_t Rows, std::size_t Cols - > - struct transpose : public visitor<Matrix, T, Rows, Cols> + template<typename Matrix> + struct clone { - T& operator()(const Matrix<T, Rows, Cols> m, index row, index col) { - // assert(col < Rows) - // assert(row < Cols) - return m.at(col, row); + Matrix matrix; + + explicit clone(Matrix&& m) : matrix(m) {} + explicit clone(const Matrix& m) : matrix(m) {} + + operator Matrix() { + return std::move(matrix); } }; -} -namespace mm { - template < - template<typename, std::size_t, std::size_t> typename Matrix, - typename T, std::size_t Rows, std::size_t Cols - > - struct view + template<typename Matrix, typename ...Algs> + struct mutate { - Matrix<T, Rows, Cols>& m; - // std::stack<std::unique_ptr<alg::visitor>> visitors; - std::unique_ptr<alg::visitor> visitor; + Matrix& matrix; + std::tuple<Algs...> visitors; + + explicit mutate(Matrix& m) : matrix(m) {} + + template<typename ...OAlgs, typename Alg> + explicit mutate(Matrix& m, std::tuple<OAlgs...>&& t, Alg&& v) + : matrix(m) + { + /// append the new operator + visitors = std::tuple_cat(t, std::make_tuple(v)); + } + + ~mutate() { + visit(); + } - T& at(index row, index col) { - return visitor(m, row, col); + void visit() { + std::apply([this](auto&&... v) { + (v(matrix),...); + }, visitors); } - view& operator|=(const alg::visitor& other) { - // visitors.push(std::move(std::make_unique<alg::visitor>(other))); - visitor = std::make_unique<alg::visistor>(other); + operator Matrix() { + return std::move(matrix); } }; - view operator|(const view& left, const alg::visitor& right) { - return left |= right; + template<typename Matrix, typename Alg> + clone<Matrix> operator|(clone<Matrix>&& cl, Alg&& v) { + static_assert(std::is_convertible<Alg, alg::visit>::value); + /// apply alg operator + v(cl.matrix); + /// forward to next alg + return clone<Matrix>(std::move(cl)); + } + + template<typename Matrix, typename ...Algs, typename Alg> + mutate<Matrix, Algs..., Alg> operator|(mutate<Matrix, Algs...>&& mut, Alg&& v) { + static_assert(std::is_convertible<Alg, alg::visit>::value); + /// append alg to the visitors tuple + return mutate<Matrix, Algs..., Alg>( + mut.matrix, + std::move(mut.visitors), + v + ); + } + + template<typename Matrix, typename Alg> + mutate<Matrix, Alg> operator|(Matrix& m, Alg&& v) { + return mutate(m) | std::move(v); } } |