Report a bug
If you spot a problem with this page, click here to create a GitHub 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.
mir.ndslice.slice
This is a submodule of mir.ndslice.
Safety note User-defined iterators should care about their safety except bounds checks. Bounds are checked in ndslice code.
License:
Authors:
Ilya Yaroshenko
Name | Description |
---|---|
Slice | N-dimensional slice. |
SliceKind | SliceKind of Slice enumeration. |
Universal | Alias for .SliceKind.universal. |
Canonical | Alias for .SliceKind.canonical. |
Contiguous | Alias for .SliceKind.contiguous. |
sliced | Creates a slice on top of an iterator, a pointer, or an array's pointer. |
slicedField | Creates a slice on top of a field, a random access range, or an array. |
slicedNdField | Creates a slice on top of an ndField. |
kindOf | Extracts SliceKind. |
isSlice | Checks if the type is Slice instance. |
Structure | A tuple of lengths and strides. |
- template
hasAsSlice
(T) - Checks if type T has asSlice property and its returns a slices. Aliases itself to a dimension countExamples:
import mir.series; static assert(!hasAsSlice!(int[])); static assert(hasAsSlice!(SeriesMap!(int, string)) == 1);
- enum auto
isConvertibleToSlice
(T); - Check if toConst function can be called with type T.Examples:
import mir.series: SeriesMap; static assert(isConvertibleToSlice!(immutable int[])); static assert(isConvertibleToSlice!(string[])); static assert(isConvertibleToSlice!(SeriesMap!(string, int))); static assert(isConvertibleToSlice!(Slice!(int*)));
- auto
toSlice
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)val
);
autotoSlice
(Iterator, size_t N, SliceKind kind)(const Slice!(Iterator, N, kind)val
);
autotoSlice
(Iterator, size_t N, SliceKind kind)(immutable Slice!(Iterator, N, kind)val
);
autotoSlice
(T)(T[]val
);
autotoSlice
(T)(Tval
)
if (hasAsSlice!T || __traits(hasMember, T, "moveToSlice"));
autotoSlice
(T)(ref Tval
)
if (hasAsSlice!T); Reurns Ndslice view in the same data.
See Also:- template
toSlices
(args...) - enum auto
isSlice
(T); - Checks if the type is Slice instance.Examples:
alias A = uint[]; alias S = Slice!(int*); static assert(isSlice!S); static assert(!isSlice!A);
- enum
mir_slice_kind
: int;
aliasSliceKind
= mir_slice_kind; - SliceKind of Slice.See Also:
universal
- A slice has strides for all dimensions.
canonical
- A slice has >=2 dimensions and row dimension is contiguous.
contiguous
- A slice is a flat contiguous data without strides.
- alias
Universal
= mir_slice_kind.universal; - Alias for .SliceKind.universal.See Also:Internal Binary Representation section in Slice.
- alias
Canonical
= mir_slice_kind.canonical; - Alias for .SliceKind.canonical.See Also:Internal Binary Representation section in Slice.
- alias
Contiguous
= mir_slice_kind.contiguous; - Alias for .SliceKind.contiguous.See Also:Internal Binary Representation section in Slice.
- enum auto
kindOf
(T : Slice!(Iterator, N, kind), Iterator, size_t N, SliceKind kind); - Extracts SliceKind.Examples:
static assert(kindOf!(Slice!(int*, 1, Universal)) == Universal);
- template
IteratorOf
(T : Slice!(Iterator, N, kind), Iterator, size_t N, SliceKind kind) - Extracts iterator type from a Slice.
- auto
sliced
(size_t N, Iterator)(Iteratoriterator
, size_t[N]lengths
...)
if (!__traits(isStaticArray, Iterator) && N && !is(Iterator : Slice!(_Iterator, _N, kind), _Iterator, size_t _N, SliceKind kind)); - Creates an n-dimensional slice-shell over an iterator.Parameters:
Iterator iterator
An iterator, a pointer, or an array. size_t[N] lengths
A list of lengths for each dimension Returns:n-dimensional sliceExamples:Random access range primitives for slices over user defined typesstruct MyIota { //`[index]` operator overloading auto opIndex(size_t index) @safe nothrow { return index; } auto lightConst()() const @property { return MyIota(); } auto lightImmutable()() immutable @property { return MyIota(); } } import mir.ndslice.iterator: FieldIterator; alias Iterator = FieldIterator!MyIota; alias S = Slice!(Iterator, 2); import std.range.primitives; static assert(hasLength!S); static assert(hasSlicing!S); static assert(isRandomAccessRange!S); auto slice = Iterator().sliced(20, 10); assert(slice[1, 2] == 12); auto sCopy = slice.save; assert(slice[1, 2] == 12);
- @trusted Slice!(T*)
sliced
(T)(T[]array
); - Creates an 1-dimensional slice-shell over an array.Parameters:
T[] array
An array. Returns:1-dimensional sliceExamples:Creates a slice from an array.auto slice = new int[10].sliced; assert(slice.length == 10); static assert(is(typeof(slice) == Slice!(int*)));
- Slice!(Iterator, N, kind)
sliced
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, 1, kind)slice
, size_t[N]lengths
...)
if (N); - Creates an n-dimensional slice-shell over the 1-dimensional input slice.Parameters:
Slice!(Iterator, 1, kind) slice
slice size_t[N] lengths
A list of lengths for each dimension. Returns:n-dimensional sliceExamples:import mir.ndslice.topology : iota; auto data = new int[24]; foreach (i, ref e; data) e = cast(int)i; auto a = data[0..10].sliced(10)[0..6].sliced(2, 3); auto b = iota!int(10)[0..6].sliced(2, 3); assert(a == b); a[] += b; foreach (i, e; data[0..6]) assert(e == 2*i); foreach (i, e; data[6..$]) assert(e == i+6);
- Slice!(FieldIterator!Field, N)
slicedField
(Field, size_t N)(Fieldfield
, size_t[N]lengths
...)
if (N);
autoslicedField
(Field)(Fieldfield
)
if (hasLength!Field); - Creates an n-dimensional slice-shell over a field.Parameters:
Field field
A field. The length of the array should be equal to or less then the product of lengths. size_t[N] lengths
A list of lengths for each dimension. Returns:n-dimensional sliceExamples:Creates an 1-dimensional slice over a field, array, or random access range.import mir.ndslice.topology : iota; auto slice = 10.iota.slicedField; assert(slice.length == 10);
- Slice!(IndexIterator!(FieldIterator!(ndIotaField!N), ndField), N)
slicedNdField
(ndField, size_t N)(ndFieldfield
, size_t[N]lengths
...)
if (N);
autoslicedNdField
(ndField)(ndFieldfield
)
if (hasShape!ndField); - Creates an n-dimensional slice-shell over an ndField.Parameters:
ndField field
A ndField. Lengths should fit into field's shape. size_t[N] lengths
A list of lengths for each dimension. Returns:n-dimensional sliceSee Also:concatenation examples. - struct
CoordinateValue
(T, size_t N = 1); - Combination of coordinate(s) and value.
- size_t[N]
index
; - T
value
; - const int
opCmp
()(auto ref scope const typeof(this)rht
);
- struct
Structure
(size_t N); - Presents .Slice.structure.
- size_t[N]
lengths
; - sizediff_t[N]
strides
;
- struct
mir_slice
(Iterator_, size_t N_ = 1, SliceKind kind_ = Contiguous, Labels_...) if (0 < N_ && (N_ < 255) && !(kind_ == Canonical && (N_ == 1)) && (Labels_.length <= N_) && isIterator!Iterator_);
aliasSlice
= mir_slice(Iterator_, ulong N_ = 1, mir_slice_kind kind_ = Contiguous, Labels_...) if (0 < N_ && (N_ < 255) && !(kind_ == Canonical && (N_ == 1)) && (Labels_.length <= N_) && isIterator!Iterator_); - 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.Operator Overloading 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 indices 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 indices with an overall length equal to N. [2,3,1] A fully defined slice is an empty sequence or a sequence composed of indices and at least one interval with an overall length equal to N. [], [3..$,0..3,0..$-1], [2,0..$,1] An indexed slice is syntax sugar for indexed and cartesian . [anNdslice], [$.iota, anNdsliceForCartesian1, $.iota] See Also:iota .Internal Binary Representation
Multidimensional Slice is a structure that consists of lengths, strides, and a iterator (pointer). FieldIterator shell is used to wrap fields and random access ranges. FieldIterator contains a shift of the current initial element of a multidimensional slice and the field itself. With the exception of mir.ndslice.allocation module, no functions in this package move 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 range. Mir n-dimensional Slices can be one of the three kinds.Contiguous slice
Contiguous in memory (or in a user-defined iterator's field) row-major tensor that doesn't store strides because they can be computed on the fly using lengths. The row stride is always equaled 1.Canonical slice
Canonical slice as contiguous in memory (or in a user-defined iterator's field) rows of a row-major tensor, it doesn't store the stride for row dimension because it is always equaled 1. BLAS/LAPACK matrices are Canonical but originally have column-major order. In the same time you can use 2D Canonical Slices with LAPACK assuming that rows are columns and columns are rows.Universal slice
A row-major tensor that stores the strides for all dimensions. NumPy strides are Universal.Internal Representation for Universal Slices
Type definitionSlice!(Iterator, N, Universal)
SchemaSlice!(Iterator, N, Universal) size_t[N] _lengths sizediff_t[N] _strides Iterator _iterator
Example
Definitionsimport mir.ndslice; auto a = new double[24]; Slice!(double*, 3, Universal) s = a.sliced(2, 3, 4).universal; Slice!(double*, 3, Universal) t = s.transposed!(1, 2, 0); Slice!(double*, 3, Universal) r = t.reversed!1;
Representations________________________ lengths[0] ::= 2 lengths[1] ::= 3 lengths[2] ::= 4 strides[0] ::= 12 strides[1] ::= 4 strides[2] ::= 1 iterator ::= &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 iterator ::= &a[0] r______________reversed!1 lengths[0] ::= 2 lengths[1] ::= 3 lengths[2] ::= 4 strides[0] ::= 12 strides[1] ::= -4 strides[2] ::= 1 iterator ::= &a[8] // (old_strides[1] * (lengths[1] - 1)) = 8
Internal Representation for Canonical Slices
Type definitionSlice!(Iterator, N, Canonical)
SchemaSlice!(Iterator, N, Canonical) size_t[N] _lengths sizediff_t[N-1] _strides Iterator _iterator
Internal Representation for Contiguous Slices
Type definitionSlice!(Iterator, N)
SchemaSlice!(Iterator, N, Contiguous) size_t[N] _lengths sizediff_t[0] _strides Iterator _iterator
Examples:Slicing, indexing, and arithmetic operations.import mir.ndslice.allocation; import mir.ndslice.dynamic : transposed; import mir.ndslice.topology : iota, universal; auto tensor = iota(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.universal.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 indices 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 mir.ndslice.allocation; import mir.ndslice.topology: universal; import mir.ndslice.dynamic: transposed, everted; auto tensor = slice!int(3, 4, 5).universal; auto matrix = slice!int(3, 4).universal; 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 mir.algorithm.iteration: filter, all; import mir.array.allocation; import mir.exception; import mir.functional: not; import mir.ndslice.allocation; import mir.parse; import mir.primitives: empty; import std.algorithm: map; import std.string: lineSplitter, split; // std.functional, std.string, std.range; Slice!(int*, 2) 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.all!(a => a.length == columns).enforce!"rows have different lengths"; auto slice = slice!int(rows, columns); foreach (i, line; data) foreach (j, num; line) slice[i, j] = num.fromString!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 import std.format; auto text2 = format("%(%(%s %)\n%)\n", matrix); assert(text2 == "1 2 3\n4 5 6\n");
- enum SliceKind
kind
; - enum size_t
N
; - Dimensions count
- enum size_t
S
; - Strides count
- enum size_t
L
; - Labels count.
- alias
Iterator
= Iterator_; - Data iterator type
- alias
This
= Slice!(Iterator, N, kind); - This type
- alias
DeepElement
= typeof(Iterator.init[size_t.init]); - Data element type
- alias
serdeKeysProxy
= DeepElement; - alias
Labels
= Labels_; - Label Iterators types
- template
Element
(size_t dimension) if (dimension < N) - alias
_Structure
= AliasSeq!(size_t[N], ptrdiff_t[S]); - _Structure
_structure
; - alias
_lengths
= _structure[0]; - alias
_strides
= _structure[1]; - Iterator
_iterator
; - Data Iterator
- Labels
_labels
; - Labels iterators
- @property scope auto
lightScope
()() return;
const @property scope autolightScope
()() return;
immutable @property scope autolightScope
()() return; - Returns:View with stripped out reference counted context. The lifetime of the result mustn't be longer then the lifetime of the original slice.
- immutable @property scope Slice!(LightImmutableOf!Iterator, N, kind, staticMap!(LightImmutableOf, Labels))
lightImmutable
()() return; - Returns:Mutable slice over immutable data.
- const @property scope @trusted Slice!(LightConstOf!Iterator, N, kind, staticMap!(LightConstOf, Labels))
lightConst
()() return;
immutable @property scope Slice!(LightImmutableOf!Iterator, N, kind, staticMap!(LightImmutableOf, Labels))lightConst
()() return; - Returns:Mutable slice over const data.
- @property Slice!(Labels[d])
label
(size_t d = 0)()
if (d <= L);
@property voidlabel
(size_t d = 0)(Slice!(Labels[d])rhs
)
if (d <= L);
const @property Slice!(LightConstOf!(Labels[d]))label
(size_t d = 0)()
if (d <= L);
immutable @property Slice!(LightImmutableOf!(Labels[d]))label
(size_t d = 0)()
if (d <= L); - Label for the dimensions 'd'. By default returns the row label.
- @property auto
values
()();
const @property autovalues
()();
immutable @property autovalues
()(); - Strips label off the DataFrame
- const ref @trusted auto
opIndex
(Indexes...)(Indexesindices
)
if (isPureSlice!Indexes || isIndexedSlice!Indexes); opIndex
overload for const slice- immutable ref @trusted auto
opIndex
(Indexes...)(Indexesindices
)
if (isPureSlice!Indexes || isIndexedSlice!Indexes); opIndex
overload for immutable slice- immutable pure nothrow @nogc scope @trusted auto
toImmutable
()() return;
const pure nothrow @nogc scope @trusted autotoConst
()() return; - Cast to const and immutable slices in case of underlying range is a pointer.
- inout @property scope auto
iterator
()() return; - IteratorReturns:Iterator (pointer) to the .Slice.first element.
- alias
ptr
= iterator; ptr
alias is available only if the slice kind is Contiguous contiguous and the .Slice.iterator is a pointers.- @property scope @trusted auto
field
()() return;
const @property scope @trusted autofield
()() return;
immutable @property scope @trusted autofield
()() return; - Field (array) data.Returns:Raw data slice.
Constraints Field is defined only for contiguous slices.
Examples:auto arr = [1, 2, 3, 4]; auto sl0 = arr.sliced; auto sl1 = arr.slicedField; assert(sl0.field is arr); assert(sl1.field is arr); arr = arr[1 .. $]; sl0 = sl0[1 .. $]; sl1 = sl1[1 .. $]; assert(sl0.field is arr); assert(sl1.field is arr); assert((cast(const)sl1).field is arr); ()@trusted{ assert((cast(immutable)sl1).field is arr); }();
- const @property scope @trusted size_t[N]
shape
()(); - Returns:static array of lengthsSee Also:Examples:Regular slice
import mir.ndslice.topology : iota; assert(iota(3, 4, 5).shape == cast(size_t[3])[3, 4, 5]);
Examples:Packed sliceimport mir.ndslice.topology : pack, iota; size_t[3] s = [3, 4, 5]; assert(iota(3, 4, 5, 6, 7).pack!2.shape == s);
- const @property scope @trusted ptrdiff_t[N]
strides
()(); - Returns:static array of lengthsSee Also:Examples:Regular slice
import mir.ndslice.topology : iota; size_t[3] s = [20, 5, 1]; assert(iota(3, 4, 5).strides == s);
Examples:Modified regular sliceimport mir.ndslice.topology : pack, iota, universal; import mir.ndslice.dynamic : reversed, strided, transposed; assert(iota(3, 4, 50) .universal .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 .strides == cast(ptrdiff_t[3])[-6, 200, 50]);
Examples:Packed sliceimport mir.ndslice.topology : pack, iota; size_t[3] s = [20 * 42, 5 * 42, 1 * 42]; assert(iota(3, 4, 5, 6, 7) .pack!2 .strides == s);
- const @property scope @safe Structure!N
structure
()(); - Returns:static array of lengths and static array of stridesSee Also:Examples:Regular slice
import mir.ndslice.topology : iota; assert(iota(3, 4, 5) .structure == Structure!3([3, 4, 5], [20, 5, 1]));
Examples:Modified regular sliceimport mir.ndslice.topology : pack, iota, universal; import mir.ndslice.dynamic : reversed, strided, transposed; assert(iota(3, 4, 50) .universal .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 sliceimport mir.ndslice.topology : pack, iota; assert(iota(3, 4, 5, 6, 7) .pack!2 .structure == Structure!3([3, 4, 5], [20 * 42, 5 * 42, 1 * 42]));
- inout @property scope auto
save
()() return; - Save primitive.Examples:Save range
import mir.ndslice.topology : iota; auto slice = iota(2, 3).save;
Examples:Pointer type.import mir.ndslice.allocation; //sl type is `Slice!(2, int*)` auto sl = slice!int(2, 3).save;
- const @property scope @safe size_t
length
(size_t dimension = 0)()
if (dimension < N); - Multidimensional
length
property.Returns:length of the corresponding dimensionSee Also:Examples:import mir.ndslice.topology : iota; auto slice = iota(3, 4, 5); assert(slice.length == 3); assert(slice.length!0 == 3); assert(slice.length!1 == 4); assert(slice.length!2 == 5);
- const @property scope @safe sizediff_t
_stride
(size_t dimension = 0)()
if (dimension < N); - Multidimensional stride property.Returns:stride of the corresponding dimensionSee Also:Examples:Regular slice
import mir.ndslice.topology : iota; auto slice = iota(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 sliceimport mir.ndslice.dynamic : reversed, strided, swapped; import mir.ndslice.topology : universal, iota; assert(iota(3, 4, 50) .universal .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 scope @safe bool
empty
(size_t dimension = 0)()
if (dimension < N);
@property ref scope @trusted autofront
(size_t dimension = 0)() return
if (dimension == 0);
const @property ref scope @trusted autofront
(size_t dimension = 0)() return
if (dimension == 0);
immutable @property ref scope @trusted autofront
(size_t dimension = 0)() return
if (dimension == 0);
@property ref scope @trusted autofront
(size_t dimension = 0, T)(Tvalue
) return
if (dimension == 0);
@property ref scope @trusted Element!dimensionback
(size_t dimension = 0)() return
if (dimension < N);
@property ref scope @trusted autoback
(size_t dimension = 0, T)(Tvalue
) return
if (dimension == 0);
@trusted voidpopFront
(size_t dimension = 0)()
if (dimension < N && (dimension == 0 || kind != Contiguous));
scope @safe voidpopBack
(size_t dimension = 0)()
if (dimension < N && (dimension == 0 || kind != Contiguous));
scope @trusted voidpopFrontExactly
(size_t dimension = 0)(size_tn
)
if (dimension < N && (dimension == 0 || kind != Contiguous));
scope @safe voidpopBackExactly
(size_t dimension = 0)(size_tn
)
if (dimension < N && (dimension == 0 || kind != Contiguous));
scope @trusted voidpopFrontN
(size_t dimension = 0)(size_tn
)
if (dimension < N && (dimension == 0 || kind != Contiguous));
scope @safe voidpopBackN
(size_t dimension = 0)(size_tn
)
if (dimension < N && (dimension == 0 || kind != Contiguous)); - Multidimensional input range primitive.Examples:
import std.range.primitives; import mir.ndslice.topology : iota, canonical; auto slice = iota(10, 20, 30).canonical; 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]);
- @property ref scope @trusted auto
first
()() return;
@property ref scope @trusted autofirst
(T)(Tvalue
) return; - Accesses the first deep element of the slice.Examples:
import mir.ndslice.topology: iota, universal, canonical; auto f = 5; assert([2, 3].iota(f).first == f);
- @property ref scope @trusted auto
last
()() return;
@property ref scope @trusted autolast
(T)(Tvalue
) return; - Accesses the last deep element of the slice.Examples:
import mir.ndslice.topology: iota; auto f = 5; assert([2, 3].iota(f).last == f + 2 * 3 - 1);
- void
popFrontAll
(); - Peforms
popFrontAll
for all dimensionsExamples:import mir.ndslice.topology: iota, canonical; auto v = [2, 3].iota.canonical; v.popFrontAll; assert(v == [[4, 5]]);
- void
popBackAll
(); - Peforms
popBackAll
for all dimensionsExamples:import mir.ndslice.topology: iota, canonical; auto v = [2, 3].iota.canonical; v.popBackAll; assert(v == [[0, 1]]);
- const @property scope @trusted bool
anyEmpty
()(); - Returns:true if for any dimension the length equals to 0, and false otherwise.Examples:
import mir.ndslice.topology : iota, canonical; auto s = iota(2, 3).canonical; assert(!s.anyEmpty); s.popFrontExactly!1(3); assert(s.anyEmpty);
- ref scope auto
backward
()(size_t[N]index
) return;
const ref scope autobackward
()(size_t[N]index
) return;
const ref scope autobackward
()(size_t[N]index
) return; - Convenience function for backward indexing.Returns:this[$-
index
[0], $-index
[1], ..., $-index
[N-1]]Examples:import mir.ndslice.topology : iota; auto s = iota(2, 3); assert(s[$ - 1, $ - 2] == s.backward([1, 2]));
- const @property scope @safe size_t
elementCount
()(); - Returns:Total number of elements in a sliceExamples:Regular slice
import mir.ndslice.topology : iota; assert(iota(3, 4, 5).elementCount == 60);
Examples:Packed sliceimport mir.ndslice.topology : pack, evertPack, iota; auto slice = iota(3, 4, 5, 6, 7, 8); auto p = slice.pack!2; assert(p.elementCount == 360); assert(p[0, 0, 0, 0].elementCount == 56); assert(p.evertPack.elementCount == 56);
- @trusted auto
select
(size_t dimension)(size_tbegin
, size_tend
); - Slice selected dimension.Parameters:
size_t begin
initial index of the sub-slice (inclusive) size_t end
final index of the sub-slice (noninclusive) Returns:ndslice with length!dimension equal toend
-begin
.Examples:import mir.ndslice.topology : iota; auto sl = iota(3, 4); assert(sl.select!1(1, 3) == sl[0 .. $, 1 .. 3]);
- scope auto
selectFront
(size_t dimension)(size_tn
) return; - Select the first n elements for the dimension.Parameters:
dimension Dimension to slice. size_t n
count of elements for the dimension Returns:ndslice with length!dimension equal ton
.Examples:import mir.ndslice.topology : iota; auto sl = iota(3, 4); assert(sl.selectFront!1(2) == sl[0 .. $, 0 .. 2]);
- scope auto
selectBack
(size_t dimension)(size_tn
) return;
const scope @trusted boolopEquals
(IteratorR, SliceKind rkind)(auto ref const Slice!(IteratorR, N, rkind)rslice
);
const scope @trusted boolopEquals
(T)(scope const(T)[]arr
); - Select the last n elements for the dimension.Parameters:
dimension Dimension to slice. size_t n
count of elements for the dimension Returns:ndslice with length!dimension equal ton
.Examples:import mir.ndslice.topology : iota; auto sl = iota(3, 4); assert(sl.selectBack!1(2) == sl[0 .. $, $ - 2 .. $]);
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 scope @safe Slice!(IotaIterator!size_t)
opSlice
(size_t dimension)(size_ti
, size_tj
)
if (dimension < N); - Slice!(IotaIterator!size_t) is the basic type for [a .. b] syntax for all ndslice based code.
- ref scope @trusted auto
opIndex
()(size_t[N]_indices
...) return;
const ref scope @trusted autoopIndex
()(size_t[N]_indices
...) return;
immutable ref scope @trusted autoopIndex
()(size_t[N]_indices
...) return; - scope @trusted auto
opIndex
(size_t I)(size_t[I]_indices
...) return
if (I && (I < N));
const scope autoopIndex
(size_t I)(size_t[I]_indices
...) return
if (I && (I < N));
immutable scope autoopIndex
(size_t I)(size_t[I]_indices
...) return
if (I && (I < N)); - scope @trusted auto
opIndex
(Slices...)(Slicesslices
) return
if (isPureSlice!Slices); - Examples:
import mir.ndslice.allocation; 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];
- scope auto
opIndex
(Slices...)(return scope Slicesslices
) return
if (isIndexedSlice!Slices); - Examples:
import mir.ndslice.allocation: slice; auto sli = slice!int(4, 3); auto idx = slice!(size_t[2])(3); idx[] = [ cast(size_t[2])[0, 2], cast(size_t[2])[3, 1], cast(size_t[2])[2, 0]]; // equivalent to: // import mir.ndslice.topology: indexed; // sli.indexed(indx)[] = 1; sli[idx] = 1; assert(sli == [ [0, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], ]); foreach (row; sli[[1, 3].sliced]) row[] += 2; assert(sli == [ [0, 0, 1], [2, 2, 2], // <-- += 2 [1, 0, 0], [2, 3, 2], // <-- += 2 ]);
Examples:import mir.ndslice.topology: iota; import mir.ndslice.allocation: slice; auto sli = slice!int(5, 6); // equivalent to // import mir.ndslice.topology: indexed, cartesian; // auto a = [0, sli.length!0 / 2, sli.length!0 - 1].sliced; // auto b = [0, sli.length!1 / 2, sli.length!1 - 1].sliced; // auto c = cartesian(a, b); // auto minor = sli.indexed(c); auto minor = sli[[0, $ / 2, $ - 1].sliced, [0, $ / 2, $ - 1].sliced]; minor[] = iota!int([3, 3], 1); assert(sli == [ // ↓ ↓ ↓︎ [1, 0, 0, 2, 0, 3], // <--- [0, 0, 0, 0, 0, 0], [4, 0, 0, 5, 0, 6], // <--- [0, 0, 0, 0, 0, 0], [7, 0, 0, 8, 0, 9], // <--- ]);
- scope auto
opUnary
(string op)() return
if (op == "*" || op == "~" || op == "-" || op == "+"); - Element-wise binary operator overloading.Returns:lazy slice of the same kind and the same structure
Note Does not allocate neither new slice nor a closure.
Examples:import mir.ndslice.topology; auto payload = [1, 2, 3, 4]; auto s = iota([payload.length], payload.ptr); // slice of references; assert(s[1] == payload.ptr + 1); auto c = *s; // the same as s.map!"*a" assert(c[1] == *s[1]); *s[1] = 3; assert(c[1] == *s[1]);
- scope auto
opBinary
(string op, T)(return scope Tvalue
) return
if (!isSlice!T);
scope autoopBinaryRight
(string op, T)(return scope Tvalue
) return
if (!isSlice!T); - Element-wise operator overloading for scalars.Parameters:
T value
a scalar Returns:lazy slice of the same kind and the same structureNote Does not allocate neither new slice nor a closure.
Examples:import mir.ndslice.topology; // 0 1 2 3 auto s = iota([4]); // 0 1 2 0 assert(s % 3 == iota([4]).map!"a % 3"); // 0 2 4 6 assert(2 * s == iota([4], 0, 2));
Examples:import mir.ndslice.topology; // 0 1 2 3 auto s = iota([4]); // 0 1 4 9 assert(s ^^ 2.0 == iota([4]).map!"a ^^ 2.0");
- scope auto
opBinary
(string op, RIterator, size_t RN, SliceKind rkind)(return scope Slice!(RIterator, RN, rkind)rhs
) return
if (N == RN && (kind == Contiguous && (rkind == Contiguous) || N == 1) && (op != "~")); - Element-wise operator overloading for slices.Parameters:
Slice!(RIterator, RN, rkind) rhs
a slice of the same shape. Returns:lazy slice the same shape that has Contiguous kindNote Binary operator overloading is allowed if both slices are contiguous or one-dimensional.
Does not allocate neither new slice nor a closure.Examples:import mir.ndslice.topology: iota, map, zip; auto s = iota([2, 3]); auto c = iota([2, 3], 5, 8); assert(s * s + c == s.map!"a * a".zip(c).map!"a + b");
- @property scope Slice!(Unqual!DeepElement*, N)
dup
()();
const @property scope Slice!(immutable(DeepElement)*, N)dup
()();
immutable @property scope Slice!(immutable(DeepElement)*, N)dup
()(); - Duplicates slice.Returns:GC-allocated Contiguous mutable slice.See Also:Examples:
import mir.ndslice; auto x = 3.iota!int; Slice!(immutable(int)*) imm = x.idup; Slice!(int*) mut = imm.dup; assert(imm == x); assert(mut == x);
- @property scope Slice!(immutable(DeepElement)*, N)
idup
()();
const @property scope Slice!(immutable(DeepElement)*, N)idup
()();
immutable @property scope Slice!(immutable(DeepElement)*, N)idup
()(); - Duplicates slice.Returns:GC-allocated Contiguous immutable slice.See Also:Examples:
import mir.ndslice; auto x = 3.iota!int; Slice!(int*) mut = x.dup; Slice!(immutable(int)*) imm = mut.idup; assert(imm == x); assert(mut == x);
- ref scope @trusted auto
accessFlat
(size_tindex
) return; - Provides access to a slice as if it were flattened.Parameters:
size_t index
location in slice Returns:value of flattened slice atindex
See Also:Examples:import mir.ndslice.topology: iota, flattened; auto x = iota(2, 3, 4); assert(x.accessFlat(9) == x.flattened[9]);
- scope void
opIndexAssign
(RIterator, size_t RN, SliceKind rkind, Slices...)(Slice!(RIterator, RN, rkind)value
, Slicesslices
) return
if (isFullPureSlice!Slices || isIndexedSlice!Slices); - Assignment of a value of Slice type to a fully defined slice.Examples:
import mir.ndslice.allocation; 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 packedimport mir.ndslice.topology : blocks, iota; import mir.ndslice.allocation : slice; auto a = slice!int(4, 4); a.blocks(2, 2)[] = iota!int(2, 2); assert(a == [[0, 0, 1, 1], [0, 0, 1, 1], [2, 2, 3, 3], [2, 2, 3, 3]]);
Examples:Both slices are packedimport mir.ndslice.topology : blocks, iota, pack; import mir.ndslice.allocation : slice; auto a = slice!int(4, 4); a.blocks(2, 2)[] = iota!int(2, 2, 2).pack!1; assert(a == [[0, 1, 2, 3], [0, 1, 2, 3], [4, 5, 6, 7], [4, 5, 6, 7]]);
- scope void
opIndexAssign
(T, Slices...)(T[]value
, Slicesslices
) return
if ((isFullPureSlice!Slices || isIndexedSlice!Slices) && (!isDynamicArray!DeepElement || isDynamicArray!T) && (DynamicArrayDimensionsCount!(T[]) - DynamicArrayDimensionsCount!DeepElement <= (typeof(this.opIndex(slices
))).N)); - Assignment of a regular multidimensional array to a fully defined slice.Examples:
import mir.ndslice.allocation; 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 slicesimport mir.ndslice.allocation : slice; import mir.ndslice.topology : 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]]);
- scope void
opIndexAssign
(T, Slices...)(Tconcatenation
, Slicesslices
) return
if ((isFullPureSlice!Slices || isIndexedSlice!Slices) && isConcatenation!T); - scope void
opIndexAssign
(T, Slices...)(Tvalue
, Slicesslices
)
if ((isFullPureSlice!Slices || isIndexedSlice!Slices) && (!isDynamicArray!T || isDynamicArray!DeepElement) && (DynamicArrayDimensionsCount!T == DynamicArrayDimensionsCount!DeepElement) && !isSlice!T && !isConcatenation!T); - Assignment of a value (e.g. a number) to a fully defined slice.
- ref scope @trusted auto
opIndexAssign
(T)(Tvalue
, size_t[N]_indices
...) return;
ref scope @trusted autoopIndexAssign
()(DeepElementvalue
, size_t[N]_indices
...) return; - Assignment of a value (e.g. a number) to a fully defined index.Examples:
import mir.ndslice.allocation; auto a = slice!int(2, 3); a[1, 2] = 3; assert(a[1, 2] == 3);
- ref scope @trusted auto
opIndexOpAssign
(string op, T)(Tvalue
, size_t[N]_indices
...) return; - Op Assignment op= of a value (e.g. a number) to a fully defined index.Examples:
import mir.ndslice.allocation; auto a = slice!int(2, 3); a[1, 2] += 3; assert(a[1, 2] == 3);
- scope void
opIndexOpAssign
(string op, RIterator, SliceKind rkind, size_t RN, Slices...)(Slice!(RIterator, RN, rkind)value
, Slicesslices
) return
if (isFullPureSlice!Slices || isIndexedSlice!Slices); - Op Assignment op= of a value of Slice type to a fully defined slice.Examples:
import mir.ndslice.allocation; 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 packedimport mir.ndslice.allocation : slice; import mir.ndslice.topology : blocks, iota; auto a = slice!size_t(4, 4); a.blocks(2, 2)[] += iota(2, 2); assert(a == [[0, 0, 1, 1], [0, 0, 1, 1], [2, 2, 3, 3], [2, 2, 3, 3]]);
Examples:Both slices are packedimport mir.ndslice.allocation : slice; import mir.ndslice.topology : blocks, iota, pack; auto a = slice!size_t(4, 4); a.blocks(2, 2)[] += iota(2, 2, 2).pack!1; assert(a == [[0, 1, 2, 3], [0, 1, 2, 3], [4, 5, 6, 7], [4, 5, 6, 7]]);
- scope void
opIndexOpAssign
(string op, T, Slices...)(T[]value
, Slicesslices
) return
if (isFullPureSlice!Slices && (!isDynamicArray!DeepElement || isDynamicArray!T) && (DynamicArrayDimensionsCount!(T[]) - DynamicArrayDimensionsCount!DeepElement <= (typeof(this.opIndex(slices
))).N)); - Op Assignment op= of a regular multidimensional array to a fully defined slice.Examples:
import mir.ndslice.allocation : slice; 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 slicesimport mir.ndslice.allocation : slice; import mir.ndslice.topology : 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]]);
- scope void
opIndexOpAssign
(string op, T, Slices...)(Tvalue
, Slicesslices
) return
if ((isFullPureSlice!Slices || isIndexedSlice!Slices) && (!isDynamicArray!T || isDynamicArray!DeepElement) && (DynamicArrayDimensionsCount!T == DynamicArrayDimensionsCount!DeepElement) && !isSlice!T && !isConcatenation!T); - Op Assignment op= of a value (e.g. a number) to a fully defined slice.Examples:
import mir.ndslice.allocation; 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]);
- scope void
opIndexOpAssign
(string op, T, Slices...)(Tconcatenation
, Slicesslices
) return
if ((isFullPureSlice!Slices || isIndexedSlice!Slices) && isConcatenation!T); - Examples:Packed slices have the same behavior.
import mir.ndslice.allocation; import mir.ndslice.topology : pack; auto a = slice!int(2, 3).pack!1; a[] += 9; assert(a == [[9, 9, 9], [9, 9, 9]]);
- ref scope @trusted auto
opIndexUnary
(string op)(size_t[N]_indices
...) return; - Increment ++ and Decrement -- operators for a fully defined index.Examples:
import mir.ndslice.allocation; auto a = slice!int(2, 3); ++a[1, 2]; assert(a[1, 2] == 1);
- scope void
opIndexUnary
(string op, Slices...)(Slicesslices
) return
if (isFullPureSlice!Slices && (op == "++" || op == "--")); - Increment ++ and Decrement -- operators for a fully defined slice.Examples:
import mir.ndslice.allocation; 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]);
- @property auto
ndassign
(string op = "", L, R)(ref Llside
, auto ref Rrside
)
if (!isSlice!L && (op.length == 0 || op[$ - 1] != '='));
@property autondassign
(string op = "", L, R)(Llside
, auto ref Rrside
)
if (isSlice!L && (op.length == 0 || op[$ - 1] != '=')); - Assignment utility for generic code that works both with scalars and with ndslices.Parameters:
op assign operation (generic, optional) L lside
left side R rside
right side Returns:expression valueExamples:import mir.ndslice.topology: iota; import mir.ndslice.allocation: slice; auto scalar = 3; auto vector = 3.iota.slice; // [0, 1, 2] // scalar = 5; scalar.ndassign = 5; assert(scalar == 5); // vector[] = vector * 2; vector.ndassign = vector * 2; assert(vector == [0, 2, 4]); // vector[] += scalar; vector.ndassign!"+"= scalar; assert(vector == [5, 7, 9]);
Copyright © 2016-2022 by Ilya Yaroshenko | Page generated by
Ddoc on Tue Jan 11 06:37:11 2022