Browse Source

math: add iterators and initializer_list constructors to vec_t.

undefined
Sam Hocevar 10 years ago
parent
commit
cc5c21c34b
2 changed files with 175 additions and 2 deletions
  1. +109
    -2
      src/lol/math/vector.h
  2. +66
    -0
      test/unit/vector.cpp

+ 109
- 2
src/lol/math/vector.h View File

@@ -54,7 +54,7 @@ namespace lol

template<typename T, int N, int SWIZZLE>
struct vec_t
/* MUST be a different base than e.g. vec_t<T,2> otherwise the unions
/* MUST have a different base than e.g. vec_t<T,2> otherwise the unions
* in vec_t<T,2> with the same base will cause empty base optimisation
* failures. */
: public swizzle_ops::base<T, SWIZZLE>
@@ -128,6 +128,17 @@ struct vec_t<T, N, FULL_SWIZZLE>
m_data[i] = (T)v.m_data[i];
}

/* Explicit constructor for initializer_list. We need these ugly
* loops until C++ lets us initialize m_data directly. */
explicit inline vec_t(std::initializer_list<element> const &list)
{
auto l = list.begin();
for (int i = 0; i < count && l != list.end(); ++i, ++l)
m_data[i] = *l;
for (int i = list.size(); i < count; ++i)
m_data[i] = (T)0;
}

/* Various explicit constructors */
explicit inline vec_t(T X)
{
@@ -139,7 +150,7 @@ struct vec_t<T, N, FULL_SWIZZLE>
inline T const& operator[](size_t n) const { return m_data[n]; }

private:
T m_data[N];
T m_data[count];
};

/*
@@ -190,6 +201,17 @@ struct vec_t<T,2>
explicit inline constexpr vec_t(vec_t<U, 2, SWIZZLE> const &v)
: x(v[0]), y(v[1]) {}

/* Explicit constructor for initializer_list. We need these ugly
* loops until C++ lets us initialize m_data directly. */
explicit inline vec_t(std::initializer_list<element> const &list)
{
auto l = list.begin();
for (int i = 0; i < count && l != list.end(); ++i, ++l)
m_data[i] = *l;
for (int i = list.size(); i < count; ++i)
m_data[i] = (T)0;
}

/* Various explicit constructors */
explicit inline constexpr vec_t(T X, T Y)
: x(X), y(Y) {}
@@ -243,6 +265,8 @@ struct vec_t<T,2>
vec_t<T,4,0x1110> const yyyx, gggr, ttts;
vec_t<T,4,0x1111> const yyyy, gggg, tttt;
#endif

T m_data[count];
};
};

@@ -284,6 +308,17 @@ struct vec_t<T,3>
explicit inline constexpr vec_t(vec_t<U, 3, SWIZZLE> const &v)
: x(v[0]), y(v[1]), z(v[2]) {}

/* Explicit constructor for initializer_list. We need these ugly
* loops until C++ lets us initialize m_data directly. */
explicit inline vec_t(std::initializer_list<element> const &list)
{
auto l = list.begin();
for (int i = 0; i < count && l != list.end(); ++i, ++l)
m_data[i] = *l;
for (int i = list.size(); i < count; ++i)
m_data[i] = (T)0;
}

/* Various explicit constructors */
explicit inline constexpr vec_t(T X)
: x(X), y(X), z(X) {}
@@ -467,6 +502,8 @@ struct vec_t<T,3>
vec_t<T,4,0x2221> const zzzy, bbbg, pppt;
vec_t<T,4,0x2222> const zzzz, bbbb, pppp;
#endif

T m_data[count];
};
};

@@ -509,6 +546,17 @@ struct vec_t<T,4>
explicit inline constexpr vec_t(vec_t<U, 4, SWIZZLE> const &v)
: x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}

/* Explicit constructor for initializer_list. We need these ugly
* loops until C++ lets us initialize m_data directly. */
explicit inline vec_t(std::initializer_list<element> const &list)
{
auto l = list.begin();
for (int i = 0; i < count && l != list.end(); ++i, ++l)
m_data[i] = *l;
for (int i = list.size(); i < count; ++i)
m_data[i] = (T)0;
}

/* Various explicit constructors */
explicit inline constexpr vec_t(T X)
: x(X), y(X), z(X), w(X) {}
@@ -884,6 +932,8 @@ struct vec_t<T,4>
vec_t<T,4,0x3332> const wwwz, aaab, qqqp;
vec_t<T,4,0x3333> const wwww, aaaa, qqqq;
#endif

T m_data[count];
};
};

@@ -1109,6 +1159,63 @@ static inline vec_t<T,N> radians(vec_t<T,N,SWIZZLE> const &a)
return ret;
}

/*
* C++11 iterators
*/

