#include "fesa/math/vector.h" #include #include #include #include "math/dense_blas_internal.h" namespace fesa { namespace { /// @brief Preserves the Vector exception contract around private size /// conversion. MKL_INT MklSizeOrThrow(const std::size_t size) { const auto converted = dense_blas_internal::ToMklSize(size); if (!converted.HasValue()) { throw std::length_error{"Dense vector size exceeds the MKL integer range."}; } return converted.Value(); } } // namespace Vector::Vector(const std::size_t size, const double value) : values_(size, value) {} Vector::Vector(const Vector& other) : values_(other.Size()) { dense_blas_internal::CopyValues(other.values_.data(), other.values_.size(), values_.data()); } Vector::Vector(Vector&& other) noexcept : values_(std::move(other.values_)) { other.values_.clear(); } Vector& Vector::operator=(const Vector& other) { if (this != &other) { std::vector copied(other.Size()); dense_blas_internal::CopyValues(other.values_.data(), other.values_.size(), copied.data()); values_.swap(copied); } return *this; } Vector& Vector::operator=(Vector&& other) noexcept { if (this != &other) { values_ = std::move(other.values_); other.values_.clear(); } return *this; } std::size_t Vector::Size() const noexcept { return values_.size(); } double* Vector::Data() noexcept { return values_.data(); } const double* Vector::Data() const noexcept { return values_.data(); } double& Vector::operator[](const std::size_t index) { return values_.at(index); } const double& Vector::operator[](const std::size_t index) const { return values_.at(index); } double Vector::Dot(const Vector& rhs) const { if (Size() != rhs.Size()) { throw std::invalid_argument{ "Vector dot product requires equal dimensions."}; } if (values_.empty()) { return 0.0; } return cblas_ddot(MklSizeOrThrow(Size()), Data(), 1, rhs.Data(), 1); } double Vector::Norm() const { if (values_.empty()) { return 0.0; } return cblas_dnrm2(MklSizeOrThrow(Size()), Data(), 1); } void Vector::Scale(const double alpha) { if (values_.empty()) { return; } cblas_dscal(MklSizeOrThrow(Size()), alpha, Data(), 1); } void Vector::Axpy(const double alpha, const Vector& x) { if (Size() != x.Size()) { throw std::invalid_argument{"Vector axpy requires equal dimensions."}; } if (values_.empty()) { return; } cblas_daxpy(MklSizeOrThrow(Size()), alpha, x.Data(), 1, Data(), 1); } } // namespace fesa