Algorithms — map, reduce, each, fold
mir.algorithm.iteration provides functional-style algorithms that work natively with ndslice: each, reduce, fold, all, any, find, and more. All are @nogc and BetterC-compatible.
mir.algorithm.iteration is the ndslice-aware equivalent of std.algorithm. Unlike std.algorithm, these functions understand multi-dimensional slices and can iterate in row-major or custom order.
Import
import mir.algorithm.iteration;
// or selectively:
import mir.algorithm.iteration : each, reduce, fold, all, any;each — side-effectful iteration
auto m = slice!double(3, 4);
// Value only
m.each!((ref double v) { v = 1.0; });
// Value + indices
m.each!((ref double v, size_t i, size_t j) {
v = cast(double)(i * 4 + j);
});
// Pair-wise: two slices of the same shape
auto a = iota!double(3, 4);
auto b = slice!double(3, 4);
each!((double x, ref double y) { y = x * 2; })(a, b);each always returns void. Use it for in-place mutation.
reduce — fold to a scalar
import mir.algorithm.iteration : reduce;
auto v = [1.0, 2.0, 3.0, 4.0].sliced;
double sum = v.reduce!"a + b"(0.0); // 10.0
double prod = v.reduce!"a * b"(1.0); // 24.0
double mx = v.reduce!fmax(double.nan); // 4.0Works on any-dimensional slice by iterating all elements in row-major order.
fold — accumulate with initial value (alias style)
import mir.algorithm.iteration : fold;
alias sum = fold!"a + b";
alias prod = fold!"a * b";
double s = sum(v, 0.0); // same as reduce but cleaner aliasingall and any — boolean tests
import mir.algorithm.iteration : all, any;
auto m = iota(3, 4);
bool allPositive = m.all!(x => x >= 0); // true
bool anyBig = m.any!(x => x > 10); // true (11)Short-circuits on first failure / success.
find — locate an element
import mir.algorithm.iteration : find;
auto v = [3.0, 1.0, 4.0, 1.0, 5.0].sliced;
auto rest = v.find!(x => x > 3.5);
// rest starts at the element 4.0minmaxIndex and minIndex / maxIndex
import mir.algorithm.iteration : minIndex, maxIndex, minmaxIndex;
auto v = [3.0, 1.0, 4.0, 1.0, 5.0].sliced;
size_t mi = v.minIndex; // 1
size_t mx = v.maxIndex; // 4
auto (mn, mx2) = v.minmaxIndex;Sorting (mir.algorithm.sorting)
import mir.algorithm.sorting : sort;
auto v = [3, 1, 4, 1, 5, 9, 2].sliced;
v.sort; // in-place ascending
v.sort!"a > b"; // descendingUnlike std.algorithm.sort, mir.algorithm.sorting.sort works on contiguous ndslice directly without converting to a range.
Performance notes
- All functions in
mir.algorithm.iterationare@nogc nothrow @safe(where the lambda allows). - For contiguous slices, the compiler typically auto-vectorizes the inner loop — no manual SIMD needed for simple kernels.
- For 2-D and higher slices, operations iterate in row-major (C) order, which is cache-friendly for contiguous slices.
Comparison with std.algorithm
| Feature | std.algorithm | mir.algorithm |
|---|---|---|
| ndslice support | Via .byElement conversion | Native |
@nogc | Some | All |
| BetterC | No | Yes |
2-D aware each | No | Yes (index args) |
| SIMD auto-vec | Limited | Better (contiguous) |
ndslice field — Custom Iterators
mir.ndslice.field lets you build ndslice-compatible iterators over arbitrary memory layouts, computed values, or external data structures without copying.
mir-core
Base building blocks for the Mir ecosystem — algebraic types (sumtype / tagged union / variant), universal reflection API, and basic math primitives. BetterC and @nogc compatible.