Skip to content

Commit 53797c8

Browse files
committed
add last, first and lastIndex properties
1 parent 40e49a3 commit 53797c8

File tree

1 file changed

+93
-9
lines changed

1 file changed

+93
-9
lines changed

source/mir/ndslice/slice.d

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,14 +1049,14 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
10491049
static if (N == 1 && isMutable!DeepElemType && !hasAccessByRef)
10501050
{
10511051
///ditto
1052-
auto front(size_t dimension = 0, T)(T value) @property
1052+
auto ref front(size_t dimension = 0, T)(auto ref T value) @property
10531053
if (dimension == 0)
10541054
{
10551055
assert(!empty!dimension);
10561056
static if (__traits(compiles, *_iterator = value))
10571057
return *_iterator = value;
10581058
else
1059-
_iterator[0] = value;
1059+
return _iterator[0] = value;
10601060
}
10611061
}
10621062

@@ -1102,7 +1102,7 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
11021102
static if (N == 1 && isMutable!DeepElemType && !hasAccessByRef)
11031103
{
11041104
///ditto
1105-
auto back(size_t dimension = 0, T)(T value) @property
1105+
auto ref back(size_t dimension = 0, T)(auto ref T value) @property
11061106
if (dimension == 0)
11071107
{
11081108
assert(!empty!dimension);
@@ -1205,6 +1205,92 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
12051205
assert(slice.shape == cast(size_t[3])[0, 0, 0]);
12061206
}
12071207

1208+
package(mir) ptrdiff_t lastIndex()() const @property
1209+
{
1210+
static if (kind == Contiguous)
1211+
{
1212+
return elementsCount - 1;
1213+
}
1214+
else
1215+
{
1216+
auto strides = strides;
1217+
ptrdiff_t shift = 0;
1218+
foreach(i; Iota!(packs[0]))
1219+
shift += strides[i] * (_lengths[i] - 1);
1220+
return shift;
1221+
}
1222+
}
1223+
1224+
static if (packs[0] > 1)
1225+
{
1226+
/// Accesses the first deep element of the slice.
1227+
auto ref first()() @property
1228+
{
1229+
assert(!anyEmpty);
1230+
static if (packs.length == 1)
1231+
return *_iterator;
1232+
else
1233+
static if (S)
1234+
return DeepElemType(_lengths[packs[0] .. $], _strides[packs[0] .. $], _iterator);
1235+
else
1236+
return DeepElemType(_lengths[packs[0] .. $], _strides, _iterator);
1237+
}
1238+
1239+
static if (isMutable!DeepElemType && !hasAccessByRef)
1240+
///ditto
1241+
auto ref first(T)(auto ref T value) @property
1242+
{
1243+
assert(!anyEmpty);
1244+
static if (__traits(compiles, *_iterator = value))
1245+
return *_iterator = value;
1246+
else
1247+
return _iterator[0] = value;
1248+
}
1249+
1250+
///
1251+
unittest
1252+
{
1253+
import mir.ndslice.topology: iota, universal, canonical;
1254+
auto f = 5;
1255+
assert([2, 3].iota(f).first == f);
1256+
}
1257+
1258+
/// Accesses the last deep element of the slice.
1259+
auto ref last()() @property
1260+
{
1261+
assert(!anyEmpty);
1262+
import mir.ndslice.topology: retro;
1263+
static if (packs.length == 1)
1264+
return _iterator[lastIndex];
1265+
else
1266+
static if (S)
1267+
return DeepElemType(_lengths[packs[0] .. $], _strides[packs[0] .. $], _iterator + lastIndex);
1268+
else
1269+
return DeepElemType(_lengths[packs[0] .. $], _strides, _iterator + lastIndex);
1270+
}
1271+
1272+
static if (isMutable!DeepElemType && !hasAccessByRef)
1273+
///ditto
1274+
auto ref last(T)(auto ref T value) @property
1275+
{
1276+
assert(!anyEmpty);
1277+
return _iterator[lastIndex] = value;
1278+
}
1279+
1280+
///
1281+
unittest
1282+
{
1283+
import mir.ndslice.topology: iota;
1284+
auto f = 5;
1285+
assert([2, 3].iota(f).last == f + 2 * 3 - 1);
1286+
}
1287+
}
1288+
else
1289+
{
1290+
alias first = front;
1291+
alias last = back;
1292+
}
1293+
12081294
/++
12091295
Returns: `true` if for any dimension the length equals to `0`, and `false` otherwise.
12101296
+/
@@ -1378,13 +1464,11 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
13781464
return _iterator[indexStride(_indexes)];
13791465
else
13801466
{
1381-
auto c = _iterator;
1382-
c += indexStride(_indexes);
13831467
static if (I == packs[0])
13841468
static if (S)
1385-
return DeepElemType(_lengths[packs[0] .. $], _strides[packs[0] .. $], c);
1469+
return DeepElemType(_lengths[packs[0] .. $], _strides[packs[0] .. $], _iterator + indexStride(_indexes));
13861470
else
1387-
return DeepElemType(_lengths[packs[0] .. $], _strides, c);
1471+
return DeepElemType(_lengths[packs[0] .. $], _strides, _iterator + indexStride(_indexes));
13881472
else
13891473
{
13901474
enum size_t diff = packs[0] - I;
@@ -1395,9 +1479,9 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
13951479
diff ~ packs[1 .. $],
13961480
Iterator);
13971481
static if (S)
1398-
return Ret(_lengths[I .. N], _strides[I .. S], c);
1482+
return Ret(_lengths[I .. N], _strides[I .. S], _iterator + indexStride(_indexes));
13991483
else
1400-
return Ret(_lengths[I .. N], _strides, c);
1484+
return Ret(_lengths[I .. N], _strides, _iterator + indexStride(_indexes));
14011485
}
14021486
}
14031487

0 commit comments

Comments
 (0)