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 a local clone.

std.experimental.ndslice.iteration

This is a submodule of std.experimental.ndslice.

Operators only change strides and lengths of a slice. The range of a slice remains unmodified. All operators return slice of the same type as the type of the argument.

Transpose operators

Function Name Descriprottion
transposed 100000.iota.sliced(3, 4, 5, 6, 7).transposed!(4, 0, 1).shape returns [7, 3, 4, 5, 6].
swapped 1000.iota.sliced(3, 4, 5).swapped!(1, 2).shape returns [3, 5, 4].
everted 1000.iota.sliced(3, 4, 5).everted.shape returns [5, 4, 3].
See also evertPack .

Iteration operators

Function Name Description
strided 1000.iota.sliced(13, 40).strided!(0, 1)(2, 5).shape equals to [7, 8].
reversed slice.reversed!0 returns the slice with reversed direction of iteration for top level dimension.
allReversed 20.iota.sliced(4, 5).allReversed equals to 20.iota.retro.sliced(4, 5).

Other operators

Function Name Description
rotated 10.iota.sliced(2, 3).rotated equals to [[2, 5], [1, 4], [0, 3]].

Drop operators

dropToHypercube drop dropBack dropOne dropBackOne dropExactly dropBackExactly allDrop allDropBack allDropOne allDropBackOne allDropExactly allDropBackExactly

DropOperatorName:
    dropToHypercube
    DropRoot
    DropRoot DropSuffix
    DropRoot Back
    DropRoot Back DropSuffix
DropRoot:
    drop
    allDrop
DropSuffix:
    One
    Exactly

Bifacial operators

Some operators are bifacial, i.e. they have two versions: one with template parameters, and another one with function parameters. Versions with template parameters are preferable because they allow compile time checks and can be optimized better.

Function Name Variadic Template Function
swapped No slice.swapped!(2, 3) slice.swapped(2, 3)
rotated No slice.rotated!(2, 3)(-1) slice.rotated(2, 3, -1)
strided Yes/No slice.strided!(1, 2)(20, 40) slice.strided(1, 20).strided(2, 40)
transposed Yes slice.transposed!(1, 4, 3) slice.transposed(1, 4, 3)
reversed Yes slice.reversed!(0, 2) slice.reversed(0, 2)

Bifacial interface of drop, dropBack dropExactly, and dropBackExactly is identical to that of strided.

Bifacial interface of dropOne and dropBackOne is identical to that of reversed.
Authors:
Ilya Yaroshenko
template swapped(size_t dimensionA, size_t dimensionB)

Slice!(N, Range) swapped(size_t N, Range)(Slice!(N, Range) slice, size_t dimensionA, size_t dimensionB);

Slice!(2, Range) swapped(Range)(Slice!(2, Range) slice);
Swaps two dimensions.
Parameters:
Slice!(N, Range) slice input slice
size_t dimensionA first dimension
size_t dimensionB second dimension
Returns:
n-dimensional slice of the same type
See Also:
Examples:
Template
import std.experimental.ndslice.slice;
import std.range: iota;
assert((3 * 4 * 5 * 6).iota
    .sliced(3, 4, 5, 6)
    .swapped!(3, 1)
    .shape == cast(size_t[4])[3, 6, 5, 4]);
Examples:
Function
import std.experimental.ndslice.slice;
import std.range: iota;
assert((3 * 4 * 5 * 6).iota
    .sliced(3, 4, 5, 6)
    .swapped(1, 3)
    .shape == cast(size_t[4])[3, 6, 5, 4]);
Examples:
2D
import std.experimental.ndslice.slice;
import std.range: iota;
assert(12.iota
    .sliced(3, 4)
    .swapped
    .shape == cast(size_t[2])[4, 3]);
template rotated(size_t dimensionA, size_t dimensionB)

Slice!(N, Range) rotated(size_t N, Range)(Slice!(N, Range) slice, size_t dimensionA, size_t dimensionB, sizediff_t k = 1);

