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     using ReadAccess = InterleavedMemoryReadAccess<StructSize, V>;
   188         typename std::conditional<std::is_const<T>::value, ReadAccess,
   189                                   InterleavedMemoryAccess<StructSize, V>>::type;
   190     using ReadSuccessiveEntries =
   191         InterleavedMemoryReadAccess<StructSize, V, SuccessiveEntries<StructSize>>;
   192     using AccessSuccessiveEntries = 
typename std::conditional<
   193         std::is_const<T>::value, ReadSuccessiveEntries,
   194         InterleavedMemoryAccess<StructSize, V, SuccessiveEntries<StructSize>>>::type;
   195     typedef T Ta Vc_MAY_ALIAS;
   198     static_assert(StructSize * 
sizeof(T) == 
sizeof(S),
   199                   "InterleavedMemoryAccess_does_not_support_packed_structs");
   208         : m_data(reinterpret_cast<Ta *>(s))
   264     template <
typename IT>
   265     Vc_ALWAYS_INLINE enable_if<!std::is_convertible<IT, size_t>::value &&
   266                                    std::is_convertible<IT, IndexType>::value &&
   267                                    !std::is_const<S>::value,
   271         return Access(m_data, indexes);
   275     Vc_ALWAYS_INLINE ReadAccess 
operator[](IndexType indexes)
 const   277         return ReadAccess(m_data, indexes);
   281     Vc_ALWAYS_INLINE ReadAccess 
gather(IndexType indexes)
 const { 
return operator[](indexes); }
   316     Vc_ALWAYS_INLINE ReadSuccessiveEntries 
operator[](
size_t first)
 const   318         return ReadSuccessiveEntries(m_data, first);
   321     Vc_ALWAYS_INLINE AccessSuccessiveEntries operator[](
size_t first)
   323         return AccessSuccessiveEntries(m_data, first);
   344 template <
typename V, 
typename S>
   351 #endif // VC_COMMON_INTERLEAVEDMEMORY_H_ Common::InterleavedMemoryWrapper< S, V > make_interleave_wrapper(S *s)
Creates an adapter around a given array of structure (AoS) that enables optimized loads...
 
enable_if<!std::is_convertible< IT, size_t >::value &&std::is_convertible< IT, IndexType >::value &&!std::is_const< S >::value, Access > operator[](IT indexes)
Interleaved scatter/gather access. 
 
Wraps a pointer to memory with convenience functions to access it via vectors. 
 
ReadSuccessiveEntries operator[](size_t first) const
Interleaved access. 
 
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)
 
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. 
 
ReadAccess gather(IndexType indexes) const
alias of the above function