#include #include #include #include #include #include #include template struct basic_vec : public std::array { static constexpr std::size_t dimensions = d; static constexpr T null_element = static_cast(0); static constexpr T unit_element = static_cast(1); static constexpr T unit_additive_inverse_element = static_cast(-1); basic_vec(); basic_vec(const std::initializer_list l); template basic_vec(const basic_vec& other); T length() const; }; template basic_vec::basic_vec() : std::array() { this->fill(basic_vec::null_element); } template basic_vec::basic_vec(const std::initializer_list l) { basic_vec(); // why can't this sh*t be a constexpr with static_assert??? assert(l.size() <= d); std::copy(l.begin(), l.end(), this->begin()); } template template basic_vec::basic_vec(const basic_vec& other) { basic_vec(); static_assert(d >= n); for (std::size_t i = 0; i < n; i++) { this->at(i) = other.at(i); } } template T basic_vec::length() const { T res = basic_vec::null_element; for (const T& val : *this) { res += val * val; } return res; } template basic_vec operator+(const basic_vec& rhs, const basic_vec& lhs) { basic_vec out; std::transform(rhs.begin(), rhs.end(), lhs.begin(), out.begin(), [](const T& r, const T& l) -> T { return r + l; } ); return out; } template basic_vec operator*(const T& rhs, const basic_vec& lhs) { basic_vec out; std::transform(lhs.begin(), lhs.end(), out.begin(), [rhs](const T& t) -> T { return t * rhs; }); return out; } template basic_vec operator-(const basic_vec& rhs, const basic_vec& lhs) { return rhs + basic_vec::unit_additive_inverse_element * lhs; } template T operator*(const basic_vec& rhs, const basic_vec& lhs) { return std::inner_product(rhs.begin(), rhs.end(), lhs.begin(), 0); } template std::ostream& operator<<(std::ostream& os, const basic_vec& v) { os << "<"; for (std::size_t i = 0; i < d -1; i++) { os << v[i] << ", "; } os << v[d-1] << ">"; return os; } template class vec: public basic_vec { public: vec(std::initializer_list l) : basic_vec(l) {} template vec(const basic_vec& other) : basic_vec(other) {} }; template class vec3 : public basic_vec { public: vec3(std::initializer_list l) : basic_vec(l) {} template vec3(const basic_vec& other) : basic_vec(other) {} static vec3 cross(const vec3& rhs, const vec3& lhs); }; template vec3 vec3::cross(const vec3& rhs, const vec3& lhs) { vec3 res; res[0] = (rhs[1] * lhs[2]) - (rhs[2] * lhs[1]); res[1] = (rhs[2] * lhs[0]) - (rhs[0] * lhs[2]); res[2] = (rhs[0] * lhs[1]) - (rhs[1] * lhs[0]); return res; } template class vec2: public basic_vec { public: vec2(std::initializer_list l) : basic_vec(l) {} template vec2(const basic_vec& other) : basic_vec(other) {} T polar(); static vec3 cross(const vec2& rhs, const vec2& lhs); }; template T vec2::polar() { return std::atan2(this->at(0), this->at(1)); } template vec3 vec2::cross(const vec2& rhs, const vec2& lhs) { return vec3::cross(vec3(rhs), vec3(lhs)); } int main(int argc, char *argv[]) { vec3 v{1, 2, 3}; vec3 u{3, 4, 5}; std::cout << v << std::endl; std::cout << v.length() << std::endl; std::cout << v + u << std::endl; std::cout << v - u << std::endl; std::cout << 2.0 * u << std::endl; std::cout << v * u << std::endl; return 0; }