#pragma once #include #include #include #include #include #include template struct Vector { public: Vector(): elements{} {}; template Vector(Args... args) : elements{ args... } {}; Vector(T values[S]) { std::copy(values, values + S, elements); }; 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; }); } 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; }); } 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; }); } T x() const { static_assert(S > 0); return elements[0]; } T y() const { static_assert(S > 1); return elements[1]; } T z() const { static_assert(S > 2); return elements[2]; } 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]; };