diff --git a/README.md b/README.md index f818ef1..b6b0b1e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If this code was helpful to you, I'll be very happy if you cite it: # Whats New? * Vector2D: operates in the same manner as the Vector3D, but with only two components. The cross product of the Vector2D results in a scalar instead of a vector. -* VectorND: is a vector with N components whose size is defined at compile time. It uses std::numerics for some of the operations. (comming soon) +* VectorND: is a vector with N components whose size is defined at compile time. * The library utilizes C++20 concepts to restrict the templates for improved compilation time, safety, and error messages. The templated vectors can support any arithmetic type or std::complex of an arithmetic type. @@ -30,7 +30,7 @@ vector2D u; vectorND w; ``` -* The vector components are public for the vector2D and vector3D types. +* The vector components are public for the vector2D and vector3D types `(v.x, v.y, v.z)`. # Compilation @@ -69,7 +69,12 @@ v[0] = 1.2; v[1] = -1.2; v[2] = 22; For N-dimensional vectors, the only way of accessing the components is with the [] operator. -# vectorND ussage (comming soon) +``` +vectorND v(1,2,3,4,5); +vectorND u = {1,2,3,4}; +vectorND w(1); // vector of 1's +w.load(1,2,3,4,5,6); // gets checked at compile time for the size of the vector and arguments +``` Print the vector to the screen with `std::cout`. You can also calculate the norm of the vector with `v.norm()` and `norm(v)` or the square norm with `v.norm2()` and `norm2(v)`. Calculate the angle between two vectors (in radians) with the functions `angle(v1,v2)` and in degrees with `angled(v1,v2)`. diff --git a/vector.h b/vector.h index 4218ad8..85c0614 100644 --- a/vector.h +++ b/vector.h @@ -2,6 +2,9 @@ #include #include #include +#include +#include + /* * This file is part of the Vector3D distribution (https://github.com/cdelv/Vector3D). * Copyright (c) 2022 Carlos Andres del Valle. @@ -58,7 +61,12 @@ std::ostream& operator<<(std::ostream& os, const __VecExpression& vec) { */ // Sumation of all elements template -inline constexpr auto sum(const __VecExpression &expr) noexcept; +inline constexpr auto sum(const __VecExpression &expr) noexcept { + auto Sum = expr[0]; + for (std::size_t i = 1; i < N; ++i) + Sum += expr[i]; + return Sum; +} // Specialization for N = 3 template inline constexpr auto sum(const __VecExpression &expr) noexcept { @@ -342,15 +350,15 @@ class vector3D : public __VecExpression, 3> { x = expr[0]; y = expr[1]; z = expr[2]; } inline constexpr const T& operator[](const std::size_t i) const { - if(i == 0) return x; - else if(i == 1) return y; - else if(i == 2) return z; + if (i == 0) return x; + else if (i == 1) return y; + else if (i == 2) return z; else throw std::out_of_range("vector3D: Index out of range"); } inline constexpr T& operator[](const std::size_t i) { - if(i == 0) return x; - else if(i == 1) return y; - else if(i == 2) return z; + if (i == 0) return x; + else if (i == 1) return y; + else if (i == 2) return z; else throw std::out_of_range("vector3D: Index out of range"); } /* @@ -492,4 +500,87 @@ class vector2D : public __VecExpression, 2> { *this /= norm(); return *this; } +}; +template <__Number T, std::size_t N> +class vectorND : public __VecExpression, N> { +private: + std::vector data; +public: + static inline constexpr const std::size_t size() { + return N; + } + std::vector::iterator begin() { return data.begin();} + std::vector::iterator end() { return data.end();} + + constexpr vectorND() noexcept = default; + constexpr vectorND(const vectorND& other) noexcept = default; + constexpr vectorND(vectorND&& other) noexcept = default; + constexpr vectorND(const T value) noexcept : data(N, value) {} + template + constexpr vectorND(const Args&... args) noexcept : data {args...} { + static_assert(sizeof...(args) == N, "vectorND: Number of arguments does not match the size of the vector."); + } + constexpr vectorND& operator=(const vectorND& other) noexcept = default; + constexpr vectorND& operator=(vectorND&& other) noexcept = default; + + template + inline constexpr void load(const Args&... args) noexcept { + static_assert(sizeof...(args) == N, "vectorND: Number of arguments does not match the size of the vector."); + data = {args...}; + } + + template + inline constexpr vectorND(const __VecExpression &expr) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] = expr[i]; + } + inline constexpr const T& operator[](const std::size_t i) const { + return data[i]; + } + inline constexpr T& operator[](const std::size_t i) { + return data[i]; + } + /* + * OPERATORS + */ + template + inline constexpr vectorND& operator+=(const __VecExpression& expr) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] += expr[i]; + return *this; + } + template + inline constexpr vectorND& operator-=(const __VecExpression& expr) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] -= expr[i]; + return *this; + } + template <__Number E> + inline constexpr vectorND& operator*=(const E& a) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] *= a; + return *this; + } + template <__Number E> + inline constexpr vectorND& operator/=(const E& a) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] /= a; + return *this; + } + template + inline constexpr vectorND& operator/=(const __VecExpression& expr) noexcept { + for (std::size_t i = 0; i < N; ++i) + data[i] /= expr[i]; + return *this; + } + inline constexpr const T norm2() const noexcept { + return dot(*this, *this); + } + inline constexpr const T norm() const noexcept { + return std::sqrt(norm2()); + } + inline constexpr const vectorND& unit() noexcept { + *this /= norm(); + return *this; + } }; \ No newline at end of file