Browse Source

math: make sure magic swizzling vectors don't actually store data, and

do the swizzling by using their address rather than their members.
legacy
Sam Hocevar sam 13 years ago
parent
commit
7723d892f7
1 changed files with 47 additions and 23 deletions
  1. +47
    -23
      src/lol/math/vector.h

+ 47
- 23
src/lol/math/vector.h View File

@@ -60,38 +60,59 @@ DECLARE_VECTOR_TYPEDEFS(Mat4, mat4)


/* /*
* Magic vector swizzling (part 1/2) * 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<typename T, int N> struct XVec2 template<typename T, int N> struct XVec2
{ {
inline Vec2<T> operator =(Vec2<T> const &that); inline Vec2<T> operator =(Vec2<T> 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<T*>(static_cast<void*>(this))[i];
}
inline T const& operator[](int n) const
{
int i = (N >> (4 * (1 - n))) & 3;
return static_cast<T const*>(static_cast<void const *>(this))[i];
}
}; };


template<typename T, int N> struct XVec3 template<typename T, int N> struct XVec3
{ {
inline Vec3<T> operator =(Vec3<T> const &that); inline Vec3<T> operator =(Vec3<T> 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<T*>(static_cast<void*>(this))[i];
}
inline T const& operator[](int n) const
{
int i = (N >> (4 * (2 - n))) & 3;
return static_cast<T const*>(static_cast<void const *>(this))[i];
}
}; };


template<typename T, int N> struct XVec4 template<typename T, int N> struct XVec4
{ {
inline Vec4<T> operator =(Vec4<T> const &that); inline Vec4<T> operator =(Vec4<T> 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<T*>(static_cast<void*>(this))[i];
}
inline T const& operator[](int n) const
{
int i = (N >> (4 * (3 - n))) & 3;
return static_cast<T const*>(static_cast<void const *>(this))[i];
}
}; };


/* /*
@@ -200,11 +221,11 @@ template <typename T> struct Vec2 : BVec2<T>


template<int N> template<int N>
inline Vec2(XVec2<T, N> const &v) inline Vec2(XVec2<T, N> const &v)
: BVec2<T>(v.ptr[v.I], v.ptr[v.J]) {}
: BVec2<T>(v[0], v[1]) {}


template<typename U, int N> template<typename U, int N>
explicit inline Vec2(XVec2<U, N> const &v) explicit inline Vec2(XVec2<U, N> const &v)
: BVec2<T>(v.ptr[v.I], v.ptr[v.J]) {}
: BVec2<T>(v[0], v[1]) {}


DECLARE_MEMBER_OPS(Vec2) DECLARE_MEMBER_OPS(Vec2)


@@ -456,11 +477,11 @@ template <typename T> struct Vec3 : BVec3<T>


template<int N> template<int N>
inline Vec3(XVec3<T, N> const &v) inline Vec3(XVec3<T, N> const &v)
: BVec3<T>(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K]) {}
: BVec3<T>(v[0], v[1], v[2]) {}


template<typename U, int N> template<typename U, int N>
explicit inline Vec3(XVec3<U, N> const &v) explicit inline Vec3(XVec3<U, N> const &v)
: BVec3<T>(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K]) {}
: BVec3<T>(v[0], v[1], v[2]) {}


DECLARE_MEMBER_OPS(Vec3) DECLARE_MEMBER_OPS(Vec3)


@@ -868,11 +889,11 @@ template <typename T> struct Vec4 : BVec4<T>


template<int N> template<int N>
inline Vec4(XVec4<T, N> const &v) inline Vec4(XVec4<T, N> const &v)
: BVec4<T>(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K], v.ptr[v.L]) {}
: BVec4<T>(v[0], v[1], v[2], v[3]) {}


template<typename U, int N> template<typename U, int N>
explicit inline Vec4(XVec4<U, N> const &v) explicit inline Vec4(XVec4<U, N> const &v)
: BVec4<T>(v.ptr[v.I], v.ptr[v.J], v.ptr[v.K], v.ptr[v.L]) {}
: BVec4<T>(v[0], v[1], v[2], v[3]) {}


DECLARE_MEMBER_OPS(Vec4) DECLARE_MEMBER_OPS(Vec4)


@@ -1237,21 +1258,24 @@ DECLARE_ALL_VECTOR_COERCE_OPS(Vec4)
template<typename T, int N> template<typename T, int N>
inline Vec2<T> XVec2<T, N>::operator =(Vec2<T> const &that) inline Vec2<T> XVec2<T, N>::operator =(Vec2<T> const &that)
{ {
ptr[I] = that[0]; ptr[J] = that[1];
for (int i = 0; i < 2; i++)
*this[i] = that[i];
return *this; return *this;
} }


template<typename T, int N> template<typename T, int N>
inline Vec3<T> XVec3<T, N>::operator =(Vec3<T> const &that) inline Vec3<T> XVec3<T, N>::operator =(Vec3<T> 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; return *this;
} }


template<typename T, int N> template<typename T, int N>
inline Vec4<T> XVec4<T, N>::operator =(Vec4<T> const &that) inline Vec4<T> XVec4<T, N>::operator =(Vec4<T> 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; return *this;
} }




Loading…
Cancel
Save