summaryrefslogblamecommitdiffstats
path: root/mvector.hpp
blob: b7347d1d35992e911310c7517ec419a7f0c6f318 (plain) (tree)



































































































































































                                                                    
#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