28 #ifndef VC_COMMON_INTERLEAVEDMEMORY_H_
29 #define VC_COMMON_INTERLEAVEDMEMORY_H_
33 namespace Vc_VERSIONED_NAMESPACE
40 template<
typename V,
typename I,
bool Readonly>
struct InterleavedMemoryAccessBase
45 typedef typename std::conditional<
46 Readonly,
typename std::add_const<typename V::EntryType>::type,
47 typename V::EntryType>::type T;
48 typedef typename V::AsArg VArg;
49 typedef T Ta Vc_MAY_ALIAS;
53 Vc_ALWAYS_INLINE InterleavedMemoryAccessBase(
typename I::AsArg indexes, Ta *data)
54 : m_indexes(indexes), m_data(data)
59 template <
typename... Vs> Vc_INTRINSIC
void deinterleave(Vs &&... vs)
const
65 using Impl = Vc::Detail::InterleaveImpl<V, V::Size, sizeof(V)>;
67 template <
typename T, std::size_t... Indexes>
68 Vc_INTRINSIC
void callInterleave(T &&a, index_sequence<Indexes...>)
78 template <
size_t StructSize,
typename V,
typename I =
typename V::IndexType,
80 struct InterleavedMemoryReadAccess :
public InterleavedMemoryAccessBase<V, I, Readonly>
82 typedef InterleavedMemoryAccessBase<V, I, Readonly> Base;
83 typedef typename Base::Ta Ta;
85 Vc_ALWAYS_INLINE InterleavedMemoryReadAccess(Ta *data,
typename I::AsArg indexes)
86 : Base(StructSize == 1u
94 : StructSize == 16u ? indexes << 4
95 : indexes * I(int(StructSize)),
100 template <
typename T, std::size_t... Indexes>
101 Vc_ALWAYS_INLINE T deinterleave_unpack(index_sequence<Indexes...>)
const
108 template <
typename T,
109 typename = enable_if<(std::is_default_constructible<T>::value &&
110 std::is_same<V, Traits::decay<decltype(std::get<0>(
111 std::declval<T &>()))>>::value)>>
112 Vc_ALWAYS_INLINE
operator T()
const
114 return deinterleave_unpack<T>(make_index_sequence<std::tuple_size<T>::value>());
119 template<
typename I>
struct CheckIndexesUnique
122 static Vc_INTRINSIC
void test(
const I &) {}
124 static void test(
const I &indexes)
126 const I test = indexes.sorted();
127 Vc_ASSERT(I::Size == 1 || (test == test.rotated(1)).isEmpty())
132 template<
size_t S>
struct CheckIndexesUnique<SuccessiveEntries<S> >
134 static Vc_INTRINSIC
void test(
const SuccessiveEntries<S> &) {}
140 template <
size_t StructSize,
typename V,
typename I =
typename V::IndexType>
141 struct InterleavedMemoryAccess :
public InterleavedMemoryReadAccess<StructSize, V, I, false>
143 typedef InterleavedMemoryAccessBase<V, I, false> Base;
144 typedef typename Base::Ta Ta;
146 Vc_ALWAYS_INLINE InterleavedMemoryAccess(Ta *data,
typename I::AsArg indexes)
147 : InterleavedMemoryReadAccess<StructSize, V, I, false>(data, indexes)
149 CheckIndexesUnique<I>::test(indexes);
152 template <
int N> Vc_ALWAYS_INLINE
void operator=(VectorReferenceArray<N, V> &&rhs)
154 static_assert(N <= StructSize,
155 "You_are_trying_to_scatter_more_data_into_the_struct_than_it_has");
156 this->callInterleave(std::move(rhs), make_index_sequence<N>());
158 template <
int N> Vc_ALWAYS_INLINE
void operator=(VectorReferenceArray<N, const V> &&rhs)
160 static_assert(N <= StructSize,
161 "You_are_trying_to_scatter_more_data_into_the_struct_than_it_has");
162 this->callInterleave(std::move(rhs), make_index_sequence<N>());
179 typedef typename std::conditional<std::is_const<S>::value,
180 const typename V::EntryType,
181 typename V::EntryType>::type T;
182 typedef typename V::IndexType I;
183 typedef typename V::AsArg VArg;
184 typedef const I &IndexType;
185 static constexpr std::size_t StructSize =
sizeof(S) /
sizeof(T);
186 typedef InterleavedMemoryAccess<StructSize, V> Access;
187 typedef InterleavedMemoryReadAccess<StructSize, V> ReadAccess;
188 typedef InterleavedMemoryAccess<StructSize, V, SuccessiveEntries<StructSize> > AccessSuccessiveEntries;
189 typedef InterleavedMemoryReadAccess<StructSize, V, SuccessiveEntries<StructSize> > ReadSuccessiveEntries;
190 typedef T Ta Vc_MAY_ALIAS;
193 static_assert(StructSize *
sizeof(T) ==
sizeof(S),
194 "InterleavedMemoryAccess_does_not_support_packed_structs");
203 : m_data(reinterpret_cast<Ta *>(s))
259 template <
typename IT>
260 Vc_ALWAYS_INLINE enable_if<
261 std::is_convertible<IT, IndexType>::value && !std::is_const<S>::value, Access>
264 return Access(m_data, indexes);
268 Vc_ALWAYS_INLINE ReadAccess
operator[](IndexType indexes)
const
270 return ReadAccess(m_data, indexes);
274 Vc_ALWAYS_INLINE ReadAccess
gather(IndexType indexes)
const {
return operator[](indexes); }
309 Vc_ALWAYS_INLINE ReadSuccessiveEntries
operator[](
size_t first)
const
311 return ReadSuccessiveEntries(m_data, first);
314 Vc_ALWAYS_INLINE AccessSuccessiveEntries operator[](
size_t first)
316 return AccessSuccessiveEntries(m_data, first);
323 using Common::InterleavedMemoryWrapper;
325 template <
typename V,
typename S>
326 inline Common::InterleavedMemoryWrapper<S, V> make_interleave_wrapper(S *s)
328 return Common::InterleavedMemoryWrapper<S, V>(s);
332 #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.