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.