export module linalgebra:vector; import std; import :error; export namespace linalgebra { class Vector { public: Vector() = default; explicit Vector(std::size_t n); Vector(std::size_t n, double value); Vector(std::initializer_list values); [[nodiscard]] std::size_t size() const noexcept; [[nodiscard]] bool empty() const noexcept; double& operator[](std::size_t i); const double& operator[](std::size_t i) const; void fill(double value); double* data() noexcept; const double* data() const noexcept; auto begin() noexcept { return data_.begin(); } auto end() noexcept { return data_.end(); } auto begin() const noexcept { return data_.begin(); } auto end() const noexcept { return data_.end(); } auto cbegin() const noexcept { return data_.cbegin(); } auto cend() const noexcept { return data_.cend(); } private: void check_index(std::size_t i) const; std::vector data_; }; Vector operator+(const Vector& lhs, const Vector& rhs); Vector operator-(const Vector& lhs, const Vector& rhs); Vector operator*(const Vector& v, double scalar); Vector operator*(double scalar, const Vector& v); Vector operator/(const Vector& v, double scalar); double dot(const Vector& lhs, const Vector& rhs); } // namespace linalgebra namespace { void check_same_size(const linalgebra::Vector& lhs, const linalgebra::Vector& rhs, const char* operation) { if (lhs.size() != rhs.size()) { std::ostringstream oss; oss << operation << " requires equal vector sizes, got " << lhs.size() << " and " << rhs.size(); throw linalgebra::DimensionMismatchError(oss.str()); } } } // namespace namespace linalgebra { Vector::Vector(std::size_t n) : data_(n) {} Vector::Vector(std::size_t n, double value) : data_(n, value) {} Vector::Vector(std::initializer_list values) : data_(values) {} std::size_t Vector::size() const noexcept { return data_.size(); } bool Vector::empty() const noexcept { return data_.empty(); } double& Vector::operator[](std::size_t i) { check_index(i); return data_[i]; } const double& Vector::operator[](std::size_t i) const { check_index(i); return data_[i]; } void Vector::fill(double value) { std::fill(data_.begin(), data_.end(), value); } double* Vector::data() noexcept { return data_.data(); } const double* Vector::data() const noexcept { return data_.data(); } void Vector::check_index(std::size_t i) const { if (i >= data_.size()) { throw std::out_of_range("Vector index out of range"); } } Vector operator+(const Vector& lhs, const Vector& rhs) { check_same_size(lhs, rhs, "Vector addition"); Vector result(lhs.size()); for (std::size_t i = 0; i < lhs.size(); ++i) { result[i] = lhs[i] + rhs[i]; } return result; } Vector operator-(const Vector& lhs, const Vector& rhs) { check_same_size(lhs, rhs, "Vector subtraction"); Vector result(lhs.size()); for (std::size_t i = 0; i < lhs.size(); ++i) { result[i] = lhs[i] - rhs[i]; } return result; } Vector operator*(const Vector& v, double scalar) { Vector result(v.size()); for (std::size_t i = 0; i < v.size(); ++i) { result[i] = v[i] * scalar; } return result; } 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"); return std::inner_product(lhs.begin(), lhs.end(), rhs.begin(), 0.0); } } // namespace linalgebra