@@ -404,6 +404,8 @@ $(TR $(TD A $(B fully defined slice) is an empty sequence
404404 or a sequence composed of $(B indexes) and at least one
405405 $(B interval) with an overall length equal to `N`.)
406406 $(STD `[]`, `[3..$,0..3,0..$-1]`, `[2,0..$,1]`))
407+ $(TR $(TD An $(B indexed slice) is syntax sugar for $(SUBREF indexed, topology) and $(SUBREF cartesian, topology).
408+ $(STD `[anNdslice]`, `[anNdsliceForCartesian0, anNdsliceForCartesian1]`))
407409)
408410
409411$(H3 Internal Binary Representation)
@@ -578,6 +580,11 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
578580 && PureIndexLength! Slices < packs[0 ]
579581 && allSatisfy! (templateOr! (isIndex, is_Slice), Slices);
580582
583+ enum isIndexedSlice (Slices... ) =
584+ Slices.length
585+ && Slices.length <= packs[0 ]
586+ && allSatisfy! (templateOr! isSlice, Slices);
587+
581588 // /
582589 public size_t [N] _lengths;
583590 // /
@@ -1495,6 +1502,81 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
14951502 auto col = slice[0 .. $, 1 ];
14961503 }
14971504
1505+ /+ +
1506+ $(BOLD Indexed slice.)
1507+ +/
1508+ auto opIndex (Slices... )(Slices slices)
1509+ if (isIndexedSlice! Slices)
1510+ {
1511+ import mir.ndslice.topology: indexed, cartesian, map;
1512+ static if (Slices.length == 1 )
1513+ alias index = slices[0 ];
1514+ else
1515+ auto index = slices.cartesian;
1516+ return this .indexed(index);
1517+ }
1518+
1519+ // /
1520+ pure nothrow unittest
1521+ {
1522+ import mir.ndslice.allocation: slice;
1523+ auto sli = slice! int (4 , 3 );
1524+ auto idx = slice! (size_t [2 ])(3 );
1525+ idx[] = [
1526+ cast (size_t [2 ])[0 , 2 ],
1527+ cast (size_t [2 ])[3 , 1 ],
1528+ cast (size_t [2 ])[2 , 0 ]];
1529+
1530+ // equivalent to:
1531+ // import mir.ndslice.topology: indexed;
1532+ // sli.indexed(indx)[] = 1;
1533+ sli[idx][] = 1 ;
1534+
1535+ assert (sli == [
1536+ [0 , 0 , 1 ],
1537+ [0 , 0 , 0 ],
1538+ [1 , 0 , 0 ],
1539+ [0 , 1 , 0 ],
1540+ ]);
1541+
1542+ foreach (row; sli[[1 , 3 ].sliced])
1543+ row[] += 2 ;
1544+
1545+ assert (sli == [
1546+ [0 , 0 , 1 ],
1547+ [2 , 2 , 2 ], // <-- += 2
1548+ [1 , 0 , 0 ],
1549+ [2 , 3 , 2 ], // <-- += 2
1550+ ]);
1551+ }
1552+
1553+ // /
1554+ pure nothrow unittest
1555+ {
1556+ import mir.ndslice.topology: iota;
1557+ import mir.ndslice.allocation: slice;
1558+ auto sli = slice! int (5 , 6 );
1559+
1560+ // equivalent to
1561+ // import mir.ndslice.topology: indexed, cartesian;
1562+ // auto a = [0, sli.length!0 / 2, sli.length!0 - 1].sliced;
1563+ // auto b = [0, sli.length!1 / 2, sli.length!1 - 1].sliced;
1564+ // auto c = cartesian(a, b);
1565+ // auto minor = sli.indexed(c);
1566+ auto minor = sli[[0 , $ / 2 , $ - 1 ].sliced, [0 , $ / 2 , $ - 1 ].sliced];
1567+
1568+ minor[] = iota([3 , 3 ], 1 );
1569+
1570+ assert (sli == [
1571+ // ↓ ↓ ↓︎
1572+ [1 , 0 , 0 , 2 , 0 , 3 ], // <---
1573+ [0 , 0 , 0 , 0 , 0 , 0 ],
1574+ [4 , 0 , 0 , 5 , 0 , 6 ], // <---
1575+ [0 , 0 , 0 , 0 , 0 , 0 ],
1576+ [7 , 0 , 0 , 8 , 0 , 9 ], // <---
1577+ ]);
1578+ }
1579+
14981580 static if (isMutable! (PureThis.DeepElemType))
14991581 {
15001582 private void opIndexOpAssignImplSlice (string op, SliceKind rkind, size_t [] rpacks, RIterator)(Slice! (rkind, rpacks, RIterator) value)
0 commit comments