Slice!(2, Range) rotated(Range)(Slice!(2, Range) slice, sizediff_t k = 1);
Rotates two selected dimensions by k*90 degrees. The order of dimensions is important. If the slice has two dimensions, the default direction is counterclockwise.
Parameters:
Slice!(N, Range) slice input slice
size_t dimensionA first dimension
size_t dimensionB second dimension
sizediff_t k rotation counter, can be negative
Returns:
n-dimensional slice of the same type
Examples:
Template
import std.experimental.ndslice.slice;
import std.range: iota;
auto slice = 6.iota.sliced(2, 3);

auto a = [[0, 1, 2],
          [3, 4, 5]];

auto b = [[2, 5],
          [1, 4],
          [0, 3]];

auto c = [[5, 4, 3],
          [2, 1, 0]];

auto d = [[3, 0],
          [4, 1],
          [5, 2]];

assert(slice.rotated       ( 4) == a);
assert(slice.rotated!(0, 1)(-4) == a);
assert(slice.rotated (1, 0,  8) == a);

assert(slice.rotated            == b);
assert(slice.rotated!(0, 1)(-3) == b);
assert(slice.rotated (1, 0,  3) == b);

assert(slice.rotated       ( 6) == c);
assert(slice.rotated!(0, 1)( 2) == c);
assert(slice.rotated (0, 1, -2) == c);

assert(slice.rotated       ( 7) == d);
assert(slice.rotated!(0, 1)( 3) == d);
assert(slice.rotated (1, 0,   ) == d);
Slice!(N, Range) everted(size_t N, Range)(auto ref Slice!(N, Range) slice);
Reverses the order of dimensions.
Parameters:
Slice!(N, Range) slice input slice
Returns:
n-dimensional slice of the same type
See Also:
Examples:
import std.experimental.ndslice.slice;
import std.range: iota;
assert(60.iota
    .sliced(3, 4, 5)
    .everted
    .shape == cast(size_t[3])[5, 4, 3]);
template transposed(Dimensions...) if (Dimensions.length)

Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice, size_t dimension);

Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice, in size_t[] dimensions...);

Slice!(2, Range) transposed(Range)(auto ref Slice!(2, Range) slice);
N-dimensional transpose operator. Brings selected dimensions to the first position.
Parameters:
Slice!(N, Range) slice input slice
Dimensions indexes of dimensions to be brought to the first position
size_t[] dimensions indexes of dimensions to be brought to the first position
size_t dimension index of dimension to be brought to the first position
Returns:
n-dimensional slice of the same type
See Also:
Examples:
Template
import std.experimental.ndslice.slice;
import std.range: iota;
assert((3 * 4 * 5 * 6 * 7).iota
    .sliced(3, 4, 5, 6, 7)
    .transposed!(4, 1, 0)
    .shape == cast(size_t[5])[7, 4, 3, 5, 6]);
Examples:
Function
import std.experimental.ndslice.slice;
import std.range: iota;
assert((3 * 4 * 5 * 6 * 7).iota
    .sliced(3, 4, 5, 6, 7)
    .transposed(4, 1, 0)
    .shape == cast(size_t[5])[7, 4, 3, 5, 6]);
Examples:
Single-argument function
import std.experimental.ndslice.slice;
import std.range: iota;
assert((3 * 4 * 5 * 6 * 7).iota
    .sliced(3, 4, 5, 6, 7)
    .transposed(4)
    .shape == cast(size_t[5])[7, 3, 4, 5, 6]);
Examples:
2-dimensional transpose
import std.experimental.ndslice.slice;
import std.range: iota;
assert(12.iota
    .sliced(3, 4)
    .transposed
    .shape == cast(size_t[2])[4, 3]);
Slice!(N, Range) allReversed(size_t N, Range)(Slice!(N, Range) slice);
Reverses the direction of iteration for all dimensions.
Parameters:
Slice!(N, Range) slice input slice
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5).allReversed;
auto b = 20.iota.retro.sliced(4, 5);
assert(a == b);
template reversed(Dimensions...) if (Dimensions.length)

