29 #ifndef VC_COMMON_INTERLEAVEDMEMORY_H_
30 #define VC_COMMON_INTERLEAVEDMEMORY_H_
34 namespace Vc_VERSIONED_NAMESPACE
41 template<
typename V,
typename I,
bool Readonly>
struct InterleavedMemoryAccessBase
46 typedef typename std::conditional<
47 Readonly,
typename std::add_const<typename V::EntryType>::type,
48 typename V::EntryType>::type T;
49 typedef typename V::AsArg VArg;
50 typedef T Ta Vc_MAY_ALIAS;
54 Vc_ALWAYS_INLINE InterleavedMemoryAccessBase(
typename I::AsArg indexes, Ta *data)
55 : m_indexes(indexes), m_data(data)
62 inline void deinterleave(V &v0, V &v1, V &v2, V &v3)
const;
63 inline void deinterleave(V &v0, V &v1, V &v2, V &v3, V &v4)
const;
64 inline void deinterleave(V &v0, V &v1, V &v2, V &v3, V &v4, V &v5)
const;
65 inline void deinterleave(V &v0, V &v1, V &v2, V &v3, V &v4, V &v5, V &v6)
const;
66 inline void deinterleave(V &v0, V &v1, V &v2, V &v3, V &v4, V &v5, V &v6, V &v7)
const;
69 inline void interleave(VArg v0, VArg v1, VArg v2);
70 inline void interleave(VArg v0, VArg v1, VArg v2, VArg v3);
71 inline void interleave(VArg v0, VArg v1, VArg v2, VArg v3, VArg v4);
72 inline void interleave(VArg v0, VArg v1, VArg v2, VArg v3, VArg v4, VArg v5);
73 inline void interleave(VArg v0, VArg v1, VArg v2, VArg v3, VArg v4, VArg v5, VArg v6);
74 inline void interleave(VArg v0, VArg v1, VArg v2, VArg v3, VArg v4, VArg v5, VArg v6, VArg v7);
77 template <
typename T, std::size_t... Indexes>
78 Vc_INTRINSIC
void callInterleave(T &&a, index_sequence<Indexes...>)
88 template <
size_t StructSize,
typename V,
typename I =
typename V::IndexType,
90 struct InterleavedMemoryReadAccess :
public InterleavedMemoryAccessBase<V, I, Readonly>
92 typedef InterleavedMemoryAccessBase<V, I, Readonly> Base;
93 typedef typename Base::Ta Ta;
95 Vc_ALWAYS_INLINE InterleavedMemoryReadAccess(Ta *data,
typename I::AsArg indexes)
97 StructSize == 1 ? indexes : StructSize == 2
105 : indexes * I(StructSize),
110 template <
typename T, std::size_t... Indexes>
111 Vc_ALWAYS_INLINE T deinterleave_unpack(index_sequence<Indexes...>)
const
118 template <
typename T,
119 typename = enable_if<(std::is_default_constructible<T>::value &&
120 std::is_same<V, Traits::decay<decltype(std::get<0>(
121 std::declval<T &>()))>>::value)>>
122 Vc_ALWAYS_INLINE
operator T()
const
124 return deinterleave_unpack<T>(make_index_sequence<std::tuple_size<T>::value>());
129 template<
typename I>
struct CheckIndexesUnique
132 static Vc_INTRINSIC
void test(
const I &) {}
134 static void test(
const I &indexes)
136 const I test = indexes.sorted();
137 Vc_ASSERT(I::Size == 1 || (test == test.rotated(1)).isEmpty())
142 template<
size_t S>
struct CheckIndexesUnique<SuccessiveEntries<S> >
144 static Vc_INTRINSIC
void test(
const SuccessiveEntries<S> &) {}
150 template <
size_t StructSize,
typename V,
typename I =
typename V::IndexType>
151 struct InterleavedMemoryAccess :
public InterleavedMemoryReadAccess<StructSize, V, I, false>
153 typedef InterleavedMemoryAccessBase<V, I, false> Base;
154 typedef typename Base::Ta Ta;
156 Vc_ALWAYS_INLINE InterleavedMemoryAccess(Ta *data,
typename I::AsArg indexes)
157 : InterleavedMemoryReadAccess<StructSize, V, I, false>(data, indexes)
159 CheckIndexesUnique<I>::test(indexes);
162 template <
int N> Vc_ALWAYS_INLINE
void operator=(VectorReferenceArray<N, V> &&rhs)
164 static_assert(N <= StructSize,
165 "You_are_trying_to_scatter_more_data_into_the_struct_than_it_has");
166 this->callInterleave(std::move(rhs), make_index_sequence<N>());
168 template <
int N> Vc_ALWAYS_INLINE
void operator=(VectorReferenceArray<N, const V> &&rhs)
170 static_assert(N <= StructSize,
171 "You_are_trying_to_scatter_more_data_into_the_struct_than_it_has");
172 this->callInterleave(std::move(rhs), make_index_sequence<N>());
189 typedef typename std::conditional<std::is_const<S>::value,
190 const typename V::EntryType,
191 typename V::EntryType>::type T;
192 typedef typename V::IndexType I;
193 typedef typename V::AsArg VArg;
194 typedef const I &IndexType;
195 static constexpr std::size_t StructSize =
sizeof(S) /
sizeof(T);
196 typedef InterleavedMemoryAccess<StructSize, V> Access;
197 typedef InterleavedMemoryReadAccess<StructSize, V> ReadAccess;
198 typedef InterleavedMemoryAccess<StructSize, V, SuccessiveEntries<StructSize> > AccessSuccessiveEntries;
199 typedef InterleavedMemoryReadAccess<StructSize, V, SuccessiveEntries<StructSize> > ReadSuccessiveEntries;
200 typedef T Ta Vc_MAY_ALIAS;
203 static_assert(StructSize *
sizeof(T) ==
sizeof(S),
204 "InterleavedMemoryAccess_does_not_support_packed_structs");
213 : m_data(reinterpret_cast<Ta *>(s))
269 template <
typename IT>
270 Vc_ALWAYS_INLINE enable_if<
271 std::is_convertible<IT, IndexType>::value && !std::is_const<S>::value, Access>
274 return Access(m_data, indexes);
278 Vc_ALWAYS_INLINE ReadAccess
operator[](IndexType indexes)
const
280 return ReadAccess(m_data, indexes);
284 Vc_ALWAYS_INLINE ReadAccess
gather(IndexType indexes)
const {
return operator[](indexes); }
319 Vc_ALWAYS_INLINE ReadSuccessiveEntries
operator[](
size_t first)
const
321 return ReadSuccessiveEntries(m_data, first);
324 Vc_ALWAYS_INLINE AccessSuccessiveEntries operator[](
size_t first)
326 return AccessSuccessiveEntries(m_data, first);
333 using Common::InterleavedMemoryWrapper;
335 template <
typename V,
typename S>
336 inline Common::InterleavedMemoryWrapper<S, V> make_interleave_wrapper(S *s)
338 return Common::InterleavedMemoryWrapper<S, V>(s);
342 #endif // VC_COMMON_INTERLEAVEDMEMORY_H_
Wraps a pointer to memory with convenience functions to access it via vectors.
ReadAccess operator[](IndexType indexes) const
const overload (gathers only) of the above function
InterleavedMemoryWrapper(S *s)
Constructs the wrapper object.
void deinterleave(V *a, V *b, const M *memory, A align)
ReadAccess gather(IndexType indexes) const
alias of the above function
enable_if< std::is_convertible< IT, IndexType >::value &&!std::is_const< S >::value, Access > operator[](IT indexes)
Interleaved scatter/gather access.
std::pair< V, V > interleave(const V &a, const V &b)
Interleaves the entries from a and b into two vectors of the same type.
ReadSuccessiveEntries operator[](size_t first) const
Interleaved access.