diff --git a/src/lol/math/all.h b/src/lol/math/all.h index 4b29957e..028fa0e5 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lol/math/arraynd.h b/src/lol/math/arraynd.h index 033403c0..2477e9b9 100644 --- a/src/lol/math/arraynd.h +++ b/src/lol/math/arraynd.h @@ -27,63 +27,10 @@ #include #include -namespace lol -{ - -template -class arraynd_proxy -{ -public: - - typedef arraynd_proxy subproxy; - - inline arraynd_proxy(ARRAY_TYPE * array, vec_t const & sizes, size_t index, size_t accumulator) : - m_array(array), - m_sizes(sizes), - m_index(index), - m_accumulator(accumulator) - { - } - - inline subproxy operator[](size_t pos) - { - return subproxy(m_array, this->m_sizes, m_index + pos * m_accumulator, m_accumulator * m_sizes[N - L]); - } - -private: - - ARRAY_TYPE * m_array; - vec_t const & m_sizes; - size_t m_index; - size_t m_accumulator; -}; - +#include -template -class arraynd_proxy +namespace lol { -public: - - inline arraynd_proxy(ARRAY_TYPE * array, vec_t const & sizes, size_t index, size_t accumulator) : - m_array(array), - m_sizes(sizes), - m_index(index), - m_accumulator(accumulator) - { - } - - inline typename ARRAY_TYPE::element_t & operator[](size_t pos) - { - return m_array[m_index + pos * m_accumulator]; - } - -private: - - ARRAY_TYPE * m_array; - vec_t const & m_sizes; - size_t m_index; - size_t m_accumulator; -}; template @@ -159,7 +106,6 @@ class arraynd : protected array public: typedef array super; typedef typename super::element_t element_t; - typedef arraynd_proxy proxy; inline arraynd() : super(), @@ -183,86 +129,96 @@ public: initializer.FillValues(&super::operator[](0), &m_sizes[0], 1); } - /* Access elements directly using index position */ - inline proxy operator[](size_t pos) const + /* Access elements directly using an ivec2, ivec3 etc. index */ + inline element_t const & operator[](vec_t const &pos) const { - return proxy(this, m_sizes, pos, m_sizes[0]); + size_t n = pos[N - 1]; + for (int i = N - 2; i >= 0; --i) + n = pos[i] + m_sizes[i + 1] * n; + return super::operator[](n); } - /* Resize the array. - * FIXME: data gets scrambled; should we care? */ - inline void SetSize(vec_t sizes, element_t e = element_t()) + inline element_t & operator[](vec_t const &pos) { - size_t total_size = 1; - - for (auto size : sizes) - total_size *= size; - - this->Resize(total_size, e); + return const_cast( + const_cast const&>(*this)[pos]); } - inline vec_t GetSize() const + /* Proxy to access slices */ + template + class slice { - return this->m_sizes; - } + public: + typedef slice subslice; -public: - inline element_t *Data() { return super::Data(); } - inline element_t const *Data() const { return super::Data(); } - inline int Count() const { return super::Count(); } - inline int Bytes() const { return super::Bytes(); } + inline slice(ARRAY_TYPE &array, size_t index, size_t accumulator) + : m_array(array), + m_index(index), + m_accumulator(accumulator) + { + } -private: - vec_t m_sizes; -}; + /* Accessors for the const version of the proxy */ + template::value> + inline typename std::enable_if::type + operator[](size_t pos) const + { + return subslice(m_array, m_index + pos * m_accumulator, + m_accumulator * m_array.m_sizes[N - L]); + } + template::value> + inline typename std::enable_if::type + const & operator[](size_t pos) const + { + return m_array.super::operator[](m_index + pos * m_accumulator); + } -template -class arraynd<1, T...> : protected array -{ -public: - typedef array super; - typedef typename super::element_t element_t; + /* Accessors for the non-const version of the proxy */ + template::value> + inline typename std::enable_if::type + operator[](size_t pos) + { + return subslice(m_array, m_index + pos * m_accumulator, + m_accumulator * m_array.m_sizes[N - L]); + } - inline arraynd() : - super(), - m_sizes() - { - } + template::value> + inline typename std::enable_if::type + & operator[](size_t pos) + { + return m_array.super::operator[](m_index + pos * m_accumulator); + } - inline arraynd(vec_t sizes, element_t e = element_t()) : - super(), - m_sizes(sizes) - { - SetSize(m_sizes, e); - } + private: + ARRAY_TYPE &m_array; + size_t m_index, m_accumulator; + }; - inline arraynd(std::initializer_list initializer) : - super(), - m_sizes() + /* Access addressable slices, allowing for array[i][j][...] syntax. */ + inline slice const> operator[](size_t pos) const { - m_sizes[0] = initializer.size(); - SetSize(m_sizes[0]); - - size_t pos = 0; - for (auto element : initializer) - (*this)[pos++] = element; + return slice const>(*this, pos, m_sizes[0]); } - /* Access elements directly using index position */ - inline element_t & operator[](size_t pos) const + inline slice> operator[](size_t pos) { - return super::operator[](pos); + return slice>(*this, pos, m_sizes[0]); } /* Resize the array. * FIXME: data gets scrambled; should we care? */ - inline void SetSize(vec_t sizes, element_t e = element_t()) + inline void SetSize(vec_t sizes, element_t e = element_t()) { - this->Resize(m_sizes[0], e); + size_t total_size = 1; + + for (auto size : sizes) + total_size *= size; + + this->Resize(total_size, e); } - inline vec_t GetSize() const + inline vec_t GetSize() const { return this->m_sizes; } @@ -274,7 +230,7 @@ public: inline int Bytes() const { return super::Bytes(); } private: - vec_t m_sizes; + vec_t m_sizes; }; } /* namespace lol */ diff --git a/test/unit/arraynd.cpp b/test/unit/arraynd.cpp index 590c4bbb..a84133e1 100644 --- a/test/unit/arraynd.cpp +++ b/test/unit/arraynd.cpp @@ -24,7 +24,21 @@ LOLUNIT_FIXTURE(ArrayNDTest) void TearDown() {} -#if 0 + LOLUNIT_TEST(Array2D) + { + arraynd<2, int> a; + a.SetSize(vec_t(1, 2)); + + a[0][0] = 1; + a[0][1] = 2; + LOLUNIT_ASSERT_EQUAL(a[0][0], 1); + LOLUNIT_ASSERT_EQUAL(a[0][1], 2); + + arraynd<2, int> const &b = a; + LOLUNIT_ASSERT_EQUAL(b[0][0], 1); + LOLUNIT_ASSERT_EQUAL(b[0][1], 2); + } + LOLUNIT_TEST(ArrayNDCreate) { arraynd<10, int> a; @@ -35,23 +49,26 @@ LOLUNIT_FIXTURE(ArrayNDTest) LOLUNIT_TEST(ArrayNDInit) { - int const dimension = 8; - vec_t size; - for (int i = 0; i < dimension; ++i) + int const NDIM = 8; + vec_t size; + for (int i = 0; i < NDIM; ++i) size[i] = 5; - arraynd a(size); + arraynd a(size); memset(a.Data(), 0, a.Bytes()); LOLUNIT_ASSERT_EQUAL(a[2][3][2][0][1][4][0][1], 0x00); - vec_t v{ 2, 3, 2, 0, 1, 4, 0, 1 }; + vec_t v = { 2, 3, 2, 0, 1, 4, 0, 1 }; LOLUNIT_ASSERT_EQUAL(a[v], 0x00); a[2][3][2][0][1][4][0][1] = 0xcd; LOLUNIT_ASSERT_EQUAL(a[2][3][2][0][1][4][0][1], 0xcd); LOLUNIT_ASSERT_EQUAL(a[v], 0xcd); + + arraynd const &b = a; + LOLUNIT_ASSERT_EQUAL(b[2][3][2][0][1][4][0][1], 0xcd); + LOLUNIT_ASSERT_EQUAL(b[v], 0xcd); } -#endif }; } /* namespace lol */