Slice!(N, Range) reversed(size_t N, Range)(Slice!(N, Range) slice, size_t dimension);

Slice!(N, Range) reversed(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...);
Reverses the direction of iteration for selected dimensions.
Parameters:
Slice!(N, Range) slice input slice
Dimensions indexes of dimensions to reverse order of iteration
size_t[] dimensions indexes of dimensions to reverse order of iteration
size_t dimension index of dimension to reverse order of iteration
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
auto slice = [1, 2, 3, 4].sliced(2, 2);
assert(slice                    == [[1, 2], [3, 4]]);

// Template
assert(slice.reversed! 0        == [[3, 4], [1, 2]]);
assert(slice.reversed! 1        == [[2, 1], [4, 3]]);
assert(slice.reversed!(0, 1)    == [[4, 3], [2, 1]]);
assert(slice.reversed!(1, 0)    == [[4, 3], [2, 1]]);
assert(slice.reversed!(1, 1)    == [[1, 2], [3, 4]]);
assert(slice.reversed!(0, 0, 0) == [[3, 4], [1, 2]]);

// Function
assert(slice.reversed (0)       == [[3, 4], [1, 2]]);
assert(slice.reversed (1)       == [[2, 1], [4, 3]]);
assert(slice.reversed (0, 1)    == [[4, 3], [2, 1]]);
assert(slice.reversed (1, 0)    == [[4, 3], [2, 1]]);
assert(slice.reversed (1, 1)    == [[1, 2], [3, 4]]);
assert(slice.reversed (0, 0, 0) == [[3, 4], [1, 2]]);
template strided(Dimensions...) if (Dimensions.length)

Slice!(N, Range) strided(size_t N, Range)(Slice!(N, Range) slice, size_t dimension, size_t factor);
Multiplies the stride of the selected dimension by the factor.
Parameters:
Slice!(N, Range) slice input slice
Dimensions indexes of dimensions to be strided
dimensions indexes of dimensions to be strided
factors list of step extension factors
size_t factor step extension factors
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
auto slice
     = [0,1,2,3,    4,5,6,7,   8,9,10,11].sliced(3, 4);

assert(slice
    == [[0,1,2,3], [4,5,6,7], [8,9,10,11]]);

// Template
assert(slice.strided!0(2)
    == [[0,1,2,3],            [8,9,10,11]]);

assert(slice.strided!1(3)
    == [[0,    3], [4,    7], [8,     11]]);

assert(slice.strided!(0, 1)(2, 3)
    == [[0,    3],            [8,     11]]);

// Function
assert(slice.strided(0, 2)
    == [[0,1,2,3],            [8,9,10,11]]);

assert(slice.strided(1, 3)
    == [[0,    3], [4,    7], [8,     11]]);

assert(slice.strided(0, 2).strided(1, 3)
    == [[0,    3],            [8,     11]]);
Examples:
import std.range: iota;
static assert(iota(13 * 40).sliced(13, 40).strided!(0, 1)(2, 5).shape == [7, 8]);
static assert(93.iota.sliced(93).strided!(0, 0)(7, 3).shape == [5]);
Slice!(N, Range) allDropOne(size_t N, Range)(Slice!(N, Range) slice);

Slice!(N, Range) allDropBackOne(size_t N, Range)(Slice!(N, Range) slice);
Convenience function which calls slice.popFront!dimension() for each dimension and returns the slice.
allDropBackOne provides the same functionality but calls slice.popBack!dimension() instead.
Parameters:
Slice!(N, Range) slice input slice
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.allDropOne[0, 0] == 6);
assert(a.allDropOne.shape == cast(size_t[2])[3, 4]);
assert(a.allDropBackOne[$ - 1, $ - 1] == 13);
assert(a.allDropBackOne.shape == cast(size_t[2])[3, 4]);
Slice!(N, Range) allDropExactly(size_t N, Range)(Slice!(N, Range) slice, size_t n);

