Chapter IV.3. Selectors

Table of Contents

IV.3.1. The selector concept
IV.3.2. Selector adaptors and items
IV.3.3. Selector geometries

A selector is capable of converting an array from a source geometry to a target geometry, while working with the same physical data in memory. Examples where this is useful include strided access, subcube extraction in datasets, matrix transposition, etc. Once a selector has been constructed, it can be used to access and/or iterate through the resulting selection.

array and array_view are special kinds of selectors which allow simple access to a block of data in memory, using the traditional 'cartesian' array indexing scheme. Other selectors are constructed by starting from an array or from an array_view, and using the template function select, which is described further down.

IV.3.1. The selector concept

The selector concept is defined by the following requirements:
typename selector::geometry_type The geometry associated to this selector.
typename selector::parameter_type The parameter needed to construct this selector.
typename selector::value_type The type of elements accessed by this selector.
typename selector::reference The reference type returned when performing non-const access.
typename selector::index_type The type used to index the elements for random access.
typename selector::global_domain_type The type of the domain specifying the bounds for the indices in global memory (MPI).
typename selector::global_index_type The type used to index the elements for random access within the global domain (MPI).
typename selector::domain_type The type of the domain specifying the bounds for the indices in local memory.
typename selector::volume_type An integer type used to represent the total number of elements in the selection.
typename selector::extents_type The type used to represent the physical extents of the data (this should become deprecated at some point and be replaced by something more elegant).
typename selector::iterator The iterator type returned by begin()/end().
selector(const parameter_type&) The constructor.
domain_type domain() const Returns the local domain.
global_domain_type global_domain() const Returns the global domain.
global_index_type corner() const Returns the global index of the first element (i.e., the beginning of the local domain with respect to the global domain).
size_t size() const Returns the number of elements accessible through this selector.
volume_type volume() const Returns the volume of data stored in this selector.
geometry_type geometry() const Returns the geometry associated with this selector.
parameter_type param() const Returns the parameter which was used to construct this selector.
parameter_type view() const Returns *this.
reference at(const index_type& pos) const Returns the element index by pos.
iterator begin() const Returns an iterator poiting to the beginning of the selection.
iterator end() const Returns an iterator poiting immediately past the end of the selection.

The main capability of a selector is to return an iterator which then allows traversal of the selected region.

IV.3.2. Selector adaptors and items

To construct selectors, the preferred mechanism is to use the select function template:

					template<BaseSelector,Item>
					typename result_of::select<BaseSelector,Item>::type 
					select(const BaseSelector & s, const Item& i);	
				

where s is an existing selector, and i is an item, that is, a small structure describing the new selection to make. For example, as we shall see in more detail below, the item could describe the stride requested when traversing the data:

					namespace cartesian {
					struct subsample_item {
						subsample_item(size_t _stride = 1) : stride(_stride) {}
						bool operator==(subsample_item o) const { return o.stride == stride ;}
						
						size_t stride;
					}; 
					}
				

An Item is required to be DefaultConstructible and EqualityComparable, and contains only publically accessible data members. Moreover, it should have a constructor which takes as sole arguments all the data members in the order in which they are declared. An item is thus entirely defined by the list of its data members, and possibly by some auxilliary typedefs.

To obtain a selector in s with a stride of 2, we would thus make the following call:

					select(s, cartesian::subsample_item(2));
				

This works provided select has been specialized for each item type, which is the case for all those that are available in the spectral array library.

To find out the actual type of the selector which is returned by select, the result_of::select class template can be used:

					namespace result_of {
						template<BaseSelector,Item>
						struct select {
							// typedef undefined-type type;
						};
					}					
				

Except array and array_view, the selector classes all derive from the selector_adaptor class template, which defines a number of common operations. In particular, it provides the following member functions and typedefs in addition to those of the Selector concept:

item_type item() const Returns a copy of the item defining the selection.
typename selector_type::base_type The type of the underlying input selector.
base_type base_type& base() Returns a reference to the underlying input selector.

In the remaining section, we describe the predefined selector/item pairs. Note that each pair consisting of a foo_selector and a foo_item is declared in a file called select_foo.hpp, which is located in one of the subdirectories of arrays. We shall characterize each item by its template parameters, and by the list of its public data members and typedefs.

IV.3.3. Selector geometries

Most of the time, one does not need to know anything about the geometry_type defined within selector classes. They are used internally