std.experimental.ndslice.selection - D Programming Language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Wiki
  - GitHub
  - Issues
  - Foundation
  - Donate
- Resources
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
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.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

## Selectors

Function Name | Description
--- | ---
blocks | n-dimensional slice composed of n-dimensional non-overlapping blocks. If the slice has two dimensions, it is a block matrix.
byElement | flat, 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.
diagonal | 1-dimensional slice composed of diagonal elements
indexSlice | lazy slice with initial multidimensional index
iotaSlice | lazy slice with initial flattened (continuous) index
mapSlice | lazy multidimensional functional map
repeatSlice | slice with identical values
reshape | new slice with changed dimensions for the same data
windows | n-dimensional slice of n-dimensional overlapping windows. If the slice has two dimensions, it is a sliding window.

License:
Boost License 1.0.
Authors:
Ilya Yaroshenko

Source: std/experimental/ndslice/selection.d

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:
  `pack`!K returns Slice!(N-K, Slice!(K+1, Range)); slice.`pack`!(K1, K2, ..., Kn) is the same as slice.`pack`!K1.`pack`!K2. ... `pack`!Kn.
  Examples:

      import std.experimental.ndslice : sliced, Slice, pack;
      import std.range : iota;

      auto r = (3 * 4 * 5 * 6).iota;
      auto a = r.sliced(3, 4, 5, 6);
      auto b = a.pack!2;

      static immutable res1 = [3, 4];
      static immutable res2 = [5, 6];
      assert(b.shape == res1);
      assert(b[0, 0].shape == res2);
      assert(a == b);
      static assert(is(typeof(b) == typeof(a.pack!2)));
      static assert(is(typeof(b) == Slice!(2, Slice!(3, typeof(r)))));