Slice!(N, Range) allDropBackExactly(size_t N, Range)(Slice!(N, Range) slice, size_t n);
These functions are similar to allDrop and allDropBack but they call slice.popFrontExactly!dimension(n) and slice.popBackExactly!dimension(n) instead.

Note: Unlike allDrop, allDropExactly(n) assume that the slice holds a multi-dimensional cube with a size of at least n. This makes allDropExactly faster than allDrop. Only use allDropExactly when it is guaranteed that the slice holds a multi-dimensional cube with a size of at least n.

Parameters:
Slice!(N, Range) slice input slice
size_t n number of elements to drop
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.allDropExactly(2)[0, 0] == 12);
assert(a.allDropExactly(2).shape == cast(size_t[2])[2, 3]);
assert(a.allDropBackExactly(2)[$ - 1, $ - 1] == 7);
assert(a.allDropBackExactly(2).shape == cast(size_t[2])[2, 3]);
Slice!(N, Range) allDrop(size_t N, Range)(Slice!(N, Range) slice, size_t n);

Slice!(N, Range) allDropBack(size_t N, Range)(Slice!(N, Range) slice, size_t n);
Convenience function which calls slice.popFrontN!dimension(n) for each dimension and returns the slice.
allDropBack provides the same functionality but calls slice.popBackN!dimension(n) instead.

Note: allDrop and allDropBack remove up to n elements and stop when the slice is empty.

Parameters:
Slice!(N, Range) slice input slice
size_t n number of elements to drop
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.allDrop(2)[0, 0] == 12);
assert(a.allDrop(2).shape == cast(size_t[2])[2, 3]);
assert(a.allDropBack(2)[$ - 1, $ - 1] == 7);
assert(a.allDropBack(2).shape == cast(size_t[2])[2, 3]);

assert(a.allDrop    (5).shape == cast(size_t[2])[0, 0]);
assert(a.allDropBack(5).shape == cast(size_t[2])[0, 0]);
template dropOne(Dimensions...) if (Dimensions.length)

Slice!(N, Range) dropOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension);

Slice!(N, Range) dropOne(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...);

template dropBackOne(Dimensions...) if (Dimensions.length)

Slice!(N, Range) dropBackOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension);

Slice!(N, Range) dropBackOne(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...);
Convenience function which calls slice.popFront!dimension() for selected dimensions and returns the slice.
dropBackOne provides the same functionality but calls slice.popBack!dimension() instead.
Parameters:
Slice!(N, Range) slice input slice
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.dropOne!(1, 0)[0, 0] == 6);
assert(a.dropOne (1, 0)[0, 0] == 6);
assert(a.dropOne!(1, 0).shape == cast(size_t[2])[3, 4]);
assert(a.dropOne (1, 0).shape == cast(size_t[2])[3, 4]);
assert(a.dropBackOne!(1, 0)[$ - 1, $ - 1] == 13);
assert(a.dropBackOne (1, 0)[$ - 1, $ - 1] == 13);
assert(a.dropBackOne!(1, 0).shape == cast(size_t[2])[3, 4]);
assert(a.dropBackOne (1, 0).shape == cast(size_t[2])[3, 4]);

assert(a.dropOne!(0, 0)[0, 0] == 10);
assert(a.dropOne (0, 0)[0, 0] == 10);
assert(a.dropOne!(0, 0).shape == cast(size_t[2])[2, 5]);
assert(a.dropOne (0, 0).shape == cast(size_t[2])[2, 5]);
assert(a.dropBackOne!(1, 1)[$ - 1, $ - 1] == 17);
assert(a.dropBackOne (1, 1)[$ - 1, $ - 1] == 17);
assert(a.dropBackOne!(1, 1).shape == cast(size_t[2])[4, 3]);
assert(a.dropBackOne (1, 1).shape == cast(size_t[2])[4, 3]);
template dropExactly(Dimensions...) if (Dimensions.length)

