dimensions to perform iteration on, length of d, 1 <= d <= n. Negative dimensions are supported.
d-dimensional slice composed of (n-d)-dimensional slices
2-dimensional slice support
import 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));
3-dimensional slice support, N-dimensional also supported
1 import mir.ndslice; 2 3 // ---------------- 4 // | 0 1 2 3 4 | 5 // | 5 6 7 8 9 | 6 // | 10 11 12 13 14 | 7 // | 15 16 17 18 19 | 8 // - - - - - - - - 9 // | 20 21 22 23 24 | 10 // | 25 26 27 28 29 | 11 // | 30 31 32 33 34 | 12 // | 35 36 37 38 39 | 13 // - - - - - - - - 14 // | 40 41 42 43 44 | 15 // | 45 46 47 48 49 | 16 // | 50 51 52 53 54 | 17 // | 55 56 57 58 59 | 18 // ---------------- 19 auto slice = iota(3, 4, 5); 20 21 size_t[2] shape45 = [4, 5]; 22 size_t[2] shape35 = [3, 5]; 23 size_t[2] shape34 = [3, 4]; 24 size_t[2] shape54 = [5, 4]; 25 size_t[1] shape3 = [3]; 26 size_t[1] shape4 = [4]; 27 size_t[1] shape5 = [5]; 28 29 // ---------------- 30 // | 0 1 2 3 4 | 31 // | 5 6 7 8 9 | 32 // | 10 11 12 13 14 | 33 // | 15 16 17 18 19 | 34 // - - - - - - - - 35 // | 20 21 22 23 24 | 36 // | 25 26 27 28 29 | 37 // | 30 31 32 33 34 | 38 // | 35 36 37 38 39 | 39 // - - - - - - - - 40 // | 40 41 42 43 44 | 41 // | 45 46 47 48 49 | 42 // | 50 51 52 53 54 | 43 // | 55 56 57 58 59 | 44 // ---------------- 45 auto x = slice.byDim!0; 46 static assert(is(typeof(x) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2), 1, Universal))); 47 48 assert(x.shape == shape3); 49 assert(x.front.shape == shape45); 50 assert(x.front == iota([4, 5])); 51 x.popFront; 52 assert(x.front == iota([4, 5], (4 * 5))); 53 54 // ---------------- 55 // | 0 1 2 3 4 | 56 // | 20 21 22 23 24 | 57 // | 40 41 42 43 44 | 58 // - - - - - - - - 59 // | 5 6 7 8 9 | 60 // | 25 26 27 28 29 | 61 // | 45 46 47 48 49 | 62 // - - - - - - - - 63 // | 10 11 12 13 14 | 64 // | 30 31 32 33 34 | 65 // | 50 51 52 53 54 | 66 // - - - - - - - - 67 // | 15 16 17 18 19 | 68 // | 35 36 37 38 39 | 69 // | 55 56 57 58 59 | 70 // ---------------- 71 auto y = slice.byDim!1; 72 static assert(is(typeof(y) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Canonical), 1, Universal))); 73 74 assert(y.shape == shape4); 75 assert(y.front.shape == shape35); 76 int err; 77 assert(y.front == slice.universal.strided!1(4).reshape([3, -1], err)); 78 y.popFront; 79 assert(y.front.front == iota([5], 5)); 80 81 // ------------- 82 // | 0 5 10 15 | 83 // | 20 25 30 35 | 84 // | 40 45 50 55 | 85 // - - - - - - - 86 // | 1 6 11 16 | 87 // | 21 26 31 36 | 88 // | 41 46 51 56 | 89 // - - - - - - - 90 // | 2 7 12 17 | 91 // | 22 27 32 37 | 92 // | 42 47 52 57 | 93 // - - - - - - - 94 // | 3 8 13 18 | 95 // | 23 28 33 38 | 96 // | 43 48 53 58 | 97 // - - - - - - - 98 // | 4 9 14 19 | 99 // | 24 29 34 39 | 100 // | 44 49 54 59 | 101 // ------------- 102 auto z = slice.byDim!2; 103 static assert(is(typeof(z) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 2, Universal)))); 104 105 assert(z.shape == shape5); 106 assert(z.front.shape == shape34); 107 assert(z.front == iota([3, 4], 0, 5)); 108 z.popFront; 109 assert(z.front.front == iota([4], 1, 5)); 110 111 // ---------- 112 // | 0 20 40 | 113 // | 5 25 45 | 114 // | 10 30 50 | 115 // | 15 35 55 | 116 // - - - - - 117 // | 1 21 41 | 118 // | 6 26 46 | 119 // | 11 31 51 | 120 // | 16 36 56 | 121 // - - - - - 122 // | 2 22 42 | 123 // | 7 27 47 | 124 // | 12 32 52 | 125 // | 17 37 57 | 126 // - - - - - 127 // | 3 23 43 | 128 // | 8 28 48 | 129 // | 13 33 53 | 130 // | 18 38 58 | 131 // - - - - - 132 // | 4 24 44 | 133 // | 9 29 49 | 134 // | 14 34 54 | 135 // | 19 39 59 | 136 // ---------- 137 auto a = slice.byDim!(2, 1); 138 static assert(is(typeof(a) == Slice!(SliceIterator!(IotaIterator!sizediff_t, 1, Universal), 2, Universal))); 139 140 assert(a.shape == shape54); 141 assert(a.front.shape == shape4); 142 assert(a.front.unpack == iota([3, 4], 0, 5).universal.transposed); 143 a.popFront; 144 assert(a.front.front == iota([3], 1, 20));
Use byDim to calculate column mean/row mean of 2-dimensional slice
import 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);
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]]);
alongDim, slice, ipack, transposed.
Returns a slice that can be iterated by dimension. Transposes dimensions on top and then packs them.
Combines transposed, ipack, and SliceKind Selectors.