/* MCL Copyright (c) 2012-18, Enzo De Sena All rights reserved. Authors: Enzo De Sena, enzodesena@gmail.com */ // This file contains definitions of matrix operations and classes #ifndef MCL_MATRIXOP_H #define MCL_MATRIXOP_H #include #include #include #include "mcltypes.h" #include "comparisonop.h" #include "basicop.h" #include "elementaryop.h" #if MCL_LOAD_EIGEN #include #endif namespace mcl { // Forward declaration std::vector Split(const std::string& string, char delim) noexcept; /** Matrix class */ template class Matrix { public: /** Default constructor with empty (0x0) matrix */ Matrix() noexcept : num_rows_(0), num_columns_(0) {} /** Constructs a matrix with default entries */ Matrix(Int num_rows, Int num_columns) noexcept : num_rows_(num_rows), num_columns_(num_columns) { for (Int i=0; i(num_columns)); } } /** Constructs a matrix from a vector of vectors (outer vector represents rows) */ Matrix(const std::vector > vectors) noexcept { num_rows_ = vectors.size(); if (num_rows_ > 0) { num_columns_ = vectors[0].size(); for (Int i=1; i column) noexcept { ASSERT((Int)column.size() == num_rows_); ASSERT(index_column < num_columns_); for (Int i=0; i row) noexcept { ASSERT((Int)row.size() == num_columns_); ASSERT(index_row < num_rows_); data_[index_row] = row; } /** Accesses an element in given row and column */ T GetElement(const Int& index_row, const Int& index_column) const noexcept { ASSERT(index_row < num_rows_); ASSERT(index_column < num_columns_); return data_[index_row][index_column]; } /** Accesses an entire row */ std::vector GetRow(Int index_row) const noexcept { ASSERT(index_row < num_rows_); return data_[index_row]; } /** Accesses an entire column */ std::vector GetColumn(Int index_column) const noexcept { ASSERT(index_column < num_columns_); std::vector output(num_rows_); for (Int i=0; i Serial() const noexcept { std::vector serial(num_columns()*num_rows()); Int k=0; for (Int j=0; j > data() noexcept { return data_; } /** Reads a matrix. Elements have to be separated by tabs and there must be no ending empty line (e.g. 5 lines == 5 rows). */ static Matrix Load(std::string file_name) { std::string line; std::ifstream in_file (file_name.c_str()); ASSERT(in_file.is_open()); // First: lets count the number of rows Int number_of_rows = 0; Int number_of_columns = 0; while (std::getline(in_file, line)) { std::vector elements = Split(line, '\t'); if (number_of_columns == 0) { number_of_columns = (Int) elements.size(); } else { ASSERT(number_of_columns == (Int)elements.size()); } ++number_of_rows; } // Reset pointer in_file.clear(); in_file.seekg(0,std::ios::beg); // Create new matrix // TODO: recognize complex matrix Matrix matrix(number_of_rows, number_of_columns); for(Int row=0; row elements = Split(line, '\t'); for (Int column=0; column<(Int)elements.size(); ++column) { matrix.SetElement(row, column, (T) StringToDouble(elements[column])); } } in_file.close(); return matrix; } /** Constructs a matrix of all ones. Equivalent to Matlab's ones(N,M). */ static Matrix Ones(Int number_of_rows, Int number_of_columns) noexcept { Matrix matrix(number_of_rows, number_of_columns); for(Int row=0; row::Ones(matrix_dimension, matrix_dimension); } private: // Outer is rows, inner is columns. Hence, data_[0] is the first column. std::vector > data_; Int num_rows_; Int num_columns_; }; template void Print(const Matrix& matrix) noexcept { for (Int i=0; i Matrix Transpose(const Matrix& matrix) noexcept { Matrix output(matrix.num_columns(), matrix.num_rows()); for (Int i=0; i Matrix Multiply(const Matrix& matrix, T value) noexcept { Matrix output(matrix.num_rows(), matrix.num_columns()); for (Int i=0; i Matrix Multiply(const Matrix& matrix_a, const Matrix& matrix_b) noexcept { ASSERT(matrix_a.num_columns() == matrix_b.num_rows()); Matrix output(matrix_a.num_rows(), matrix_b.num_columns()); for (Int i=0; i std::vector Multiply(const Matrix& matrix_a, const std::vector& vector) noexcept { ASSERT(matrix_a.num_columns() == (Int)vector.size()); Matrix temp_input((Int) vector.size(), 1); temp_input.SetColumn(0, vector); Matrix temp_output = Multiply(matrix_a, temp_input); ASSERT(temp_output.num_columns() == 1); ASSERT(temp_output.num_rows() == (Int)vector.size()); return temp_output.GetColumn(0); } /** Extract the maximum value of the matrix. Equivalent to Matlab's max(max(matrix)) */ template T Max(const Matrix& matrix) noexcept { return Max(matrix.Serial()); } /** Contains eigenvalues and eigenvectors */ struct EigOutput { std::vector eigen_values; /**< Eigenvalues */ std::vector > eigen_vectors; /**< Eigenvectors */ }; EigOutput Eig(const Matrix& matrix) noexcept; Matrix RealPart(const Matrix& input) noexcept; #if MCL_LOAD_EIGEN Eigen::MatrixXd ConvertToEigen(const Matrix& input); #endif template bool IsEqual(const Matrix& matrix_a, const Matrix& matrix_b) noexcept { if (matrix_a.num_rows() != matrix_b.num_rows() | matrix_a.num_columns() != matrix_b.num_columns()) { return false; } for (Int i=0; i