diff --git a/libnum/include/num/vec.h b/libnum/include/num/vec.h index cd685b1..13fda84 100644 --- a/libnum/include/num/vec.h +++ b/libnum/include/num/vec.h @@ -22,13 +22,19 @@ namespace libnum { -template requires(N > 0) -struct vec +/* _vec_mixin: CRTP support type with common methods + This structure type is inherited by all vec types. It assumes that the + vector type is isomorphic to T[N] and implements all the methods that can be + derived from that. */ +template requires(N > 0) +struct _vec_mixin { - T coords[N]; - - inline constexpr int size() const { return N; } + /* Number of components in the vector. */ + inline constexpr int size() const { + return N; + } + /* Access to the i-th component as an lvalue. */ inline constexpr T &operator[](int i) { return ((T *)this)[i]; } @@ -36,39 +42,57 @@ struct vec return ((T *)this)[i]; } - constexpr T dot(vec const &other) const { + /* Dot product with another vector of the same size. */ + constexpr T dot(Vector const &other) const { T r(0); for(int i = 0; i < N; ++i) - r += coords[i] * other[i]; + r += (*this)[i] * other[i]; return r; } + + /* Vector norm, squared. */ + constexpr T norm2() const { + T r(0); + for(int i = 0; i < N; ++i) + r += (*this)[i] * (*this)[i]; + return r; + } + + /* Vector norm. */ + // TODO: _vec_mixin::norm() only works for num (uses .sqrt() method) + constexpr T norm() const { + return norm2().sqrt(); + } + + /* Normalized */ + constexpr Vector normalize() const { + return *static_cast(this) / norm(); + } +}; + +/* Vector type implementations. The generic type vec uses an array and no + specific facilities. The specialized types vec through vec provide + access to members as .x, .y, .z, .w in addition to operator[]. They also + provide swizzling-style constructors and methods. */ + +template requires(N > 0) +struct vec: _vec_mixin, T, N> +{ + T coords[N]; }; template -struct vec +struct vec: _vec_mixin, T, 2> { T x, y; vec(): x {0}, y {0} {} vec(T _x, T _y): x {_x}, y {_y} {} - - inline constexpr int size() const { return 2; } - - inline constexpr T &operator[](int i) { - return ((T *)this)[i]; - } - inline constexpr T const &operator[](int i) const { - return ((T *)this)[i]; - } - - inline constexpr T dot(vec const &other) const { - return x * other.x + y * other.y; - } }; using vec2 = vec; template -struct vec +struct vec: _vec_mixin, T, 3> { T x, y, z; @@ -78,15 +102,6 @@ struct vec vec(vec v): x {v.x}, y {v.y}, z {0} {} vec(vec v, T _z): x {v.x}, y {v.y}, z {_z} {} - inline constexpr int size() const { return 3; } - - inline constexpr T &operator[](int i) { - return ((T *)this)[i]; - } - inline constexpr T const &operator[](int i) const { - return ((T *)this)[i]; - } - inline constexpr vec xy() const { return vec(x, y); } @@ -96,15 +111,11 @@ struct vec inline constexpr vec yz() const { return vec(y, z); } - - inline constexpr T dot(vec const &other) const { - return x * other.x + y * other.y + z * other.z; - } }; using vec3 = vec; template -struct vec +struct vec: _vec_mixin, T, 4> { T x, y, z, w; @@ -116,22 +127,9 @@ struct vec vec(vec v): x {v.x}, y {v.y}, z {v.z}, w {0} {} vec(vec v, T _w): x {v.x}, y {v.y}, z {v.z}, w {_w} {} - inline constexpr int size() const { return 4; } - - inline constexpr T &operator[](int i) { - return ((T *)this)[i]; - } - inline constexpr T const &operator[](int i) const { - return ((T *)this)[i]; - } - inline constexpr vec xyz() const { return vec(x, y, z); } - - constexpr T dot(vec const &other) const { - return x * other.x + y * other.y + z * other.z + w * other.w; - } }; using vec4 = vec; @@ -167,11 +165,10 @@ inline constexpr vec &operator*=(vec &lhs, T const &rhs) { return lhs; } template -inline constexpr vec &operator*=(vec &lhs, vec const &rhs) { - T r = T(0); +inline constexpr vec &operator*=(vec &lhs, int rhs) { for(int i = 0; i < N; i++) - r += lhs[i] * rhs[i]; - return r; + lhs[i] *= rhs; + return lhs; } template inline constexpr vec &operator/=(vec &lhs, T const &rhs) { @@ -179,6 +176,12 @@ inline constexpr vec &operator/=(vec &lhs, T const &rhs) { lhs[i] /= rhs; return lhs; } +template +inline constexpr vec &operator/=(vec &lhs, int rhs) { + for(int i = 0; i < N; i++) + lhs[i] /= rhs; + return lhs; +} template inline constexpr vec operator+(vec const &lhs) { @@ -209,9 +212,17 @@ inline constexpr vec operator*(T const &lhs, vec rhs) { return rhs; } template +inline constexpr vec operator*(vec lhs, int rhs) { + return lhs *= rhs; +} +template inline constexpr vec operator/(vec lhs, T const &rhs) { return lhs /= rhs; } +template +inline constexpr vec operator/(vec lhs, int rhs) { + return lhs /= rhs; +} /* Comparisons */