@@ -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 */ | |||