#pragma once #include #include #include #include template struct Vector { Vector(): elements{} {}; template = 0> Vector(Args... args) : elements{ args... } {}; Vector(T values[S]) { std::copy(values, values + S, elements); }; Vector(T scalar) { std::fill(elements, elements + S, scalar); }; Vector(Vector vector, T scalar) { std::copy(vector.elements, vector.elements + S - 1, elements); elements[S - 1] = scalar; } Vector map(std::function f) const { Vector result{}; for (int i = 0; i < S; i++) { result[i] = f(elements[i]); } return result; } Vector map(std::function f) const { Vector result{}; for (int i = 0; i < S; i++) { result[i] = f(i, elements[i]); } return result; } T reduce(std::function f) const { T result = elements[0]; for (int i = 1; i < S; i++) { result = f(result, elements[i]); } return result; } T sum() const { return reduce([](auto x, auto y) { return x + y; }); } T magnitude() const { return sqrt(map([](auto x) { return x * x;}).sum()); } Vector normalize() const { auto m = magnitude(); return map([=](auto x) { return x / m; }); } T distance(Vector other) const { return (*this - other).magnitude(); } Vector abs() const { return map([=](auto x) { return std::abs(x); }); } Vector<3, T> cross(Vector<3, T> other) const { return { y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(), x() * other.y() - y() * other.x(), }; } T operator[](size_t index) const { return elements[index]; } T& operator[](size_t index) { return elements[index]; } Vector operator+(Vector other) const { return map([&](auto i, auto x) { return x + other[i]; }); } Vector operator+(T scalar) const { return map([=](auto x) { return x + scalar; }); } Vector operator*(T scalar) const { return map([=](auto x) { return x * scalar; }); } T operator*(Vector other) const { return map([&](auto i, auto x) { return x * other[i]; }).sum(); } Vector operator-(Vector other) const { return map([&](auto i, auto x) { return x - other[i]; }); } Vector operator-() const { return map([](T x) -> T { return -x; }); } Vector operator/(T scalar) const { return map([=](auto x) { return x / scalar; }); } T& x() { static_assert(S > 0); return elements[0]; } const T& x() const { static_assert(S > 0); return elements[0]; } T& y() { static_assert(S > 1); return elements[1]; } const T& y() const { static_assert(S > 1); return elements[1]; } T& z() { static_assert(S > 2); return elements[2]; } const T& z() const { static_assert(S > 2); return elements[2]; } T& w() { static_assert(S > 3); return elements[3]; } const T& w() const { static_assert(S > 3); return elements[3]; } std::string string() const { std::stringstream str{}; str << "[ "; for (int i = 0; i < S; i++) { str << elements[i] << " "; } str << "]"; return str.str(); } T elements[S]; };