// BlockyFroggy
// Copyright © 2017 John Ryland.
// All rights reserved.
#pragma once
#ifndef SoA_AoS_h
#define SoA_AoS_h
#include <cstdlib>
#define DECLARE_STRUCT_BEGIN(StructName) \
template <size_t SIZE> \
class StructName \
{ \
public:
#define DECLARE_MEMBER2(t, name) \
t name[SIZE];
#define DECLARE_STRUCT_END(StructName) \
const size_t s_size = SIZE; \
};
/*
template <typename T>
struct ArrayAccessor
{
explicit ArrayAccessor(std::function<T&(size_t)> func) : m_getter(func) {}
inline T& operator[](std::size_t idx) {
return m_getter(idx);
}
std::function<T&(size_t)> m_getter;
};
#define VAR(a, m) \
var(&decltype(a)::TYPE::m)
*/
#define MEMBER(v, m) \
v.var(&decltype(v)::TYPE::m)
template <template<size_t> class t, size_t SIZE>
struct SOA
{
template <template<size_t> class t2, size_t SIZE2>
struct MemberAccessor
{
typedef t2<SIZE2> TYPE;
template <typename T>
T& var(T (TYPE::*memberPtr)[SIZE])
{
return (m_this->m_array[0].*memberPtr)[m_idx];
}
size_t m_idx;
SOA<t2,SIZE2>* m_this;
};
inline MemberAccessor<t,SIZE> operator[](std::size_t idx) {
return MemberAccessor<t,SIZE>{idx, this};
}
/*
template <typename T>
ArrayAccessor<T> get(T (TYPE::*memberPtr)[SIZE]) {
return ArrayAccessor<T>([this, memberPtr](size_t idx)->T& { return (m_array[0].*memberPtr)[idx]; });
}
template <typename T, T (TYPE::*memberPtr)[SIZE]>
ArrayAccessor<T> test() {
return ArrayAccessor<T>([&](size_t idx)->T& { return (m_array[0].*memberPtr)[idx]; });
}
*/
t<SIZE> m_array[1];
};
template <template<size_t> class t, size_t SIZE>
struct AOS
{
template <template<size_t> class t2, size_t SIZE2>
struct MemberAccessor
{
typedef t2<1> TYPE;
template <typename T>
T& var(T (t2<1>::*memberPtr)[1])
{
return (m_this->m_array[m_idx].*memberPtr)[0];
}
size_t m_idx;
AOS<t2,SIZE2>* m_this;
};
inline MemberAccessor<t,SIZE> operator[](std::size_t idx) {
return MemberAccessor<t,SIZE>{idx, this};
}
/*
typedef t<1> TYPE;
template <typename T>
ArrayAccessor<T> get(T (t<1>::*memberPtr)[1]) {
return ArrayAccessor<T>([this, memberPtr](size_t idx)->T& { return (m_array[idx].*memberPtr)[0]; });
}
*/
t<1> m_array[SIZE];
};
#define ARRAY_GET(array, idx, member) \
array.get(&std::remove_reference<decltype(array.m_array[0])>::type::member) idx
#define ARRAY_MEMBER(array, member) \
array.get(&std::remove_reference<decltype(array.m_array[0])>::type::member)
#define MAKE_AOS(array, S, SIZE) \
S<1> array[SIZE]; \
const bool array##_isSOA = false;
#define MAKE_SOA(array, S, SIZE) \
S<SIZE> array[1]; \
const bool array##_isSOA = true;
#define GET(array, a, n) \
((array##_isSOA) ? array[0].a[n] : array[n].a[0])
#endif // SoA_AoS_h