Vc  0.7.5-dev
SIMD Vector Classes for C++
InterleavedMemoryWrapper< S, V > Class Template Reference

Detailed Description

template<typename S, typename V>
class Vc::InterleavedMemoryWrapper< S, V >

Wraps a pointer to memory with convenience functions to access it via vectors.

Parameters
SThe type of the struct.
VThe type of the vector to be returned when read. This should reflect the type of the members inside the struct.
See Also
operator[]

#include <Vc/Memory>

Public Member Functions

 InterleavedMemoryWrapper (S *s)
 Constructs the wrapper object.
Access operator[] (IndexType indexes)
 Interleaved scatter/gather access.
ReadAccess operator[] (const IndexType indexes) const
 const overload (gathers only) of the above function
ReadAccess gather (const IndexType indexes) const
 alias of the above function

Constructor & Destructor Documentation

Constructs the wrapper object.

Parameters
sA pointer to a C-array.

Member Function Documentation

Access operator[] ( IndexType  indexes)

Interleaved scatter/gather access.

Assuming you have a struct of floats and a vector of indexes into the array, this function can be used to access the struct entries as vectors using the minimal number of store or load instructions.

Parameters
indexesVector of indexes that determine the gather locations.
Returns
A special (magic) object that executes the loads and deinterleave on assignment to a vector tuple.

Example:

struct Foo {
float x, y, z;
};
void fillWithBar(Foo *_data, uint_v indexes)
{
const float_v x = bar(1);
const float_v y = bar(2);
const float_v z = bar(3);
data[indexes] = (x, y, z);
// it's also possible to just store a subset at the front of the struct:
data[indexes] = (x, y);
// if you want to store a single entry, use scatter:
z.scatter(_data, &Foo::x, indexes);
}
float_v normalizeStuff(Foo *_data, uint_v indexes)
{
float_v x, y, z;
(x, y, z) = data[indexes];
// it is also possible to just load a subset from the front of the struct:
// (x, y) = data[indexes];
return Vc::sqrt(x * x + y * y + z * z);
}

You may think of the gather operation (or scatter as the inverse) like this:

             Memory: {x0 y0 z0 x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4 x5 y5 z5 x6 y6 z6 x7 y7 z7 x8 y8 z8}
            indexes: [5, 0, 1, 7]
Result in (x, y, z): ({x5 x0 x1 x7}, {y5 y0 y1 y7}, {z5 z0 z1 z7})
Warning
If indexes contains non-unique entries on scatter, the result is undefined. If NDEBUG is not defined the implementation will assert that the indexes entries are unique.