From 0958256e0b795c73f154ffb20d484d85b0b015f5 Mon Sep 17 00:00:00 2001 From: ancarola Date: Fri, 28 Jun 2019 02:32:59 +0200 Subject: Optimising matrices access and operations Creating the K-diagonal matrix --- include/mm/experiments/mmdiag_matrix.hpp | 159 ++++++++++++ include/mm/experiments/mmsubdiag.h | 277 +++++++++++++++++++++ include/mm/mmmatrix.hpp | 405 ++++++++++++++++++++++++++++++- 3 files changed, 832 insertions(+), 9 deletions(-) create mode 100644 include/mm/experiments/mmdiag_matrix.hpp create mode 100644 include/mm/experiments/mmsubdiag.h diff --git a/include/mm/experiments/mmdiag_matrix.hpp b/include/mm/experiments/mmdiag_matrix.hpp new file mode 100644 index 0000000..124e4b3 --- /dev/null +++ b/include/mm/experiments/mmdiag_matrix.hpp @@ -0,0 +1,159 @@ +#pragma once + +namespace mm { + + template + class diag_component; + + template + class multi_diag_matrix; +} + +/* + * Optimized case of square matrix + * It's a matrix only composed by a diagonal + */ + +template +class mm::diag_component +{ +public: + virtual int dimension() const = 0; +}; + +template +class mm::diag_vector +{ +public: + + // TODO, define constructor + + virtual int dimension() const override + { + return N; + } + +private: + std::array vector; +}; + +template +class mm::multi_diag_matrix { +public: + using type = T; + + template + friend class mm::multi_diag_matrix; + + multi_diag_matrix() : shared_zero(0) {} + ~multi_diag_matrix(); + + // copyable and movable + multi_diag_matrix(const multi_diag_matrix& other); + multi_diag_matrix(multi_diag_matrix&& other); + + // copy from another matrix + template + multi_diag_matrix(const multi_diag_matrix& other); + + // standard access data + T& at(std::size_t row, std::size_t col); + const T& at(std::size_t row, std::size_t col) const; + + // allows to access a matrix M at row j col k with M[j][k] + auto operator[](std::size_t index); + + // swap two diagonals + void swap_diags(std::size_t k, std::size_t l); + + // diagonal construction or substitution + template + void put_diag(const mm::diag_vector& diag) + { + //static_assert((Diag <= -N) || (Diag >= N), + static_assert(K < 1, + "Diagonal number must be bounded between ]-N,N[") + + auto exist = diagonals.find(Diag); + + if (exist != diagonals.end()) + // copy + *exists = diag; + else + // create and copy + diagonals.insert(new mm::diag_vector(diag)); + } + + // mathematical operations + virtual multi_diag_matrix transposed() const; + inline multi_diag_matrix td() const { return transposed(); } + + // multiplication rhs and lhs + // TODO, need super class matrix abstraction and auto return type + + // A * M, TODO abstraction virtual method + template + basic_matrix rhs_mult(const mm::basic_matrix& A) const; + + // M * A, TODO abstraction virtual method + template + basic_matrix lhs_mult(const mm::basic_matrix& A) const; + +protected: + template + multi_diag_matrix(ConstIterator begin, ConstIterator end); + +private: + // return an arbitrary zero in non-const mode + T shared_zero; + + // ordered set of diagonals + std::unordered_map*> diagonals; +}; + +template +T& mm::multi_diag_matrix::at(std::size_t row, std::size_t col) { + assert(row < N); // "out of row bound" + assert(col < N); // "out of column bound" + + const int k = row - col; + auto diag = diagonals.find(k); + const int line = (k > 0) ? col : row; + + return (diag == diagonals.end()) ? (shared_zero = 0) : (*diag)[line]; +} + +template +const T& mm::multi_diag_matrix::at(std::size_t row, std::size_t col) const { + assert(row < N); // "out of row bound" + assert(col < N); // "out of column bound" + + const int k = row - col; + auto diag = diagonals.find(k); + const int line = (k > 0) ? col : row; + + return (diag == diagonals.end()) ? 0 : (*diag)[line]; +} + +template +auto mm::multi_diag_matrix::operator[](std::size_t index) { + assert(index < N) + + // TODO, single row mapping +} + +template +mm::basic_matrix mm::multi_diag_matrix::rhs_mult(const mm::basic_matrix& A) const +{ + // TODO +} + +template +mm::basic_matrix mm::multi_diag_matrix::lhs_mult(const mm::basic_matrix& A) const +{ + mm::basic_matrix out; + + +} + + diff --git a/include/mm/experiments/mmsubdiag.h b/include/mm/experiments/mmsubdiag.h new file mode 100644 index 0000000..2f6c93c --- /dev/null +++ b/include/mm/experiments/mmsubdiag.h @@ -0,0 +1,277 @@ +#pragma once + +#ifndef __TRIDIAG_H__ +#define __TRIDIAG_H__ + +template +class tridiag +{ + std::vector diag, lower, upper; + + struct row + { + std::size_t index; + tridiag& ref; + + T shared_zero = 0; + + row(std::size_t i, tridiag& _ref) : index(i), ref(_ref) {} + + T& operator[](std::size_t j) + { + switch(static_cast(j) - index) + { + case -1: + return ref.lower[j]; + case 0: + return ref.diag[j]; + case 1: + return ref.upper[index]; + default: + shared_zero = 0; // assure zero + return shared_zero; + } + } + }; + + struct const_row + { + std::size_t index; + const tridiag& ref; + + const T shared_zero = 0; + + const_row(std::size_t i, const tridiag& _ref) : index(i), ref(_ref) {} + + const T& operator[](std::size_t j) const + { + switch(static_cast(j) - index) + { + case -1: + return ref.lower[j]; + case 0: + return ref.diag[j]; + case 1: + return ref.upper[index]; + default: + return shared_zero; + } + } + }; + +public: + + tridiag(std::size_t N = 1) : diag(N), lower(N-1), upper(N-1) + { + } + + void resize(std::size_t N) + { + diag.reserve(N); + lower.reserve(N-1); + upper.reserve(N-1); + } + + void zeros() + { + for (std::size_t i = 0; i < size()-1; ++i) + diag[i] = lower[i] = upper[i] = 0; + + diag[size()-1] = 0; + } + + // set diagonal to zero + void zeros_diag() + { + for (std::size_t i = 0; i < size(); ++i) + diag[i] = 0; + } + + row operator[](std::size_t i) + { + return row(i, *this); + } + + const const_row operator[](std::size_t i) const + { + return const_row(i, *this); + } + + std::size_t size() const + { + return diag.size(); + } + + template