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

This is a submodule of std.experimental.ndslice.
License:
Boost License 1.0.
Authors:
Ilya Yaroshenko

Source: std/experimental/ndslice/slice.d

auto `sliced`(Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Flag!"allowDownsize" ad = No.allowDownsize, Range, size_t N)(Range `range`, size_t[N] `lengths`...)
if (!isStaticArray!Range && !isNarrowString!Range && N);
auto `sliced`(Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Flag!"allowDownsize" ad = No.allowDownsize, size_t N, Range)(Range `range`, size_t[N] `lengths`, size_t `shift` = 0)
if (!isStaticArray!Range && !isNarrowString!Range && N);
template `sliced`(Names...) if (Names.length && !anySatisfy!(isType, Names) && allSatisfy!(isStringValue, Names))
auto `sliced`(Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Flag!"allowDownsize" ad = No.allowDownsize, Range)(Range `range`)
if (!isStaticArray!Range && !isNarrowString!Range && hasLength!Range);
  Creates an n-dimensional slice-shell over a `range`.
  Parameters:

  Range `range` | a random access `range` or an array; only index operator auto opIndex(size_t index) is required for ranges. The length of the `range` should be equal to the sum of `shift` and the product of `lengths`. If ad, the length of the `range` should be greater than or equal to the sum of `shift` and the product of `lengths`.
  size_t[N] `lengths` | list of `lengths` for each dimension
  size_t `shift` | index of the first element of a `range`. The first `shift` elements of `range` are ignored.
  Names | names of elements in a slice tuple. Slice tuple is a slice, which holds single set of `lengths` and strides for a number of ranges.
  ra | If yes, the array will be replaced with its pointer to improve performance. Use no for compile time function evaluation.
  ad | If yes, no assert error will be thrown for `range`, which has a length and its length is greater then the sum of `shift` and the product of `lengths`.

  Returns:
  n-dimensional slice
  Examples:
  Creates a slice from an array.

      auto slice = slice!int(5, 6, 7);
      assert(slice.length == 5);
      assert(slice.elementsCount == 5 * 6 * 7);
      static assert(is(typeof(slice) == Slice!(3, int*)));

  Examples:
  Creates a slice using `shift` parameter.

      import std.range : iota;
      auto slice = (5 * 6 * 7 + 9).iota.sliced([5, 6, 7], 9);
      assert(slice.length == 5);
      assert(slice.elementsCount == 5 * 6 * 7);
      assert(slice[0, 0, 0] == 9);

  Examples:
  Creates an 1-dimensional slice over a `range`.

      import std.range : iota;
      auto slice = 10.iota.sliced;
      assert(slice.length == 10);

  Examples:
  Vandermonde matrix

      auto vandermondeMatrix(Slice!(1, double*) x)
      {
          auto ret = slice!double(x.length, x.length);
          foreach (i; 0 .. x.length)
          foreach (j; 0 .. x.length)
              ret[i, j] = x[i] ^^ j;
          return ret;
      }

      auto x = [1.0, 2, 3, 4, 5].sliced(5);
      auto v = vandermondeMatrix(x);
      assert(v ==
          [[  1.0,   1,   1,   1,   1],
           [  1.0,   2,   4,   8,  16],
           [  1.0,   3,   9,  27,  81],
           [  1.0,   4,  16,  64, 256],
           [  1.0,   5,  25, 125, 625]]);

  Examples:
  Creates a slice composed of named elements, each one of which corresponds to a given argument. See also assumeSameStructure.

      import std.algorithm.comparison : equal;
      import std.experimental.ndslice.selection : byElement;
      import std.range : iota;

      auto alpha = 12.iota;
      auto beta = new int[12];

      auto m = sliced!("a", "b")(alpha, beta, 4, 3);
      foreach (r; m)
          foreach (e; r)
              e.b = e.a;
      assert(equal(alpha, beta));

      beta[] = 0;
      foreach (e; m.byElement)
          e.b = e.a;
      assert(equal(alpha, beta));

  Examples:
  Random access `range` primitives for slices over user defined types

      struct MyIota
      {
          //`[index]` operator overloading
          auto opIndex(size_t index)
          {
              return index;
          }
      }

      alias S = Slice!(3, MyIota);
      import std.range.primitives;
      static assert(hasLength!S);
      static assert(hasSlicing!S);
      static assert(isRandomAccessRange!S);

      auto slice = MyIota().sliced(20, 10);
      assert(slice[1, 2] == 12);
      auto sCopy = slice.save;
      assert(slice[1, 2] == 12);

  Examples:
  Slice tuple and flags

      import std.typecons : Yes, No;
      static immutable a = [1, 2, 3, 4, 5, 6];
      static immutable b = [1.0, 2, 3, 4, 5, 6];
      alias namedSliced = sliced!("a", "b");
      auto slice = namedSliced!(No.replaceArrayWithPointer, Yes.allowDownsize)
          (a, b, 2, 3);
      assert(slice[1, 2].a == slice[1, 2].b);