Slice!(N, Range) dropExactly(size_t N, Range)(Slice!(N, Range) slice, size_t dimension, size_t n);

template dropBackExactly(Dimensions...) if (Dimensions.length)

Slice!(N, Range) dropBackExactly(size_t N, Range)(Slice!(N, Range) slice, size_t dimension, size_t n);
These functions are similar to drop and dropBack but they call slice.popFrontExactly!dimension(n) and slice.popBackExactly!dimension(n) instead.

Note: Unlike drop, dropExactly assumes that the slice holds enough elements in the selected dimension. This makes dropExactly faster than drop.

Parameters:
Slice!(N, Range) slice input slice
ns list of numbers of elements to drop
size_t n number of elements to drop
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.dropExactly    !(1, 0)(2, 3)[0, 0] == 17);
assert(a.dropExactly    !(1, 0)(2, 3).shape == cast(size_t[2])[1, 3]);
assert(a.dropBackExactly!(0, 1)(2, 3)[$ - 1, $ - 1] == 6);
assert(a.dropBackExactly!(0, 1)(2, 3).shape == cast(size_t[2])[2, 2]);

assert(a.dropExactly(1, 2).dropExactly(0, 3)[0, 0] == 17);
assert(a.dropExactly(1, 2).dropExactly(0, 3).shape == cast(size_t[2])[1, 3]);
assert(a.dropBackExactly(0, 2).dropBackExactly(1, 3)[$ - 1, $ - 1] == 6);
assert(a.dropBackExactly(0, 2).dropBackExactly(1, 3).shape == cast(size_t[2])[2, 2]);
template drop(Dimensions...) if (Dimensions.length)

Slice!(N, Range) drop(size_t N, Range)(Slice!(N, Range) slice, size_t dimension, size_t n);

template dropBack(Dimensions...) if (Dimensions.length)

Slice!(N, Range) dropBack(size_t N, Range)(Slice!(N, Range) slice, size_t dimension, size_t n);
Convenience function which calls slice.popFrontN!dimension(n) for the selected dimension and returns the slice.
dropBack provides the same functionality but calls slice.popBackN!dimension(n) instead.

Note: drop and dropBack remove up to n elements and stop when the slice is empty.

Parameters:
Slice!(N, Range) slice input slice
ns list of numbers of elements to drop
size_t n number of elements to drop
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
auto a = 20.iota.sliced(4, 5);

assert(a.drop    !(1, 0)(2, 3)[0, 0] == 17);
assert(a.drop    !(1, 0)(2, 3).shape == cast(size_t[2])[1, 3]);
assert(a.dropBack!(0, 1)(2, 3)[$ - 1, $ - 1] == 6);
assert(a.dropBack!(0, 1)(2, 3).shape == cast(size_t[2])[2, 2]);
assert(a.dropBack!(0, 1)(5, 5).shape == cast(size_t[2])[0, 0]);


assert(a.drop(1, 2).drop(0, 3)[0, 0] == 17);
assert(a.drop(1, 2).drop(0, 3).shape == cast(size_t[2])[1, 3]);
assert(a.dropBack(0, 2).dropBack(1, 3)[$ - 1, $ - 1] == 6);
assert(a.dropBack(0, 2).dropBack(1, 3).shape == cast(size_t[2])[2, 2]);
assert(a.dropBack(0, 5).dropBack(1, 5).shape == cast(size_t[2])[0, 0]);
Slice!(N, Range) dropToHypercube(size_t N, Range)(Slice!(N, Range) slice);
Returns maximal multidimensional cube.
Parameters:
Slice!(N, Range) slice input slice
Returns:
n-dimensional slice of the same type
Examples:
import std.experimental.ndslice.slice;
import std.range: iota, retro;
assert((5 * 3 * 6 * 7).iota
    .sliced(5, 3, 6, 7)
    .dropToHypercube
    .shape == cast(size_t[4])[3, 3, 3, 3]);