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.topology
This is a submodule of mir.ndslice.
Selectors create new views and iteration patterns over the same data, without copying.
Subspace selectors serve to generalize and combine other selectors easily.
For a slice of Slice!(Iterator, N, kind) type slice.pack!K creates a slice of
slices of Slice!(kind, [N - K, K], Iterator) type by packing
the last K dimensions of the top dimension pack,
and the type of element of flattened is Slice!(Iterator, K).
Another way to use pack is transposition of dimension packs using
evertPack.
Examples of use of subspace selectors are available for selectors,
Slice.shape , and Slice.elementCount .
Function Name | Description |
---|---|
cycle | Cycle repeates 1-dimensional field/range/array/slice in a fixed length 1-dimensional slice |
iota | Contiguous Slice with initial flattened (contiguous) index. |
linspace | Evenly spaced numbers over a specified interval. |
magic | Magic square. |
ndiota | Contiguous Slice with initial multidimensional index. |
repeat | Slice with identical values |
Function Name | Description |
---|---|
blocks | n-dimensional slice composed of n-dimensional non-overlapping blocks. If the slice has two dimensions, it is a block matrix. |
diagonal | 1-dimensional slice composed of diagonal elements |
dropBorders | Drops borders for all dimensions. |
reshape | New slice view with changed dimensions |
squeeze | New slice view of an n-dimensional slice with dimension removed |
unsqueeze | New slice view of an n-dimensional slice with a dimension added |
windows | n-dimensional slice of n-dimensional overlapping windows. If the slice has two dimensions, it is a sliding window. |
Function Name | Description |
---|---|
alongDim | Returns a slice that can be iterated along dimension. |
byDim | Returns a slice that can be iterated by dimension. |
pack | Returns slice of slices. |
ipack | Returns slice of slices. |
unpack | Merges two hight dimension packs. See also fuse . |
evertPack | Reverses dimension packs. |
Function Name | Description |
---|---|
asKindOf | Converts a slice to a user provied kind SliceKind . |
universal | Converts a slice to universal SliceKind . |
canonical | Converts a slice to canonical SliceKind . |
assumeCanonical | Converts a slice to canonical SliceKind . Does only assert checks. |
assumeContiguous | Converts a slice to contiguous SliceKind . Does only assert checks. |
assumeHypercube | Helps the compiler to use optimisations related to the shape form. Does only assert checks. |
assumeSameShape | Helps the compiler to use optimisations related to the shape form. Does only assert checks. |
Function Name | Description |
---|---|
cartesian | Cartesian product. |
kronecker | Kronecker product. |
Function Name | Description |
---|---|
as | Convenience function that creates a lazy view, where each element of the original slice is converted to a type T. |
bitpack | Bitpack slice over an unsigned integral slice. |
bitwise | Bitwise slice over an unsigned integral slice. |
bytegroup | Groups existing slice into fixed length chunks and uses them as data store for destination type. |
cached | Random access cache. It is usefull in combiation with map and vmap. |
cachedGC | Random access cache auto-allocated in GC heap. It is usefull in combiation with map and vmap. |
diff | Differences between vector elements. |
flattened | Contiguous 1-dimensional slice of all elements of a slice. |
map | Multidimensional functional map. |
member | Field (element's member) projection. |
orthogonalReduceField | Functional deep-element wise reduce of a slice composed of fields or iterators. |
pairwise | Pairwise map for vectors. |
pairwiseMapSubSlices | Maps pairwise index pairs to subslices. |
retro | Reverses order of iteration for all dimensions. |
slide | Lazy convolution for tensors. |
slideAlong | Lazy convolution for tensors. |
stairs | Two functions to pack, unpack, and iterate triangular and symmetric matrix storage. |
stride | Strides 1-dimensional slice. |
subSlices | Maps index pairs to subslices. |
triplets | Constructs a lazy view of triplets with left, center, and right members. The topology is usefull for Math and Physics. |
unzip | Selects a slice from a zipped slice. |
withNeighboursSum | Zip view of elements packed with sum of their neighbours. |
zip | Zips slices into a slice of refTuples. |
License:
Authors:
Ilya Yaroshenko, John Michael Hall, Shigeki Karita (original numir code)
Sponsors Part of this work has been sponsored by Symmetry Investments and Kaleidic Associates.
- template
asKindOf
(SliceKind kind) - Converts a slice to user provided kind.Contiguous slices can be converted to any kind. Canonical slices can't be converted to contiguous slices. Universal slices can be converted only to the same kind.See Also:Examples:Universal
import mir.ndslice.slice: Universal; auto slice = iota(2, 3).asKindOf!Universal; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == [3, 1]);
Examples:Canonicalimport mir.ndslice.slice: Canonical; auto slice = iota(2, 3).asKindOf!Canonical; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == [3]);
Examples:Contiguousimport mir.ndslice.slice: Contiguous; auto slice = iota(2, 3).asKindOf!Contiguous; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == []);
- auto
universal
(Iterator, size_t N, SliceKind kind, Labels...)(Slice!(Iterator, N, kind, Labels)slice
); - Converts a slice to universal kind.Parameters:
Slice!(Iterator, N, kind, Labels) slice
a slice Returns:universal sliceSee Also:Examples:auto slice = iota(2, 3).universal; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == [3, 1]);
Examples:import mir.ndslice.slice; import mir.ndslice.allocation: slice; auto dataframe = slice!(double, int, string)(2, 3); dataframe.label[] = [1, 2]; dataframe.label!1[] = ["Label1", "Label2", "Label3"]; auto universaldf = dataframe.universal; assert(universaldf._lengths == [2, 3]); assert(universaldf._strides == [3, 1]); assert(is(typeof(universaldf) == Slice!(double*, 2, Universal, int*, string*))); assert(universaldf.label!0[0] == 1); assert(universaldf.label!1[1] == "Label2");
- Slice!(Iterator, N, N == 1 ? Contiguous : Canonical, Labels)
canonical
(Iterator, size_t N, SliceKind kind, Labels...)(Slice!(Iterator, N, kind, Labels)slice
)
if (kind == Contiguous || kind == Canonical); - Converts a slice to canonical kind.Parameters:
Slice!(Iterator, N, kind, Labels) slice
contiguous or canonical slice Returns:canonical sliceSee Also:Examples:auto slice = iota(2, 3).canonical; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == [3]);
Examples:import mir.ndslice.slice; import mir.ndslice.allocation: slice; auto dataframe = slice!(double, int, string)(2, 3); dataframe.label[] = [1, 2]; dataframe.label!1[] = ["Label1", "Label2", "Label3"]; auto canonicaldf = dataframe.canonical; assert(canonicaldf._lengths == [2, 3]); assert(canonicaldf._strides == [3]); assert(is(typeof(canonicaldf) == Slice!(double*, 2, Canonical, int*, string*))); assert(canonicaldf.label!0[0] == 1); assert(canonicaldf.label!1[1] == "Label2");
- Slice!(Iterator, N, Canonical, Labels)
assumeCanonical
(Iterator, size_t N, SliceKind kind, Labels...)(Slice!(Iterator, N, kind, Labels)slice
); - Converts a slice to canonical kind (unsafe).Parameters:
Slice!(Iterator, N, kind, Labels) slice
a slice Returns:canonical sliceSee Also:Examples:auto slice = iota(2, 3).universal.assumeCanonical; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); assert(slice._strides == [3]);
Examples:import mir.ndslice.slice; import mir.ndslice.allocation: slice; auto dataframe = slice!(double, int, string)(2, 3); dataframe.label[] = [1, 2]; dataframe.label!1[] = ["Label1", "Label2", "Label3"]; auto assmcanonicaldf = dataframe.assumeCanonical; assert(assmcanonicaldf._lengths == [2, 3]); assert(assmcanonicaldf._strides == [3]); assert(is(typeof(assmcanonicaldf) == Slice!(double*, 2, Canonical, int*, string*))); assert(assmcanonicaldf.label!0[0] == 1); assert(assmcanonicaldf.label!1[1] == "Label2");
- Slice!(Iterator, N, Contiguous, Labels)
assumeContiguous
(Iterator, size_t N, SliceKind kind, Labels...)(Slice!(Iterator, N, kind, Labels)slice
); - Converts a slice to contiguous kind (unsafe).Parameters:
Slice!(Iterator, N, kind, Labels) slice
a slice Returns:canonical sliceSee Also:Examples:auto slice = iota(2, 3).universal.assumeContiguous; assert(slice == [[0, 1, 2], [3, 4, 5]]); assert(slice._lengths == [2, 3]); static assert(slice._strides.length == 0);
Examples:import mir.ndslice.slice; import mir.ndslice.allocation: slice; auto dataframe = slice!(double, int, string)(2, 3); dataframe.label[] = [1, 2]; dataframe.label!1[] = ["Label1", "Label2", "Label3"]; auto assmcontdf = dataframe.canonical.assumeContiguous; assert(assmcontdf._lengths == [2, 3]); static assert(assmcontdf._strides.length == 0); assert(is(typeof(assmcontdf) == Slice!(double*, 2, Contiguous, int*, string*))); assert(assmcontdf.label!0[0] == 1); assert(assmcontdf.label!1[1] == "Label2");
- void
assumeHypercube
(Iterator, size_t N, SliceKind kind, Labels...)(ref scope Slice!(Iterator, N, kind, Labels)slice
); - Helps the compiler to use optimisations related to the shape formExamples:
auto b = iota(5, 5); assumeHypercube(b); assert(b == iota(5, 5));
- void
assumeSameShape
(T...)(ref scope Tslices
)
if (allSatisfy!(isSlice, T)); - Helps the compiler to use optimisations related to the shape formExamples:
auto a = iota(5, 5); auto b = iota(5, 5); assumeHypercube(a); // first use this one, if applicable assumeSameShape(a, b); // assert(a == iota(5, 5)); assert(b == iota(5, 5));
- auto
assumeFieldsHaveZeroShift
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (__traits(hasMember, Iterator, "assumeFieldsHaveZeroShift
")); - Slice!(SliceIterator!(Iterator, P, P == 1 && (kind == Canonical) ? Contiguous : kind), N - P, Universal)
pack
(size_t P, Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (P && (P < N)); - Creates a packed slice, i.e. slice of slices. Packs the last P dimensions. The function does not allocate any data.Parameters:
P size of dimension pack Slice!(Iterator, N, kind) slice
a slice to pack Returns:slice
.pack
!p returns Slice!(kind, [N - p, p], Iterator)See Also:Examples:import mir.ndslice.slice: sliced, Slice; auto a = iota(3, 4, 5, 6); auto b = a.pack!2; static immutable res1 = [3, 4]; static immutable res2 = [5, 6]; assert(b.shape == res1); assert(b[0, 0].shape == res2); assert(a == b.unpack); assert(a.pack!2 == b); static assert(is(typeof(b) == typeof(a.pack!2)));
- Slice!(SliceIterator!(Iterator, N - P, N - P == 1 && (kind == Canonical) ? Contiguous : kind), P, Universal)
ipack
(size_t P, Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (P && (P < N)); - Creates a packed slice, i.e. slice of slices. Packs the last N - P dimensions. The function does not allocate any data.Parameters:
Slice!(Iterator, N, kind) slice
a slice to pack See Also:Examples:import mir.ndslice.slice: sliced, Slice; auto a = iota(3, 4, 5, 6); auto b = a.ipack!2; static immutable res1 = [3, 4]; static immutable res2 = [5, 6]; assert(b.shape == res1); assert(b[0, 0].shape == res2); assert(a.ipack!2 == b); static assert(is(typeof(b) == typeof(a.ipack!2)));
- Slice!(Iterator, N + M, min(innerKind, Canonical))
unpack
(Iterator, size_t M, SliceKind innerKind, size_t N, SliceKind outerKind)(Slice!(SliceIterator!(Iterator, M, innerKind), N, outerKind)slice
); - Unpacks a packed slice.The functions does not allocate any data.Parameters:
Slice!(SliceIterator!(Iterator, M, innerKind), N, outerKind) slice
packed slice Returns:unpacked slice, that is a view on the same data. - Slice!(SliceIterator!(Iterator, N, outerKind), M, innerKind)
evertPack
(Iterator, size_t M, SliceKind innerKind, size_t N, SliceKind outerKind)(Slice!(SliceIterator!(Iterator, M, innerKind), N, outerKind)slice
); - Reverses the order of dimension packs. This function is used in a functional pipeline with other selectors.Parameters:
Slice!(SliceIterator!(Iterator, M, innerKind), N, outerKind) slice
packed slice Returns:packed sliceExamples:import mir.ndslice.dynamic : transposed; auto slice = iota(3, 4, 5, 6, 7, 8, 9, 10, 11).universal; assert(slice .pack!2 .evertPack .unpack == slice.transposed!( slice.shape.length-2, slice.shape.length-1));
Examples:import mir.ndslice.iterator: SliceIterator; import mir.ndslice.slice: sliced, Slice, Universal; import mir.ndslice.allocation: slice; static assert(is(typeof( slice!int(6) .sliced(1,2,3) .pack!1 .evertPack ) == Slice!(SliceIterator!(int*, 2, Universal), 1)));
Examples:auto a = iota(3, 4, 5, 6, 7, 8, 9, 10, 11); auto b = a.pack!2.unpack; static assert(is(typeof(a.canonical) == typeof(b))); assert(a == b);
- Slice!(IotaIterator!I, N)
iota
(I = sizediff_t, size_t N)(size_t[N]lengths
...)
if (__traits(isIntegral, I));
Slice!(IotaIterator!sizediff_t, N)iota
(size_t N)(size_t[N]lengths
, sizediff_tstart
);
Slice!(StrideIterator!(IotaIterator!sizediff_t), N)iota
(size_t N)(size_t[N]lengths
, sizediff_tstart
, size_tstride
);
templateiota
(I) if (__traits(isIntegral, I))
Slice!(IotaIterator!I, N)iota
(I, size_t N)(size_t[N]lengths
, Istart
)
if (is(I P : P*));
Slice!(StrideIterator!(IotaIterator!I), N)iota
(I, size_t N)(size_t[N]lengths
, Istart
, size_tstride
)
if (is(I P : P*)); - Returns a slice, the elements of which are equal to the initial flattened index value.Parameters:
N dimension count size_t[N] lengths
list of dimension lengths sizediff_t start
value of the first element in a slice (optional for integer I) size_t stride
value of the stride between elements (optional) Returns:n-dimensional slice composed of indicesSee Also:Examples:import mir.primitives: DeepElementType; auto slice = iota(2, 3); static immutable array = [[0, 1, 2], [3, 4, 5]]; assert(slice == array); static assert(is(DeepElementType!(typeof(slice)) == sizediff_t));
Examples:int[6] data; auto slice = iota([2, 3], data.ptr); assert(slice[0, 0] == data.ptr); assert(slice[0, 1] == data.ptr + 1); assert(slice[1, 0] == data.ptr + 3);
Examples:auto im = iota([10, 5], 100); assert(im[2, 1] == 111); // 100 + 2 * 5 + 1 //slicing works correctly auto cm = im[1 .. $, 3 .. $]; assert(cm[2, 1] == 119); // 119 = 100 + (1 + 2) * 5 + (3 + 1)
Examples:iota
with stepauto sl = iota([2, 3], 10, 10); assert(sl == [[10, 20, 30], [40, 50, 60]]);
- Slice!(Iterator, 1, N == 1 ? kind : Universal)
diagonal
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
); - Returns a 1-dimensional slice over the main diagonal of an n-dimensional slice.
diagonal
can be generalized with other selectors such as blocks (diagonal blocks) and windows (multi-diagonal slice).Parameters:Slice!(Iterator, N, kind) slice
input slice Returns:1-dimensional slice composed of diagonal elementsSee Also:Examples:Matrix, main diagonal// ------- // | 0 1 2 | // | 3 4 5 | // ------- //-> // | 0 4 | static immutable d = [0, 4]; assert(iota(2, 3).diagonal == d);
Examples:Non-square matrix// ------- // | 0 1 | // | 2 3 | // | 4 5 | // ------- //-> // | 0 3 | assert(iota(3, 2).diagonal == iota([2], 0, 3));
Examples:Loop through diagonalimport mir.ndslice.slice; import mir.ndslice.allocation; auto slice = slice!int(3, 3); int i; foreach (ref e; slice.diagonal) e = ++i; assert(slice == [ [1, 0, 0], [0, 2, 0], [0, 0, 3]]);
Examples:Matrix, subdiagonal// ------- // | 0 1 2 | // | 3 4 5 | // ------- //-> // | 1 5 | static immutable d = [1, 5]; auto a = iota(2, 3).canonical; a.popFront!1; assert(a.diagonal == d);
Examples:3D, main diagonal// ----------- // | 0 1 2 | // | 3 4 5 | // - - - - - - // | 6 7 8 | // | 9 10 11 | // ----------- //-> // | 0 10 | static immutable d = [0, 10]; assert(iota(2, 2, 3).diagonal == d);
Examples:3D, subdiagonal// ----------- // | 0 1 2 | // | 3 4 5 | // - - - - - - // | 6 7 8 | // | 9 10 11 | // ----------- //-> // | 1 11 | static immutable d = [1, 11]; auto a = iota(2, 2, 3).canonical; a.popFront!2; assert(a.diagonal == d);
Examples:3D, diagonal plain// ----------- // | 0 1 2 | // | 3 4 5 | // | 6 7 8 | // - - - - - - // | 9 10 11 | // | 12 13 14 | // | 15 16 17 | // - - - - - - // | 18 20 21 | // | 22 23 24 | // | 24 25 26 | // ----------- //-> // ----------- // | 0 4 8 | // | 9 13 17 | // | 18 23 26 | // ----------- static immutable d = [[ 0, 4, 8], [ 9, 13, 17], [18, 22, 26]]; auto slice = iota(3, 3, 3) .pack!2 .evertPack .diagonal .evertPack; assert(slice == d);
- Slice!(Iterator, 1, Universal)
antidiagonal
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (N == 2); - Returns a 1-dimensional slice over the main antidiagonal of an 2D-dimensional slice.
antidiagonal
can be generalized with other selectors such as blocks (diagonal blocks) and windows (multi-diagonal slice).It runs from the top right corner to the bottom left corner.Pseudo code
auto antidiagonal = slice.dropToHypercube.reversed!1.diagonal;
Parameters:Slice!(Iterator, N, kind) slice
input slice Returns:1-dimensional slice composed of antidiagonal elements.See Also:Examples:// ----- // | 0 1 | // | 2 3 | // ----- //-> // | 1 2 | static immutable c = [1, 2]; import std.stdio; assert(iota(2, 2).antidiagonal == c);
Examples:// ------- // | 0 1 2 | // | 3 4 5 | // ------- //-> // | 1 3 | static immutable d = [1, 3]; assert(iota(2, 3).antidiagonal == d);
- Slice!(SliceIterator!(Iterator, N, N == 1 ? Universal : min(kind, Canonical)), N, Universal)
blocks
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
, size_t[N]rlengths_
...); - Returns an n-dimensional slice of n-dimensional non-overlapping blocks.
blocks
can be generalized with other selectors. For example,blocks
in combination with diagonal can be used to get a slice of diagonal blocks. For overlapped blocks, combine windows with strided .Parameters:N dimension count Slice!(Iterator, N, kind) slice
slice to be split into blocks size_t[N] rlengths_
dimensions of block, residual blocks are ignored Returns:packed N-dimensional slice composed of N-dimensional slicesSee Also:Examples:import mir.ndslice.slice; import mir.ndslice.allocation; auto slice = slice!int(5, 8); auto blocks = slice.blocks(2, 3); int i; foreach (blocksRaw; blocks) foreach (block; blocksRaw) block[] = ++i; assert(blocks == [[[[1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2]]], [[[3, 3, 3], [3, 3, 3]], [[4, 4, 4], [4, 4, 4]]]]); assert( slice == [[1, 1, 1, 2, 2, 2, 0, 0], [1, 1, 1, 2, 2, 2, 0, 0], [3, 3, 3, 4, 4, 4, 0, 0], [3, 3, 3, 4, 4, 4, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Diagonal blocksimport mir.ndslice.slice; import mir.ndslice.allocation; auto slice = slice!int(5, 8); auto blocks = slice.blocks(2, 3); auto diagonalBlocks = blocks.diagonal.unpack; diagonalBlocks[0][] = 1; diagonalBlocks[1][] = 2; assert(diagonalBlocks == [[[1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2]]]); assert(blocks == [[[[1, 1, 1], [1, 1, 1]], [[0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0]], [[2, 2, 2], [2, 2, 2]]]]); assert(slice == [[1, 1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 2, 2, 2, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Matrix divided into vertical blocksimport mir.ndslice.allocation; import mir.ndslice.slice; auto slice = slice!int(5, 13); auto blocks = slice .pack!1 .evertPack .blocks(3) .unpack; int i; foreach (block; blocks) block[] = ++i; assert(slice == [[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0], [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0]]);
- Slice!(SliceIterator!(Iterator, N, N == 1 ? kind : min(kind, Canonical)), N, Universal)
windows
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
, size_t[N]rlengths
...); - Returns an n-dimensional slice of n-dimensional overlapping windows.
windows
can be generalized with other selectors. For example,windows
in combination with diagonal can be used to get a multi-diagonal slice.Parameters:N dimension count Slice!(Iterator, N, kind) slice
slice to be iterated size_t[N] rlengths
dimensions of windows Returns:packed N-dimensional slice composed of N-dimensional slicesExamples:import mir.ndslice.allocation; import mir.ndslice.slice; auto slice = slice!int(5, 8); auto windows = slice.windows(2, 3); int i; foreach (windowsRaw; windows) foreach (window; windowsRaw) ++window[]; assert(slice == [[1, 2, 3, 3, 3, 3, 2, 1], [2, 4, 6, 6, 6, 6, 4, 2], [2, 4, 6, 6, 6, 6, 4, 2], [2, 4, 6, 6, 6, 6, 4, 2], [1, 2, 3, 3, 3, 3, 2, 1]]);
Examples:import mir.ndslice.allocation; import mir.ndslice.slice; auto slice = slice!int(5, 8); auto windows = slice.windows(2, 3); windows[1, 2][] = 1; windows[1, 2][0, 1] += 1; windows.unpack[1, 2, 0, 1] += 1; assert(slice == [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 3, 1, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]);
Examples:Multi-diagonal matriximport mir.ndslice.allocation; import mir.ndslice.slice; auto slice = slice!int(8, 8); auto windows = slice.windows(3, 3); auto multidiagonal = windows .diagonal .unpack; foreach (window; multidiagonal) window[] += 1; assert(slice == [[ 1, 1, 1, 0, 0, 0, 0, 0], [ 1, 2, 2, 1, 0, 0, 0, 0], [ 1, 2, 3, 2, 1, 0, 0, 0], [0, 1, 2, 3, 2, 1, 0, 0], [0, 0, 1, 2, 3, 2, 1, 0], [0, 0, 0, 1, 2, 3, 2, 1], [0, 0, 0, 0, 1, 2, 2, 1], [0, 0, 0, 0, 0, 1, 1, 1]]);
Examples:Sliding window over matrix columnsimport mir.ndslice.allocation; import mir.ndslice.slice; auto slice = slice!int(5, 8); auto windows = slice .pack!1 .evertPack .windows(3) .unpack; foreach (window; windows) window[] += 1; assert(slice == [[1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1], [1, 2, 3, 3, 3, 3, 2, 1]]);
Examples:Overlapping blocks using windows// ---------------- // | 0 1 2 3 4 | // | 5 6 7 8 9 | // | 10 11 12 13 14 | // | 15 16 17 18 19 | // | 20 21 22 23 24 | // ---------------- //-> // --------------------- // | 0 1 2 | 2 3 4 | // | 5 6 7 | 7 8 9 | // | 10 11 12 | 12 13 14 | // | - - - - - - - - - - | // | 10 11 13 | 12 13 14 | // | 15 16 17 | 17 18 19 | // | 20 21 22 | 22 23 24 | // --------------------- import mir.ndslice.slice; import mir.ndslice.dynamic : strided; auto overlappingBlocks = iota(5, 5) .windows(3, 3) .universal .strided!(0, 1)(2, 2); assert(overlappingBlocks == [[[[ 0, 1, 2], [ 5, 6, 7], [10, 11, 12]], [[ 2, 3, 4], [ 7, 8, 9], [12, 13, 14]]], [[[10, 11, 12], [15, 16, 17], [20, 21, 22]], [[12, 13, 14], [17, 18, 19], [22, 23, 24]]]]);
- enum
ReshapeError
: int; - Error codes for reshape.
none
- No error
empty
- Slice should be not empty
total
- Total element count should be the same
incompatible
- Structure is incompatible with new shape
- Slice!(Iterator, M, kind)
reshape
(Iterator, size_t N, SliceKind kind, size_t M)(Slice!(Iterator, N, kind)slice
, ptrdiff_t[M]rlengths
, ref interr
); - Returns a new slice for the same data with different dimensions.Parameters:
Slice!(Iterator, N, kind) slice
slice to be reshaped ptrdiff_t[M] rlengths
list of new dimensions. One of the lengths can be set to -1. In this case, the corresponding dimension is inferable. int err
ReshapeError code Returns:reshaped sliceExamples:import mir.ndslice.dynamic : allReversed; int err; auto slice = iota(3, 4) .universal .allReversed .reshape([-1, 3], err); assert(err == 0); assert(slice == [[11, 10, 9], [ 8, 7, 6], [ 5, 4, 3], [ 2, 1, 0]]);
Examples:Reshaping with memory allocationimport mir.ndslice.slice: sliced; import mir.ndslice.allocation: slice; import mir.ndslice.dynamic : reversed; auto reshape2(S, size_t M)(S sl, ptrdiff_t[M] lengths) { int err; // Tries to reshape without allocation auto ret = sl.reshape(lengths, err); if (!err) return ret; if (err == ReshapeError.incompatible) // allocates, flattens, reshapes with `sliced`, converts to universal kind return sl.slice.flattened.sliced(cast(size_t[M])lengths).universal; throw new Exception("total elements count is different or equals to zero"); } auto sl = iota!int(3, 4) .slice .universal .reversed!0; assert(reshape2(sl, [4, 3]) == [[ 8, 9, 10], [11, 4, 5], [ 6, 7, 0], [ 1, 2, 3]]);
- Slice!(FlattenedIterator!(Iterator, N, kind))
flattened
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (N != 1 && (kind != Contiguous));
Slice!Iteratorflattened
(Iterator, size_t N)(Slice!(Iterator, N)slice
);
Slice!(StrideIterator!Iterator)flattened
(Iterator)(Slice!(Iterator, 1, Universal)slice
); - A contiguous 1-dimensional slice of all elements of a slice.
flattened
iterates existing data. The order of elements is preserved.flattened
can be generalized with other selectors.Parameters:Slice!(Iterator, N, kind) slice
slice to be iterated Returns:contiguous 1-dimensional slice of elements of theslice
Examples:Regular sliceassert(iota(4, 5).flattened == iota(20)); assert(iota(4, 5).canonical.flattened == iota(20)); assert(iota(4, 5).universal.flattened == iota(20));
Examples:Packed sliceimport mir.ndslice.slice; import mir.ndslice.dynamic; assert(iota(3, 4, 5, 6, 7).pack!2.flattened[1] == iota([6, 7], 6 * 7));
Examples:Propertiesauto elems = iota(3, 4).universal.flattened; elems.popFrontExactly(2); assert(elems.front == 2); /// `_index` is available only for canonical and universal ndslices. assert(elems._iterator._indices == [0, 2]); elems.popBackExactly(2); assert(elems.back == 9); assert(elems.length == 8);
Examples:Index propertyimport mir.ndslice.slice; auto slice = new long[20].sliced(5, 4); for (auto elems = slice.universal.flattened; !elems.empty; elems.popFront) { ptrdiff_t[2] index = elems._iterator._indices; elems.front = index[0] * 10 + index[1] * 3; } assert(slice == [[ 0, 3, 6, 9], [10, 13, 16, 19], [20, 23, 26, 29], [30, 33, 36, 39], [40, 43, 46, 49]]);
Examples:Random access and slicingimport mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; auto elems = iota(4, 5).slice.flattened; elems = elems[11 .. $ - 2]; assert(elems.length == 7); assert(elems.front == 11); assert(elems.back == 17); foreach (i; 0 .. 7) assert(elems[i] == i + 11); // assign an element elems[2 .. 6] = -1; assert(elems[2 .. 6] == repeat(-1, 4)); // assign an array static ar = [-1, -2, -3, -4]; elems[2 .. 6] = ar; assert(elems[2 .. 6] == ar); // assign a slice ar[] *= 2; auto sl = ar.sliced(ar.length); elems[2 .. 6] = sl; assert(elems[2 .. 6] == sl);
- Slice!(FieldIterator!(ndIotaField!N), N)
ndiota
(size_t N)(size_t[N]lengths
...)
if (N); - Returns a slice, the elements of which are equal to the initial multidimensional index value. For a flattened (contiguous) index, see iota.Parameters:
N dimension count size_t[N] lengths
list of dimension lengths Returns:N-dimensional slice composed of indicesSee Also:Examples:auto slice = ndiota(2, 3); static immutable array = [[[0, 0], [0, 1], [0, 2]], [[1, 0], [1, 1], [1, 2]]]; assert(slice == array);
Examples:auto im = ndiota(7, 9); assert(im[2, 1] == [2, 1]); //slicing works correctly auto cm = im[1 .. $, 4 .. $]; assert(cm[2, 1] == [3, 5]);
- auto
linspace
(T, size_t N)(size_t[N]lengths
, T[2][N]intervals
...)
if (N && (isFloatingPoint!T || isComplex!T)); - Evenly spaced numbers over a specified interval.Parameters:
T floating point or complex numbers type size_t[N] lengths
list of dimension lengths. Each length must be greater then 1. T[2][N] intervals
list of [start, end] pairs. Returns:n-dimensional grid of evenly spaced numbers over specified intervals.Examples:1Dauto s = linspace!double([5], [1.0, 2.0]); assert(s == [1.0, 1.25, 1.5, 1.75, 2.0]); // reverse order assert(linspace!double([5], [2.0, 1.0]) == s.retro); // remove endpoint s.popBack; assert(s == [1.0, 1.25, 1.5, 1.75]);
Examples:2Dimport mir.functional: refTuple; auto s = linspace!double([5, 3], [1.0, 2.0], [0.0, 1.0]); assert(s == [ [refTuple(1.00, 0.00), refTuple(1.00, 0.5), refTuple(1.00, 1.0)], [refTuple(1.25, 0.00), refTuple(1.25, 0.5), refTuple(1.25, 1.0)], [refTuple(1.50, 0.00), refTuple(1.50, 0.5), refTuple(1.50, 1.0)], [refTuple(1.75, 0.00), refTuple(1.75, 0.5), refTuple(1.75, 1.0)], [refTuple(2.00, 0.00), refTuple(2.00, 0.5), refTuple(2.00, 1.0)], ]); assert(s.map!"a * b" == [ [0.0, 0.500, 1.00], [0.0, 0.625, 1.25], [0.0, 0.750, 1.50], [0.0, 0.875, 1.75], [0.0, 1.000, 2.00], ]);
Examples:Complex numbersimport mir.complex; alias C = Complex!double; auto s = linspace!C([3], [C(1.0, 0), C(2.0, 4)]); assert(s == [C(1.0, 0), C(1.5, 2), C(2.0, 4)]);
- @trusted Slice!(FieldIterator!(RepeatField!T), M, Universal)
repeat
(T, size_t M)(Tvalue
, size_t[M]lengths
...)
if (M && !isSlice!T);
Slice!(SliceIterator!(Iterator, N, kind), M, Universal)repeat
(SliceKind kind, size_t N, Iterator, size_t M)(Slice!(Iterator, N, kind)slice
, size_t[M]lengths
...)
if (M); - Returns a slice with identical elements. RepeatSlice stores only single value.Parameters:
size_t[M] lengths
list of dimension lengths Returns:n-dimensional slice composed of identical values, where n is dimension count.Examples:auto sl = iota(3).repeat(4); assert(sl == [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]);
Examples:import mir.ndslice.dynamic : transposed; auto sl = iota(3) .repeat(4) .unpack .universal .transposed; assert(sl == [[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2]]);
Examples:import mir.ndslice.allocation; auto sl = iota([3], 6).slice; auto slC = sl.repeat(2, 3); sl[1] = 4; assert(slC == [[[6, 4, 8], [6, 4, 8], [6, 4, 8]], [[6, 4, 8], [6, 4, 8], [6, 4, 8]]]);
Examples:import mir.primitives: DeepElementType; auto sl = repeat(4.0, 2, 3); assert(sl == [[4.0, 4.0, 4.0], [4.0, 4.0, 4.0]]); static assert(is(DeepElementType!(typeof(sl)) == double)); sl[1, 1] = 3; assert(sl == [[3.0, 3.0, 3.0], [3.0, 3.0, 3.0]]);
- auto
cycle
(Field)(Fieldfield
, size_tloopLength
, size_tlength
)
if (!isSlice!Field && !is(Field : T[], T));
autocycle
(size_t loopLength, Field)(Fieldfield
, size_tlength
)
if (!isSlice!Field && !is(Field : T[], T));
autocycle
(Iterator, SliceKind kind)(Slice!(Iterator, 1, kind)slice
, size_tlength
);
autocycle
(size_t loopLength, Iterator, SliceKind kind)(Slice!(Iterator, 1, kind)slice
, size_tlength
);
autocycle
(T)(T[]array
, size_tlength
);
autocycle
(size_t loopLength, T)(T[]array
, size_tlength
);
autocycle
(size_t loopLength, T)(TwithAsSlice
, size_tlength
)
if (hasAsSlice!T); - Cycle repeates 1-dimensional field/range/array/slice in a fixed length 1-dimensional slice.Examples:
auto slice = iota(3); assert(slice.cycle(7) == [0, 1, 2, 0, 1, 2, 0]); assert(slice.cycle!2(7) == [0, 1, 0, 1, 0, 1, 0]); assert([0, 1, 2].cycle(7) == [0, 1, 2, 0, 1, 2, 0]); assert([4, 3, 2, 1].cycle!4(7) == [4, 3, 2, 1, 4, 3, 2]);
- auto
stride
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
, ptrdiff_tfactor
)
if (N == 1);
templatestride
(size_t factor = 2) if (factor > 1)
autostride
(T)(T[]array
, ptrdiff_tfactor
);
autostride
(T)(TwithAsSlice
, ptrdiff_tfactor
)
if (hasAsSlice!T); - Strides 1-dimensional slice.Parameters:
Slice!(Iterator, N, kind) slice
1-dimensional unpacked slice. ptrdiff_t factor
positive stride size. Returns:Contiguous slice with strided iterator.See Also:Examples:auto slice = iota(6); static immutable str = [0, 2, 4]; assert(slice.stride(2) == str); // runtime factor assert(slice.stride!2 == str); // compile time factor assert(slice.stride == str); // default compile time factor is 2 assert(slice.universal.stride(2) == str);
Examples:ND-compile timeauto slice = iota(4, 6); static immutable str = [[0, 2, 4], [12, 14, 16]]; assert(slice.stride!2 == str); // compile time factor assert(slice.stride == str); // default compile time factor is 2
- @trusted auto
retro
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autoretro
(T)(T[]array
);
autoretro
(T)(TwithAsSlice
)
if (hasAsSlice!T);
autoretro
(Range)(Ranger
)
if (!hasAsSlice!Range && !isSlice!Range && !is(Range : T[], T));
structRetroRange
(Range); - Reverses order of iteration for all dimensions.Parameters:
Slice!(Iterator, N, kind) slice
slice, range, or array. Returns:Slice/range with reversed order of iteration for all dimensions.See Also:reversed , allReversed .Examples:auto slice = iota(2, 3); static immutable reversed = [[5, 4, 3], [2, 1, 0]]; assert(slice.retro == reversed); assert(slice.canonical.retro == reversed); assert(slice.universal.retro == reversed); static assert(is(typeof(slice.retro.retro) == typeof(slice))); static assert(is(typeof(slice.canonical.retro.retro) == typeof(slice.canonical))); static assert(is(typeof(slice.universal.retro) == typeof(slice.universal)));
Examples:Rangesimport mir.algorithm.iteration: equal; import std.range: std_iota = iota; assert(std_iota(4).retro.equal(iota(4).retro)); static assert(is(typeof(std_iota(4).retro.retro) == typeof(std_iota(4))));
- auto
bitwise
(Iterator, size_t N, SliceKind kind, I = typeof(Iterator.init[size_t.init]))(Slice!(Iterator, N, kind)slice
)
if (__traits(isIntegral, I) && (kind != Universal || N == 1));
autobitwise
(T)(T[]array
);
autobitwise
(T)(TwithAsSlice
)
if (hasAsSlice!T); - Bitwise slice over an integral slice.Parameters:
Slice!(Iterator, N, kind) slice
a contiguous or canonical slice on top of integral iterator. Returns:A bitwise slice.Examples:size_t[10] data; auto bits = data[].bitwise; assert(bits.length == data.length * size_t.sizeof * 8); bits[111] = true; assert(bits[111]); bits.popFront; assert(bits[110]); bits[] = true; bits[110] = false; bits = bits[10 .. $]; assert(bits[100] == false);
- auto
bitwiseField
(Field, I = typeof(Field.init[size_t.init]))(Fieldfield
)
if (__traits(isUnsigned, I)); - Bitwise field over an integral field.Parameters:
Field field
an integral field. Returns:A bitwise field. - auto
bitpack
(size_t pack, Iterator, size_t N, SliceKind kind, I = typeof(Iterator.init[size_t.init]))(Slice!(Iterator, N, kind)slice
)
if (__traits(isIntegral, I) && (kind == Contiguous || kind == Canonical) && (pack > 1));
autobitpack
(size_t pack, T)(T[]array
);
autobitpack
(size_t pack, T)(TwithAsSlice
)
if (hasAsSlice!T); - Bitpack slice over an integral slice.Bitpack is used to represent unsigned integer slice with fewer number of bits in integer binary representation.Parameters:
pack counts of bits in the integer. Slice!(Iterator, N, kind) slice
a contiguous or canonical slice on top of integral iterator. Returns:A bitpack slice.Examples:size_t[10] data; // creates a packed unsigned integer slice with max allowed value equal to `2^^6 - 1 == 63`. auto packs = data[].bitpack!6; assert(packs.length == data.length * size_t.sizeof * 8 / 6); packs[$ - 1] = 24; assert(packs[$ - 1] == 24); packs.popFront; assert(packs[$ - 1] == 24);
- Slice!(BytegroupIterator!(Iterator, group, DestinationType), N, kind)
bytegroup
(size_t group, DestinationType, Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if ((kind == Contiguous || kind == Canonical) && group);
autobytegroup
(size_t pack, DestinationType, T)(T[]array
);
autobytegroup
(size_t pack, DestinationType, T)(TwithAsSlice
)
if (hasAsSlice!T); - Bytegroup slice over an integral slice.Groups existing slice into fixed length chunks and uses them as data store for destination type. Correctly handles scalar types on both little-endian and big-endian platforms.Parameters:
group count of iterator items used to store the destination type. DestinationType deep element type of the result slice. Slice!(Iterator, N, kind) slice
a contiguous or canonical slice. Returns:A bytegroup slice.Examples:24 bit integersimport mir.ndslice.slice: DeepElementType, sliced; ubyte[20] data; // creates a packed unsigned integer slice with max allowed value equal to `2^^6 - 1 == 63`. auto int24ar = data[].bytegroup!(3, int); // 24 bit integers assert(int24ar.length == data.length / 3); enum checkInt = ((1 << 20) - 1); int24ar[3] = checkInt; assert(int24ar[3] == checkInt); int24ar.popFront; assert(int24ar[2] == checkInt); static assert(is(DeepElementType!(typeof(int24ar)) == int));
Examples:48 bit integersimport mir.ndslice.slice: DeepElementType, sliced; ushort[20] data; // creates a packed unsigned integer slice with max allowed value equal to `2^^6 - 1 == 63`. auto int48ar = data[].sliced.bytegroup!(3, long); // 48 bit integers assert(int48ar.length == data.length / 3); enum checkInt = ((1L << 44) - 1); int48ar[3] = checkInt; assert(int48ar[3] == checkInt); int48ar.popFront; assert(int48ar[2] == checkInt); static assert(is(DeepElementType!(typeof(int48ar)) == long));
- template
map
(fun...) if (fun.length)
structMapRange
(alias fun, Range); - Implements the homonym function (also known as transform) present in many languages of functional flavor. The call
map
!(fun)(slice) returns a slice of which elements are obtained by applying fun for all elements in slice. The original slices are not changed. Evaluation is done lazily.Note transposed and pack can be used to specify dimensions.
Parameters:fun One or more functions. See Also:Examples:import mir.ndslice.topology : iota; auto s = iota(2, 3).map!(a => a * 3); assert(s == [[ 0, 3, 6], [ 9, 12, 15]]);
Examples:String lambdasimport mir.ndslice.topology : iota; assert(iota(2, 3).map!"a * 2" == [[0, 2, 4], [6, 8, 10]]);
Examples:Input rangesimport mir.algorithm.iteration: filter, equal; assert (6.iota.filter!"a % 2".map!"a * 10".equal([10, 30, 50]));
Examples:Packed tensorsimport mir.ndslice.topology : iota, windows; import mir.math.sum: sum; // iota windows map sums ( reduce!"a + b" ) // -------------- // ------- | --- --- | ------ // | 0 1 2 | => || 0 1 || 1 2 || => | 8 12 | // | 3 4 5 | || 3 4 || 4 5 || ------ // ------- | --- --- | // -------------- auto s = iota(2, 3) .windows(2, 2) .map!sum; assert(s == [[8, 12]]);
Examples:Zipped tensorsimport mir.ndslice.topology : iota, zip; // 0 1 2 // 3 4 5 auto sl1 = iota(2, 3); // 1 2 3 // 4 5 6 auto sl2 = iota([2, 3], 1); auto z = zip(sl1, sl2); assert(zip(sl1, sl2).map!"a + b" == sl1 + sl2); assert(zip(sl1, sl2).map!((a, b) => a + b) == sl1 + sl2);
Examples:Multiple functions can be passed tomap
. In that case, the element type ofmap
is a refTuple containing one element for each function.import mir.ndslice.topology : iota; auto sl = iota(2, 3); auto s = sl.map!("a + a", "a * a"); auto sums = [[0, 2, 4], [6, 8, 10]]; auto products = [[0, 1, 4], [9, 16, 25]]; assert(s.map!"a[0]" == sl + sl); assert(s.map!"a[1]" == sl * sl);
Examples:map
can be aliased to a symbol and be used separately:import mir.ndslice.topology : iota; alias halfs = map!"double(a) / 2"; assert(halfs(iota(2, 3)) == [[0.0, 0.5, 1], [1.5, 2, 2.5]]);
Examples:Type normalizationimport mir.functional : pipe; import mir.ndslice.topology : iota; auto a = iota(2, 3).map!"a + 10".map!(pipe!("a * 2", "a + 1")); auto b = iota(2, 3).map!(pipe!("a + 10", "a * 2", "a + 1")); assert(a == b); static assert(is(typeof(a) == typeof(b)));
Examples:Use map with byDim/alongDim to apply functions to each dimensionimport mir.ndslice.topology: byDim, alongDim; import mir.ndslice.fuse: fuse; import mir.math.stat: mean; import mir.algorithm.iteration: all; import mir.math.common: approxEqual; auto x = [ [0.0, 1.0, 1.5, 2.0, 3.5, 4.25], [2.0, 7.5, 5.0, 1.0, 1.5, 0.0] ].fuse; // Use byDim/alongDim with map to compute mean of row/column. assert(x.byDim!0.map!mean.all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.byDim!1.map!mean.all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125])); assert(x.alongDim!1.map!mean.all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.alongDim!0.map!mean.all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125]));
Examples:Use map with a lambda and with byDim/alongDim, but may need to allocate result. This example uses fuse, which allocates. Note: fuse!1 will transpose the result.import mir.ndslice.topology: iota, byDim, alongDim, map; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; auto x = [1, 2, 3].sliced; auto y = [1, 2].sliced; auto s1 = iota(2, 3).byDim!0.map!(a => a * x).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s2 = iota(2, 3).byDim!1.map!(a => a * y).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]); auto s3 = iota(2, 3).alongDim!1.map!(a => a * x).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s4 = iota(2, 3).alongDim!0.map!(a => a * y).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]);
Examples:import mir.algorithm.iteration: reduce; import mir.math.common: fmax; import mir.math.stat: mean; import mir.math.sum; /// Returns maximal column average. auto maxAvg(S)(S matrix) { return reduce!fmax(0.0, matrix.alongDim!1.map!mean); } // 1 2 // 3 4 auto matrix = iota([2, 2], 1); assert(maxAvg(matrix) == 3.5);
- auto
map
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
automap
(T)(T[]array
);
automap
(T)(TwithAsSlice
)
if (hasAsSlice!T);
automap
(Range)(Ranger
)
if (!hasAsSlice!Range && !isSlice!Range && !is(Range : T[], T)); - Parameters:
Slice!(Iterator, N, kind) slice
An ndslice, array, or an input range. Returns:ndslice or an input range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
- auto
vmap
(Iterator, size_t N, SliceKind kind, Callable)(Slice!(Iterator, N, kind)slice
, Callablecallable
);
autovmap
(T, Callable)(T[]array
, Callablecallable
);
autovmap
(T, Callable)(TwithAsSlice
, Callablecallable
)
if (hasAsSlice!T); - Implements the homonym function (also known as transform) present in many languages of functional flavor. The call
slice
.vmap
(fun) returns a slice of which elements are obtained by applying fun for all elements inslice
. The original slices are not changed. Evaluation is done lazily.Note transposed and pack can be used to specify dimensions.
Parameters:Slice!(Iterator, N, kind) slice
ndslice Callable callable
callable object, structure, delegate, or function pointer. Examples:import mir.ndslice.topology : iota; static struct Mul { double factor; this(double f) { factor = f; } auto opCall(long x) const {return x * factor; } auto lightConst()() const @property { return Mul(factor); } } auto callable = Mul(3); auto s = iota(2, 3).vmap(callable); assert(s == [[ 0, 3, 6], [ 9, 12, 15]]);
Examples:Packed tensors.import mir.math.sum: sum; import mir.ndslice.topology : iota, windows; // iota windows vmap scaled sums // -------------- // ------- | --- --- | ----- // | 0 1 2 | => || 0 1 || 1 2 || => | 4 6 | // | 3 4 5 | || 3 4 || 4 5 || ----- // ------- | --- --- | // -------------- struct Callable { double factor; this(double f) {factor = f;} auto opCall(S)(S x) { return x.sum * factor; } auto lightConst()() const @property { return Callable(factor); } auto lightImmutable()() immutable @property { return Callable(factor); } } auto callable = Callable(0.5); auto s = iota(2, 3) .windows(2, 2) .vmap(callable); assert(s == [[4, 6]]);
Examples:Zipped tensorsimport mir.ndslice.topology : iota, zip; struct Callable { double factor; this(double f) {factor = f;} auto opCall(S, T)(S x, T y) { return x + y * factor; } auto lightConst()() const { return Callable(factor); } auto lightImmutable()() immutable { return Callable(factor); } } auto callable = Callable(10); // 0 1 2 // 3 4 5 auto sl1 = iota(2, 3); // 1 2 3 // 4 5 6 auto sl2 = iota([2, 3], 1); auto z = zip(sl1, sl2); assert(zip(sl1, sl2).vmap(callable) == [[10, 21, 32], [43, 54, 65]]);
Examples:Use vmap with byDim/alongDim to apply functions to each dimensionimport mir.ndslice.fuse: fuse; import mir.math.stat: mean; import mir.algorithm.iteration: all; import mir.math.common: approxEqual; auto x = [ [0.0, 1.0, 1.5, 2.0, 3.5, 4.25], [2.0, 7.5, 5.0, 1.0, 1.5, 0.0] ].fuse; static struct Callable { double factor; this(double f) {factor = f;} auto opCall(U)(U x) const {return x.mean + factor; } auto lightConst()() const @property { return Callable(factor); } } auto callable = Callable(0.0); // Use byDim/alongDim with map to compute callable of row/column. assert(x.byDim!0.vmap(callable).all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.byDim!1.vmap(callable).all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125])); assert(x.alongDim!1.vmap(callable).all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.alongDim!0.vmap(callable).all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125]));
Examples:Use vmap with a lambda and with byDim/alongDim, but may need to allocate result. This example uses fuse, which allocates. Note: fuse!1 will transpose the result.import mir.ndslice.topology: iota, alongDim, map; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; static struct Mul(T) { T factor; this(T f) { factor = f; } auto opCall(U)(U x) {return x * factor; } auto lightConst()() const @property { return Mul!(typeof(factor.lightConst))(factor.lightConst); } } auto a = [1, 2, 3].sliced; auto b = [1, 2].sliced; auto A = Mul!(typeof(a))(a); auto B = Mul!(typeof(b))(b); auto x = [ [0, 1, 2], [3, 4, 5] ].fuse; auto s1 = x.byDim!0.vmap(A).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s2 = x.byDim!1.vmap(B).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]); auto s3 = x.alongDim!1.vmap(A).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s4 = x.alongDim!0.vmap(B).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]);
- template
rcmap
(fun...) if (fun.length) - Implements the homonym function (also known as transform) present in many languages of functional flavor. The call rmap!(fun)(slice) returns an RC array (1D) or RC slice (ND) of which elements are obtained by applying fun for all elements in slice. The original slices are not changed. Evaluation is done eagerly.
Note transposed and pack can be used to specify dimensions.
Parameters:fun One or more functions. Examples:Returns RCArray for input ranges and one-dimensional slices.import mir.algorithm.iteration: filter, equal; auto factor = 10; auto step = 20; assert (3.iota.rcmap!(a => a * factor).moveToSlice.equal(3.iota * factor)); assert (6.iota.filter!"a % 2".rcmap!(a => a * factor).moveToSlice.equal([3].iota(factor, step)));
Examples:For multidimensional case returns Slice!(RCI!T, N).import mir.ndslice.topology : iota; auto factor = 3; auto s = iota(2, 3).rcmap!(a => a * factor); assert(s == iota(2, 3) * factor);
Examples:String lambdasimport mir.ndslice.topology : iota; assert(iota(2, 3).rcmap!"a * 2" == iota(2, 3) * 2);
- auto
rcmap
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autorcmap
(T)(T[]array
);
autorcmap
(T)(TwithAsSlice
)
if (hasAsSlice!T);
autorcmap
(Range)(Ranger
)
if (!hasAsSlice!Range && !isSlice!Range && !is(Range : T[], T)); - Parameters:
Slice!(Iterator, N, kind) slice
An ndslice, array, or an input range. Returns:ndslice or an input range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
- Slice!(CachedIterator!(Iterator, CacheIterator, FlagIterator), N, kind)
cached
(Iterator, SliceKind kind, size_t N, CacheIterator, FlagIterator)(Slice!(Iterator, N, kind)original
, Slice!(CacheIterator, N, kind)caches
, Slice!(FlagIterator, N, kind)flags
); - Creates a random access cache for lazyly computed elements.Parameters:
Slice!(Iterator, N, kind) original
original ndslice Slice!(CacheIterator, N, kind) caches
cached values Slice!(FlagIterator, N, kind) flags
array composed of flags that indicates if values are already computed Returns:ndslice, which is internally composed of three ndslices:original
, allocated cache and allocated bit-ndslice.Examples:import mir.ndslice.topology: cached, iota, map; import mir.ndslice.allocation: bitSlice, uninitSlice; int[] funCalls; auto v = 5.iota!int .map!((i) { funCalls ~= i; return 2 ^^ i; }); auto flags = v.length.bitSlice; auto cache = v.length.uninitSlice!int; // cached lazy slice: 1 2 4 8 16 auto sl = v.cached(cache, flags); assert(funCalls == []); assert(sl[1] == 2); // remember result assert(funCalls == [1]); assert(sl[1] == 2); // reuse result assert(funCalls == [1]); assert(sl[0] == 1); assert(funCalls == [1, 0]); funCalls = []; // set values directly sl[1 .. 3] = 5; assert(sl[1] == 5); assert(sl[2] == 5); // no function calls assert(funCalls == []);
Examples:Cache of immutable elementsimport mir.ndslice.slice: DeepElementType; import mir.ndslice.topology: cached, iota, map, as; import mir.ndslice.allocation: bitSlice, uninitSlice; int[] funCalls; auto v = 5.iota!int .map!((i) { funCalls ~= i; return 2 ^^ i; }) .as!(immutable int); auto flags = v.length.bitSlice; auto cache = v.length.uninitSlice!(immutable int); // cached lazy slice: 1 2 4 8 16 auto sl = v.cached(cache, flags); static assert(is(DeepElementType!(typeof(sl)) == immutable int)); assert(funCalls == []); assert(sl[1] == 2); // remember result assert(funCalls == [1]); assert(sl[1] == 2); // reuse result assert(funCalls == [1]); assert(sl[0] == 1); assert(funCalls == [1, 0]);
- @trusted Slice!(CachedIterator!(Iterator, typeof(Iterator.init[0])*, FieldIterator!(BitField!(size_t*))), N)
cachedGC
(Iterator, size_t N)(Slice!(Iterator, N)original
);
autocachedGC
(Iterator)(Slice!(Iterator, 1, Universal)from
);
autocachedGC
(T)(TwithAsSlice
)
if (hasAsSlice!T); - Creates a random access cache for lazyly computed elements.Parameters:
Slice!(Iterator, N) original
ND Contiguous or 1D Universal ndslice. Returns:ndslice, which is internally composed of three ndslices:original
, allocated cache and allocated bit-ndslice.Examples:import mir.ndslice.topology: cachedGC, iota, map; int[] funCalls; // cached lazy slice: 1 2 4 8 16 auto sl = 5.iota!int .map!((i) { funCalls ~= i; return 2 ^^ i; }) .cachedGC; assert(funCalls == []); assert(sl[1] == 2); // remember result assert(funCalls == [1]); assert(sl[1] == 2); // reuse result assert(funCalls == [1]); assert(sl[0] == 1); assert(funCalls == [1, 0]); funCalls = []; // set values directly sl[1 .. 3] = 5; assert(sl[1] == 5); assert(sl[2] == 5); // no function calls assert(funCalls == []);
Examples:Cache of immutable elementsimport mir.ndslice.slice: DeepElementType; import mir.ndslice.topology: cachedGC, iota, map, as; int[] funCalls; // cached lazy slice: 1 2 4 8 16 auto sl = 5.iota!int .map!((i) { funCalls ~= i; return 2 ^^ i; }) .as!(immutable int) .cachedGC; static assert(is(DeepElementType!(typeof(sl)) == immutable int)); assert(funCalls == []); assert(sl[1] == 2); // remember result assert(funCalls == [1]); assert(sl[1] == 2); // reuse result assert(funCalls == [1]); assert(sl[0] == 1); assert(funCalls == [1, 0]);
- 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 map and to composition under the hood.Parameters:
Slice!(Iterator, N, kind) slice a slice to create a view on. Returns:A lazy slice with elements converted to the type T.Examples:import mir.ndslice.slice: Slice; import mir.ndslice.allocation : slice; import mir.ndslice.topology : diagonal, as; auto matrix = slice!double([2, 2], 0); auto stringMatrixView = matrix.as!int; assert(stringMatrixView == [[0, 0], [0, 0]]); matrix.diagonal[] = 1; assert(stringMatrixView == [[1, 0], [0, 1]]); /// allocate new slice composed of strings Slice!(int*, 2) stringMatrix = stringMatrixView.slice;
Examples:Special behavior for pointers to a constant data.import mir.ndslice.allocation : slice; import mir.ndslice.slice: Contiguous, Slice; Slice!(double*, 2) matrix = slice!double([2, 2], 0); Slice!(const(double)*, 2) const_matrix = matrix.as!(const double);
Examples:Rangesimport mir.algorithm.iteration: filter, equal; assert(5.iota.filter!"a % 2".as!double.map!"a / 2".equal([0.5, 1.5]));
- auto
as
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autoas
(S)(S[]array
);
autoas
(S)(SwithAsSlice
)
if (hasAsSlice!S);
autoas
(Range)(Ranger
)
if (!hasAsSlice!Range && !isSlice!Range && !is(Range : T[], T));
- Slice!(IndexIterator!(Iterator, Field), N, kind)
indexed
(Field, Iterator, size_t N, SliceKind kind)(Fieldsource
, Slice!(Iterator, N, kind)indices
);
autoindexed
(Field, S)(Fieldsource
, S[]indices
);
autoindexed
(Field, S)(Fieldsource
, Sindices
)
if (hasAsSlice!S); - Takes a field
source
and a sliceindices
, and creates a view of source as if its elements were reordered according to indices.indices
may include only a subset of the elements ofsource
and may also repeat elements.Parameters:Field source
a filed, source of data. source
must be an array or a pointer, or have opIndex primitive. Full random access range API is not required.Slice!(Iterator, N, kind) indices
a slice, source of indices. Returns:n-dimensional slice with the same kind, shape and strides.See Also:indexed
is similar to vmap, but a field ([]) is used instead of a function (()), and order of arguments is reversed.Examples:auto source = [1, 2, 3, 4, 5]; auto indices = [4, 3, 1, 2, 0, 4]; auto ind = source.indexed(indices); assert(ind == [5, 4, 2, 3, 1, 5]); assert(ind.retro == source.indexed(indices.retro)); ind[3] += 10; // for index 2 // 0 1 2 3 4 assert(source == [1, 2, 13, 4, 5]);
- Slice!(SubSliceIterator!(Iterator, Sliceable), N, kind)
subSlices
(Iterator, size_t N, SliceKind kind, Sliceable)(Sliceablesliceable
, Slice!(Iterator, N, kind)slices
);
autosubSlices
(S, Sliceable)(Sliceablesliceable
, S[]slices
);
autosubSlices
(S, Sliceable)(Sliceablesliceable
, Sslices
)
if (hasAsSlice!S); - Maps index pairs to subslices.Parameters:
Sliceable sliceable
pointer, array, ndslice, series, or something sliceable with [a .. b]. Slice!(Iterator, N, kind) slices
ndslice composed of index pairs. Returns:ndslice composed of subslices.Examples:import mir.functional: staticArray; auto subs =[ staticArray(2, 4), staticArray(2, 10), ]; auto sliceable = 10.iota; auto r = sliceable.subSlices(subs); assert(r == [ iota([4 - 2], 2), iota([10 - 2], 2), ]);
- Slice!(ChopIterator!(Iterator, Sliceable))
chopped
(Iterator, Sliceable)(Sliceablesliceable
, Slice!Iteratorbounds
);
autochopped
(S, Sliceable)(Sliceablesliceable
, S[]bounds
);
autochopped
(S, Sliceable)(Sliceablesliceable
, Sbounds
)
if (hasAsSlice!S); - Maps index pairs to subslices.Parameters:
Slice!Iterator bounds
ndslice composed of consequent (a_i <= a_(i+1)) pairwise index bounds. Sliceable sliceable
pointer, array, ndslice, series, or something sliceable with [a_i .. a_(i+1)]. Returns:ndslice composed of subslices.Examples:import mir.functional: staticArray; import mir.ndslice.slice: sliced; auto pairwiseIndexes = [2, 4, 10].sliced; auto sliceable = 10.iota; auto r = sliceable.chopped(pairwiseIndexes); assert(r == [ iota([4 - 2], 2), iota([10 - 4], 4), ]);
- template
zip
(bool sameStrides = false) - Groups slices into a slice of refTuples. The slices must have identical strides or be 1-dimensional.Parameters:
sameStrides if true assumes that all slices has the same strides. Slices slices list of slices Returns:n-dimensional slice of elements refTupleSee Also:Examples:import mir.ndslice.allocation : slice; import mir.ndslice.topology : flattened, iota; auto alpha = iota!int(4, 3); auto beta = slice!int(4, 3).universal; auto m = zip!true(alpha, beta); foreach (r; m) foreach (e; r) e.b = e.a; assert(alpha == beta); beta[] = 0; foreach (e; m.flattened) e.b = cast(int)e.a; assert(alpha == beta);
- auto
zip
(Slices...)(Slicesslices
)
if (Slices.length > 1 && allSatisfy!(isConvertibleToSlice, Slices)); - Groups slices into a slice of refTuples. The slices must have identical strides or be 1-dimensional.Parameters:
Slices slices
list of slices Returns:n-dimensional slice of elements refTupleSee Also:
- auto
unzip
(char name, size_t N, SliceKind kind, Iterators...)(Slice!(ZipIterator!Iterators, N, kind)slice
);
autounzip
(char name, size_t N, SliceKind kind, Iterators...)(ref Slice!(ZipIterator!Iterators, N, kind)slice
); - Selects a slice from a zipped slice.Parameters:
name name of a slice to unzip. Slice!(ZipIterator!Iterators, N, kind) slice
zipped slice Returns:unzipped sliceExamples:import mir.ndslice.allocation : slice; import mir.ndslice.topology : iota; auto alpha = iota!int(4, 3); auto beta = iota!int([4, 3], 1).slice; auto m = zip(alpha, beta); static assert(is(typeof(unzip!'a'(m)) == typeof(alpha))); static assert(is(typeof(unzip!'b'(m)) == typeof(beta))); assert(m.unzip!'a' == alpha); assert(m.unzip!'b' == beta);
- template
slideAlong
(size_t params, alias fun, SDimensions...) if (params <= 'z' - 'a' + 1 && (SDimensions.length > 0)) - Lazy convolution for tensors.Suitable for advanced convolution algorithms.Parameters:
params convolution windows length. fun one dimensional convolution function with params arity. SDimensions dimensions to perform lazy convolution along. Negative dimensions are supported. Examples:auto data = [4, 5].iota; alias scaled = a => a * 0.25; auto v = data.slideAlong!(3, "a + 2 * b + c", 0).map!scaled; auto h = data.slideAlong!(3, "a + 2 * b + c", 1).map!scaled; assert(v == [4, 5].iota[1 .. $ - 1, 0 .. $]); assert(h == [4, 5].iota[0 .. $, 1 .. $ - 1]);
- auto
slideAlong
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autoslideAlong
(S)(S[]slice
);
autoslideAlong
(S)(Sslice
)
if (hasAsSlice!S); - Parameters:
Slice!(Iterator, N, kind) slice
ndslice or array Returns:lazy convolution result
- template
slide
(size_t params, alias fun) if (params <= 'z' - 'a' + 1) - Lazy convolution for tensors.Suitable for simple convolution algorithms.Parameters:
params windows length. fun one dimensional convolution function with params arity. See Also:Examples:auto data = 10.iota; auto sw = data.slide!(3, "a + 2 * b + c"); import mir.utility: max; assert(sw.length == max(0, cast(ptrdiff_t)data.length - 3 + 1)); assert(sw == sw.length.iota.map!"(a + 1) * 4"); assert(sw == [4, 8, 12, 16, 20, 24, 28, 32]);
Examples:ND-use caseauto data = [4, 5].iota; enum factor = 1.0 / 4 ^^ data.shape.length; alias scaled = a => a * factor; auto sw = data.slide!(3, "a + 2 * b + c").map!scaled; assert(sw == [4, 5].iota[1 .. $ - 1, 1 .. $ - 1]);
- auto
slide
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autoslide
(S)(S[]slice
);
autoslide
(S)(Sslice
)
if (hasAsSlice!S); - Parameters:
Slice!(Iterator, N, kind) slice
ndslice or array Returns:lazy convolution result
- template
pairwise
(alias fun, size_t lag = 1) - Pairwise map for tensors.The computation is performed on request, when the element is accessed.Parameters:
fun function to accumulate lag an integer indicating which lag to use Returns:lazy ndslice composed of fun(a_n, a_n+1) values.See Also:Examples:import mir.ndslice.slice: sliced; assert([2, 4, 3, -1].sliced.pairwise!"a + b" == [6, 7, 2]);
Examples:N-dimensional// performs pairwise along each dimension // 0 1 2 3 // 4 5 6 7 // 8 9 10 11 assert([3, 4].iota.pairwise!"a + b" == [[10, 14, 18], [26, 30, 34]]);
- template
diff
(size_t lag = 1) - Differences between tensor elements.The computation is performed on request, when the element is accessed.Parameters:
lag an integer indicating which lag to use Returns:lazy differences.Examples:import mir.ndslice.slice: sliced; assert([2, 4, 3, -1].sliced.diff == [2, -1, -4]);
Examples:N-dimensional// 0 1 2 3 // 4 5 6 7 => // 8 9 10 11 // 1 1 1 // 1 1 1 => // 1 1 1 // 0 0 0 // 0 0 0 assert([3, 4].iota.diff == repeat(0, [2, 3]));
Examples:packed slices// 0 1 2 3 // 4 5 6 7 // 8 9 10 11 auto s = iota(3, 4); import std.stdio; assert(iota(3, 4).byDim!0.diff == [ [4, 4, 4, 4], [4, 4, 4, 4]]); assert(iota(3, 4).byDim!1.diff == [ [1, 1, 1], [1, 1, 1], [1, 1, 1]]);
- Slice!(Iterator, N, N > 1 && (kind == Contiguous) ? Canonical : kind, Labels)
dropBorders
(Iterator, size_t N, SliceKind kind, Labels...)(Slice!(Iterator, N, kind, Labels)slice
); - Drops borders for all dimensions.Parameters:
Slice!(Iterator, N, kind, Labels) slice
ndslice Returns:Tensors with striped bordersSee Also:Examples:assert([4, 5].iota.dropBorders == [[6, 7, 8], [11, 12, 13]]);
- template
withNeighboursSum
(alias fun = "a + b") - Lazy zip view of elements packed with sum of their neighbours.Parameters:
fun neighbours accumulation function. See Also:Examples:import mir.ndslice.allocation: slice; import mir.algorithm.iteration: all; auto wn = [4, 5].iota.withNeighboursSum; assert(wn.all!"a[0] == a[1] * 0.25"); assert(wn.map!"a" == wn.map!"b * 0.25");
- auto
withNeighboursSum
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
autowithNeighboursSum
(S)(S[]slice
);
autowithNeighboursSum
(S)(Sslice
)
if (hasAsSlice!S); - Parameters:
Slice!(Iterator, N, kind) slice
ndslice or array Returns:Lazy zip view of elements packed with sum of their neighbours.
- auto
cartesian
(NdFields...)(NdFieldsfields
)
if (NdFields.length > 1 && allSatisfy!(templateOr!(hasShape, hasLength), NdFields)); - Cartesian product.Constructs lazy cartesian product Slice without memory allocation.Parameters:
NdFields fields
list of fields with lengths or ndFields with shapes Returns:Examples:1D x 1Dauto a = [10, 20, 30]; auto b = [ 1, 2, 3]; auto c = cartesian(a, b) .map!"a + b"; assert(c == [ [11, 12, 13], [21, 22, 23], [31, 32, 33]]);
Examples:1D x 2Dauto a = [10, 20, 30]; auto b = iota([2, 3], 1); auto c = cartesian(a, b) .map!"a + b"; assert(c.shape == [3, 2, 3]); assert(c == [ [ [11, 12, 13], [14, 15, 16], ], [ [21, 22, 23], [24, 25, 26], ], [ [31, 32, 33], [34, 35, 36], ]]);
Examples:1D x 1D x 1Dauto u = [100, 200]; auto v = [10, 20, 30]; auto w = [1, 2]; auto c = cartesian(u, v, w) .map!"a + b + c"; assert(c.shape == [2, 3, 2]); assert(c == [ [ [111, 112], [121, 122], [131, 132], ], [ [211, 212], [221, 222], [231, 232], ]]);
- template
kronecker
(alias fun = product) - Constructs lazy kronecker product Slice without memory allocation.Examples:2D
import mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; // eye auto a = slice!double([4, 4], 0); a.diagonal[] = 1; auto b = [ 1, -1, -1, 1].sliced(2, 2); auto c = kronecker(a, b); assert(c == [ [ 1, -1, 0, 0, 0, 0, 0, 0], [-1, 1, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, -1, 0, 0, 0, 0], [ 0, 0, -1, 1, 0, 0, 0, 0], [ 0, 0, 0, 0, 1, -1, 0, 0], [ 0, 0, 0, 0, -1, 1, 0, 0], [ 0, 0, 0, 0, 0, 0, 1, -1], [ 0, 0, 0, 0, 0, 0, -1, 1]]);
Examples:1Dauto a = iota([3], 1); auto b = [ 1, -1]; auto c = kronecker(a, b); assert(c == [1, -1, 2, -2, 3, -3]);
Examples:2D with 3 argumentsimport mir.ndslice.allocation: slice; import mir.ndslice.slice: sliced; auto a = [ 1, 2, 3, 4].sliced(2, 2); auto b = [ 1, 0, 0, 1].sliced(2, 2); auto c = [ 1, -1, -1, 1].sliced(2, 2); auto d = kronecker(a, b, c); assert(d == [ [ 1, -1, 0, 0, 2, -2, 0, 0], [-1, 1, 0, 0, -2, 2, 0, 0], [ 0, 0, 1, -1, 0, 0, 2, -2], [ 0, 0, -1, 1, 0, 0, -2, 2], [ 3, -3, 0, 0, 4, -4, 0, 0], [-3, 3, 0, 0, -4, 4, 0, 0], [ 0, 0, 3, -3, 0, 0, 4, -4], [ 0, 0, -3, 3, 0, 0, -4, 4]]);
- auto
kronecker
(NdFields...)(NdFieldsfields
)
if (allSatisfy!(hasShape, NdFields) || allSatisfy!(hasLength, NdFields)); - Parameters:
NdFields fields
list of either fields with lengths or ndFields with shapes. All ndFields must have the same dimension count. Returns:
- auto
magic
(size_tlength
); - Parameters:
size_t length
square matrix length. Returns:Lazy magic matrix.Examples:import mir.math.sum; import mir.ndslice: slice, magic, byDim, map, as, repeat, diagonal, antidiagonal; bool isMagic(S)(S matrix) { auto n = matrix.length; auto c = n * (n * n + 1) / 2; // magic number return // check shape matrix.length!0 > 0 && matrix.length!0 == matrix.length!1 && // each row sum should equal magic number matrix.byDim!0.map!sum == c.repeat(n) && // each columns sum should equal magic number matrix.byDim!1.map!sum == c.repeat(n) && // diagonal sum should equal magic number matrix.diagonal.sum == c && // antidiagonal sum should equal magic number matrix.antidiagonal.sum == c; } assert(isMagic(magic(1))); assert(!isMagic(magic(2))); // 2x2 magic square does not exist foreach(n; 3 .. 24) assert(isMagic(magic(n))); assert(isMagic(magic(3).as!double.slice));
- Slice!(StairsIterator!(Iterator, type))
stairs
(string type, Iterator)(Slice!Iteratorslice
, size_tn
)
if (type == "+" || type == "-");
Slice!(StairsIterator!(S*, type))stairs
(string type, S)(S[]slice
, size_tn
)
if (type == "+" || type == "-");
autostairs
(string type, S)(Sslice
, size_tn
)
if (hasAsSlice!S && (type == "+" || type == "-")); - Chops 1D input slice into n chunks with ascending or descending lengths.
stairs
can be used to pack and unpack symmetric and triangular matrix storage.Note
stairs
is defined for 1D (packet) input and 2D (general) input. This part of documentation is for 1D input.Parameters:type - "-" for stairs with lengths
n
,n
-1, ..., 1. - "+" for stairs with lengths 1, 2, ...,
n
;
Slice!Iterator slice
input slice with length equal to n
* (n
+ 1) / 2size_t n
stairs count Returns:1D contiguous slice composed of 1D contiguous slices.Examples:import mir.ndslice.topology: iota, stairs; auto pck = 15.iota; auto inc = pck.stairs!"+"(5); auto dec = pck.stairs!"-"(5); assert(inc == [ [0], [1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13, 14]]); assert(inc[1 .. $][2] == [6, 7, 8, 9]); assert(dec == [ [0, 1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11], [12, 13], [14]]); assert(dec[1 .. $][2] == [12, 13]); static assert(is(typeof(inc.front) == typeof(pck))); static assert(is(typeof(dec.front) == typeof(pck)));
- "-" for stairs with lengths
- auto
stairs
(string type, Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)slice
)
if (type == "+" || type == "-"); - Slice composed of rows of lower or upper triangular matrix.
stairs
can be used to pack and unpack symmetric and triangular matrix storage.Note
stairs
is defined for 1D (packet) input and 2D (general) input. This part of documentation is for 2D input.Parameters:type - "+" for stairs with lengths 1, 2, ..., n, lower matrix;
- "-" for stairs with lengths n, n-1, ..., 1, upper matrix.
Slice!(Iterator, 2, kind) slice
input slice with length equal to n * (n + 1) / 2 Returns:1D slice composed of 1D contiguous slices.See Also:Examples:import mir.ndslice.topology: iota, as, stairs; auto gen = [3, 3].iota.as!double; auto inc = gen.stairs!"+"; auto dec = gen.stairs!"-"; assert(inc == [ [0], [3, 4], [6, 7, 8]]); assert(dec == [ [0, 1, 2], [4, 5], [8]]); static assert(is(typeof(inc.front) == typeof(gen.front))); static assert(is(typeof(dec.front) == typeof(gen.front))); ///////////////////////////////////////// // Pack lower and upper matrix parts auto n = gen.length; auto m = n * (n + 1) / 2; // allocate memory import mir.ndslice.allocation: uninitSlice; auto lowerData = m.uninitSlice!double; auto upperData = m.uninitSlice!double; // construct packed stairs auto lower = lowerData.stairs!"+"(n); auto upper = upperData.stairs!"-"(n); // copy data import mir.algorithm.iteration: each; each!"a[] = b"(lower, inc); each!"a[] = b"(upper, dec); assert(&lower[0][0] is &lowerData[0]); assert(&upper[0][0] is &upperData[0]); assert(lowerData == [0, 3, 4, 6, 7, 8]); assert(upperData == [0, 1, 2, 4, 5, 8]);
- template
alongDim
(SDimensions...) if (SDimensions.length > 0) - Returns a slice that can be iterated along dimension. Transposes other dimensions on top and then packs them.Parameters:
SDimensions dimensions to iterate along, length of d, 1 <= d < n. Negative dimensions are supported. Returns:(n-d)-dimensional slice composed of d-dimensional slicesSee Also:Examples:2-dimensional slice supportimport mir.ndslice; // ------------ // | 0 1 2 3 | // | 4 5 6 7 | // | 8 9 10 11 | // ------------ auto slice = iota(3, 4); //-> // | 3 | //-> // | 4 | size_t[1] shape3 = [3]; size_t[1] shape4 = [4]; // ------------ // | 0 1 2 3 | // | 4 5 6 7 | // | 8 9 10 11 | // ------------ auto x = slice.alongDim!(-1); // -1 is the last dimension index, the same as 1 for this case. static assert(is(typeof(x) == Slice!(SliceIterator!(IotaIterator!sizediff_t), 1, Universal))); assert(x.shape == shape3); assert(x.front.shape == shape4); assert(x.front == iota(4)); x.popFront; assert(x.front == iota([4], 4)); // --------- // | 0 4 8 | // | 1 5 9 | // | 2 6 10 | // | 3 7 11 | // --------- auto y = slice.alongDim!0; // alongDim!(-2) is the same for matrices. static assert(is(typeof(y) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 1, Universal)))); assert(y.shape == shape4); assert(y.front.shape == shape3); assert(y.front == iota([3], 0, 4)); y.popFront; assert(y.front == iota([3], 1, 4));
Examples:3-dimensional slice support, N-dimensional also supportedimport mir.ndslice; // ---------------- // | 0 1 2 3 4 | // | 5 6 7 8 9 | // | 10 11 12 13 14 | // | 15 16 17 18 19 | // - - - - - - - - // | 20 21 22 23 24 | // | 25 26 27 28 29 | // | 30 31 32 33 34 | // | 35 36 37 38 39 | // - - - - - - - - // | 40 41 42 43 44 | // | 45 46 47 48 49 | // | 50 51 52 53 54 | // | 55 56 57 58 59 | // ---------------- auto slice = iota(3, 4, 5); size_t[2] shape45 = [4, 5]; size_t[2] shape35 = [3, 5]; size_t[2] shape34 = [3, 4]; size_t[2] shape54 = [5, 4]; size_t[1] shape3 = [3]; size_t[1] shape4 = [4]; size_t[1] shape5 = [5]; // ---------- // | 0 20 40 | // | 5 25 45 | // | 10 30 50 | // | 15 35 55 | // - - - - - // | 1 21 41 | // | 6 26 46 | // | 11 31 51 | // | 16 36 56 | // - - - - - // | 2 22 42 | // | 7 27 47 | // | 12 32 52 | // | 17 37 57 | // - - - - - // | 3 23 43 | // | 8 28 48 | // | 13 33 53 | // | 18 38 58 | // - - - - - // | 4 24 44 | // | 9 29 49 | // | 14 34 54 | // | 19 39 59 | // ---------- auto a = slice.alongDim!0.transposed; static assert(is(typeof(a) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 1, Universal), 2, Universal))); assert(a.shape == shape54); assert(a.front.shape == shape4); assert(a.front.unpack == iota([3, 4], 0, 5).universal.transposed); a.popFront; assert(a.front.front == iota([3], 1, 20)); // ---------------- // | 0 1 2 3 4 | // | 5 6 7 8 9 | // | 10 11 12 13 14 | // | 15 16 17 18 19 | // - - - - - - - - // | 20 21 22 23 24 | // | 25 26 27 28 29 | // | 30 31 32 33 34 | // | 35 36 37 38 39 | // - - - - - - - - // | 40 41 42 43 44 | // | 45 46 47 48 49 | // | 50 51 52 53 54 | // | 55 56 57 58 59 | // ---------------- auto x = slice.alongDim!(1, 2); static assert(is(typeof(x) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2), 1, Universal))); assert(x.shape == shape3); assert(x.front.shape == shape45); assert(x.front == iota([4, 5])); x.popFront; assert(x.front == iota([4, 5], (4 * 5))); // ---------------- // | 0 1 2 3 4 | // | 20 21 22 23 24 | // | 40 41 42 43 44 | // - - - - - - - - // | 5 6 7 8 9 | // | 25 26 27 28 29 | // | 45 46 47 48 49 | // - - - - - - - - // | 10 11 12 13 14 | // | 30 31 32 33 34 | // | 50 51 52 53 54 | // - - - - - - - - // | 15 16 17 18 19 | // | 35 36 37 38 39 | // | 55 56 57 58 59 | // ---------------- auto y = slice.alongDim!(0, 2); static assert(is(typeof(y) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Canonical), 1, Universal))); assert(y.shape == shape4); assert(y.front.shape == shape35); int err; assert(y.front == slice.universal.strided!1(4).reshape([3, -1], err)); y.popFront; assert(y.front.front == iota([5], 5)); // ------------- // | 0 5 10 15 | // | 20 25 30 35 | // | 40 45 50 55 | // - - - - - - - // | 1 6 11 16 | // | 21 26 31 36 | // | 41 46 51 56 | // - - - - - - - // | 2 7 12 17 | // | 22 27 32 37 | // | 42 47 52 57 | // - - - - - - - // | 3 8 13 18 | // | 23 28 33 38 | // | 43 48 53 58 | // - - - - - - - // | 4 9 14 19 | // | 24 29 34 39 | // | 44 49 54 59 | // ------------- auto z = slice.alongDim!(0, 1); static assert(is(typeof(z) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Universal)))); assert(z.shape == shape5); assert(z.front.shape == shape34); assert(z.front == iota([3, 4], 0, 5)); z.popFront; assert(z.front.front == iota([4], 1, 5));
Examples:Use alongDim to calculate column mean/row mean of 2-dimensional sliceimport mir.ndslice.topology: alongDim; import mir.ndslice.fuse: fuse; import mir.math.stat: mean; import mir.algorithm.iteration: all; import mir.math.common: approxEqual; auto x = [ [0.0, 1.0, 1.5, 2.0, 3.5, 4.25], [2.0, 7.5, 5.0, 1.0, 1.5, 0.0] ].fuse; // Use alongDim with map to compute mean of row/column. assert(x.alongDim!1.map!mean.all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.alongDim!0.map!mean.all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125])); // FIXME // Without using map, computes the mean of the whole slice // assert(x.alongDim!1.mean == x.sliced.mean); // assert(x.alongDim!0.mean == x.sliced.mean);
Examples:Use alongDim and map with a lambda, but may need to allocate result. This example uses fuse, which allocates. Note: fuse!1 will transpose the result.import mir.ndslice.topology: iota, alongDim, map; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; auto x = [1, 2, 3].sliced; auto y = [1, 2].sliced; auto s1 = iota(2, 3).alongDim!1.map!(a => a * x).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s2 = iota(2, 3).alongDim!0.map!(a => a * y).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]);
- auto
alongDim
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (N > SDimensions.length); - Parameters:
Slice!(Iterator, N, kind) slice
input n-dimensional slice, n > d Returns:(n-d)-dimensional slice composed of d-dimensional slices
- template
byDim
(SDimensions...) if (SDimensions.length > 0) - Returns a slice that can be iterated by dimension. Transposes dimensions on top and then packs them.Combines transposed , ipack, and SliceKind Selectors.Parameters:
SDimensions dimensions to perform iteration on, length of d, 1 <= d <= n. Negative dimensions are supported. Returns:d-dimensional slice composed of (n-d)-dimensional slicesSee Also:Examples:2-dimensional slice supportimport mir.ndslice; // ------------ // | 0 1 2 3 | // | 4 5 6 7 | // | 8 9 10 11 | // ------------ auto slice = iota(3, 4); //-> // | 3 | //-> // | 4 | size_t[1] shape3 = [3]; size_t[1] shape4 = [4]; // ------------ // | 0 1 2 3 | // | 4 5 6 7 | // | 8 9 10 11 | // ------------ auto x = slice.byDim!0; // byDim!(-2) is the same for matrices. static assert(is(typeof(x) == Slice!(SliceIterator!(IotaIterator!sizediff_t), 1, Universal))); assert(x.shape == shape3); assert(x.front.shape == shape4); assert(x.front == iota(4)); x.popFront; assert(x.front == iota([4], 4)); // --------- // | 0 4 8 | // | 1 5 9 | // | 2 6 10 | // | 3 7 11 | // --------- auto y = slice.byDim!(-1); // -1 is the last dimension index, the same as 1 for this case. static assert(is(typeof(y) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 1, Universal)))); assert(y.shape == shape4); assert(y.front.shape == shape3); assert(y.front == iota([3], 0, 4)); y.popFront; assert(y.front == iota([3], 1, 4));
Examples:3-dimensional slice support, N-dimensional also supportedimport mir.ndslice; // ---------------- // | 0 1 2 3 4 | // | 5 6 7 8 9 | // | 10 11 12 13 14 | // | 15 16 17 18 19 | // - - - - - - - - // | 20 21 22 23 24 | // | 25 26 27 28 29 | // | 30 31 32 33 34 | // | 35 36 37 38 39 | // - - - - - - - - // | 40 41 42 43 44 | // | 45 46 47 48 49 | // | 50 51 52 53 54 | // | 55 56 57 58 59 | // ---------------- auto slice = iota(3, 4, 5); size_t[2] shape45 = [4, 5]; size_t[2] shape35 = [3, 5]; size_t[2] shape34 = [3, 4]; size_t[2] shape54 = [5, 4]; size_t[1] shape3 = [3]; size_t[1] shape4 = [4]; size_t[1] shape5 = [5]; // ---------------- // | 0 1 2 3 4 | // | 5 6 7 8 9 | // | 10 11 12 13 14 | // | 15 16 17 18 19 | // - - - - - - - - // | 20 21 22 23 24 | // | 25 26 27 28 29 | // | 30 31 32 33 34 | // | 35 36 37 38 39 | // - - - - - - - - // | 40 41 42 43 44 | // | 45 46 47 48 49 | // | 50 51 52 53 54 | // | 55 56 57 58 59 | // ---------------- auto x = slice.byDim!0; static assert(is(typeof(x) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2), 1, Universal))); assert(x.shape == shape3); assert(x.front.shape == shape45); assert(x.front == iota([4, 5])); x.popFront; assert(x.front == iota([4, 5], (4 * 5))); // ---------------- // | 0 1 2 3 4 | // | 20 21 22 23 24 | // | 40 41 42 43 44 | // - - - - - - - - // | 5 6 7 8 9 | // | 25 26 27 28 29 | // | 45 46 47 48 49 | // - - - - - - - - // | 10 11 12 13 14 | // | 30 31 32 33 34 | // | 50 51 52 53 54 | // - - - - - - - - // | 15 16 17 18 19 | // | 35 36 37 38 39 | // | 55 56 57 58 59 | // ---------------- auto y = slice.byDim!1; static assert(is(typeof(y) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Canonical), 1, Universal))); assert(y.shape == shape4); assert(y.front.shape == shape35); int err; assert(y.front == slice.universal.strided!1(4).reshape([3, -1], err)); y.popFront; assert(y.front.front == iota([5], 5)); // ------------- // | 0 5 10 15 | // | 20 25 30 35 | // | 40 45 50 55 | // - - - - - - - // | 1 6 11 16 | // | 21 26 31 36 | // | 41 46 51 56 | // - - - - - - - // | 2 7 12 17 | // | 22 27 32 37 | // | 42 47 52 57 | // - - - - - - - // | 3 8 13 18 | // | 23 28 33 38 | // | 43 48 53 58 | // - - - - - - - // | 4 9 14 19 | // | 24 29 34 39 | // | 44 49 54 59 | // ------------- auto z = slice.byDim!2; static assert(is(typeof(z) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Universal)))); assert(z.shape == shape5); assert(z.front.shape == shape34); assert(z.front == iota([3, 4], 0, 5)); z.popFront; assert(z.front.front == iota([4], 1, 5)); // ---------- // | 0 20 40 | // | 5 25 45 | // | 10 30 50 | // | 15 35 55 | // - - - - - // | 1 21 41 | // | 6 26 46 | // | 11 31 51 | // | 16 36 56 | // - - - - - // | 2 22 42 | // | 7 27 47 | // | 12 32 52 | // | 17 37 57 | // - - - - - // | 3 23 43 | // | 8 28 48 | // | 13 33 53 | // | 18 38 58 | // - - - - - // | 4 24 44 | // | 9 29 49 | // | 14 34 54 | // | 19 39 59 | // ---------- auto a = slice.byDim!(2, 1); static assert(is(typeof(a) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 1, Universal), 2, Universal))); assert(a.shape == shape54); assert(a.front.shape == shape4); assert(a.front.unpack == iota([3, 4], 0, 5).universal.transposed); a.popFront; assert(a.front.front == iota([3], 1, 20));
Examples:Use byDim to calculate column mean/row mean of 2-dimensional sliceimport mir.ndslice.topology: byDim; import mir.ndslice.fuse: fuse; import mir.math.stat: mean; import mir.algorithm.iteration: all; import mir.math.common: approxEqual; auto x = [ [0.0, 1.0, 1.5, 2.0, 3.5, 4.25], [2.0, 7.5, 5.0, 1.0, 1.5, 0.0] ].fuse; // Use byDim with map to compute mean of row/column. assert(x.byDim!0.map!mean.all!approxEqual([12.25 / 6, 17.0 / 6])); assert(x.byDim!1.map!mean.all!approxEqual([1, 4.25, 3.25, 1.5, 2.5, 2.125])); // FIXME // Without using map, computes the mean of the whole slice // assert(x.byDim!0.mean == x.sliced.mean); // assert(x.byDim!1.mean == x.sliced.mean);
Examples:Use byDim and map with a lambda, but may need to allocate result. This example uses fuse, which allocates. Note: fuse!1 will transpose the result.import mir.ndslice.topology: iota, byDim, map; import mir.ndslice.fuse: fuse; import mir.ndslice.slice: sliced; auto x = [1, 2, 3].sliced; auto y = [1, 2].sliced; auto s1 = iota(2, 3).byDim!0.map!(a => a * x).fuse; assert(s1 == [[ 0, 2, 6], [ 3, 8, 15]]); auto s2 = iota(2, 3).byDim!1.map!(a => a * y).fuse!1; assert(s2 == [[ 0, 1, 2], [ 6, 8, 10]]);
- auto
byDim
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
)
if (N >= SDimensions.length); - Parameters:
Slice!(Iterator, N, kind) slice
input n-dimensional slice, n >= d Returns:d-dimensional slice composed of (n-d)-dimensional slices
- template
squeeze
(sizediff_t axis = 0) - Constructs a new view of an n-dimensional slice with dimension axis removed.Throws:AssertError if the length of the corresponding dimension doesn' equal 1.Parameters:
axis dimension to remove, if it is single-dimensional Slice!(Iterator, N, kind) slice n-dimensional slice Returns:new view of a slice with dimension removedExamples:import mir.ndslice.topology : iota; import mir.ndslice.allocation : slice; // [[0, 1, 2]] -> [0, 1, 2] assert([1, 3].iota.squeeze == [3].iota); // [[0], [1], [2]] -> [0, 1, 2] assert([3, 1].iota.squeeze!1 == [3].iota); assert([3, 1].iota.squeeze!(-1) == [3].iota); assert([1, 3].iota.canonical.squeeze == [3].iota); assert([3, 1].iota.canonical.squeeze!1 == [3].iota); assert([3, 1].iota.canonical.squeeze!(-1) == [3].iota); assert([1, 3].iota.universal.squeeze == [3].iota); assert([3, 1].iota.universal.squeeze!1 == [3].iota); assert([3, 1].iota.universal.squeeze!(-1) == [3].iota); assert([1, 3, 4].iota.squeeze == [3, 4].iota); assert([3, 1, 4].iota.squeeze!1 == [3, 4].iota); assert([3, 4, 1].iota.squeeze!(-1) == [3, 4].iota); assert([1, 3, 4].iota.canonical.squeeze == [3, 4].iota); assert([3, 1, 4].iota.canonical.squeeze!1 == [3, 4].iota); assert([3, 4, 1].iota.canonical.squeeze!(-1) == [3, 4].iota); assert([1, 3, 4].iota.universal.squeeze == [3, 4].iota); assert([3, 1, 4].iota.universal.squeeze!1 == [3, 4].iota); assert([3, 4, 1].iota.universal.squeeze!(-1) == [3, 4].iota);
- Slice!(Iterator, N + 1, kind)
unsqueeze
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
, sizediff_taxis
);
templateunsqueeze
(sizediff_t axis = 0) - Constructs a view of an n-dimensional slice with a dimension added at
axis
. Used to unsqueeze a squeezed slice.Parameters:Slice!(Iterator, N, kind) slice
n-dimensional slice sizediff_t axis
dimension to be unsqueezed (add new dimension), default values is 0, the first dimension Returns:unsqueezed n+1-dimensional slice of the same slice kindExamples:// [0, 1, 2] -> [[0, 1, 2]] assert([3].iota.unsqueeze == [1, 3].iota); assert([3].iota.universal.unsqueeze == [1, 3].iota); assert([3, 4].iota.unsqueeze == [1, 3, 4].iota); assert([3, 4].iota.canonical.unsqueeze == [1, 3, 4].iota); assert([3, 4].iota.universal.unsqueeze == [1, 3, 4].iota); // [0, 1, 2] -> [[0], [1], [2]] assert([3].iota.unsqueeze(-1) == [3, 1].iota); assert([3].iota.unsqueeze!(-1) == [3, 1].iota); assert([3].iota.universal.unsqueeze(-1) == [3, 1].iota); assert([3].iota.universal.unsqueeze!(-1) == [3, 1].iota); assert([3, 4].iota.unsqueeze(-1) == [3, 4, 1].iota); assert([3, 4].iota.unsqueeze!(-1) == [3, 4, 1].iota); assert([3, 4].iota.canonical.unsqueeze(-1) == [3, 4, 1].iota); assert([3, 4].iota.canonical.unsqueeze!(-1) == [3, 4, 1].iota); assert([3, 4].iota.universal.unsqueeze(-1) == [3, 4, 1].iota); assert([3, 4].iota.universal.unsqueeze!(-1) == [3, 4, 1].iota);
- template
member
(string name) if (name.length) - Field (element's member) projection.Parameters:
name element's member name Returns:lazy n-dimensional slice of the same shapeSee Also:Examples:// struct, union or class struct S { // Property support // Getter always must be defined. double _x; double x() @property { return x; } void x(double x) @property { _x = x; } /// Field support double y; /// Zero argument function support double f() { return _x * 2; } } import mir.ndslice.allocation: slice; import mir.ndslice.topology: iota; auto matrix = slice!S(2, 3); matrix.member!"x"[] = [2, 3].iota; matrix.member!"y"[] = matrix.member!"f"; assert(matrix.member!"y" == [2, 3].iota * 2);
- Slice!(MemberIterator!(Iterator, name), N, kind)
member
(Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)slice
);
Slice!(MemberIterator!(T*, name))member
(T)(T[]array
);
automember
(T)(TwithAsSlice
)
if (hasAsSlice!T); - Parameters:
Slice!(Iterator, N, kind) slice
n-dimensional slice composed of structs, classes or unions Returns:lazy n-dimensional slice of the same shape
- template
orthogonalReduceField
(alias fun) - Functional deep-element wise reduce of a slice composed of fields or iterators.Examples:bit array operations
import mir.ndslice.slice: slicedField; import mir.ndslice.allocation: bitSlice; import mir.ndslice.dynamic: strided; import mir.ndslice.topology: iota, orthogonalReduceField; auto len = 100; auto a = len.bitSlice; auto b = len.bitSlice; auto c = len.bitSlice; a[len.iota.strided!0(7)][] = true; b[len.iota.strided!0(11)][] = true; c[len.iota.strided!0(13)][] = true; // this is valid since bitslices above are oroginal slices of allocated memory. auto and = orthogonalReduceField!"a & b"(size_t.max, [ a.iterator._field._field, // get raw data pointers b.iterator._field._field, c.iterator._field._field, ]) // operation on size_t .bitwiseField .slicedField(len); assert(and == (a & b & c));
- OrthogonalReduceField!(Iterator, fun, I)
orthogonalReduceField
(I, Iterator)(IinitialValue
, Slice!Iteratorslice
);
OrthogonalReduceField!(T*, fun, I)orthogonalReduceField
(I, T)(IinitialValue
, T[]array
);
autoorthogonalReduceField
(I, T)(IinitialValue
, TwithAsSlice
)
if (hasAsSlice!T); - Parameters:
Slice!Iterator slice
Non empty input slice composed of fields or iterators. Returns:a lazy field with each element of which is reduced value of element of the same index of all iterators.
- Slice!(TripletIterator!(Iterator, kind))
triplets
(Iterator, SliceKind kind)(Slice!(Iterator, 1, kind)slice
);
Slice!(TripletIterator!(T*))triplets
(T)(return scope T[]slice
);
autotriplets
(string type, S)(Sslice
, size_tn
)
if (hasAsSlice!S); - Constructs a lazy view of triplets with left, center, and right members.Returns:Parameters:
Slice!(Iterator, 1, kind) slice
a slice or an array to iterate over Example
triplets(eeeeee) => ||c|lllll| |r|c|llll| |rr|c|lll| |rrr|c|ll| |rrrr|c|l| |rrrrr|c||
See Also:Examples:import mir.ndslice.slice: sliced; import mir.ndslice.topology: triplets, member, iota; auto a = [4, 5, 2, 8]; auto h = a.triplets; assert(h[1].center == 5); assert(h[1].left == [4]); assert(h[1].right == [2, 8]); h[1].center = 9; assert(a[1] == 9); assert(h.member!"center" == a); // `triplets` topology can be used with iota to index a slice auto s = a.sliced; auto w = s.length.iota.triplets[1]; assert(&s[w.center] == &a[1]); assert(s[w.left].field is a[0 .. 1]); assert(s[w.right].field is a[2 .. $]);
Copyright © 2016-2022 by Ilya Yaroshenko | Page generated by
Ddoc on Tue Jan 11 06:37:11 2022