template `assumeSameStructure`(Names...) if (Names.length && !anySatisfy!(isType, Names) && allSatisfy!(isStringValue, Names))
  Groups slices into a slice tuple. The slices must have identical structure. Slice tuple is a slice, which holds single set of lengths and strides for a number of ranges.
  Parameters:

  Names | names of elements in a slice tuple

  Returns:
  n-dimensional slice
  See Also:
  .Slice.structure.
  Examples:

      import std.algorithm.comparison : equal;
      import std.experimental.ndslice.selection : byElement, iotaSlice;

      auto alpha = iotaSlice(4, 3);
      auto beta = slice!int(4, 3);

      auto m = assumeSameStructure!("a", "b")(alpha, beta);
      foreach (r; m)
          foreach (e; r)
              e.b = cast(int)e.a;
      assert(alpha == beta);

      beta[] = 0;
      foreach (e; m.byElement)
          e.b = cast(int)e.a;
      assert(alpha == beta);

  Examples:

      import std.algorithm.iteration : map, sum, reduce;
      import std.algorithm.comparison : max;
      import std.experimental.ndslice.iteration : transposed;
      import std.typecons : No;

      /// Returns maximal column average.
      auto maxAvg(S)(S matrix) {
          return matrix.transposed.map!sum.reduce!max
               / matrix.length;
      }
      enum matrix = [1, 2,
                     3, 4].sliced!(No.replaceArrayWithPointer)(2, 2);
      ///Сompile time function evaluation
      static assert(maxAvg(matrix) == 3);

  Examples:

      import std.algorithm.iteration : map, sum, reduce;
      import std.algorithm.comparison : max;
      import std.experimental.ndslice.iteration : transposed;
      import std.typecons : No;

      /// Returns maximal column average.
      auto maxAvg(S)(S matrix) {
          return matrix.transposed.map!sum.reduce!max
               / matrix.length;
      }
      enum matrix = [1, 2,
                     3, 4].sliced!(No.replaceArrayWithPointer)(2, 2);
      ///Сompile time function evaluation
      static assert(maxAvg(matrix) == 3);

Slice!(N, Select!(ra, T*, T[])) `slice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, size_t N)(size_t[N] `lengths`...);
auto `slice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, size_t N)(size_t[N] `lengths`, T `init`);
auto `slice`(Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, size_t N, Range)(Slice!(N, Range) `slice`);
  Creates an array and an n-dimensional `slice` over it.
  Parameters:

  size_t[N] `lengths` | list of `lengths` for each dimension
  Slice!(N, Range) `slice` | `slice` to copy shape and data from

  Returns:
  n-dimensional `slice`
  Examples:

      auto tensor = slice!int(5, 6, 7);
      assert(tensor.length == 5);
      assert(tensor.elementsCount == 5 * 6 * 7);
      static assert(is(typeof(tensor) == Slice!(3, int*)));

      // creates duplicate using `slice`
      auto dup = tensor.slice;
      assert(dup == tensor);

  Examples:

      auto tensor = slice([2, 3], 5);
      assert(tensor.elementsCount == 2 * 3);
      assert(tensor[1, 1] == 5);

auto `uninitializedSlice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, size_t N)(size_t[N] `lengths`...);
  Creates an uninitialized array and an n-dimensional slice over it.
  Parameters:

  size_t[N] `lengths` | list of `lengths` for each dimension
  slice | slice to copy shape and data from

  Returns:
  uninitialized n-dimensional slice
  Examples:

      auto tensor = uninitializedSlice!int(5, 6, 7);
      assert(tensor.length == 5);
      assert(tensor.elementsCount == 5 * 6 * 7);
      static assert(is(typeof(tensor) == Slice!(3, int*)));

auto `makeSlice`(Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Allocator, size_t N, Range)(auto ref Allocator `alloc`, Slice!(N, Range) `slice`);
SliceAllocationResult!(N, T, ra) `makeSlice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Allocator, size_t N)(auto ref Allocator `alloc`, size_t[N] `lengths`...);
SliceAllocationResult!(N, T, ra) `makeSlice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Allocator, size_t N)(auto ref Allocator `alloc`, size_t[N] `lengths`, T `init`);
SliceAllocationResult!(N, T, ra) `makeSlice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Allocator, size_t N, Range)(auto ref Allocator `alloc`, Slice!(N, Range) `slice`);
  Allocates an array through a specified allocator and creates an n-dimensional `slice` over it. See also std.experimental.allocator.
  Parameters:

  Allocator `alloc` | allocator
  size_t[N] `lengths` | list of `lengths` for each dimension
  T `init` | default value for array initialization
  Slice!(N, Range) `slice` | `slice` to copy shape and data from

  Returns:
  a structure with fields array and `slice`

  Note: `makeSlice` always returns `slice` with mutable elements

  Examples:

      import std.experimental.allocator;
      import std.experimental.allocator.mallocator;

      auto tup = makeSlice!int(Mallocator.instance, 2, 3, 4);

      assert(tup.array.length           == 24);
      assert(tup.slice.elementsCount    == 24);
      assert(tup.array.ptr == &tup.slice[0, 0, 0]);

      // makes duplicate using `makeSlice`
      tup.slice[0, 0, 0] = 3;
      auto dup = makeSlice(Mallocator.instance, tup.slice);
      assert(dup.slice == tup.slice);

      Mallocator.instance.dispose(tup.array);
      Mallocator.instance.dispose(dup.array);

  Examples:
  Initialization with default value

      import std.experimental.allocator;
      import std.experimental.allocator.mallocator;

      auto tup = makeSlice(Mallocator.instance, [2, 3, 4], 10);
      auto slice = tup.slice;
      assert(slice[1, 1, 1] == 10);
      Mallocator.instance.dispose(tup.array);

SliceAllocationResult!(N, T, ra) `makeUninitializedSlice`(T, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Allocator, size_t N)(auto ref Allocator `alloc`, size_t[N] `lengths`...);
  Allocates an uninitialized array through a specified allocator and creates an n-dimensional slice over it. See also std.experimental.allocator.
  Parameters:

  Allocator `alloc` | allocator
  size_t[N] `lengths` | list of `lengths` for each dimension
  init | default value for array initialization
  slice | slice to copy shape and data from

  Returns:
  a structure with fields array and slice
  Examples:

      import std.experimental.allocator;
      import std.experimental.allocator.mallocator;

      auto tup = makeUninitializedSlice!int(Mallocator.instance, 2, 3, 4);

      assert(tup.array.length           == 24);
      assert(tup.slice.elementsCount    == 24);
      assert(tup.array.ptr == &tup.slice[0, 0, 0]);

      Mallocator.instance.dispose(tup.array);

