A function
import mir.ndslice.allocation: slice; import mir.ndslice.topology: iota; //| 1 2 3 | //| 4 5 6 | //| 7 8 9 | auto m = iota([3, 3], 1).slice; m.eachUpper!"a = 0"; assert(m == [ [1, 0, 0], [4, 5, 0], [7, 8, 9]]);
Swap two slices
import mir.utility : swap; import mir.ndslice.allocation : slice; import mir.ndslice.topology : as, iota; //| 0 1 2 | //| 3 4 5 | //| 6 7 8 | auto a = iota([3, 3]).as!double.slice; //| 10 11 12 | //| 13 14 15 | //| 16 17 18 | auto b = iota([3, 3], 10).as!double.slice; eachUpper!swap(a, b); assert(a == [ [0, 11, 12], [3, 4, 15], [6, 7, 8]]); assert(b == [ [10, 1, 2], [13, 14, 5], [16, 17, 18]]);
Swap two zipped slices
import mir.utility : swap; import mir.ndslice.allocation : slice; import mir.ndslice.topology : as, zip, iota; //| 0 1 2 | //| 3 4 5 | //| 6 7 8 | auto a = iota([3, 3]).as!double.slice; //| 10 11 12 | //| 13 14 15 | //| 16 17 18 | auto b = iota([3, 3], 10).as!double.slice; auto z = zip(a, b); z.eachUpper!(z => swap(z.a, z.b)); assert(a == [ [0, 11, 12], [3, 4, 15], [6, 7, 8]]); assert(b == [ [10, 1, 2], [13, 14, 5], [16, 17, 18]]);
This is functionally similar to each.
The call eachUpper!(fun)(slice1, ..., sliceN) evaluates fun on the upper triangle in slice1, ..., sliceN, respectively.
eachUpper allows iterating multiple slices in the lockstep.