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

This is a submodule of mir.ndslice.
The module contains chunks routine. Chunks structure is multidimensional random access range with slicing.
slicedField , slicedNdField  can be used to construct ndslice view on top of Chunks.
Authors:
Ilya Yaroshenko
template chunks(Dimensions...) if (Dimensions.length)

Chunks!([0], kind, packs, Iterator) chunks(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice, size_t chunkLength);
Creates Chunks.
Parameters:
Dimensions compile time list of dimensions to chunk
See Also:
Examples:
1Dx1D
import mir.ndslice.chunks: chunks, isChunks;
import mir.ndslice.topology: iota;

// 0 1 2 3 4 5 6 7 8 9 10
auto sl = iota(11);
// 0 1 2 | 3 4 5 | 6 7 8 | 9 10
auto ch = sl.chunks(3);

static assert(isChunks!(typeof(ch)) == [0]); // isChunks returns dimension indexes

assert(ch.length == 4);

// 0 1 2
assert(ch.front == iota([3], 0));
ch.popFront;

// 3 4 5
assert(ch.front == iota([3], 3));
assert(ch.length == 3);

// 9 10
assert(ch[$ - 1] == ch.back);
assert(ch.back == iota([2], 9));

ch.popBack;
assert(ch.back == iota([3], 6));

assert(ch[$ - 1 .. $].length == 1);
assert(ch[$ .. $].length == 0);
assert(ch[0 .. 0].empty);

import std.range.primitives: isRandomAccessRange;
static assert(isRandomAccessRange!(typeof(ch)));
Examples:
2Dx2D
import mir.ndslice.chunks: chunks, isChunks;
import mir.ndslice.topology: iota;

//   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
//  60  61  62  63  64  65  66  67  68  69
//  70  71  72  73  74  75  76  77  78  79
//  80  81  82  83  84  85  86  87  88  89
//  90  91  92  93  94  95  96  97  98  99
// 100 101 102 103 104 105 106 107 108 109
auto sl = iota(11, 10); // [0, 1, .. 10]

//   ----------------   ----------------   -------- 
//  |  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 |
//  |----------------| |----------------| |--------|
//  | 60  61  62  63 | | 64  65  66  67 | | 68  69 |
//  | 70  71  72  73 | | 74  75  76  77 | | 78  79 |
//  | 80  81  82  83 | | 84  85  86  87 | | 88  89 |
//  |----------------| |----------------| |--------|
//  | 90  91  92  93 | | 94  95  96  97 | | 98  99 |
//  | 00 101 102 103 | |104 105 106 107 | |108 109 |
//   ----------------   ----------------   -------- 
// Chunk columns first, then blocks rows.
auto ch = sl.chunks!(1, 0)(4, 3);

assert(ch.slice == sl);
assert(ch.front.slice == sl[0 .. $, 0 .. 4]);

assert(ch.front.front == sl[0 .. 3, 0 .. 4]);

assert(ch.front!0[1] == sl[3 .. 6, 0 .. 4]);
assert(ch.front!1[1] == sl[0 .. 3, 4 .. 8]);

assert (ch[$ - 1, $ - 1] == [[98, 99], [108, 109]]);

static assert(isChunks!(typeof(ch)) == [1, 0]); // isChunks returns dimension indexes

assert(ch.length == 3);
assert(ch.length!1 == 4);

ch.popFront;
assert(ch.front.front == sl[0 .. 3, 4 .. 8]);
ch.popFront!1;
assert(ch.front.front == sl[3 .. 6, 4 .. 8]);

assert(ch.back.slice == sl[3 .. $, 8 .. $]);
ch.popBack;
assert(ch.back.slice == sl[3 .. $, 4 .. 8]);

import std.range.primitives: isRandomAccessRange;
static assert(isRandomAccessRange!(typeof(ch)));
Examples:
1Dx2D
import mir.ndslice.chunks: chunks, isChunks;
import mir.ndslice.topology: iota;

//   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
auto sl = iota(4, 10); // [0, 1, .. 10]

//   ----------------   ----------------   -------- 
//  |  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 |
//   ----------------   ----------------   -------- 
// Chunk columns
auto ch = sl.chunks!1(4);

assert(ch.slice == sl);
assert(ch.front == sl[0 .. $, 0 .. 4]);

assert(ch.back == sl[0 .. $, 8 .. $]);

import std.range.primitives: isRandomAccessRange;
static assert(isRandomAccessRange!(typeof(ch)));
struct Chunks(size_t[] dimensions, SliceKind kind, size_t[] packs, Iterator);
@property size_t[dimensions.length] chunkLengths()();

size_t[dimensions.length] _chunkLengths;
Chunk shape.
@property Slice!(kind, packs, Iterator) slice()();
Underlying ndslice. It always correspond to current chunks state. Its shape equal to the concatenation of the all chunks.
Slice!(kind, packs, Iterator) _slice;
const @property bool empty(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);

const @property size_t length(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);

@property auto front(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);
ndslice-like primitives
@property auto back(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);

void popFront(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);

void popBack(size_t dimensionIndex = 0)()
if (dimensionIndex < dimensions.length);

const _Slice!() opSlice(size_t dimensionIndex)(size_t i, size_t j)
if (dimensionIndex < dimensions.length);

const ChunksSlice!() opSlice(size_t dimensionIndex)(size_t i, ChunksDollar!() j)
if (dimensionIndex < dimensions.length);

@property ChunksDollar!() opDollar(size_t dimensionIndex)();

auto opIndex(Slices...)(Slices slices)
if (Slices.length <= dimensions.length);

auto opIndex()(size_t[dimensions.length] index);

@property auto save()();
@property auto select(size_t dimensionIndex = 0)(size_t index)
if (dimensionIndex < dimensions.length);

@property auto select(size_t dimensionIndex = 0)(size_t i, size_t j)
if (dimensionIndex < dimensions.length);
template isChunks(T)
Checks if T is Chunks type.
Returns:
array of dimension indexes.
Examples:
import mir.ndslice.chunks: chunks, isChunks;
import mir.ndslice.topology: iota;

static assert(isChunks!int == null);
static assert(isChunks!(typeof(iota(20, 30).chunks!(1, 0)(3, 7))) == [1, 0]);
void popFrontTuple(size_t dimmensionIndex = 0, Master, Followers...)(ref Master master, ref Followers followers)
if (isChunks!Master && allSatisfy!(isChunks, Followers));
Evaluates popFront!dimmensionIndex for multiple Chunks structures at once. All chunks structures must have for the appropriate dimension the same chunk lengths and the same underlying slice lengths.
Parameters:
dimmensionIndex dimensionIndex
Master master the fist chunks structure
Followers followers following chunks structures
Examples:
import mir.ndslice.chunks: chunks;
import mir.ndslice.topology: iota;

auto a = iota(10, 20).chunks!(0, 1)(3, 7);
auto b = iota(20, 10).chunks!(1, 0)(3, 7);

auto as = a;
auto bs = b;

as.popFront;
bs.popFront;

popFrontTuple(a, b);

assert(as.slice == a.slice);
assert(bs.slice == b.slice);

assert(as.chunkLengths == a.chunkLengths);
assert(bs.chunkLengths == b.chunkLengths);