struct `SliceAllocationResult`(size_t N, T, Flag!"replaceArrayWithPointer" ra);
  Structure used by makeSlice and makeUninitializedSlice.
  T[] `array`;
  Slice!(N, Select!(ra, T*, T[])) `slice`;
auto `ndarray`(size_t N, Range)(Slice!(N, Range) `slice`);
  Creates a common n-dimensional array from a `slice`.
  Parameters:

  Slice!(N, Range) `slice` | `slice`

  Returns:
  multidimensional D array
  Examples:

      import std.experimental.ndslice.selection : iotaSlice;
      auto slice = iotaSlice(3, 4);
      auto m = slice.ndarray;
      static assert(is(typeof(m) == size_t[][]));
      assert(m == [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]);

auto `makeNdarray`(T, Allocator, size_t N, Range)(auto ref Allocator `alloc`, Slice!(N, Range) `slice`);
  Allocates a common n-dimensional array using data from a `slice`.
  Parameters:

  Allocator `alloc` | allocator (optional)
  Slice!(N, Range) `slice` | `slice`

  Returns:
  multidimensional D array
  Examples:

      import std.experimental.allocator;
      import std.experimental.allocator.mallocator;
      import std.experimental.ndslice.selection : iotaSlice;

      auto slice = iotaSlice(3, 4);
      auto m = Mallocator.instance.makeNdarray!long(slice);

      static assert(is(typeof(m) == long[][]));

      static immutable ar = [[0L, 1, 2, 3], [4L, 5, 6, 7], [8L, 9, 10, 11]];
      assert(m == ar);

      foreach (ref row; m)
          Mallocator.instance.dispose(row);
      Mallocator.instance.dispose(m);

@property auto `shape`(T)(T[] `array`, ref int `err`);
  Shape of a common n-dimensional `array`.
  Parameters:

  T[] `array` | common n-dimensional `array`
  int `err` | error flag

  Returns:
  static `array` of dimensions type of size_t[n]
  Examples:

      int err;
      size_t[2] shape = [[1, 2, 3], [4, 5, 6]].shape(err);
      assert(shape == [2, 3]);
      assert(err == 0);

      [[1, 2], [4, 5, 6]].shape(err);
      assert(err != 0);

  Examples:
  Slice from ndarray

      int err;
      auto array = [[1, 2, 3], [4, 5, 6]];
      auto slice = array.shape(err).slice!int;
      assert(err == 0);
      slice[] = [[1, 2, 3], [4, 5, 6]];
      assert(slice == array);

template `as`(T)
  Convenience function that creates a lazy view, where each element of the original slice is converted to the type T. It uses mapSlice and to composition under the hood.
  Parameters:

  Slice!(N, Range) slice | a slice to create a view on.

  Returns:
  A lazy slice with elements converted to the type T.
  Examples:

      import std.experimental.ndslice.slice : as;
      import std.experimental.ndslice.selection : diagonal;

      auto matrix = slice!double([2, 2], 0);
      auto stringMatrixView = matrix.as!string;
      assert(stringMatrixView ==
              [["0", "0"],
               ["0", "0"]]);

      matrix.diagonal[] = 1;
      assert(stringMatrixView ==
              [["1", "0"],
               ["0", "1"]]);

      /// allocate new slice composed of strings
      Slice!(2, string*) stringMatrix = stringMatrixView.slice;

  auto `as`(size_t N, Range)(Slice!(N, Range) `slice`);
class `SliceException`: object.Exception;
  Base Exception class for std.experimental.ndslice.
  pure nothrow @nogc @safe this(string `msg`, string `file` = __FILE__, uint `line` = cast(uint)1041, Throwable `next` = null);
template `DeepElementType`(S : Slice!(N, Range), size_t N, Range)
  Returns the element type of the Slice type.
  Examples:

      import std.range : iota;
      static assert(is(DeepElementType!(Slice!(4, const(int)[]))     == const(int)));
      static assert(is(DeepElementType!(Slice!(4, immutable(int)*))  == immutable(int)));
      static assert(is(DeepElementType!(Slice!(4, typeof(100.iota))) == int));
      //packed slice
      static assert(is(DeepElementType!(Slice!(2, Slice!(5, int*)))  == Slice!(4, int*)));

struct `Structure`(size_t N);
  Presents .Slice.structure.
  size_t[N] `lengths`;
  sizediff_t[N] `strides`;
