| @@ -0,0 +1,18 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||
| // | |||
| // Lol Engine is free software. It comes without any warranty, to | |||
| // the extent permitted by applicable law. You can redistribute it | |||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||
| // See http://www.wtfpl.net/ for more details. | |||
| // | |||
| #pragma once | |||
| #include "private/push_macros.h" | |||
| #include "private/base/narray.h" | |||
| #include "private/pop_macros.h" | |||
| @@ -0,0 +1,141 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||
| // | |||
| // Lol Engine is free software. It comes without any warranty, to | |||
| // the extent permitted by applicable law. You can redistribute it | |||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||
| // See http://www.wtfpl.net/ for more details. | |||
| // | |||
| #pragma once | |||
| // | |||
| // The narray class | |||
| // ———————————————— | |||
| // An N-dimensional row-major array template class | |||
| // | |||
| #include <lol/vector> // lol::vec_t | |||
| #include <vector> // std::vector | |||
| namespace lol | |||
| { | |||
| template<typename T, size_t N> | |||
| class [[nodiscard]] narray | |||
| { | |||
| public: | |||
| typedef T value_type; | |||
| inline narray() = default; | |||
| inline ~narray() = default; | |||
| // Construct array with args: size1, size2, ..., sizen | |||
| template<typename... I> inline narray(I... sizes) | |||
| { | |||
| static_assert(N == sizeof...(I)); | |||
| resize(sizes...); | |||
| } | |||
| // Construct array with integer vec_t arg: | |||
| inline narray(vec_t<int, N> const &sizes) | |||
| { | |||
| resize(sizes); | |||
| } | |||
| // Empty array | |||
| inline void clear() { resize(vec_t<size_t, N>(0)); } | |||
| // Access element i | |||
| inline value_type &operator[](size_t i) | |||
| { | |||
| return m_data[i]; | |||
| } | |||
| inline value_type const &operator[](size_t i) const | |||
| { | |||
| return m_data[i]; | |||
| } | |||
| // Access element (i, j, .., z) in row-major fashion | |||
| template<typename... I> | |||
| inline value_type &operator()(I... indices) | |||
| { | |||
| static_assert(N == sizeof...(I)); | |||
| return m_data[offset(indices...)]; | |||
| } | |||
| template<typename... I> | |||
| inline value_type const &operator()(I... indices) const | |||
| { | |||
| static_assert(N == sizeof...(I)); | |||
| return m_data[offset(indices...)]; | |||
| } | |||
| inline value_type &operator()(vec_t<int, N> const &indices) | |||
| { | |||
| return m_data[offset_helper(indices, std::make_index_sequence<N>{})]; | |||
| } | |||
| inline value_type const &operator()(vec_t<int, N> const &indices) const | |||
| { | |||
| return m_data[offset_helper(indices, std::make_index_sequence<N>{})]; | |||
| } | |||
| // Resize array with a list of sizes (size1, size2, ..., sizen) | |||
| template<typename... I> | |||
| inline void resize(I... sizes) | |||
| { | |||
| static_assert(N == sizeof...(I)); | |||
| m_data.resize((size_t(sizes) * ... * 1)); | |||
| m_sizes = { size_t(sizes)... }; | |||
| } | |||
| inline void resize(vec_t<int, N> const &sizes) | |||
| { | |||
| resize_helper(sizes, std::make_index_sequence<N>{}); | |||
| } | |||
| // Return sizes of each dimension | |||
| inline vec_t<int, N> sizes() const | |||
| { | |||
| return vec_t<int, N>(this->m_sizes); | |||
| } | |||
| inline value_type *data() { return m_data.data(); } | |||
| inline value_type const *data() const { return m_data.data(); } | |||
| inline size_t size() const { return m_data.size(); } | |||
| inline size_t bytes() const { return size() * sizeof(value_type); } | |||
| private: | |||
| template<typename... I> size_t offset(size_t i, I... indices) const | |||
| { | |||
| if constexpr(sizeof...(I) > 0) | |||
| i += m_sizes[N - sizeof...(I) - 1] * offset(indices...); | |||
| return i; | |||
| } | |||
| template <std::size_t... I> | |||
| size_t offset_helper(vec_t<int, N> const &sizes, std::index_sequence<I...>) const | |||
| { | |||
| return offset(size_t(sizes[I])...); | |||
| } | |||
| template <std::size_t... I> | |||
| void resize_helper(vec_t<int, N> const &sizes, std::index_sequence<I...>) | |||
| { | |||
| resize(sizes[I]...); | |||
| } | |||
| vec_t<size_t, N> m_sizes { 0 }; | |||
| std::vector<T> m_data; | |||
| }; | |||
| template<typename T> using array2d = narray<T, 2>; | |||
| template<typename T> using array3d = narray<T, 3>; | |||
| } // namespace lol | |||
| @@ -15,8 +15,8 @@ | |||
| #pragma once | |||
| // | |||
| // The arraynd class | |||
| // ----------------- | |||
| // The old_arraynd class | |||
| // ————————————————————— | |||
| // A N-Dimensional array class allowing var[i][j][k]... indexing, | |||
| // | |||
| @@ -31,11 +31,11 @@ namespace lol | |||
| { | |||
| template<typename T, int L> | |||
| class arraynd_initializer | |||
| class old_arraynd_initializer | |||
| { | |||
| public: | |||
| arraynd_initializer(std::initializer_list<arraynd_initializer<T, L - 1> > const & initializers) : | |||
| old_arraynd_initializer(std::initializer_list<old_arraynd_initializer<T, L - 1> > const & initializers) : | |||
| m_initializers(initializers) | |||
| { | |||
| } | |||
| @@ -58,16 +58,16 @@ public: | |||
| private: | |||
| std::initializer_list<arraynd_initializer<T, L - 1> > const & m_initializers; | |||
| std::initializer_list<old_arraynd_initializer<T, L - 1> > const & m_initializers; | |||
| }; | |||
| template<typename T> | |||
| class arraynd_initializer<T, 1> | |||
| class old_arraynd_initializer<T, 1> | |||
| { | |||
| public: | |||
| arraynd_initializer(std::initializer_list<T> const & initializers) : | |||
| old_arraynd_initializer(std::initializer_list<T> const & initializers) : | |||
| m_initializers(initializers) | |||
| { | |||
| } | |||
| @@ -92,14 +92,14 @@ private: | |||
| template<int N, typename T> | |||
| class [[nodiscard]] arraynd | |||
| class [[nodiscard]] old_arraynd | |||
| { | |||
| public: | |||
| typedef T element_t; | |||
| inline arraynd() = default; | |||
| inline old_arraynd() = default; | |||
| inline arraynd(vec_t<size_t, N> sizes, element_t e = element_t()) | |||
| inline old_arraynd(vec_t<size_t, N> sizes, element_t e = element_t()) | |||
| : m_sizes(sizes) | |||
| { | |||
| resize_data(e); | |||
| @@ -107,13 +107,13 @@ public: | |||
| /* Additional constructor if size_t != int */ | |||
| template<typename T2 = int, typename T3 = typename std::enable_if<!std::is_same<size_t, T2>::value, int>::type> | |||
| inline arraynd(vec_t<T2, N> sizes, element_t e = element_t()) | |||
| inline old_arraynd(vec_t<T2, N> sizes, element_t e = element_t()) | |||
| : m_sizes(vec_t<size_t, N>(sizes)) | |||
| { | |||
| resize_data(e); | |||
| } | |||
| inline arraynd(std::initializer_list<arraynd_initializer<element_t, N - 1> > initializer) | |||
| inline old_arraynd(std::initializer_list<old_arraynd_initializer<element_t, N - 1> > initializer) | |||
| { | |||
| m_sizes[N - 1] = initializer.size(); | |||
| @@ -140,7 +140,7 @@ public: | |||
| inline element_t & operator[](vec_t<size_t, N> const &pos) | |||
| { | |||
| return const_cast<element_t &>( | |||
| const_cast<arraynd<N, T> const&>(*this)[pos]); | |||
| const_cast<old_arraynd<N, T> const&>(*this)[pos]); | |||
| } | |||
| /* If int != size_t, access elements directly using an ivec2, | |||
| @@ -158,7 +158,7 @@ public: | |||
| inline element_t & operator[](vec_t<T2, N> const &pos) | |||
| { | |||
| return const_cast<element_t &>( | |||
| const_cast<arraynd<N, T> const&>(*this)[pos]); | |||
| const_cast<old_arraynd<N, T> const&>(*this)[pos]); | |||
| } | |||
| /* Proxy to access slices */ | |||
| @@ -213,14 +213,14 @@ public: | |||
| }; | |||
| /* Access addressable slices, allowing for array[i][j][...] syntax. */ | |||
| inline slice<arraynd<N, T> const> operator[](size_t pos) const | |||
| inline slice<old_arraynd<N, T> const> operator[](size_t pos) const | |||
| { | |||
| return slice<arraynd<N, T> const>(*this, pos, m_sizes[0]); | |||
| return slice<old_arraynd<N, T> const>(*this, pos, m_sizes[0]); | |||
| } | |||
| inline slice<arraynd<N, T>> operator[](size_t pos) | |||
| inline slice<old_arraynd<N, T>> operator[](size_t pos) | |||
| { | |||
| return slice<arraynd<N, T>>(*this, pos, m_sizes[0]); | |||
| return slice<old_arraynd<N, T>>(*this, pos, m_sizes[0]); | |||
| } | |||
| /* Resize the array. | |||
| @@ -266,8 +266,8 @@ private: | |||
| vec_t<size_t, N> m_sizes { 0 }; | |||
| }; | |||
| template<typename T> using array2d = arraynd<2, T>; | |||
| template<typename T> using array3d = arraynd<3, T>; | |||
| template<typename T> using old_array2d = old_arraynd<2, T>; | |||
| template<typename T> using old_array3d = old_arraynd<3, T>; | |||
| } /* namespace lol */ | |||