From 7723d892f7dcb155ebc704c6cec581e32c48502f Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 12 Mar 2012 01:57:11 +0000 Subject: [PATCH] math: make sure magic swizzling vectors don't actually store data, and do the swizzling by using their address rather than their members. --- src/lol/math/vector.h | 70 +++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index a6e2ce16..304a822e 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -60,38 +60,59 @@ DECLARE_VECTOR_TYPEDEFS(Mat4, mat4) /* * Magic vector swizzling (part 1/2) + * These vectors are empty, but thanks to static_cast we can take their + * address and access the vector of T's that they are union'ed with. We + * use static_cast instead of reinterpret_cast because there is a stronger + * guarantee (by the standard) that the address will stay the same across + * casts. */ template struct XVec2 { inline Vec2 operator =(Vec2 const &that); - static int const I = (N >> 4) & 3; - static int const J = (N >> 0) & 3; - T ptr[1 + (I > J ? I : J)]; + inline T& operator[](int n) + { + int i = (N >> (4 * (1 - n))) & 3; + return static_cast(static_cast(this))[i]; + } + inline T const& operator[](int n) const + { + int i = (N >> (4 * (1 - n))) & 3; + return static_cast(static_cast(this))[i]; + } }; template struct XVec3 { inline Vec3 operator =(Vec3 const &that); - static int const I = (N >> 8) & 3; - static int const J = (N >> 4) & 3; - static int const K = (N >> 0) & 3; - T ptr[1 + (I > J ? I > K ? I : K - : J > K ? J : K)]; + inline T& operator[](int n) + { + int i = (N >> (4 * (2 - n))) & 3; + return static_cast(static_cast(this))[i]; + } + inline T const& operator[](int n) const + { + int i = (N >> (4 * (2 - n))) & 3; + return static_cast(static_cast(this))[i]; + } }; template struct XVec4 { inline Vec4 operator =(Vec4 const &that); - static int const I = (N >> 12) & 3; - static int const J = (N >> 8) & 3; - static int const K = (N >> 4) & 3; - static int const L = (N >> 0) & 3; - T ptr[1 + (I > J ? I > K ? I > L ? I : L : K > L ? K : L - : J > K ? J > L ? J : L : K > L ? K : L)]; + inline T& operator[](int n) + { + int i = (N >> (4 * (3 - n))) & 3; + return static_cast(static_cast(this))[i]; + } + inline T const& operator[](int n) const + { + int i = (N >> (4 * (3 - n))) & 3; + return static_cast(static_cast(this))[i]; + } }; /* @@ -200,11 +221,11 @@ template struct Vec2 : BVec2 template inline Vec2(XVec2 const &v) - : BVec2(v.ptr[v.I], v.ptr[v.J]) {} + : BVec2(v[0], v[1]) {} template explicit inline Vec2(XVec2 const &v) - : BVec2(v.ptr[v.I], v.ptr[v.J]) {} + : BVec2(v[0], v[1]) {} DECLARE_MEMBER_OPS(Vec2) @@ -456,11 +477,11 @@ template struct Vec3 : BVec3 template inline Vec3(XVec3 const &v) - : BVec3(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K]) {} + : BVec3(v[0], v[1], v[2]) {} template explicit inline Vec3(XVec3 const &v) - : BVec3(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K]) {} + : BVec3(v[0], v[1], v[2]) {} DECLARE_MEMBER_OPS(Vec3) @@ -868,11 +889,11 @@ template struct Vec4 : BVec4 template inline Vec4(XVec4 const &v) - : BVec4(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K], v.ptr[v.L]) {} + : BVec4(v[0], v[1], v[2], v[3]) {} template explicit inline Vec4(XVec4 const &v) - : BVec4(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K], v.ptr[v.L]) {} + : BVec4(v[0], v[1], v[2], v[3]) {} DECLARE_MEMBER_OPS(Vec4) @@ -1237,21 +1258,24 @@ DECLARE_ALL_VECTOR_COERCE_OPS(Vec4) template inline Vec2 XVec2::operator =(Vec2 const &that) { - ptr[I] = that[0]; ptr[J] = that[1]; + for (int i = 0; i < 2; i++) + *this[i] = that[i]; return *this; } template inline Vec3 XVec3::operator =(Vec3 const &that) { - ptr[I] = that[0]; ptr[J] = that[1]; ptr[K] = that[2]; + for (int i = 0; i < 3; i++) + *this[i] = that[i]; return *this; } template inline Vec4 XVec4::operator =(Vec4 const &that) { - ptr[I] = that[0]; ptr[J] = that[1]; ptr[K] = that[2]; ptr[L] = that[3]; + for (int i = 0; i < 4; i++) + *this[i] = that[i]; return *this; }