template<typename T, int N, int SWIZZLE>
class vec_const_iter
{
public:
inline vec_const_iter(vec_t<T,N,SWIZZLE> const &vec, int pos)
: m_pos(pos),
m_vec(vec)
{ }

inline bool operator !=(vec_const_iter<T,N,SWIZZLE> const & that) const
{
return m_pos != that.m_pos;
}

template<int S = SWIZZLE>
inline typename std::enable_if<S != -1, T const &>::type
operator *() const
{
return m_vec[m_pos];
}

template<int S = SWIZZLE>
inline typename std::enable_if<S == -1, T const &>::type
operator *() const
{
return m_vec[m_pos];
}

inline vec_const_iter<T,N,SWIZZLE> const & operator ++()
{
++m_pos;
return *this;
}

private:
int m_pos;
vec_t<T,N,SWIZZLE> const &m_vec;
};

/* FIXME: do we need a non-const iterator? Looks almost useless to me,
* and a lot of hassle with swizzling. */
template<typename T, int N, int SWIZZLE>
inline vec_const_iter<T,N,SWIZZLE> begin(vec_t<T,N,SWIZZLE> const &a)
{
return vec_const_iter<T,N,SWIZZLE>(a, 0);
}

template<typename T, int N, int SWIZZLE>
inline vec_const_iter<T,N,SWIZZLE> end(vec_t<T,N,SWIZZLE> const &a)
{
return vec_const_iter<T,N,SWIZZLE>(a, N);
}

#if !LOL_FEATURE_CXX11_CONSTEXPR
#undef constexpr
#endif


+ 66
- 0
test/unit/vector.cpp View File

@@ -96,6 +96,36 @@ LOLUNIT_FIXTURE(VectorTest)
LOLUNIT_ASSERT_LESS(a2, f2);
}

LOLUNIT_TEST(VectorInit)
{
vec2 a { 1.f, 2.f };
LOLUNIT_ASSERT_EQUAL(1.f, a.x);
LOLUNIT_ASSERT_EQUAL(2.f, a.y);

vec3 b { 1.f, 2.f, 3.f };
LOLUNIT_ASSERT_EQUAL(1.f, b.x);
LOLUNIT_ASSERT_EQUAL(2.f, b.y);
LOLUNIT_ASSERT_EQUAL(3.f, b.z);

vec4 c { 1.f, 2.f, 3.f, 4.f };
LOLUNIT_ASSERT_EQUAL(1.f, c.x);
LOLUNIT_ASSERT_EQUAL(2.f, c.y);
LOLUNIT_ASSERT_EQUAL(3.f, c.z);
LOLUNIT_ASSERT_EQUAL(4.f, c.w);

vec_t<float, 10> d { 1.f, 2.f, 3.f, 4.f, 5.f };
LOLUNIT_ASSERT_EQUAL(1.f, d[0]);
LOLUNIT_ASSERT_EQUAL(2.f, d[1]);
LOLUNIT_ASSERT_EQUAL(3.f, d[2]);
LOLUNIT_ASSERT_EQUAL(4.f, d[3]);
LOLUNIT_ASSERT_EQUAL(5.f, d[4]);
LOLUNIT_ASSERT_EQUAL(0.f, d[5]);
LOLUNIT_ASSERT_EQUAL(0.f, d[6]);
LOLUNIT_ASSERT_EQUAL(0.f, d[7]);
LOLUNIT_ASSERT_EQUAL(0.f, d[8]);
LOLUNIT_ASSERT_EQUAL(0.f, d[9]);
}

LOLUNIT_TEST(VectorSwizzle)
{
vec3 a(1.0f, 2.0f, 3.0f);
@@ -237,6 +267,42 @@ LOLUNIT_FIXTURE(VectorTest)
auto vb = v1 + v2;
LOLUNIT_ASSERT(va == vb);
}

LOLUNIT_TEST(VectorIterator)
{
vec4 v4(1.125f, 1.25f, 1.375f, 1.25f);

for (auto x : v4)
{
LOLUNIT_ASSERT_GREATER(x, 1.0f);
LOLUNIT_ASSERT_LESS(x, 1.5f);
}

for (auto &x : v4)
{
LOLUNIT_ASSERT_GREATER(x, 1.0f);
LOLUNIT_ASSERT_LESS(x, 1.5f);
}

for (auto x : v4.zywx)
{
LOLUNIT_ASSERT_GREATER(x, 1.0f);
LOLUNIT_ASSERT_LESS(x, 1.5f);
}

vec4 const &v4c = v4;
for (auto x : v4c)
{
LOLUNIT_ASSERT_GREATER(x, 1.0f);
LOLUNIT_ASSERT_LESS(x, 1.5f);
}

for (auto &x : v4c)
{
LOLUNIT_ASSERT_GREATER(x, 1.0f);
LOLUNIT_ASSERT_LESS(x, 1.5f);
}
}
};

} /* namespace lol */


Loading…
Cancel
Save