From cc5c21c34b3d9b16f2bf43ac39a1a500a2f1c0a7 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 15 Jul 2014 12:46:32 +0000 Subject: [PATCH] math: add iterators and initializer_list constructors to vec_t. --- src/lol/math/vector.h | 111 +++++++++++++++++++++++++++++++++++++++++- test/unit/vector.cpp | 66 +++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index 6c3b5466..31529fa0 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -54,7 +54,7 @@ namespace lol template struct vec_t - /* MUST be a different base than e.g. vec_t otherwise the unions + /* MUST have a different base than e.g. vec_t otherwise the unions * in vec_t with the same base will cause empty base optimisation * failures. */ : public swizzle_ops::base @@ -128,6 +128,17 @@ struct vec_t 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 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 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 explicit inline constexpr vec_t(vec_t 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 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 vec_t const yyyx, gggr, ttts; vec_t const yyyy, gggg, tttt; #endif + + T m_data[count]; }; }; @@ -284,6 +308,17 @@ struct vec_t explicit inline constexpr vec_t(vec_t 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 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 vec_t const zzzy, bbbg, pppt; vec_t const zzzz, bbbb, pppp; #endif + + T m_data[count]; }; }; @@ -509,6 +546,17 @@ struct vec_t explicit inline constexpr vec_t(vec_t 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 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 vec_t const wwwz, aaab, qqqp; vec_t const wwww, aaaa, qqqq; #endif + + T m_data[count]; }; }; @@ -1109,6 +1159,63 @@ static inline vec_t radians(vec_t const &a) return ret; } +/* + * C++11 iterators + */ + +template +class vec_const_iter +{ +public: + inline vec_const_iter(vec_t const &vec, int pos) + : m_pos(pos), + m_vec(vec) + { } + + inline bool operator !=(vec_const_iter const & that) const + { + return m_pos != that.m_pos; + } + + template + inline typename std::enable_if::type + operator *() const + { + return m_vec[m_pos]; + } + + template + inline typename std::enable_if::type + operator *() const + { + return m_vec[m_pos]; + } + + inline vec_const_iter const & operator ++() + { + ++m_pos; + return *this; + } + +private: + int m_pos; + vec_t const &m_vec; +}; + +/* FIXME: do we need a non-const iterator? Looks almost useless to me, + * and a lot of hassle with swizzling. */ +template +inline vec_const_iter begin(vec_t const &a) +{ + return vec_const_iter(a, 0); +} + +template +inline vec_const_iter end(vec_t const &a) +{ + return vec_const_iter(a, N); +} + #if !LOL_FEATURE_CXX11_CONSTEXPR #undef constexpr #endif diff --git a/test/unit/vector.cpp b/test/unit/vector.cpp index c0269f5c..cfa75f0c 100644 --- a/test/unit/vector.cpp +++ b/test/unit/vector.cpp @@ -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 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 */