aboutsummaryrefslogtreecommitdiff
path: root/src/matrix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/matrix.cpp')
-rw-r--r--src/matrix.cpp87
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