Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
local clone.
std.experimental.ndslice.selection
This is a submodule of std.experimental.ndslice.
Selectors create new views and iteration patterns over the same data, without copying.
Subspace selectors
Subspace selectors serve to generalize and combine other selectors easily. For a slice of Slice!(N, Range) type slice.pack!K creates a slice of slices of Slice!(N-K, Slice!(K+1, Range)) type by packing the last K dimensions of the top dimension pack, and the type of element of slice.byElement is Slice!(K, Range). Another way to use pack is transposition of dimension packs using evertPack. Examples of use of subspace selectors are available for selectors, Slice.shape , and Slice.elementsCount .Function Name | Description |
---|---|
pack | returns slice of slices |
unpack | merges all dimension packs |
evertPack | reverses dimension packs |
Function Name | Description |
---|---|
byElement | a random access range of all elements with index property |
byElementInStandardSimplex | an input range of all elements in standard simplex of hypercube with index property. If the slice has two dimensions, it is a range of all elements of upper left triangular matrix. |
indexSlice | returns a slice with elements equal to the initial index |
reshape | returns a new slice for the same data |
diagonal | 1-dimensional slice composed of diagonal elements |
blocks | n-dimensional slice composed of n-dimensional non-overlapping blocks. If the slice has two dimensions, it is a block matrix. |
windows | n-dimensional slice of n-dimensional overlapping windows. If the slice has two dimensions, it is a sliding window. |
License:
Authors:
Ilya Yaroshenko
- template pack(K...)
- Creates a packed slice, i.e. slice of slices. The function does not carry out any calculations, it simply returns the same binary data presented differently.Parameters:
K sizes of dimension packs Returns:Examples:import std.experimental.ndslice.slice; import std.range.primitives: ElementType; import std.range: iota; import std.algorithm.comparison: equal; auto r = 100000000.iota; auto a = r.sliced(3, 4, 5, 6, 7, 8, 9, 10, 11); auto b = a.pack!(2, 3); // same as `a.pack!2.pack!3` auto c = b[1, 2, 3, 4]; auto d = c[5, 6, 7]; auto e = d[8, 9]; auto g = a[1, 2, 3, 4, 5, 6, 7, 8, 9]; assert(e == g); assert(a == b); assert(c == a[1, 2, 3, 4]); alias R = typeof(r); static assert(is(typeof(b) == typeof(a.pack!2.pack!3))); static assert(is(typeof(b) == Slice!(4, Slice!(4, Slice!(3, R))))); static assert(is(typeof(c) == Slice!(3, Slice!(3, R)))); static assert(is(typeof(d) == Slice!(2, R))); static assert(is(typeof(e) == ElementType!R));
- Slice!(N, Range).PureThis unpack(size_t N, Range)(auto ref Slice!(N, Range) slice);
- Unpacks a packed slice.The function does not carry out any calculations, it simply returns the same binary data presented differently.Parameters:
Slice!(N, Range) slice packed slice Returns:unpacked sliceExamples:import std.experimental.ndslice.slice; import std.range: iota; import std.algorithm.comparison: equal; auto r = 100000000.iota; auto a = r.sliced(3, 4, 5, 6, 7, 8, 9, 10, 11); auto b = a.pack!(2, 3).unpack(); static assert(is(typeof(a) == typeof(b))); assert(a == b);
- SliceFromSeq!(Slice!(N, Range).PureRange, NSeqEvert!(Slice!(N, Range).NSeq)) evertPack(size_t N, Range)(auto ref Slice!(N, Range) slice);
- Reverses the order of dimension packs. This function is used in a functional pipeline with other selectors.Parameters:
Slice!(N, Range) slice packed slice Returns:packed sliceExamples:import std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: transposed; import std.range: iota; auto slice = 100000000.iota.sliced(3, 4, 5, 6, 7, 8, 9, 10, 11); assert(slice .pack!2 .evertPack .unpack == slice.transposed!( slice.shape.length-2, slice.shape.length-1));
Examples:import std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: transposed; import std.range.primitives: ElementType; import std.range: iota; import std.algorithm.comparison: equal; auto r = 100000000.iota; auto a = r.sliced(3, 4, 5, 6, 7, 8, 9, 10, 11); auto b = a .pack!(2, 3) .evertPack; auto c = b[8, 9]; auto d = c[5, 6, 7]; auto e = d[1, 2, 3, 4]; auto g = a[1, 2, 3, 4, 5, 6, 7, 8, 9]; assert(e == g); assert(a == b.evertPack); assert(c == a.transposed!(7, 8, 4, 5, 6)[8, 9]); alias R = typeof(r); static assert(is(typeof(b) == Slice!(2, Slice!(4, Slice!(5, R))))); static assert(is(typeof(c) == Slice!(3, Slice!(5, R)))); static assert(is(typeof(d) == Slice!(4, R))); static assert(is(typeof(e) == ElementType!R));
- Slice!(1, Range) diagonal(size_t N, Range)(auto ref Slice!(N, Range) slice);
- Returns a 1-dimensional slice over the main diagonal of an n-dimensional slice. diagonal can be generalized with other selectors such as blocks (diagonal blocks) and windows (multi-diagonal slice).Parameters:
N dimension count Slice!(N, Range) slice input slice Returns:packed 1-dimensional composed of N-dimensional slicesExamples:Examples:dittoimport std.experimental.ndslice.slice; auto slice = new int[9].sliced(3, 3); int i; foreach (ref e; slice.diagonal) e = ++i; assert(slice == [ [1, 0, 0], [0, 2, 0], [0, 0, 3]]);
Examples:Matrix, subdiagonalimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: dropOne; import std.algorithm.comparison: equal; import std.range: iota, only; // ------- // | 0 1 2 | // | 3 4 5 | // ------- //-> // | 1 5 | assert(10.iota .sliced(2, 3) .dropOne!1 .diagonal .equal(only(1, 5)));
Examples:Matrix, antidiagonalimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: dropToHypercube, reversed; import std.algorithm.comparison: equal; import std.range: iota, only; // ------- // | 0 1 2 | // | 3 4 5 | // ------- //-> // | 1 3 | assert(10.iota .sliced(2, 3) .dropToHypercube .reversed!1 .diagonal .equal(only(1, 3)));
Examples:3D, main diagonalimport std.experimental.ndslice.slice; import std.algorithm.comparison: equal; import std.range: iota, only; // ----------- // | 0 1 2 | // | 3 4 5 | // - - - - - - // | 6 7 8 | // | 9 10 11 | // ----------- //-> // | 0 10 | assert(100.iota .sliced(2, 2, 3) .diagonal .equal(only(0, 10)));
Examples:3D, subdiagonalimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: dropOne; import std.algorithm.comparison: equal; import std.range: iota, only; // ----------- // | 0 1 2 | // | 3 4 5 | // - - - - - - // | 6 7 8 | // | 9 10 11 | // ----------- //-> // | 1 11 | assert(100.iota .sliced(2, 2, 3) .dropOne!2 .diagonal .equal(only(1, 11)));
Examples:3D, diagonal plainimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: dropOne; import std.algorithm.comparison: equal; import std.range: iota; // ----------- // | 0 1 2 | // | 3 4 5 | // | 6 7 8 | // - - - - - - // | 9 10 11 | // | 12 13 14 | // | 15 16 17 | // - - - - - - // | 18 20 21 | // | 22 23 24 | // | 24 25 26 | // ----------- //-> // ----------- // | 0 4 8 | // | 9 13 17 | // | 18 23 26 | // ----------- auto slice = 100.iota .sliced(3, 3, 3) .pack!2 .evertPack .diagonal .evertPack; assert(slice == [[ 0, 4, 8], [ 9, 13, 17], [18, 22, 26]]);
- Slice!(N, Slice!(N + 1, Range)) blocks(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) if (allSatisfy!(isIndex, Lengths) && Lengths.length == N);
- Returns an n-dimensional slice of n-dimensional non-overlapping blocks. blocks can be generalized with other selectors. For example, blocks in combination with diagonal can be used to get a slice of diagonal blocks.Parameters:Returns:packed N-dimensional slice composed of N-dimensional slicesExamples:
import std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 8); auto blocks = slice.blocks(2, 3); int i; foreach (block; blocks.byElement) block[] = ++i; assert(blocks == [[[[1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2]]], [[[3, 3, 3], [3, 3, 3]], [[4, 4, 4], [4, 4, 4]]]]); assert( slice == [[1, 1, 1, 2, 2, 2, 0, 0], [1, 1, 1, 2, 2, 2, 0, 0], [3, 3, 3, 4, 4, 4, 0, 0], [3, 3, 3, 4, 4, 4, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Diagonal blocksimport std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 8); auto blocks = slice.blocks(2, 3); auto diagonalBlocks = blocks.diagonal.unpack; diagonalBlocks[0][] = 1; diagonalBlocks[1][] = 2; assert(diagonalBlocks == [[[1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2]]]); assert(blocks == [[[[1, 1, 1], [1, 1, 1]], [[0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0]], [[2, 2, 2], [2, 2, 2]]]]); assert(slice == [[1, 1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Matrix divided into vertical blocksimport std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 13); auto blocks = slice .pack!1 .evertPack .blocks(3) .unpack .pack!2; int i; foreach (block; blocks.byElement) block[] = ++i; assert(slice == [[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0]]);
- Slice!(N, Slice!(N + 1, Range)) windows(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) if (allSatisfy!(isIndex, Lengths) && Lengths.length == N);
- Returns an n-dimensional slice of n-dimensional overlapping windows. windows can be generalized with other selectors. For example, windows in combination with diagonal can be used to get a multi-diagonal slice.Parameters:Returns:packed N-dimensional slice composed of N-dimensional slicesExamples:
import std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 8); auto windows = slice.windows(2, 3); foreach (window; windows.byElement) window[] += 1; assert(slice == [[1, 2, 3, 3, 3, 3, 2, 1], [2, 4, 6, 6, 6, 6, 4, 2], [2, 4, 6, 6, 6, 6, 4, 2], [2, 4, 6, 6, 6, 6, 4, 2], [1, 2, 3, 3, 3, 3, 2, 1]]);
Examples:import std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 8); auto windows = slice.windows(2, 3); windows[1, 2][] = 1; windows[1, 2][0, 1] += 1; windows.unpack[1, 2, 0, 1] += 1; assert(slice == [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 3, 1, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Multi-diagonal matriximport std.experimental.ndslice.slice; auto slice = new int[1000].sliced(8, 8); auto windows = slice.windows(3, 3); auto multidiagonal = windows .diagonal .unpack; foreach (window; multidiagonal) window[] += 1; assert(slice == [[ 1, 1, 1, 0, 0, 0, 0, 0], [ 1, 2, 2, 1, 0, 0, 0, 0], [ 1, 2, 3, 2, 1, 0, 0, 0], [0, 1, 2, 3, 2, 1, 0, 0], [0, 0, 1, 2, 3, 2, 1, 0], [0, 0, 0, 1, 2, 3, 2, 1], [0, 0, 0, 0, 1, 2, 2, 1], [0, 0, 0, 0, 0, 1, 1, 1]]);
Examples:Sliding window over matrix columnsimport std.experimental.ndslice.slice; auto slice = new int[1000].sliced(5, 8); auto windows = slice .pack!1 .evertPack .windows(3) .unpack .pack!2; foreach (window; windows.byElement) window[] += 1; assert(slice == [[1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1]]);
- Slice!(Lengths.length, Range) reshape(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) if (allSatisfy!(isIndex, Lengths) && Lengths.length);
- Returns a new slice for the same data.Parameters:
Slice!(N, Range) slice slice to be reshaped Lengths lengths list of new dimensions. One of the lengths can be set to -1. In this case, the corresponding dimension is inferable. Returns:reshaped sliceThrows:ReshapeException if the slice cannot be reshaped with the input lengths.Examples:import std.experimental.ndslice.slice; import std.range: iota; import std.experimental.ndslice.iteration: allReversed; auto slice = 100.iota .sliced(3, 4) .allReversed .reshape(-1, 3); assert(slice == [[11, 10, 9], [ 8, 7, 6], [ 5, 4, 3], [ 2, 1, 0]]);
Examples:Reshaping with memory allocationimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration: reversed; import std.array: array; auto reshape2(S, L...)(S slice, L lengths) { // Tries to reshape without allocation try return slice.reshape(lengths); catch(ReshapeException e) //allocates the elements and creates a slice //Note: -1 length is not supported by reshape2 return slice.byElement.array.sliced(lengths); } auto slice = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] .sliced(3, 4) .reversed!0; assert(reshape2(slice, 4, 3) == [[ 8, 9, 10], [11, 4, 5], [ 6, 7, 0], [ 1, 2, 3]]);
- class ReshapeException: object.Exception;
- See Also:
- auto byElement(size_t N, Range)(auto ref Slice!(N, Range) slice);
- Returns a random access range of all elements of a slice. The order of elements is preserved. byElement can be generalized with other selectors.Parameters:
N dimension count Slice!(N, Range) slice slice to be iterated Returns:random access range composed of elements of the sliceExamples:Regular sliceimport std.experimental.ndslice.slice; import std.algorithm.comparison: equal; import std.range: iota; assert(100.iota .sliced(4, 5) .byElement .equal(20.iota));
Examples:Packed sliceimport std.experimental.ndslice.slice; import std.experimental.ndslice.iteration; import std.range: iota, drop; import std.algorithm.comparison: equal; assert(100000.iota .sliced(3, 4, 5, 6, 7) .pack!2 .byElement() .drop(1) .front .byElement .equal(iota(6 * 7, 6 * 7 * 2)));
Examples:Propertiesimport std.experimental.ndslice.slice; import std.range: iota; auto elems = 12.iota.sliced(3, 4).byElement; elems.popFrontExactly(2); assert(elems.front == 2); assert(elems.index == [0, 2]); elems.popBackExactly(2); assert(elems.back == 9); assert(elems.length == 8);
Examples:Index propertyimport std.experimental.ndslice.slice; auto slice = new long[20].sliced(5, 4); for(auto elems = slice.byElement; !elems.empty; elems.popFront) { size_t[2] index = elems.index; elems.front = index[0] * 10 + index[1] * 3; } assert(slice == [[ 0, 3, 6, 9], [10, 13, 16, 19], [20, 23, 26, 29], [30, 33, 36, 39], [40, 43, 46, 49]]);
Examples:Random access and slicingimport std.experimental.ndslice.slice; import std.range: iota; auto elems = 100.iota.sliced(4, 5).byElement; elems = elems[11 .. $ - 2]; assert(elems.length == 7); assert(elems.front == 11); assert(elems.back == 17); foreach (i; 0 .. 7) assert(elems[i] == i + 11);
Examples:Forward access works faster than random access or backward access. Use allReversed in pipeline before byElement to achieve fast backward access.import std.range: retro, iota; import std.experimental.ndslice.iteration: allReversed; auto slice = 100.iota.sliced(3, 4, 5); /// Slow backward iteration #1 foreach (ref e; slice.byElement.retro) { //... } /// Slow backward iteration #2 foreach_reverse (ref e; slice.byElement) { //... } /// Fast backward iteration foreach (ref e; slice.allReversed.byElement) { //... }
- auto byElementInStandardSimplex(size_t N, Range)(auto ref Slice!(N, Range) slice, size_t maxCobeLength = size_t.max);
- Returns an forward range of all elements of standard simplex of a slice. In case the slice has two dimensions, it is composed of elements of upper left triangular matrix. The order of elements is preserved. byElementInStandardSimplex can be generalized with other selectors.Parameters:
N dimension count Slice!(N, Range) slice slice to be iterated Returns:forward range composed of all elements of standard simplex of the sliceExamples:import std.experimental.ndslice.slice; auto slice = new int[20].sliced(4, 5); auto elems = slice .byElementInStandardSimplex; int i; foreach (ref e; elems) e = ++i; assert(slice == [[ 1, 2, 3, 4, 0], [ 5, 6, 7, 0, 0], [ 8, 9, 0, 0, 0], [10, 0, 0, 0, 0]]);
Examples:import std.experimental.ndslice.slice; import std.experimental.ndslice.iteration; auto slice = new int[20].sliced(4, 5); auto elems = slice .transposed .allReversed .byElementInStandardSimplex; int i; foreach (ref e; elems) e = ++i; assert(slice == [[0, 0, 0, 0, 4], [0, 0, 0, 7, 3], [0, 0, 9, 6, 2], [0, 10, 8, 5, 1]]);
Examples:Propertiesimport std.experimental.ndslice.slice; import std.range: iota; auto elems = 12.iota.sliced(3, 4).byElementInStandardSimplex; elems.popFront; assert(elems.front == 1); assert(elems.index == cast(size_t[2])[0, 1]); import std.range: popFrontN; elems.popFrontN(3); assert(elems.front == 5); assert(elems.index == cast(size_t[2])[1, 1]); assert(elems.length == 2);
- IndexSlice!(Lengths.length) indexSlice(Lengths...)(Lengths lengths) if (allSatisfy!(isIndex, Lengths));
IndexSlice!N indexSlice(size_t N)(auto ref size_t[N] lengths); - Returns a slice, the elements of which are equal to the initial index value.Parameters:
N dimension count Lengths lengths list of dimension lengths Returns:N-dimensional slice composed of indexesSee Also:Examples:auto im = indexSlice(7, 9); assert(im[2, 1] == cast(size_t[2])[2, 1]); for (auto elems = im.byElement; !elems.empty; elems.popFront) assert(elems.front == elems.index); //slicing works correctly auto cm = im[1 .. $ - 3, 4 .. $ - 1]; assert(cm[2, 1] == cast(size_t[2])[3, 5]);
- template IndexSlice(size_t N) if (N)
- Slice composed of indexes.See Also:Examples:
alias IS4 = IndexSlice!4; static assert(is(IS4 == Slice!(4, Range), Range));