Slice!(N, Range).PureThis `unpack`(size_t N, Range)(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 `slice`
  See Also:
  pack, evertPack
  Examples:

      auto a = iotaSlice(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)(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 `slice`
  See Also:
  pack, unpack
  Examples:

      import std.experimental.ndslice.iteration : transposed;
      auto slice = iotaSlice(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 = (3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11).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)(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:
  1-dimensional `slice` composed of `diagonal` elements
  Examples:
  Matrix, main `diagonal`

      //  -------
      // | 0 1 2 |
      // | 3 4 5 |
      //  -------
      //->
      // | 0 4 |
      static immutable d = [0, 4];
      assert(iotaSlice(2, 3).diagonal == d);

  Examples:
  Non-square matrix

      import std.algorithm.comparison : equal;
      import std.range : only;

      //  -------
      // | 0 1 |
      // | 2 3 |
      // | 4 5 |
      //  -------
      //->
      // | 0 3 |

      assert(iotaSlice(3, 2)
          .diagonal
          .equal(only(0, 3)));

  Examples:
  Loop through `diagonal`

      import std.experimental.ndslice.slice;

      auto slice = slice!int(3, 3);
      int i;
      foreach (ref e; slice.diagonal)
          e = ++i;
      assert(slice == [
          [1, 0, 0],
          [0, 2, 0],
          [0, 0, 3]]);

  Examples:
  Matrix, subdiagonal

      import std.experimental.ndslice.iteration : dropOne;
      //  -------
      // | 0 1 2 |
      // | 3 4 5 |
      //  -------
      //->
      // | 1 5 |
      static immutable d = [1, 5];
      assert(iotaSlice(2, 3).dropOne!1.diagonal == d);

  Examples:
  Matrix, antidiagonal

      import std.experimental.ndslice.iteration : dropToHypercube, reversed;
      //  -------
      // | 0 1 2 |
      // | 3 4 5 |
      //  -------
      //->
      // | 1 3 |
      static immutable d = [1, 3];
      assert(iotaSlice(2, 3).dropToHypercube.reversed!1.diagonal == d);

  Examples:
  3D, main `diagonal`

      //  -----------
      // |  0   1  2 |
      // |  3   4  5 |
      //  - - - - - -
      // |  6   7  8 |
      // |  9  10 11 |
      //  -----------
      //->
      // | 0 10 |
      static immutable d = [0, 10];
      assert(iotaSlice(2, 2, 3).diagonal == d);

  Examples:
  3D, subdiagonal

      import std.experimental.ndslice.iteration : dropOne;
      //  -----------
      // |  0   1  2 |
      // |  3   4  5 |
      //  - - - - - -
      // |  6   7  8 |
      // |  9  10 11 |
      //  -----------
      //->
      // | 1 11 |
      static immutable d = [1, 11];
      assert(iotaSlice(2, 2, 3).dropOne!2.diagonal == d);

  Examples:
  3D, `diagonal` plain

      //  -----------
      // |  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 |
      //  -----------

      static immutable d =
          [[ 0,  4,  8],
           [ 9, 13, 17],
           [18, 22, 26]];

      auto slice = iotaSlice(3, 3, 3)
          .pack!2
          .evertPack
          .diagonal
          .evertPack;

      assert(slice == d);

Slice!(N, Slice!(N + 1, Range)) `blocks`(size_t N, Range)(Slice!(N, Range) `slice`, size_t[N] `lengths`...);
  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`. For overlapped `blocks`, combine windows with strided .
  Parameters:

  N | dimension count
  Slice!(N, Range) `slice` | `slice` to be split into `blocks`
  size_t[N] `lengths` | dimensions of block, residual `blocks` are ignored

  Returns:
  packed N-dimensional `slice` composed of N-dimensional slices
  Examples:

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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 `blocks`

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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 `blocks`

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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)(Slice!(N, Range) `slice`, size_t[N] `lengths`...);
  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:

  N | dimension count
  Slice!(N, Range) `slice` | `slice` to be iterated
  size_t[N] `lengths` | dimensions of `windows`

  Returns:
  packed N-dimensional `slice` composed of N-dimensional slices
  Examples:

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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 = slice!int(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 matrix

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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 columns

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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]]);

  Examples:
  Overlapping blocks using `windows`

      //  ----------------
      // |  0  1  2  3  4 |
      // |  5  6  7  8  9 |
      // | 10 11 12 13 14 |
      // | 15 16 17 18 19 |
      // | 20 21 22 23 24 |
      //  ----------------
      //->
      //  ---------------------
      // |  0  1  2 |  2  3  4 |
      // |  5  6  7 |  7  8  9 |
      // | 10 11 12 | 12 13 14 |
      // | - - - - - - - - - - |
      // | 10 11 13 | 12 13 14 |
      // | 15 16 17 | 17 18 19 |
      // | 20 21 22 | 22 23 24 |
      //  ---------------------

      import std.experimental.ndslice.slice;
      import std.experimental.ndslice.iteration : strided;

      auto overlappingBlocks = iotaSlice(5, 5)
          .windows(3, 3)
          .strided!(0, 1)(2, 2);

      assert(overlappingBlocks ==
              [[[[ 0,  1,  2], [ 5,  6,  7], [10, 11, 12]],
                [[ 2,  3,  4], [ 7,  8,  9], [12, 13, 14]]],
               [[[10, 11, 12], [15, 16, 17], [20, 21, 22]],
                [[12, 13, 14], [17, 18, 19], [22, 23, 24]]]]);

enum `ReshapeError`: int;
  Error codes for reshape.
  `none`
    No error
  `empty`
    Slice should be not `empty`
  `total`
    Total element count should be the same
  `incompatible`
    Structure is `incompatible` with new shape
Slice!(M, Range) `reshape`(size_t N, Range, size_t M)(Slice!(N, Range) `slice`, size_t[M] `lengths`, ref int `err`);
  Returns a new `slice` for the same data with different dimensions.
  Parameters:

  Slice!(N, Range) `slice` | `slice` to be reshaped
  size_t[M] `lengths` | list of new dimensions. One of the `lengths` can be set to -1. In this case, the corresponding dimension is inferable.
  int `err` | ReshapeError code

  Returns:
  reshaped `slice`
  Examples:

      import std.experimental.ndslice.iteration : allReversed;
      int err;
      auto slice = iotaSlice(3, 4)
          .allReversed
          .reshape([-1, 3], err);
      assert(err == 0);
      assert(slice ==
          [[11, 10, 9],
           [ 8,  7, 6],
           [ 5,  4, 3],
           [ 2,  1, 0]]);

  Examples:
  Reshaping with memory allocation

      import std.experimental.ndslice.slice;
      import std.experimental.ndslice.iteration : reversed;
      import std.array : array;

      auto reshape2(S, size_t M)(S slice, size_t[M] lengths...)
      {
          int err;
          // Tries to reshape without allocation
          auto ret = slice.reshape(lengths, err);
          if (!err)
              return ret;
          if (err == ReshapeError.incompatible)
              return slice.slice.reshape(lengths, err);
          throw new Exception("total elements count is different or equals to zero");
      }

      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`: std.experimental.ndslice.slice.SliceException;
  See Also:
  reshape
  size_t[] `lengths`;
    Old `lengths`
  sizediff_t[] `strides`;
    Old `strides`
  size_t[] `newLengths`;
    New lengths
  pure nothrow @nogc @safe this(size_t[] `lengths`, sizediff_t[] `strides`, size_t[] `newLengths`, string `msg`, string `file` = __FILE__, uint `line` = cast(uint)1086, Throwable `next` = null);
auto `byElement`(size_t N, Range)(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 `slice`
  Examples:
  Regular `slice`

      import std.algorithm.comparison : equal;
      import std.range : iota;
      assert(iotaSlice(4, 5)
          .byElement
          .equal(20.iota));

  Examples:
  Packed `slice`

      import std.experimental.ndslice.slice;
      import std.experimental.ndslice.iteration;
      import std.range : drop;
      assert(iotaSlice(3, 4, 5, 6, 7)
          .pack!2
          .byElement()
          .drop(1)
          .front
           == iotaSlice([6, 7], 6 * 7));

  Examples:
  Properties

      auto elems = iotaSlice(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 property

      import 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 slicing

      import std.experimental.ndslice.slice;
      import std.algorithm.comparison : equal;
      import std.array : array;
      import std.range : iota, repeat;
      static data = 20.iota.array;
      auto elems = data.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);

      // assign an element
      elems[2 .. 6] = -1;
      assert(elems[2 .. 6].equal(repeat(-1, 4)));

      // assign an array
      static ar = [-1, -2, -3, -4];
      elems[2 .. 6] = ar;
      assert(elems[2 .. 6].equal(ar));

      // assign a slice
      ar[] *= 2;
      auto sl = ar.sliced(ar.length);
      elems[2 .. 6] = sl;
      assert(elems[2 .. 6].equal(sl));

  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;
      import std.experimental.ndslice.iteration : allReversed;

      auto slice = iotaSlice(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)(Slice!(N, Range) `slice`, size_t `maxHypercubeLength` = 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
  size_t `maxHypercubeLength` | maximal length of simplex hypercube.

  Returns:
  forward range composed of all elements of standard simplex of the `slice`
  Examples:

      import std.experimental.ndslice.slice;
      auto slice = slice!int(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 = slice!int(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:
  Properties

      import std.range.primitives : popFrontN;

      auto elems = iotaSlice(3, 4).byElementInStandardSimplex;

      elems.popFront;
      assert(elems.front == 1);
      assert(elems.index == cast(size_t[2])[0, 1]);

      elems.popFrontN(3);
      assert(elems.front == 5);

  Examples:
  Save

      auto elems = iotaSlice(3, 4).byElementInStandardSimplex;
      import std.range : dropOne, popFrontN;
      elems.popFrontN(4);

      assert(elems.save.dropOne.front == 8);
      assert(elems.front == 5);
      assert(elems.index == cast(size_t[2])[1, 1]);
      assert(elems.length == 2);

IndexSlice!N `indexSlice`(size_t N)(size_t[N] `lengths`...);
  Returns a slice, the elements of which are equal to the initial multidimensional index value. This is multidimensional analog of std.range.iota. For a flattened (continuous) index, see iotaSlice.
  Parameters:

  N | dimension count
  size_t[N] `lengths` | list of dimension `lengths`

  Returns:
  N-dimensional slice composed of indexes
  See Also:
  IndexSlice, iotaSlice
  Examples:

      auto slice = indexSlice(2, 3);
      static immutable array =
          [[[0, 0], [0, 1], [0, 2]],
           [[1, 0], [1, 1], [1, 2]]];

      assert(slice == array);

      static assert(is(IndexSlice!2 : Slice!(2, Range), Range));
      static assert(is(DeepElementType!(IndexSlice!2) == size_t[2]));

  Examples:

      auto im = indexSlice(7, 9);

      assert(im[2, 1] == [2, 1]);

      //slicing works correctly
      auto cm = im[1 .. $, 4 .. $];
      assert(cm[2, 1] == [3, 5]);

template `IndexSlice`(size_t N) if (N)
  Slice composed of indexes.
  See Also:
  indexSlice
IotaSlice!N `iotaSlice`(size_t N)(size_t[N] `lengths`...);
IotaSlice!N `iotaSlice`(size_t N)(size_t[N] `lengths`, size_t `shift`);
IotaSlice!N `iotaSlice`(size_t N)(size_t[N] `lengths`, size_t `shift`, size_t `step`);
  Returns a slice, the elements of which are equal to the initial flattened index value. For a multidimensional index, see indexSlice.
  Parameters:

  N | dimension count
  size_t[N] `lengths` | list of dimension `lengths`
  size_t `shift` | value of the first element in a slice (optional)
  size_t `step` | value of the `step` between elements (optional)

  Returns:
  N-dimensional slice composed of indexes
  See Also:
  IotaSlice, indexSlice
  Examples:

      auto slice = iotaSlice(2, 3);
      static immutable array =
          [[0, 1, 2],
           [3, 4, 5]];

      assert(slice == array);

      import std.range.primitives : isRandomAccessRange;
      static assert(isRandomAccessRange!(IotaSlice!2));
      static assert(is(IotaSlice!2 : Slice!(2, Range), Range));
      static assert(is(DeepElementType!(IotaSlice!2) == size_t));

  Examples:

      auto im = iotaSlice([10, 5], 100);

      assert(im[2, 1] == 111); // 100 + 2 * 5 + 1

      //slicing works correctly
      auto cm = im[1 .. $, 3 .. $];
      assert(cm[2, 1] == 119); // 119 = 100 + (1 + 2) * 5 + (3 + 1)

  Examples:
  `iotaSlice` with `step`

      auto sl = iotaSlice([2, 3], 10, 10);

      assert(sl == [[10, 20, 30],
                    [40, 50, 60]]);

template `IotaSlice`(size_t N) if (N)
  Slice composed of flattened indexes.
  See Also:
  iotaSlice
RepeatSlice!(M, T) `repeatSlice`(T, size_t M)(T `value`, size_t[M] `lengths`...)
if (!is(T : Slice!(N, Range), size_t N, Range));
Slice!(M, Slice!(N + 1, Range)) `repeatSlice`(size_t N, Range, size_t M)(Slice!(N, Range) `slice`, size_t[M] `lengths`...);
  Returns a `slice` with identical elements. RepeatSlice stores only single `value`.
  Parameters:

  size_t[M] `lengths` | list of dimension `lengths`

  Returns:
  n-dimensional `slice` composed of identical values, where n is dimension count.
  See Also:
  std.range.repeat
  Examples:

      auto sl = iotaSlice(3)
          .repeatSlice(4);
      assert(sl == [[0, 1, 2],
                    [0, 1, 2],
                    [0, 1, 2],
                    [0, 1, 2]]);

  Examples:

      import std.experimental.ndslice.iteration : transposed;

      auto sl = iotaSlice(3)
          .repeatSlice(4)
          .unpack
          .transposed;

      assert(sl == [[0, 0, 0, 0],
                    [1, 1, 1, 1],
                    [2, 2, 2, 2]]);

  Examples:

      import std.experimental.ndslice.slice : slice;

      auto sl = iotaSlice([3], 6).slice;
      auto slC = sl.repeatSlice(2, 3);
      sl[1] = 4;
      assert(slC == [[[6, 4, 8],
                      [6, 4, 8],
                      [6, 4, 8]],
                     [[6, 4, 8],
                      [6, 4, 8],
                      [6, 4, 8]]]);

  Examples:

      auto sl = repeatSlice(4.0, 2, 3);
      assert(sl == [[4.0, 4.0, 4.0],
                    [4.0, 4.0, 4.0]]);

      static assert(is(DeepElementType!(typeof(sl)) == double));

      sl[1, 1] = 3;
      assert(sl == [[3.0, 3.0, 3.0],
                    [3.0, 3.0, 3.0]]);

template `RepeatSlice`(size_t N, T) if (N)
  Slice composed of identical values.
template `mapSlice`(fun...) if (fun.length)
  Implements the homonym function (also known as transform) present in many languages of functional flavor. The call `mapSlice`!(fun)(tensor) returns a tensor of which elements are obtained by applying fun for all elements in tensor. The original tensors are not changed. Evaluation is done lazily.

  Note: transposed and pack can be used to specify dimensions.

  Parameters:

  fun | One or more functions.
  Slice!(N, Range) tensor | An input tensor.

  Returns:
  a tensor with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
  See Also:
  std.algorithm.iteration.map Map (higher-order function)
  Examples:

      import std.experimental.ndslice.selection : iotaSlice;

      auto s = iotaSlice(2, 3).mapSlice!(a => a * 3);
      assert(s == [[ 0,  3,  6],
                   [ 9, 12, 15]]);

  Examples:
  Packed tensors.

      import std.experimental.ndslice.selection : iotaSlice, windows;

      //  iotaSlice        windows     mapSlice  sums ( ndFold!"a + b" )
      //                --------------
      //  -------      |  ---    ---  |      ------
      // | 0 1 2 |  => || 0 1 || 1 2 ||  => | 8 12 |
      // | 3 4 5 |     || 3 4 || 4 5 ||      ------
      //  -------      |  ---    ---  |
      //                --------------
      auto s = iotaSlice(2, 3)
          .windows(2, 2)
          .mapSlice!((a) {
              size_t s;
              foreach (r; a)
                  foreach (e; r)
                      s += e;
              return s;
              });

      assert(s == [[8, 12]]);

  Examples:
  Zipped tensors

      import std.experimental.ndslice.slice : assumeSameStructure;
      import std.experimental.ndslice.selection : iotaSlice;

      // 0 1 2
      // 3 4 5
      auto sl1 = iotaSlice(2, 3);
      // 1 2 3
      // 4 5 6
      auto sl2 = iotaSlice([2, 3], 1);

      // tensors must have the same strides
      assert(sl1.structure == sl2.structure);

      auto zip = assumeSameStructure!("a", "b")(sl1, sl2);

      auto lazySum = zip.mapSlice!(z => z.a + z.b);

      assert(lazySum == [[ 1,  3,  5],
                         [ 7,  9, 11]]);

  Examples:
  Multiple functions can be passed to `mapSlice`. In that case, the element type of `mapSlice` is a tuple containing one element for each function.

      import std.experimental.ndslice.selection : iotaSlice;

      auto s = iotaSlice(2, 3).mapSlice!("a + a", "a * a");

      auto sums     = [[0, 2, 4], [6,  8, 10]];
      auto products = [[0, 1, 4], [9, 16, 25]];

      foreach (i; 0..s.length!0)
      foreach (j; 0..s.length!1)
      {
          auto values = s[i, j];
          assert(values[0] == sums[i][j]);
          assert(values[1] == products[i][j]);
      }

  Examples:
  You may alias `mapSlice` with some function(s) to a symbol and use it separately:

      import std.conv : to;
      import std.experimental.ndslice.selection : iotaSlice;

      alias stringize = mapSlice!(to!string);
      assert(stringize(iotaSlice(2, 3)) == [["0", "1", "2"], ["3", "4", "5"]]);

  auto `mapSlice`(size_t N, Range)(Slice!(N, Range) `tensor`);

Copyright © 1999-2017 by the D Language Foundation | Page generated by Ddoc on Thu Feb 16 13:40:06 2017