The data accessed and manipulated through the View API is actually stored in blocks. Blocks are reference-countable, allowing multiple views to share a single block. However, blocks may themselves be proxies that access their data from other blocks (possibly computing the actual values only when these values are accessed). These blocks are thus not modifiable. They aren't allocated directly by users, but rather internally during the creation of subviews, for example.
The default block type used by all views is Dense, meaning that Vector<float> is actually a shorthand notation for Vector<float, Dense<1, float> >. As such Dense is the most common block type directly used by users. Dense blocks are modifiable and allocatable. They explicitly store one value for each index in the supported domain:
// create uninitialized array of size 3 Dense<1, float> array1(Domain<1>(3)); // create array of size 3 with initial values 0.f Dense<1, float> array2(Domain<1>(3), 0.f); // assign array2 to array1 array1 = array2; // access first item float value = array1.get(0); // modify first item array1.put(0, 1.f);
Beside the two template parameters already discussed above, Dense provides an optional third parameter to specify its dimension ordering. Using this parameter you can explicitly control whether a 2-dimensional array should be stored in row-major or column-major format:
// array using row-major ordering Dense<2, float, tuple<0, 1> > rm_array; // array using column-major ordering Dense<2, float, tuple<1, 0> > cm_array;
Row-major arrays store rows as contiguous chunks of memory. Iterating over its columns will thus access close-by memory regions, reducing cache misses and thus enhancing performance:
length_type size = rm_array.size(0); for (index_type i = 0; i != size; ++i) rm_array.put(i, 1.f);
They also allow user-storage to be provided, either at construction time,
or later via a call to rebind:
float *storage = ...; // create array operating on user storage Dense<1, float> array3(Domain<1>(3), storage); // create uninitialized array... Dense<1, float> array4(Domain<1>(3)); // ...and rebind it to user-storage array4.rebind(storage);
However, special care has to be taken in these cases to synchronize the user storage with the block using it. While the storage is being used via the block it was rebound to, it has to be admitted, and released in order to be accessed directly, i.e. outside the block.
// grant exclusive access to the block array3.admit(); // modify it array3.put(0, 1.f); // force synchronization with storage array3.release(); // access storage directly assert(storage == 1.f);