Accessor Concept
Accessor and const_accessor objects
obtained via
n_container::access()
and
n_container::const_access()
provide access to read from or
write to cells inside an
n_container
.
Syntax
The following methods return objects meeting the
requirements of the accessor concept.
auto n_container::access();
auto n_container::const_access();
auto accessor_concept::section(n_bounds_t<…>);
auto accessor_concept::translated_to(n_index_t<…>);
auto accessor_concept::translated_to_zero();
Description
Accessor objects provide read/write access to individual
cells of an n-dimensional container. Index values passed to a sequence of array
subscript operator calls will produce a proxy concept that can import to or
export the primitive data the corresponding cell inside the container.
auto image = make_n_container<MyStruct, layout::soa>(n_extent[128][256]);
auto acc = image.access();
MyStruct in_value(100.0f, 200.0f, 300.0f);
acc[64][128] = in_value;
MyStruct out_value = acc[64][128];
assert(out_value == in_value);
Accessors also know their valid iteration space, which can queried
using the template function bound_d<int DimensionT>(accessor).
assert(bounds_d<0>(acc) == bounds(0_fixed,128));
assert(bounds_d<1>(acc) == bounds(0_fixed,256));
An accessor may have a non-zero index space if it has a
translation embedded into it,
bounds_d
will reflect any such translation.
auto shifted_acc = acc.translated_to(n_index[1000][2000]);
assert(bounds_d<0>(shifted_acc) == bounds(1000,1128));
assert(bounds_d<1>(shifted_acc) == bounds(2000,2256));
This is useful to have a smaller sized container
participate in a calculation over a portion of a larger index space,
simplifying programming as the same index variable can be used, and the
accessor takes care of applying the necessary translation. An accessor may
represent a subsection over the original extents, bounds_d will identify the
valid iteration space for that accessor.
auto subsection_acc = a.section(n_bounds[bounds(64,96)][bounds(128,160)]);
assert(bounds_d<0>(subsection_acc) == bounds(64, 96));
assert(bounds_d<1>(subsection_acc) == bounds(128, 160);
It can also be useful to have subsections be translated
back to start their iteration space at 0. For efficiency, the
translated_to_zero() method is provided to create an accessor shifted back to
zero.
auto zb_sub_acc = a.section( n_bounds[bounds(64, 96)][bounds(128, 160)] ).translated_to_zero();
assert(bounds_d<0>(zb_sub_acc) == bounds(0, 32));
assert(bounds_d<1>(zb_sub_acc) == bounds(0, 32));
If fewer array subscript calls applied to an accessor
than its rank, the result is another accessor of a lower rank. This can be
useful to obtain accessors suitable to pass to code expecting lower rank
accessors. Such as a obtaining a 3d accessor from a 4d container by specifying
only a single index via array subscript. This has the effect of embedding the
index value of the dimension inside accessor. When the final dimension is
sliced, the result is a proxy object to the cell inside the container
corresponding to the embedded index values inside the sliced accessors
auto image4d = make_n_container<MyStruct, layout::soa>(n_extent[10][20][128][256]);
MyStruct in_value(100.0f, 200.0f, 300.0f);
auto acc4d = image4d.access();
auto acc3d = acc4d[5];
auto acc2d = acc3d[10];
auto acc1d = acc2d[64];
acc1d[128] = in_value;
MyStruct out_value = acc4d[5][10][64][128];
assert(out_value == in_value);
The following table provides information on the
requirements of the accessor concept.
Pseudo-Signature
| Description
|
---|---|
| Data type inside the cells of the container.
|
| Number of free dimensions of accessor
|
| Effects: constructs a copy of another accessor of the exact same
type
|
| Requirements: rank == 1 and IndexT is one of: int,
aligned<AlignmentT>, fixed<NumberT>, linear_index, or
simd_index<LaneCountT>
Effects: When only 1 free dimension is left, the operator[]
will construct an element_concept which is the proxy to the cell inside the
container. If this accessor was obtained with const_access(), then the proxy
will provide read only interface to the cell’s data.
Returns: The proxy object to cell inside the container
corresponding to the position identified by the a_index along with any embedded
index values for other dimensions
|
| Requirements: rank > 1 and IndexT is one of: int,
aligned<AlignmentT>, fixed<NumberT>, linear_index, or
simd_index<LaneCountT>
Effects: When 2 or more free dimensions are left, the
operator[] will construct another accessor_concept of lower rank embeding
a_index inside of it, effectively fixing that dimension’s index value for any
accesses made through the returned accessor_concept.
Returns: The accessor_concept of lower rank ( one less free
dimension).
|
| Requirements: DimensionT >=0 and DimensionT < rank
Effects: Determine the bounds of a free dimension using
DimensionT as a 0 based index starting at the leftmost dimension.
Returns: bounds_t of the DimensionT
|
| Requirements: XX >=0 and XX < rank and XX < 20
Effects: Non templated methods to determine the bounds of a
free dimension using XX as a 0 based index starting at the leftmost dimension.
Returns: bounds_t of the XX dimension
|
| Requirements: DimensionT >=0 and DimensionT < rank
Effects: Determine the extent of a free dimension using
DimensionT as a 0 based index starting at the leftmost dimension.
Returns: extent of the DimensionT
|
| Requirements: XX >=0 and XX < rank and XX < 20
Effects: Non templated methods to determine the extent of a
free dimension using XX as a 0 based index starting at the leftmost dimension.
Returns: extent of the XX dimension
|
| Requirements: a_n_index has same rank as the accessor
Effects: construct an accessor_concept with an embedded
translation such that accessing a_n_index will corresponds back to the current
lower bounds. Easy way to think of it is that current iteration space is
translated to a_n_index space.
Returns: accessor_concept whose bounds have the same
extents, but whose lower bounds start at the supplied a_n_index
|
| Effects: construct an accessor_concept with an embedded
translation such that accessing [0] index for all dimensions will corresponds
back to the current lower bounds. Easy way to think of it is that current
iteration space is translated to [0] for all free dimensions.
Returns: accessor_concept whose bounds have the same
extents, but whose lower bounds start [0]…[0]
|
| Requirements: a_n_bounds has same rank as the accessor and
a_n_bounds is contained by the accessors current bounds.
Effects: construct an accessor_concept with using the
supplied a_n_bounds to represent its valid iteration space. Because a_n_bounds
must be contained within the existing bounds, we are effictively creating an
accessor over a section of the container. Easy way to think of it is that
current bounds are being restricted to a_n_bounds. Note: can be useful to chain
a call
translated_to_zero() on to the return value.
Returns: accessor_concept whose bounds are
set to the supplied a_n_bounds
|