#ifndef MATH_VECTOR_HPP
#define MATH_VECTOR_HPP 1
#include <concepts>
#include <array>
namespace mvec
{
template<typename T, std::size_t S>
requires(std::is_arithmetic_v<T>)
class vec
{
protected:
std::array<T, S> v;
public:
constexpr vec(const std::array<T, S> &vs)
: v(vs)
{}
constexpr vec(T vs)
: v(vs)
{}
template<std::size_t S2>
constexpr vec &operator+=(const vec<T, S2> &rhs) {
for(std::size_t i = 0; i < S2 && i < S; i++) v[i] += rhs[i];
return *this;
}
template<std::size_t S2>
constexpr vec &operator-=(const vec<T, S2> &rhs) {
for(std::size_t i = 0; i < S2 && i < S; i++) v[i] -= rhs[i];
return *this;
}
template<std::size_t S2>
constexpr vec &operator*=(const vec<T, S2> &rhs) {
for(std::size_t i = 0; i < S2 && i < S; i++) v[i] *= rhs[i];
return *this;
}
template<std::size_t S2>
constexpr vec &operator/=(const vec<T, S2> &rhs) {
for(std::size_t i = 0; i < S2 && i < S; i++) v[i] /= rhs[i];
return *this;
}
template<std::size_t S2>
friend constexpr vec operator+(vec lhs, const vec<T, S2> &rhs) {
lhs += rhs;
return lhs;
}
template<std::size_t S2>
friend constexpr vec operator-(vec lhs, const vec<T, S2> &rhs) {
lhs -= rhs;
return lhs;
}
template<std::size_t S2>
friend constexpr vec operator*(vec lhs, const vec<T, S2> &rhs) {
lhs *= rhs;
return lhs;
}
template<std::size_t S2>
friend constexpr vec operator/(vec lhs, const vec<T, S2> &rhs) {
lhs /= rhs;
return lhs;
}
constexpr T &operator[](std::size_t i) {
return v[i];
}
constexpr T operator[](std::size_t i) const {
return v[i];
}
};
template<typename T>
requires(std::is_arithmetic_v<T>)
class vec2 final : public vec<T, 2>
{
public:
T &x;
T &y;
constexpr vec2(T X, T Y) :
vec<T, 2>(std::array<T, 2>{X, Y}),
x(this->v[0]),
y(this->v[1])
{}
constexpr vec2(std::array<T, 2> vs) :
vec<T, 2>(vs),
x(this->v[0]),
y(this->v[1])
{}
constexpr vec2(T vs) :
vec<T, 2>(vs),
x(this->v[0]),
y(this->v[1])
{}
};
template<typename T>
requires(std::is_arithmetic_v<T>)
class vec3 final : public vec<T, 3>
{
public:
T &x;
T &y;
T &z;
constexpr vec3(T X, T Y, T Z) :
vec<T, 3>(std::array<T, 3>{X, Y, Z}),
x(this->v[0]),
y(this->v[1]),
z(this->v[2])
{}
constexpr vec3(std::array<T, 3> vs) :
vec<T, 3>(vs),
x(this->v[0]),
y(this->v[1]),
z(this->v[2])
{}
constexpr vec3(T vs) :
vec<T, 3>(vs),
x(this->v[0]),
y(this->v[1]),
z(this->v[2])
{}
};
template<typename T>
requires(std::is_arithmetic_v<T>)
class vec4 final : public vec<T, 4>
{
public:
T &x;
T &y;
T &z;
T &w;
constexpr vec4(T X, T Y, T Z, T W) :
vec<T, 4>(std::array<T, 4>{X, Y, Z, W}),
x(this->v[0]),
y(this->v[1]),
z(this->v[2]),
w(this->v[3])
{}
constexpr vec4(std::array<T, 4> vs) :
vec<T, 4>(vs),
x(this->v[0]),
y(this->v[1]),
z(this->v[2]),
w(this->v[3])
{}
constexpr vec4(T vs) :
vec<T, 4>(vs),
x(this->v[0]),
y(this->v[1]),
z(this->v[2]),
w(this->v[3])
{}
};
}
#endif