gslice class — Generalized slice
class gslice { public: gslice( ); gslice(size_t start, const valarray<size_t>& size, const valarray<size_t>& stride); size_t start( ) const; valarray<size_t> size( ) const; valarray<size_t> stride( ) const; };
The gslice
class describes
a generalized slice of a valarray
. A generalized slice is a subset
of the elements of a valarray
,
characterized by a starting index and a set of sizes and strides.
The size
and stride
arrays must have the same size.
Each size/stride pair denotes a set of elements at periodic indices.
The number of elements in the generalized slice is equal to the
product of the values in the size
array. The elements are taken from a valarray
at each index
i
:
i = start + Σ k
j × stride
j |
in which kj
takes all the values in
the range [0
, size
[j
]), and
j
is in the range [0
, stride.size(
)
). The highest value of j
varies fastest. With a single element in stride
and size
, gslice
is the same as plain slice
. Example 13-41 demonstrates
gslice
more clearly. Pay
particular attention to the final gslice
, where you can see how the indices
advance, first with a stride of 3 (k
1
ranges from 0 to 2), then with a stride of 2
(k
0 ranges from 0 to 3)
Example 13-41. Generalized slicing of a valarray
// Construct valarray objects from a few integers. std::valarray<std::size_t> va(std::size_t a0) { std::valarray<std::size_t> result(1); result[0] = a0; return result; } std::valarray<std::size_t> va(std::size_t a0, std::size_t a1) { std::valarray<std::size_t> result(2); result[0] = a0; result[1] = a1; return result; } int main( ) { using namespace std; valarray<int> a(24); for (size_t i = 0; i < a.size( ); ++i) a[i] = i; cout << a << '\n'; // Prints { 0 1 2 3 4 5 6 7 8 9 10 11 ... 20 21 22 23 } cout << a[slice(1, 4, 3)] << '\n'; // Prints { 1 4 7 10 } cout << a[gslice(1, va(4), va(3))] << '\n'; // Prints { 1 4 7 10 } const valarray<int> const_a(a); cout << const_a[gslice(2, va(4, 3), va(2, 3))] << '\n'; // Prints { 2 5 8 4 7 10 6 9 12 8 11 14 } }
Notice also that the final gslice
requires a const
valarray
. This is because it contains
degenerate slices, in which an element (e.g., 8) appears more than
once in the result. The aliasing rules of a valarray
prohibit multiple references to
the same element, so if a const
valarray
were not used, the
results would be undefined. By using a const
valarray
, the result is a copy of the
sliced elements, so the two occurrences of element 8 are separate
objects, not aliases for the same object, and disaster is
averted.
A generalized slice is most often used to represent a
multidimensional array. For example, you can treat a valarray
of 24 elements as a 2 × 3 × 4
matrix. To extract a plane of the matrix, you can use a gslice
. Figure 13-27 depicts the
matrix and the plane. Example
13-42 shows the code.
Example 13-42. Using gslice for multidimensional arrays
// SeeExample 13-41 for the va function. int main( ) { using namespace std; valarray<int> a(24); for (size_t i = 0; i < a.size( ); ++i) a[i] = i; cout << a[gslice(1, va(2, 3), va(12, 4))] << '\n'; // Prints: { 1 5 9 13 17 21 } }
To create an n
-dimensional submatrix of an m
-dimensional matrix, the size
and stride
arrays must both have length
n
. The size
array determines the dimensions of
the result.
Use the subscript operator to take a generalized slice of a
valarray
. You can assign a
valarray
to a generalized slice,
in which the righthand side of the assignment must have the same
size as the size of the slice. You can also convert the slice to a
valarray
, which copies only those
elements of the slice to the new valarray
.
When you take a generalized slice of a valarray
, the result is a gslice_array
object, but the gslice_array
type is mostly transparent to
the programmer. See gslice_array
later in this section for details.