D Programming Language
Report a bug If you spot a problem with this page, click here to create a Bugzilla issue. Improve this page Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

# std.experimental.ndslice.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(ReplaceArrayWithPointer mod = ReplaceArrayWithPointer.yes, Range, Lengths...)(Range range, Lengths lengths) if (!isStaticArray!Range && !isNarrowString!Range && allSatisfy!(isIndex, Lengths) && Lengths.length);
auto sliced(ReplaceArrayWithPointer mod = ReplaceArrayWithPointer.yes, size_t N, Range)(Range range, auto ref 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))
  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 must be greater than or equal to the sum of shift and the product of lengths.
  Lengths 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.

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

      auto slice = new int [1000].sliced(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 = 1000.iota.sliced([5, 6, 7], 9);
      assert(slice.length == 5);
      assert(slice.elementsCount == 5 * 6 * 7);
      assert(slice[0, 0, 0] == 9);

  Examples:
  Vandermonde matrix

      pure nothrow
      Slice!(2, double*) vandermondeMatrix(Slice!(1, double*) x)
      {
          auto ret = new double[x.length ^^ 2]
              .sliced(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:
  Creates an array and an n-dimensional slice over it.

      auto createSlice(T, Lengths...)(Lengths lengths)
      {
          return createSlice2!(T, Lengths.length)(cast(size_t[Lengths.length])[lengths]);
      }

      ///ditto
      auto createSlice2(T, size_t N)(auto ref size_t[N] lengths)
      {
          size_t length = lengths[0];
          foreach (len; lengths[1 .. N])
                  length *= len;
          return new T[length].sliced(lengths);
      }

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

      auto duplicate = createSlice2!int(slice.shape);
      duplicate[] = slice;

  Examples:
  Creates a common n-dimensional array.

      auto ndarray(size_t N, Range)(auto ref Slice!(N, Range) slice)
      {
          import std.array: array;
          static if (N == 1)
          {
              return slice.array;
          }
          else
          {
              import std.algorithm.iteration: map;
              return slice.map!(a => ndarray(a)).array;
          }
      }

      import std.range: iota;
      auto ar = ndarray(100.iota.sliced(3, 4));
      static assert(is(typeof(ar) == int[][]));
      assert(ar == [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]);

  Examples:
  Allocates an array through a specified allocator and creates an n-dimensional slice over it. See also std.experimental.allocator.

      import std.experimental.allocator;

      // `theAllocator.makeSlice(3, 4)` allocates an array with length equal to `12`
      // and returns this array and a `2`-dimensional slice-shell over it.
      auto makeSlice(T, Allocator, Lengths...)(auto ref Allocator alloc, Lengths lengths)
      {
          enum N = Lengths.length;
          struct Result { T[] array; Slice!(N, T*) slice; }
          size_t length = lengths[0];
          foreach (len; lengths[1 .. N])
                  length *= len;
          T[] a = alloc.makeArray!T(length);
          return Result(a, a.sliced(lengths));
      }

      auto tup = makeSlice!int(theAllocator, 2, 3, 4);

      static assert(is(typeof(tup.array) == int[]));
      static assert(is(typeof(tup.slice) == Slice!(3, int*)));

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

      theAllocator.dispose(tup.array);

  Examples:
  Input 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);
      auto slice = MyIota().sliced(20, 10);

      import std.range.primitives;
      static assert(hasLength!S);
      static assert(isInputRange!S);
      static assert(isForwardRange!S == false);

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

      struct MyIota
      {
          //`[index]` operator overloading
          auto opIndex(size_t index)
          {
              return index;
          }
          // `save` property to allow a slice to be a forward range
          auto save() @property
          {
              return this;
          }
      }

      alias S = Slice!(3, MyIota);
      auto slice = MyIota().sliced(20, 10);

      import std.range.primitives;
      static assert(hasLength!S);
      static assert(hasSlicing!S);
      static assert(isForwardRange!S);
      static assert(isBidirectionalRange!S);
      static assert(isRandomAccessRange!S);

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;
      import std.range: iota;

      auto alpha = 12.iota   .sliced(4, 3);
      auto beta = new int[12].sliced(4, 3);

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

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

alias ReplaceArrayWithPointer = std.typecons.Flag!"replaceArrayWithPointer".Flag;
  If yes, the array will be replaced with its pointer to improve performance. Use no for compile time function evaluation.
  Examples:

      import std.algorithm.iteration: map, sum, reduce;
      import std.algorithm.comparison: max;
      import std.experimental.ndslice.iteration: transposed;
      /// 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!(ReplaceArrayWithPointer.no)(2, 2);
      ///Сompile time function evaluation
      static assert(maxAvg(matrix) == 3);

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
  An index is a part of a sequence of type i. | 3, $-1
  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]
  A fully defined index is a sequence composed only of indexes with an overall length equal to N. | [2,3,1]
  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]

  ### 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 = r.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 = r.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.array: array;
      import std.range: iota;
      import std.experimental.ndslice.iteration: transposed;

      auto tensor = 60.iota.array.sliced(3, 4, 5);

      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 = new int[60].sliced(3, 4, 5);
      auto matrix = new int[12].sliced(3, 4);
      auto vector = new int[ 3].sliced(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 = new int[rows * columns].sliced(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");

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

        import std.range: iota;
        assert(100.iota
            .sliced(3, 4, 5)
            .shape == cast(size_t[3])[3, 4, 5]);

    Examples:
    Packed slice

        import std.experimental.ndslice.selection: pack;
        import std.range: iota;
        assert(10000.iota
            .sliced(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.range: iota;
        assert(100.iota
            .sliced(3, 4, 5)
            .structure == Structure!3([3, 4, 5], [20, 5, 1]));

    Examples:
    Modified regular slice

        import std.experimental.ndslice.selection: pack;
        import std.experimental.ndslice.iteration: reversed, strided, transposed;
        import std.range: iota;
        assert(1000.iota
            .sliced(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;
        import std.range: iota;
        assert(10000.iota
            .sliced(3, 4, 5, 6, 7)
            .pack!2
            .structure == Structure!3([3, 4, 5], [20 * 42, 5 * 42, 1 * 42]));

  @property auto save();
    Range primitive. Defined only if Range is a forward range or a pointer type.
    Examples:
    Forward range

        import std.range: iota;
        auto slice = 100.iota.sliced(2, 3).save;

    Examples:
    Pointer type.

        //slice type is `Slice!(2, int*)`
        auto slice = new int[6].sliced(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.range: iota;
        auto slice = 100.iota.sliced(3, 4, 5);
        assert(slice.length   == 3);
        assert(slice.length!0 == 3);
        assert(slice.length!1 == 4);
        assert(slice.length!2 == 5);

  const @property size_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.range: iota;
        auto slice = 100.iota.sliced(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.range: iota;
        assert(1000.iota
            .sliced(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: iota;
        import std.range.primitives;
        auto slice = 10000.iota.sliced(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 size_t elementsCount();
    Returns:
    total number of elements in a slice
    Examples:
    Regular slice

        import std.range: iota;
        assert(100.iota.sliced(3, 4, 5).elementsCount == 60);

    Examples:
    Packed slice

        import std.experimental.ndslice.selection: pack, evertPack;
        import std.range: iota;
        auto slice = 50000.iota.sliced(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)(auto ref 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]]);

  ref auto opIndex(Indexes...)(Indexes _indexes) if (isFullPureIndex!Indexes);
    Fully defined index.
    Examples:

        auto slice = new int[10].sliced(5, 2);

        auto p = &slice[1, 1];
        *p = 3;
        assert(slice[1, 1] == 3);

        size_t[2] index = [1, 1];
        assert(slice[index] == 3);

  auto opIndex(Slices...)(Slices slices) if (isPureSlice!Slices);
    Partially or fully defined slice.
    Examples:

        auto slice = new int[15].sliced(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.
    Examples:

        auto a = new int[6].sliced(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 == [[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]);

  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.
    Examples:

        auto a = new int[6].sliced(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]);

  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.
    Examples:

        auto a = new int[6].sliced(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]);

  ref auto opIndexAssign(T, Indexes...)(T value, Indexes _indexes) if (isFullPureIndex!Indexes);
    Assignment of a value (e.g. a number) to a fully defined index.
    Examples:

        auto a = new int[6].sliced(2, 3);

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

  ref auto opIndexOpAssign(string op, T, Indexes...)(T value, Indexes _indexes) if (isFullPureIndex!Indexes);
    Op Assignment op= of a value (e.g. a number) to a fully defined index.
    Examples:

        auto a = new int[6].sliced(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.
    Examples:

        auto a = new int[6].sliced(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]);

  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.
    Examples:

        auto a = new int[6].sliced(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]);

  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.
    Examples:

        auto a = new int[6].sliced(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, Indexes...)(Indexes _indexes) if (isFullPureIndex!Indexes && (op == "++" || op == "--"));
    Increment ++ and Decrement -- operators for a fully defined index.
    Examples:

        auto a = new int[6].sliced(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 = new int[6].sliced(2, 3);

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

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

Copyright © 1999-2016 by Digital Mars ®, All Rights Reserved | Page generated by Ddoc on Sat Feb 27 18:58:51 2016