struct `Slice`(size_t _N, _Range) if (_N && _N < 256LU && (!is(Unqual!_Range : `Slice`!(N0, Range0), size_t N0, Range0) && (isPointer!_Range || is(typeof(_Range.init[size_t.init]))) || is(_Range == `Slice`!(N1, Range1), size_t N1, Range1)));
  Presents an n-dimensional view over a range.

  ### Definitions

  In order to change data in a slice using overloaded operators such as =, +=, ++, a syntactic structure of type <slice to change>[<index and interval sequence...>] must be used. It is worth noting that just like for regular arrays, operations a = b and a[] = b have different meanings. In the first case, after the operation is carried out, a simply points at the same data as b does, and the data which a previously pointed at remains unmodified. Here, а and b must be of the same type. In the second case, a points at the same data as before, but the data itself will be changed. In this instance, the number of dimensions of b may be less than the number of dimensions of а; and b can be a `Slice`, a regular multidimensional array, or simply a value (e.g. a number).
  In the following table you will find the definitions you might come across in comments on operator overloading.

  Definition | Examples at N == 3
  --- | ---
  An interval is a part of a sequence of type i .. j. | 2..$-3, 0..4 @@@DEPRECATED_2017-04@@@
  An index is a part of a sequence of type i. | 3, $-1 @@@DEPRECATED_2017-04@@@
  A partially defined slice is a sequence composed of intervals and indexes with an overall length strictly less than N. | [3], [0..$], [3, 3], [0..$,0..3], [0..$,2] @@@DEPRECATED_2017-04@@@
  A fully defined index is a sequence composed only of indexes with an overall length equal to N. | [2,3,1] @@@DEPRECATED_2017-04@@@
  A fully defined slice is an empty sequence or a sequence composed of indexes and at least one interval with an overall length equal to N. | [], [3..$,0..3,0..$-1], [2,0..$,1] @@@DEPRECATED_2017-04@@@

  ### Internal Binary Representation

  Multidimensional `Slice` is a structure that consists of lengths, strides, and a pointer. For ranges, a shell is used instead of a pointer. This shell contains a shift of the current initial element of a multidimensional slice and the range itself. With the exception of overloaded operators, no functions in this package change or copy data. The operations are only carried out on lengths, strides, and pointers. If a slice is defined over a range, only the shift of the initial element changes instead of the pointer.

  #### Internal Representation for Pointers

  Type definition

      Slice!(N, T*)

  Schema

      Slice!(N, T*)
          size_t[N]     lengths
          sizediff_t[N] strides
          T*            ptr

  Example: Definitions

      import std.experimental.ndslice;
      auto a = new double[24];
      Slice!(3, double*) s = a.sliced(2, 3, 4);
      Slice!(3, double*) t = s.transposed!(1, 2, 0);
      Slice!(3, double*) r = t.reversed!1;

  Representation

      s________________________
          lengths[0] ::=  2
          lengths[1] ::=  3
          lengths[2] ::=  4

          strides[0] ::= 12
          strides[1] ::=  4
          strides[2] ::=  1

          ptr        ::= &a[0]

      t____transposed!(1, 2, 0)
          lengths[0] ::=  3
          lengths[1] ::=  4
          lengths[2] ::=  2

          strides[0] ::=  4
          strides[1] ::=  1
          strides[2] ::= 12

          ptr        ::= &a[0]

      r______________reversed!1
          lengths[0] ::=  2
          lengths[1] ::=  3
          lengths[2] ::=  4

          strides[0] ::= 12
          strides[1] ::= -4
          strides[2] ::=  1

          ptr        ::= &a[8] // (old_strides[1] * (lengths[1] - 1)) = 8

  #### Internal Representation for Ranges

  Type definition

      Slice!(N, Range)

  Representation

      Slice!(N, Range)
          size_t[N]     lengths
          sizediff_t[N] strides
          PtrShell!T    ptr
              sizediff_t shift
              Range      range

  Example: Definitions

      import std.experimental.ndslice;
      import std.range : iota;
      auto a = iota(24);
      alias A = typeof(a);
      Slice!(3, A) s = a.sliced(2, 3, 4);
      Slice!(3, A) t = s.transposed!(1, 2, 0);
      Slice!(3, A) r = t.reversed!1;

  Representation

      s________________________
          lengths[0] ::=  2
          lengths[1] ::=  3
          lengths[2] ::=  4

          strides[0] ::= 12
          strides[1] ::=  4
          strides[2] ::=  1

              shift  ::=  0
              range  ::=  a

      t____transposed!(1, 2, 0)
          lengths[0] ::=  3
          lengths[1] ::=  4
          lengths[2] ::=  2

          strides[0] ::=  4
          strides[1] ::=  1
          strides[2] ::= 12

              shift  ::=  0
              range  ::=  a

      r______________reversed!1
          lengths[0] ::=  2
          lengths[1] ::=  3
          lengths[2] ::=  4

          strides[0] ::= 12
          strides[1] ::= -4
          strides[2] ::=  1

              shift  ::=  8 // (old_strides[1] * (lengths[1] - 1)) = 8
              range  ::=  a

  Examples:
  Slicing, indexing, and arithmetic operations.

      import std.experimental.ndslice.iteration : transposed;
      import std.experimental.ndslice.selection : iotaSlice;
      auto tensor = iotaSlice(3, 4, 5).slice;

      assert(tensor[1, 2] == tensor[1][2]);
      assert(tensor[1, 2, 3] == tensor[1][2][3]);

      assert( tensor[0..$, 0..$, 4] == tensor.transposed!2[4]);
      assert(&tensor[0..$, 0..$, 4][1, 2] is &tensor[1, 2, 4]);

      tensor[1, 2, 3]++; //`opIndex` returns value by reference.
      --tensor[1, 2, 3]; //`opUnary`

      ++tensor[];
      tensor[] -= 1;

      // `opIndexAssing` accepts only fully defined indexes and slices.
      // Use an additional empty slice `[]`.
      static assert(!__traits(compiles, tensor[0 .. 2] *= 2));

      tensor[0 .. 2][] *= 2;          //OK, empty slice
      tensor[0 .. 2, 3, 0..$] /= 2; //OK, 3 index or slice positions are defined.

      //fully defined index may be replaced by a static array
      size_t[3] index = [1, 2, 3];
      assert(tensor[index] == tensor[1, 2, 3]);

  Examples:
  Operations with rvalue slices.

      import std.experimental.ndslice.iteration : transposed, everted;

      auto tensor = slice!int(3, 4, 5);
      auto matrix = slice!int(3, 4);
      auto vector = slice!int(3);

      foreach (i; 0..3)
          vector[i] = i;

      // fills matrix columns
      matrix.transposed[] = vector;

      // fills tensor with vector
      // transposed tensor shape is (4, 5, 3)
      //            vector shape is (      3)
      tensor.transposed!(1, 2)[] = vector;

      // transposed tensor shape is (5, 3, 4)
      //            matrix shape is (   3, 4)
      tensor.transposed!2[] += matrix;

      // transposed tensor shape is (5, 4, 3)
      // transposed matrix shape is (   4, 3)
      tensor.everted[] ^= matrix.transposed; // XOR

  Examples:
  Creating a slice from text. See also std.format.

      import std.algorithm,  std.conv, std.exception, std.format,
          std.functional, std.string, std.range;

      Slice!(2, int*) toMatrix(string str)
      {
          string[][] data = str.lineSplitter.filter!(not!empty).map!split.array;

          size_t rows    = data   .length.enforce("empty input");
          size_t columns = data[0].length.enforce("empty first row");

          data.each!(a => enforce(a.length == columns, "rows have different lengths"));

          auto slice = slice!int(rows, columns);
          foreach (i, line; data)
              foreach (j, num; line)
                  slice[i, j] = num.to!int;
          return slice;
      }

      auto input = "\r1 2  3\r\n 4 5 6\n";

      auto matrix = toMatrix(input);
      assert(matrix == [[1, 2, 3], [4, 5, 6]]);

      // back to text
      auto text2 = format("%(%(%s %)\n%)\n", matrix);
      assert(text2 == "1 2 3\n4 5 6\n");

  size_t[PureN] `_lengths`;
    Direct access to the lengths. Use for ndslice plugins only.
  sizediff_t[PureN] `_strides`;
    Direct access to the strides. Use for ndslice plugins only.
  SlicePtr!PureRange `_ptr`;
    Direct access to the pointer. Use for ndslice plugins only.
  this(in size_t[PureN] `lengths`, in sizediff_t[PureN] `strides`, PureRange `range`);
    This constructor should be used only for integration with other languages or libraries such as Julia and numpy.
    Parameters:

    size_t[PureN] `lengths` | `lengths`
    sizediff_t[PureN] `strides` | `strides`
    PureRange `range` | `range` or pointer to iterate on

    Examples:
    Creates a 2-dimentional slice with custom `strides`.

        import std.experimental.ndslice.selection : byElement;
        import std.algorithm.comparison : equal;
        import std.range : only;

        uint[8] array = [1, 2, 3, 4, 5, 6, 7, 8];
        auto slice = Slice!(2, uint*)([2, 2], [4, 1], array.ptr);

        assert(&slice[0, 0] == &array[0]);
        assert(&slice[0, 1] == &array[1]);
        assert(&slice[1, 0] == &array[4]);
        assert(&slice[1, 1] == &array[5]);
        assert(slice.byElement.equal(only(1, 2, 5, 6)));

        array[2] = 42;
        assert(slice.byElement.equal(only(1, 2, 5, 6)));

        array[1] = 99;
        assert(slice.byElement.equal(only(1, 99, 5, 6)));

  const pure nothrow @nogc ref @trusted ConstThis `toConst`();
    Implicit cast to const slices in case of underlaying range is a pointer.
  @property auto `ptr`();
    Returns:
    Pointer to the first element of a slice if slice is defined as Slice!(N, T*) or plain structure with two fields shift and range otherwise. In second case the expression range[shift] refers to the first element. For slices with named elements the type of a return value has the same behavior like a pointer.

    Note: `ptr` is defined only for non-packed slices.

    Attention: `ptr` refers to the first element in the memory representation if and only if all strides are positive.

  const @property size_t[N] `shape`();
    Returns:
    static array of lengths
    See Also:
    .Slice.structure
    Examples:
    Regular slice

        import std.experimental.ndslice.selection : iotaSlice;
        assert(iotaSlice(3, 4, 5)
            .shape == cast(size_t[3])[3, 4, 5]);

    Examples:
    Packed slice

        import std.experimental.ndslice.selection : pack, iotaSlice;
        assert(iotaSlice(3, 4, 5, 6, 7)
            .pack!2
            .shape == cast(size_t[3])[3, 4, 5]);

  const @property Structure!N `structure`();
    Returns:
    static array of lengths and static array of strides
    See Also:
    .Slice.shape
    Examples:
    Regular slice

        import std.experimental.ndslice.selection : iotaSlice;
        assert(iotaSlice(3, 4, 5)
            .structure == Structure!3([3, 4, 5], [20, 5, 1]));

    Examples:
    Modified regular slice

        import std.experimental.ndslice.selection : pack, iotaSlice;
        import std.experimental.ndslice.iteration : reversed, strided, transposed;
        assert(iotaSlice(3, 4, 50)
            .reversed!2      //makes stride negative
            .strided!2(6)    //multiplies stride by 6 and changes corresponding length
            .transposed!2    //brings dimension `2` to the first position
            .structure == Structure!3([9, 3, 4], [-6, 200, 50]));

    Examples:
    Packed slice

        import std.experimental.ndslice.selection : pack, iotaSlice;
        assert(iotaSlice(3, 4, 5, 6, 7)
            .pack!2
            .structure == Structure!3([3, 4, 5], [20 * 42, 5 * 42, 1 * 42]));

  @property auto `save`();
    Forward range primitive.
    Examples:
    Forward range

        import std.experimental.ndslice.selection : iotaSlice;
        auto slice = iotaSlice(2, 3).save;

    Examples:
    Pointer type.

        //slice type is `Slice!(2, int*)`
        auto slice = slice!int(2, 3).save;

  const @property size_t `length`(size_t dimension = 0)()
  if (dimension < N);
    Multidimensional `length` property.
    Returns:
    `length` of the corresponding dimension
    See Also:
    .Slice.shape, .Slice.structure
    Examples:

        import std.experimental.ndslice.selection : iotaSlice;
        auto slice = iotaSlice(3, 4, 5);
        assert(slice.length   == 3);
        assert(slice.length!0 == 3);
        assert(slice.length!1 == 4);
        assert(slice.length!2 == 5);

  const @property sizediff_t `stride`(size_t dimension = 0)()
  if (dimension < N);
    Multidimensional `stride` property.
    Returns:
    `stride` of the corresponding dimension
    See Also:
    .Slice.structure
    Examples:
    Regular slice

        import std.experimental.ndslice.selection : iotaSlice;
        auto slice = iotaSlice(3, 4, 5);
        assert(slice.stride   == 20);
        assert(slice.stride!0 == 20);
        assert(slice.stride!1 == 5);
        assert(slice.stride!2 == 1);

    Examples:
    Modified regular slice

        import std.experimental.ndslice.iteration : reversed, strided, swapped;
        import std.experimental.ndslice.selection : iotaSlice;
        assert(iotaSlice(3, 4, 50)
            .reversed!2      //makes stride negative
            .strided!2(6)    //multiplies stride by 6 and changes the corresponding length
            .swapped!(1, 2)  //swaps dimensions `1` and `2`
            .stride!1 == -6);

  const @property bool `empty`(size_t dimension = 0)()
  if (dimension < N);
  @property ref auto `front`(size_t dimension = 0)()
  if (dimension < N);
  @property auto `front`(size_t dimension = 0, T)(T `value`)
  if (dimension == 0);
  @property ref auto `back`(size_t dimension = 0)()
  if (dimension < N);
  @property auto `back`(size_t dimension = 0, T)(T `value`)
  if (dimension == 0);
  void `popFront`(size_t dimension = 0)()
  if (dimension < N);
  void `popBack`(size_t dimension = 0)()
  if (dimension < N);
  void `popFrontExactly`(size_t dimension = 0)(size_t `n`)
  if (dimension < N);
  void `popBackExactly`(size_t dimension = 0)(size_t `n`)
  if (dimension < N);
  void `popFrontN`(size_t dimension = 0)(size_t `n`)
  if (dimension < N);
  void `popBackN`(size_t dimension = 0)(size_t `n`)
  if (dimension < N);
    Multidimensional input range primitive.
    Examples:

        import std.range.primitives;
        import std.experimental.ndslice.selection : iotaSlice;
        auto slice = iotaSlice(10, 20, 30);

        static assert(isRandomAccessRange!(typeof(slice)));
        static assert(hasSlicing!(typeof(slice)));
        static assert(hasLength!(typeof(slice)));

        assert(slice.shape == cast(size_t[3])[10, 20, 30]);
        slice.popFront;
        slice.popFront!1;
        slice.popBackExactly!2(4);
        assert(slice.shape == cast(size_t[3])[9, 19, 26]);

        auto matrix = slice.front!1;
        assert(matrix.shape == cast(size_t[2])[9, 26]);

        auto column = matrix.back!1;
        assert(column.shape == cast(size_t[1])[9]);

        slice.popFrontExactly!1(slice.length!1);
        assert(slice.empty   == false);
        assert(slice.empty!1 == true);
        assert(slice.empty!2 == false);
        assert(slice.shape == cast(size_t[3])[9, 0, 26]);

        assert(slice.back.front!1.empty);

        slice.popFrontN!0(40);
        slice.popFrontN!2(40);
        assert(slice.shape == cast(size_t[3])[0, 0, 0]);

  const bool `anyEmpty`();
    Returns:
    true if for any dimension the length equals to 0, and false otherwise.
    Examples:

        import std.experimental.ndslice.selection : iotaSlice;
        auto s = iotaSlice(2, 3);
        assert(!s.anyEmpty);
        s.popFrontExactly!1(3);
        assert(s.anyEmpty);

  ref auto `backward`(size_t[N] `index`);
    Convenience function for `backward` indexing.
    Returns:
    this[$-`index`[0], $-`index`[1], ..., $-`index`[N-1]]
    Examples:

        import std.experimental.ndslice.selection : iotaSlice;
        auto s = iotaSlice(2, 3);
        assert(s[$ - 1, $ - 2] == s.backward([1, 2]));

  const size_t `elementsCount`();
    Returns:
    Total number of elements in a slice
    Examples:
    Regular slice

        import std.experimental.ndslice.selection : iotaSlice;
        assert(iotaSlice(3, 4, 5).elementsCount == 60);

    Examples:
    Packed slice

        import std.experimental.ndslice.selection : pack, evertPack, iotaSlice;
        auto slice = iotaSlice(3, 4, 5, 6, 7, 8);
        auto p = slice.pack!2;
        assert(p.elementsCount == 360);
        assert(p[0, 0, 0, 0].elementsCount == 56);
        assert(p.evertPack.elementsCount == 56);

  bool `opEquals`(size_t NR, RangeR)(Slice!(NR, RangeR) `rslice`)
  if (Slice!(NR, RangeR).PureN == PureN);
  bool `opEquals`(T)(T[] `rarrary`);
    Overloading == and !=
    Examples:

        auto a = [1, 2, 3, 4].sliced(2, 2);

        assert(a != [1, 2, 3, 4, 5, 6].sliced(2, 3));
        assert(a != [[1, 2, 3], [4, 5, 6]]);

        assert(a == [1, 2, 3, 4].sliced(2, 2));
        assert(a == [[1, 2], [3, 4]]);

        assert(a != [9, 2, 3, 4].sliced(2, 2));
        assert(a != [[9, 2], [3, 4]]);

  const @safe size_t `toHash`();
    Computes hash value using MurmurHash3 algorithms without the finalization step. Built-in associative arrays have the finalization step.
    Returns:
    Hash value type of size_t.
    See Also:
    Slice.toMurmurHash3, std.digest.murmurhash.
    Examples:

        import std.experimental.ndslice.selection : iotaSlice;
        const sl = iotaSlice(3, 7);
        size_t hash = sl.toHash;

    Examples:

        import std.experimental.ndslice.iteration : allReversed;
        import std.experimental.ndslice.selection : iotaSlice;

        // hash is the same for allocated data and for generated data
        auto a = iotaSlice(3, 7);
        auto b = iotaSlice(3, 7).slice;

        assert(a.toHash == b.toHash);
        assert(typeid(typeof(a)).getHash(&a) == typeid(typeof(b)).getHash(&b));

        // hash does not depend on strides
        a = iotaSlice(3, 7).allReversed;
        b = iotaSlice(3, 7).allReversed.slice;

        assert(a.toHash == b.toHash);
        assert(typeid(typeof(a)).getHash(&a) == typeid(typeof(b)).getHash(&b));

  const @trusted auto `toMurmurHash3`(uint size, uint opt = size_t.sizeof == 8 ? 64 : 32)();
    Computes hash value using MurmurHash3 algorithms without the finalization step.
    Returns:
    Hash value type of MurmurHash3!(size, opt).get().
    See Also:
    Slice.toHash, std.digest.murmurhash
  ref auto `opIndex`(size_t I)(size_t[I] `_indexes`...)
  if (I && I <= N);
  ref auto `opCall`()(size_t[N] `_indexes`...);
    Examples:

        auto slice = slice!int(5, 2);

        auto q = &slice[3, 1];      // D & C order
        auto p = &slice(1, 3);      // Math & Fortran order
        assert(p is q);
        *q = 4;
        assert(slice[3, 1] == 4);   // D & C order
        assert(slice(1, 3) == 4);   // Math & Fortran order

        size_t[2] indexP = [1, 3];
        size_t[2] indexQ = [3, 1];
        assert(slice[indexQ] == 4);  // D & C order
        assert(slice(indexP) == 4);  // Math & Fortran order

  auto `opIndex`(Slices...)(Slices `slices`)
  if (isPureSlice!Slices);
    Examples:

        auto slice = slice!int(5, 3);

        /// Fully defined slice
        assert(slice[] == slice);
        auto sublice = slice[0..$-2, 1..$];

        /// Partially defined slice
        auto row = slice[3];
        auto col = slice[0..$, 1];

  void `opIndexAssign`(size_t RN, RRange, Slices...)(Slice!(RN, RRange) `value`, Slices `slices`)
  if (isFullPureSlice!Slices && RN <= ReturnType!(opIndex!Slices).N);
    Assignment of a `value` of Slice type to a fully defined slice.

    Optimization: SIMD instructions may be used if both `slices` have the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);
        auto b = [1, 2, 3, 4].sliced(2, 2);

        a[0..$, 0..$-1] = b;
        assert(a == [[1, 2, 0], [3, 4, 0]]);

        // fills both rows with b[0]
        a[0..$, 0..$-1] = b[0];
        assert(a == [[1, 2, 0], [1, 2, 0]]);

        a[1, 0..$-1] = b[1];
        assert(a[1] == [3, 4, 0]);

        a[1, 0..$-1][] = b[0];
        assert(a[1] == [1, 2, 0]);

    Examples:
    Left slice is packed

        import std.experimental.ndslice.selection : blocks, iotaSlice;
        auto a = slice!size_t(4, 4);
        a.blocks(2, 2)[] = iotaSlice(2, 2);

        assert(a ==
                [[0, 0, 1, 1],
                 [0, 0, 1, 1],
                 [2, 2, 3, 3],
                 [2, 2, 3, 3]]);

    Examples:
    Both `slices` are packed

        import std.experimental.ndslice.selection : blocks, iotaSlice, pack;
        auto a = slice!size_t(4, 4);
        a.blocks(2, 2)[] = iotaSlice(2, 2, 2).pack!1;

        assert(a ==
                [[0, 1, 2, 3],
                 [0, 1, 2, 3],
                 [4, 5, 6, 7],
                 [4, 5, 6, 7]]);

  void `opIndexAssign`(T, Slices...)(T[] `value`, Slices `slices`)
  if (isFullPureSlice!Slices && !isDynamicArray!DeepElemType && DynamicArrayDimensionsCount!(T[]) <= ReturnType!(opIndex!Slices).N);
    Assignment of a regular multidimensional array to a fully defined slice.

    Optimization: SIMD instructions may be used if the slice has the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);
        auto b = [[1, 2], [3, 4]];

        a[] = [[1, 2, 3], [4, 5, 6]];
        assert(a == [[1, 2, 3], [4, 5, 6]]);

        a[0..$, 0..$-1] = [[1, 2], [3, 4]];
        assert(a == [[1, 2, 3], [3, 4, 6]]);

        a[0..$, 0..$-1] = [1, 2];
        assert(a == [[1, 2, 3], [1, 2, 6]]);

        a[1, 0..$-1] = [3, 4];
        assert(a[1] == [3, 4, 6]);

        a[1, 0..$-1][] = [3, 4];
        assert(a[1] == [3, 4, 6]);

    Examples:
    Packed `slices`

        import std.experimental.ndslice.selection : blocks;
        auto a = slice!int(4, 4);
        a.blocks(2, 2)[] = [[0, 1], [2, 3]];

        assert(a ==
                [[0, 0, 1, 1],
                 [0, 0, 1, 1],
                 [2, 2, 3, 3],
                 [2, 2, 3, 3]]);

  void `opIndexAssign`(T, Slices...)(T `value`, Slices `slices`)
  if (isFullPureSlice!Slices && (!isDynamicArray!T || isDynamicArray!DeepElemType) && !is(T : Slice!(RN, RRange), size_t RN, RRange));
    Assignment of a `value` (e.g. a number) to a fully defined slice.

    Optimization: SIMD instructions may be used if the slice has the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);

        a[] = 9;
        assert(a == [[9, 9, 9], [9, 9, 9]]);

        a[0..$, 0..$-1] = 1;
        assert(a == [[1, 1, 9], [1, 1, 9]]);

        a[0..$, 0..$-1] = 2;
        assert(a == [[2, 2, 9], [2, 2, 9]]);

        a[1, 0..$-1] = 3;
        assert(a[1] == [3, 3, 9]);

        a[1, 0..$-1] = 4;
        assert(a[1] == [4, 4, 9]);

        a[1, 0..$-1][] = 5;
        assert(a[1] == [5, 5, 9]);

    Examples:
    Packed `slices` have the same behavior.

        import std.experimental.ndslice.selection : pack;
        auto a = slice!int(2, 3).pack!1;

        a[] = 9;
        assert(a == [[9, 9, 9], [9, 9, 9]]);

  ref auto `opIndexAssign`(T)(T `value`, size_t[N] `_indexes`...);
    Assignment of a `value` (e.g. a number) to a fully defined index.
    Examples:

        auto a = slice!int(2, 3);

        a[1, 2] = 3;
        assert(a[1, 2] == 3);

  ref auto `opIndexOpAssign`(string op, T)(T `value`, size_t[N] `_indexes`...);
    Op Assignment op= of a `value` (e.g. a number) to a fully defined index.
    Examples:

        auto a = slice!int(2, 3);

        a[1, 2] += 3;
        assert(a[1, 2] == 3);

  void `opIndexOpAssign`(string op, size_t RN, RRange, Slices...)(Slice!(RN, RRange) `value`, Slices `slices`)
  if (isFullPureSlice!Slices && RN <= ReturnType!(opIndex!Slices).N);
    Op Assignment op= of a `value` of Slice type to a fully defined slice.

    Optimization: SIMD instructions may be used if both `slices` have the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);
        auto b = [1, 2, 3, 4].sliced(2, 2);

        a[0..$, 0..$-1] += b;
        assert(a == [[1, 2, 0], [3, 4, 0]]);

        a[0..$, 0..$-1] += b[0];
        assert(a == [[2, 4, 0], [4, 6, 0]]);

        a[1, 0..$-1] += b[1];
        assert(a[1] == [7, 10, 0]);

        a[1, 0..$-1][] += b[0];
        assert(a[1] == [8, 12, 0]);

    Examples:
    Left slice is packed

        import std.experimental.ndslice.selection : blocks, iotaSlice;
        auto a = slice!size_t(4, 4);
        a.blocks(2, 2)[] += iotaSlice(2, 2);

        assert(a ==
                [[0, 0, 1, 1],
                 [0, 0, 1, 1],
                 [2, 2, 3, 3],
                 [2, 2, 3, 3]]);

    Examples:
    Both `slices` are packed

        import std.experimental.ndslice.selection : blocks, iotaSlice, pack;
        auto a = slice!size_t(4, 4);
        a.blocks(2, 2)[] += iotaSlice(2, 2, 2).pack!1;

        assert(a ==
                [[0, 1, 2, 3],
                 [0, 1, 2, 3],
                 [4, 5, 6, 7],
                 [4, 5, 6, 7]]);

  void `opIndexOpAssign`(string op, T, Slices...)(T[] `value`, Slices `slices`)
  if (isFullPureSlice!Slices && !isDynamicArray!DeepElemType && DynamicArrayDimensionsCount!(T[]) <= ReturnType!(opIndex!Slices).N);
    Op Assignment op= of a regular multidimensional array to a fully defined slice.

    Optimization: SIMD instructions may be used if the slice has the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);

        a[0..$, 0..$-1] += [[1, 2], [3, 4]];
        assert(a == [[1, 2, 0], [3, 4, 0]]);

        a[0..$, 0..$-1] += [1, 2];
        assert(a == [[2, 4, 0], [4, 6, 0]]);

        a[1, 0..$-1] += [3, 4];
        assert(a[1] == [7, 10, 0]);

        a[1, 0..$-1][] += [1, 2];
        assert(a[1] == [8, 12, 0]);

    Examples:
    Packed `slices`

        import std.experimental.ndslice.selection : blocks;
        auto a = slice!int(4, 4);
        a.blocks(2, 2)[] += [[0, 1], [2, 3]];

        assert(a ==
                [[0, 0, 1, 1],
                 [0, 0, 1, 1],
                 [2, 2, 3, 3],
                 [2, 2, 3, 3]]);

    Examples:
    Packed `slices` have the same behavior.

        import std.experimental.ndslice.selection : pack;
        auto a = slice!int(2, 3).pack!1;

        a[] += 9;
        assert(a == [[9, 9, 9], [9, 9, 9]]);

  void `opIndexOpAssign`(string op, T, Slices...)(T `value`, Slices `slices`)
  if (isFullPureSlice!Slices && (!isDynamicArray!T || isDynamicArray!DeepElemType) && !is(T : Slice!(RN, RRange), size_t RN, RRange));
    Op Assignment op= of a `value` (e.g. a number) to a fully defined slice.

    Optimization: SIMD instructions may be used if the slice has the last stride equals to 1.

    Examples:

        auto a = slice!int(2, 3);

        a[] += 1;
        assert(a == [[1, 1, 1], [1, 1, 1]]);

        a[0..$, 0..$-1] += 2;
        assert(a == [[3, 3, 1], [3, 3, 1]]);

        a[1, 0..$-1] += 3;
        assert(a[1] == [6, 6, 1]);

  ref auto `opIndexUnary`(string op)(size_t[N] `_indexes`...);
    Increment ++ and Decrement -- operators for a fully defined index.
    Examples:

        auto a = slice!int(2, 3);

        ++a[1, 2];
        assert(a[1, 2] == 1);

  void `opIndexUnary`(string op, Slices...)(Slices `slices`)
  if (isFullPureSlice!Slices && (op == "++" || op == "--"));
    Increment ++ and Decrement -- operators for a fully defined slice.
    Examples:

        auto a = slice!int(2, 3);

        ++a[];
        assert(a == [[1, 1, 1], [1, 1, 1]]);

        --a[1, 0..$-1];
        assert(a[1] == [0, 0, 1]);

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