From fc1e5a7e8d025eec4d01478269f9acd5bf914b31 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Wed, 2 May 2018 15:52:42 +0200 Subject: [PATCH] matrix utility --- .gitignore | 50 +++++++++++ CMakeLists.txt | 7 ++ main.cpp | 29 ++++++ matrix.h | 233 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 matrix.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79d3eed --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +/.idea/ + + +# common +*.csv +*.obj +*.exe +*.lst +*.tmp +*.pdb + +# tex +*.aux +*.lof +*.log +*.lot +*.fls +*.out +*.toc +*.fmt +*.fot +*.cb +*.cb2 +.*.lb +*.pdf + +/cmake-*/ + +/sprawozdanie/*-figure* + +## Build tool auxiliary files: +*.fdb_latexmk +*.synctex +*.synctex(busy) +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync +*.auxlock + +# hyperref +*.brf + +# listings +*.lol + +# makeidx +*.idx +*.ilg +*.ind +*.ist diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1058d27 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) +project(P02) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_C_STANDARD 11) + +add_executable(main main.cpp) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..a7b6893 --- /dev/null +++ b/main.cpp @@ -0,0 +1,29 @@ +#include "matrix.h" +#include +#include + +const size_t N = 10; + +std::pair, Matrix> prepare(size_t index, size_t n) { + double a1, a2, a3; + a2 = a3 = -1; + a1 = 5 + (index / 100) % 10; + + auto M = Matrix::diag(n, a1) + + Matrix::diag(n, a2, 1) + Matrix::diag(n, a2, -1) + + Matrix::diag(n, a3, 2) + Matrix::diag(n, a3, -2); + + Matrix b(n, 1); + for (size_t i = 0; i < n; ++i) { + b(i, 0) = sin((i + 1)*((index / 1000) % 10 + 1)); + } + + return std::make_pair(M, b); +} + +int main(int argc, const char argv[]) +{ + auto tuple = prepare(165581, N); + auto M = std::get<0>(tuple); + auto b = std::get<1>(tuple); +} \ No newline at end of file diff --git a/matrix.h b/matrix.h new file mode 100644 index 0000000..36936f4 --- /dev/null +++ b/matrix.h @@ -0,0 +1,233 @@ +#ifndef P02_MATRIX_H +#define P02_MATRIX_H + +#include +#include +#include +#include +#include +#include + +#define NORM_INF INT_MAX + +using std::size_t; + +template +class Matrix { + using self_t = Matrix; + + std::unique_ptr values; + size_t _rows, _cols; + +public: + explicit Matrix(size_t n); + Matrix(std::initializer_list> values); + Matrix(size_t n, size_t m); + + Matrix(const self_t& m); + + T& operator()(size_t n, size_t m); + T operator()(size_t n, size_t m) const; + + self_t operator*(const self_t& rhs); + self_t operator+(const self_t& rhs); + + self_t operator*(T rhs); + self_t operator+(T rhs); + + self_t& operator=(self_t&& rhs) noexcept; + + size_t rows() const; + size_t cols() const; + + template + friend std::ostream &operator<<(std::ostream &os, const Matrix &matrix); + + static self_t diag(size_t n, T value, int offset = 0); + static self_t hvec(std::initializer_list values); + static self_t vvec(std::initializer_list values); +// static self_t diag(std::initializer_list values, size_t offset = 0); +}; + +template +Matrix::Matrix(size_t n, size_t m) : _rows(n), _cols(m), values(new T[m*n]) { + for(size_t i = 0; i < m*n; i++) { + this->values.get()[i] = T(); + } +} + +template +Matrix::Matrix(size_t n) : Matrix(n, n) { } + +template +Matrix::Matrix(const Matrix &m) : Matrix(m._rows, m._cols) { + std::copy(m.values.get(), m.values.get() + m._cols*m._rows, values.get()); +} + +template +T &Matrix::operator()(size_t n, size_t m) { + return values.get()[n*this->_cols + m]; +} + +template +T Matrix::operator()(size_t n, size_t m) const { + return values.get()[n*this->_cols + m]; +} + +template +Matrix Matrix::operator+(const Matrix &rhs) { + assert(this->_cols == rhs._cols && this->_rows == rhs._rows); + self_t result(this->_rows, this->_cols); + + for (size_t i = 0; i < _rows; i++) + for (size_t j = 0; j < _cols; j++) + result(i, j) = (*this)(i, j) + rhs(i, j); + + return result; +} + +template +Matrix Matrix::operator*(const Matrix &rhs) { + assert(_cols == rhs._rows); + self_t result(_rows, rhs._cols); + + for (size_t i = 0; i < _rows; i++) { + for (size_t j = 0; j < rhs._cols; j++) { + T accumulator = 0; + for(size_t k = 0; k < _cols; k++) + accumulator += (*this)(i, k) * rhs(k, j); + + result(i, j) = std::move(accumulator); + } + } + + return result; +} + +template +Matrix Matrix::operator*(const T rhs) { + self_t result(*this); + + for (size_t i = 0; i < _rows; i++) + for (size_t j = 0; j < _cols; j++) + result(i, j) *= rhs; + + return result; +} + +template +Matrix Matrix::operator+(const T rhs) { + self_t result(*this); + + for (size_t i = 0; i < _rows; i++) + for (size_t j = 0; j < _cols; j++) + result(i, j) += rhs; + + return result; +} + +template +std::ostream &operator<<(std::ostream &os, const Matrix &matrix) { + os << "[ "; + + for (size_t i = 0; i < matrix._rows; i++) { + for (size_t j = 0; j < matrix._cols; j++) { + os << matrix(i, j) << " "; + } + os << (i == matrix._rows - 1 ? "]\n" : "\n "); + } + + return os; +} + +template +Matrix Matrix::diag(size_t n, T value, int offset) { + self_t result(n); + if (offset >= 0) + for(size_t i = 0; i < n - offset; i++) + result(i,i+offset) = value; + else + for(size_t i = 0; i < n - offset; i++) + result(i-offset, i) = value; + + return result; +} + +template +Matrix::Matrix(std::initializer_list> values) : Matrix(values.size(), values.begin()->size()) { + size_t i = 0; + for (auto h : values) { + if (i > _rows) break; + + size_t j = 0; + for (auto x : h) { + if (j > _cols) break; + + (*this)(i, j) = x; + j++; + } + i++; + } +} + +template +Matrix& Matrix::operator=(Matrix &&rhs) noexcept { + this->_cols = rhs._cols; + this->_rows = rhs._rows; + std::swap(values, rhs.values); + + return *this; +} + +template +inline size_t Matrix::rows() const { + return this->_rows; +} + +template +inline size_t Matrix::cols() const { + return this->_cols; +} + +template +Matrix Matrix::hvec(std::initializer_list values) { + Matrix result(1, values.size()); + + size_t i = 0; + for(auto val : values) { + result(0, i++) = val; + } + + return result; +} + +template +Matrix Matrix::vvec(std::initializer_list values) { + Matrix result(values.size(), 1); + + size_t i = 0; + for(auto val : values) { + result(i++, 0) = val; + } + + return result; +} + +template +double norm(const Matrix& matrix, unsigned norm = 2) +{ +// needed? +// assert(matrix.cols() == 1 || matrix.rows() == 1); + + double accumulator = 0.; + + for (size_t i = 0; i < matrix.cols(); ++i) { + for (size_t j = 0; j < matrix.rows(); ++j) { + accumulator += std::pow(matrix(j, i), norm); + } + } + + return std::pow(accumulator, 1. / norm); +} + +#endif //P02_MATRIX_H