summaryrefslogtreecommitdiffstats
path: root/include/mm/view.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mm/view.hpp')
-rw-r--r--include/mm/view.hpp134
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);
}
}