#include "fesa/math/matrix.h" #include #include #include #include "math/dense_blas_internal.h" namespace fesa { namespace { /// @brief Rejects shape overflow before logical dimensions diverge from /// storage. std::size_t CheckedStorageSize(const std::size_t rows, const std::size_t columns) { if (columns != 0 && rows > (std::numeric_limits::max)() / columns) { throw std::length_error{ "Dense matrix dimensions exceed the storage size range."}; } return rows * columns; } } // namespace Matrix::Matrix(const std::size_t rows, const std::size_t columns, const double value) : rows_(rows), columns_(columns), values_(CheckedStorageSize(rows, columns), value) {} Matrix::Matrix(const Matrix& other) : rows_(other.rows_), columns_(other.columns_), values_(other.values_.size()) { dense_blas_internal::CopyValues(other.values_.data(), other.values_.size(), values_.data()); } Matrix::Matrix(Matrix&& other) noexcept : rows_(other.rows_), columns_(other.columns_), values_(std::move(other.values_)) { other.rows_ = 0; other.columns_ = 0; other.values_.clear(); } Matrix& Matrix::operator=(const Matrix& other) { if (this != &other) { std::vector copied(other.values_.size()); dense_blas_internal::CopyValues(other.values_.data(), other.values_.size(), copied.data()); rows_ = other.rows_; columns_ = other.columns_; values_.swap(copied); } return *this; } Matrix& Matrix::operator=(Matrix&& other) noexcept { if (this != &other) { rows_ = other.rows_; columns_ = other.columns_; values_ = std::move(other.values_); other.rows_ = 0; other.columns_ = 0; other.values_.clear(); } return *this; } std::size_t Matrix::Rows() const noexcept { return rows_; } std::size_t Matrix::Columns() const noexcept { return columns_; } double* Matrix::Data() noexcept { return values_.data(); } const double* Matrix::Data() const noexcept { return values_.data(); } double Matrix::Norm() const { return dense_blas_internal::NormValues(Data(), values_.size()); } void Matrix::Scale(const double alpha) { dense_blas_internal::ScaleValues(alpha, Data(), values_.size()); } double& Matrix::operator()(const std::size_t row, const std::size_t column) { if (row >= rows_ || column >= columns_) { throw std::out_of_range{"Matrix index is outside its dimensions."}; } return values_[row * columns_ + column]; } const double& Matrix::operator()(const std::size_t row, const std::size_t column) const { if (row >= rows_ || column >= columns_) { throw std::out_of_range{"Matrix index is outside its dimensions."}; } return values_[row * columns_ + column]; } Vector Matrix::Multiply(const Vector& rhs) const { return dense_blas_internal::Multiply(*this, rhs); } Matrix Matrix::Multiply(const Matrix& rhs) const { return dense_blas_internal::Multiply(*this, rhs); } } // namespace fesa