#pragma once #include #include namespace hpr { // forward declarations template requires (S >= 0) class Vector; template using SubVector = typename std::conditional= 2, Vector, Vector>::type; // type traits template struct is_vector : public std::false_type {}; template struct is_vector> : public std::true_type {}; // concepts template concept IsVector = is_vector::value; // aliases template using vec = Vector; using vec2 = Vector; using vec3 = Vector; using vec4 = Vector; template requires (S >= 0) class Vector : public StaticArray { using base = StaticArray; public: using value_type = Type; using size_type = Size; using pointer = Type*; using reference = Type&; using iterator = Iterator; using const_iterator = Iterator; public: //! null constructor constexpr Vector() : base {} {} //! copy constructor constexpr Vector(const Vector& vs) : base {static_cast(vs)} {} //! move constructor constexpr Vector(Vector&& vs) noexcept : base {std::forward(static_cast(vs))} {} //! copy assignment operator constexpr Vector& operator=(const Vector& vs) { base::operator=(vs); return *this; } //! move assignment operator constexpr Vector& operator=(Vector&& vs) noexcept { swap(*this, vs); return *this; } //! destructor virtual ~Vector() = default; //! copy constructor from base constexpr Vector(const base& arr) : base {arr} {} //! move constructor from base constexpr Vector(base&& arr) : base {std::forward(arr)} {} //! construct from iterators constexpr Vector(typename base::iterator start, typename base::iterator end) : base {start, end} {} //! construct from constant iterators constexpr Vector(typename base::const_iterator start, typename base::const_iterator end) : base {start, end} {} //! construct from initializer list constexpr Vector(std::initializer_list list) : base {list} {} //! copy constructor with variadic args template constexpr Vector(const value_type& v, const Args& ...args) requires (S == 1 + sizeof...(args)): base {v, static_cast(args)...} {} //! move constructor with variadic args template constexpr Vector(value_type&& v, Args&& ...args) requires (S == 1 + sizeof...(args)): base {v, static_cast(std::forward(args))...} {} //! copy constructor with sub vector and value constexpr Vector(const SubVector& svs, const value_type& v) requires (S >= 1): base {} { for (auto n = 0; n < svs.size(); ++n) (*this)[n] = svs[n]; (*this)[svs.size()] = v; } //! copy constructor from greater vector template requires (GS > S) constexpr explicit Vector(const Vector& vs) : base {vs.begin(), vs.begin() + S} {} }; // global operators template inline Vector operator+(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = lhs[n]; return vs; } template inline Vector operator-(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = -lhs[n]; return vs; } template inline Vector& operator+=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs[n]; return lhs; } template inline Vector& operator-=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs[n]; return lhs; } template inline Vector& operator*=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs[n]; return lhs; } template inline Vector& operator/=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs[n]; return lhs; } template inline Vector operator+(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs[n]; return vs; } template inline Vector operator-(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs[n]; return vs; } template inline Vector operator*(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs[n]; return vs; } template inline Vector operator/(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs[n]; return vs; } template inline bool operator==(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] != rhs[n]) return false; return true; } template inline bool operator!=(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] == rhs[n]) return false; return true; } template inline Vector& operator+=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs; return lhs; } template inline Vector& operator-=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs; return lhs; } template inline Vector& operator*=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs; return lhs; } template inline Vector& operator/=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs; return lhs; } template inline Vector operator+(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs; return vs; } template inline Vector operator-(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs; return vs; } template inline Vector operator*(const Vector& lhs, const T2& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= static_cast(rhs); return vs; } template inline Vector operator/(const Vector& lhs, const T2& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= static_cast(rhs); return vs; } template inline Vector operator+(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] += lhs; return vs; } template inline Vector operator-(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] -= lhs; return vs; } template inline Vector operator*(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] *= lhs; return vs; } template inline Vector operator/(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] /= lhs; return vs; } // boolean operations template inline Vector equal(const Vector& lhs, const Vector& rhs, const scalar& precision = hpr::precision()) { Vector vs; for (auto n = 0; n < S; ++n) vs[n] = equal(lhs[n], rhs[n], precision); return vs; } template inline bool any(const Vector& vs) { bool res = false; for (auto e : vs) res = res || e; return res; } template inline bool all(const Vector& vs) { bool res = true; for (auto e : vs) res = res && e; return res; } // per element operations template inline Vector abs(const Vector& vs) { Vector res; for (auto n = 0; n < S; ++n) res[n] = abs(vs[n]); return res; } template inline Type sum(const Vector& vs) { Type sum {}; for (const Type& v : vs) sum += v; return sum; } template inline Vector pow(const Vector& vs, scalar degree) { Vector res; for (auto n = 0; n < S; ++n) res[n] = pow(vs[n], degree); return res; } // vector operations template inline Type norm(const Vector& vs) { return sqrt(sum(pow(abs(vs), 2))); } template inline Type dot(const Vector& lhs, const Vector& rhs) { return sum(lhs * rhs); } template inline Type length(const Vector& vs) { return sqrt(dot(vs, vs)); } template inline Type mag(const Vector& vs) { return length(vs); } template inline Type distance(const Vector& vs1, const Vector& vs2) { return length(vs1 - vs2); } template inline Vector normalize(const Vector& vs) { return vs * isqrt(dot(vs, vs)); } template inline Type angle(const Vector& lhs, const Vector& rhs) { scalar cos = dot(lhs, rhs) / (norm(lhs) * norm(rhs)); return acos(cos); //clip(cos, -1., 1.)); } // vector 3 operations template inline Vector cross(const Vector& lhs, const Vector& rhs) { return Vector( lhs[1] * rhs[2] - lhs[2] * rhs[1], lhs[2] * rhs[0] - lhs[0] * rhs[2], lhs[0] * rhs[1] - lhs[1] * rhs[0] ); } } // end namespace hpr