From 38004f74df5b2dbcb07e6ad5ac2272f16882e018 Mon Sep 17 00:00:00 2001 From: y-jan137 Date: Thu, 12 Mar 2026 16:40:43 +0300 Subject: Add basic ops --- src/matrix.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/norms.cpp | 9 ++++++ src/vector.cpp | 12 ++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/norms.cpp (limited to 'src') 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 +#include #include 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 diff --git a/src/norms.cpp b/src/norms.cpp new file mode 100644 index 0000000..cafee69 --- /dev/null +++ b/src/norms.cpp @@ -0,0 +1,9 @@ +#include "norms.hpp" + +#include + +namespace linalg { + +double norm2(const Vector& vector) { return std::sqrt(dot(vector, vector)); } + +} // namespace linalg diff --git a/src/vector.cpp b/src/vector.cpp index b8b1c6f..8c4a8c4 100644 --- a/src/vector.cpp +++ b/src/vector.cpp @@ -83,6 +83,18 @@ Vector operator*(const Vector& v, double scalar) { Vector operator*(double scalar, const Vector& v) { return v * scalar; } +Vector operator/(const Vector& v, double scalar) { + if (scalar == 0.0) { + throw std::invalid_argument("Vector scalar division requires a nonzero scalar"); + } + + Vector result(v.size()); + for (std::size_t i = 0; i < v.size(); ++i) { + result[i] = v[i] / scalar; + } + return result; +} + double dot(const Vector& lhs, const Vector& rhs) { check_same_size(lhs, rhs, "Dot product"); -- cgit v1.2.3