diff options
Diffstat (limited to 'src/matrix.cpp')
| -rw-r--r-- | src/matrix.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/matrix.cpp b/src/matrix.cpp index dd19e02..c6888a4 100644 --- a/src/matrix.cpp +++ b/src/matrix.cpp @@ -1,10 +1,24 @@ #include "matrix.hpp" +#include "linalg_error.hpp" #include <algorithm> +#include <sstream> #include <stdexcept> namespace linalg { +namespace { + +void check_same_shape(const Matrix& lhs, const Matrix& rhs, const char* operation) { + if (lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols()) { + std::ostringstream oss; + oss << operation << " requires equal matrix shapes, got " << lhs.rows() << "x" << lhs.cols() << " and " << rhs.rows() << "x" << rhs.cols(); + throw DimensionMismatchError(oss.str()); + } +} + +} // namespace + Matrix::Matrix(std::size_t rows, std::size_t cols) : rows_(rows), cols_(cols), data_(rows * cols) {} @@ -69,4 +83,77 @@ void Matrix::check_bounds(std::size_t i, std::size_t j) const { } } +Matrix transpose(const Matrix& matrix) { + Matrix result(matrix.cols(), matrix.rows()); + for (std::size_t i = 0; i < matrix.rows(); ++i) { + for (std::size_t j = 0; j < matrix.cols(); ++j) { + result(j, i) = matrix(i, j); + } + } + return result; +} + +Matrix operator+(const Matrix& lhs, const Matrix& rhs) { + check_same_shape(lhs, rhs, "Matrix addition"); + + Matrix result(lhs.rows(), lhs.cols()); + for (std::size_t i = 0; i < lhs.rows(); ++i) { + for (std::size_t j = 0; j < lhs.cols(); ++j) { + result(i, j) = lhs(i, j) + rhs(i, j); + } + } + return result; +} + +Matrix operator-(const Matrix& lhs, const Matrix& rhs) { + check_same_shape(lhs, rhs, "Matrix subtraction"); + + Matrix result(lhs.rows(), lhs.cols()); + for (std::size_t i = 0; i < lhs.rows(); ++i) { + for (std::size_t j = 0; j < lhs.cols(); ++j) { + result(i, j) = lhs(i, j) - rhs(i, j); + } + } + return result; +} + +Vector operator*(const Matrix& matrix, const Vector& vector) { + if (matrix.cols() != vector.size()) { + std::ostringstream oss; + oss << "Matrix-vector multiplication requires matrix columns to match vector size, got " + << matrix.cols() << " and " << vector.size(); + throw DimensionMismatchError(oss.str()); + } + + Vector result(matrix.rows()); + for (std::size_t i = 0; i < matrix.rows(); ++i) { + double sum = 0.0; + for (std::size_t j = 0; j < matrix.cols(); ++j) { + sum += matrix(i, j) * vector[j]; + } + result[i] = sum; + } + return result; +} + +Matrix operator*(const Matrix& lhs, const Matrix& rhs) { + if (lhs.cols() != rhs.rows()) { + std::ostringstream oss; + oss << "Matrix multiplication requires lhs.cols() == rhs.rows(), got " << lhs.cols() + << " and " << rhs.rows(); + throw DimensionMismatchError(oss.str()); + } + + Matrix result(lhs.rows(), rhs.cols()); + for (std::size_t i = 0; i < lhs.rows(); ++i) { + for (std::size_t k = 0; k < lhs.cols(); ++k) { + const double lhs_ik = lhs(i, k); + for (std::size_t j = 0; j < rhs.cols(); ++j) { + result(i, j) += lhs_ik * rhs(k, j); + } + } + } + return result; +} + } // namespace linalg |