Skip to content

Commit 2b7970a

Browse files
committed
add field projection
1 parent 08504a1 commit 2b7970a

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

source/mir/ndslice/iterator.d

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ $(T2 FlattenedIterator, $(SUBREF topology, flattened))
1313
$(T2 IndexIterator, $(SUBREF topology, indexed))
1414
$(T2 IotaIterator, $(SUBREF topology, iota))
1515
$(T2 MapIterator, $(SUBREF topology, map))
16+
$(T2 MemberIterator, $(SUBREF topology, member))
1617
$(T2 RetroIterator, $(SUBREF topology, retro))
1718
$(T2 SliceIterator, $(SUBREF topology, map) in composition with $(LREF MapIterator) for packed slices.)
1819
$(T2 SlideIterator, $(SUBREF topology, diff), $(SUBREF topology, pairwise), and $(SUBREF topology, slide).)
@@ -864,6 +865,58 @@ auto mapIterator(alias fun, Iterator)(Iterator iterator)
864865
assert(y == result);
865866
}
866867

868+
/++
869+
`MemberIterator` is used by $(SUBREF topology, member).
870+
+/
871+
struct MemberIterator(Iterator, string member)
872+
{
873+
@optmath:
874+
///
875+
Iterator _iterator;
876+
877+
///
878+
auto lightConst()() const @property
879+
{
880+
return MemberIterator!(LightConstOf!Iterator, member)(.lightConst(_iterator));
881+
}
882+
883+
///
884+
auto lightImmutable()() immutable @property
885+
{
886+
return MemberIterator!(LightImmutableOf!Iterator, member)(.lightImmutable(_iterator));
887+
}
888+
889+
auto ref opUnary(string op : "*")()
890+
{
891+
return __traits(getMember, *_iterator, member);
892+
}
893+
894+
auto ref opIndex()(ptrdiff_t index)
895+
{
896+
return __traits(getMember, _iterator[index], member);
897+
}
898+
899+
static if (!__traits(compiles, &opIndex(ptrdiff_t.init)))
900+
{
901+
auto ref opIndexAssign(T)(auto ref T value, ptrdiff_t index)
902+
{
903+
return __traits(getMember, _iterator[index], member) = value;
904+
}
905+
906+
auto ref opIndexUnary(string op)(ptrdiff_t index)
907+
{
908+
return mixin(op ~ "__traits(getMember, _iterator[index], member)");
909+
}
910+
911+
auto ref opIndexOpAssign(string op, T)(T value, ptrdiff_t index)
912+
{
913+
return mixin("__traits(getMember, _iterator[index], member)" ~ op ~ "= value");
914+
}
915+
}
916+
917+
mixin(std_ops);
918+
}
919+
867920
/++
868921
`BytegroupIterator` is used by $(SUBREF topology, Bytegroup) and $(SUBREF topology, bytegroup).
869922
+/

source/mir/ndslice/package.d

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,16 @@ $(TR $(TDNW $(SUBMODULE allocation) $(BR)
103103
$(TD
104104
$(SUBREF allocation, makeNdarray)
105105
$(SUBREF allocation, makeSlice)
106-
$(SUBREF allocation, makeUninitializedSlice)
106+
$(SUBREF allocation, makeUninitSlice)
107107
$(SUBREF allocation, ndarray)
108108
$(SUBREF allocation, shape)
109109
$(SUBREF allocation, slice)
110-
$(SUBREF allocation, uninitializedSlice)
110+
$(SUBREF allocation, uninitAlignedSlice)
111+
$(SUBREF allocation, uninitSlice)
111112
$(SUBREF allocation, stdcSlice)
113+
$(SUBREF allocation, stdcFreeAlignedSlice)
112114
$(SUBREF allocation, stdcFreeSlice)
115+
$(SUBREF allocation, stdcUninitAlignedSlice)
113116
$(SUBREF allocation, stdcUninitSlice)
114117
)
115118
)
@@ -143,6 +146,7 @@ $(TR $(TDNW $(SUBMODULE topology) $(BR)
143146
$(SUBREF topology, map)
144147
$(SUBREF topology, mapSubSlices)
145148
$(SUBREF topology, magic)
149+
$(SUBREF topology, member)
146150
$(SUBREF topology, ndiota)
147151
$(SUBREF topology, pack)
148152
$(SUBREF topology, pairwise)

source/mir/ndslice/topology.d

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ $(T2 diff, Differences between vector elements.)
4545
$(T2 flattened, Contiguous 1-dimensional slice of all elements of a slice.)
4646
$(T2 map, Multidimensional functional map.)
4747
$(T2 mapSubSlices, Maps indexes pairs to subslices.)
48+
$(T2 member, Field (element's member) projection.)
4849
$(T2 pairwise, Pairwise map for vectors.)
4950
$(T2 pairwiseMapSubSlices, Maps pairwise indexes pairs to subslices.)
5051
$(T2 retro, Reverses order of iteration for all dimensions.)
@@ -5291,3 +5292,66 @@ version(mir_test) unittest
52915292
auto x = slice.byDim!0;
52925293
assert(x == slice);
52935294
}
5295+
5296+
/++
5297+
Field (element's member) projection.
5298+
5299+
Params:
5300+
name = element's member name
5301+
Returns:
5302+
lazy n-dimensional slice of the same shape
5303+
See_also:
5304+
$(LREF map)
5305+
+/
5306+
5307+
template member(string name)
5308+
if (name.length)
5309+
{
5310+
/++
5311+
Params:
5312+
slice = n-dimensional slice composed of structs, classes or unions
5313+
Returns:
5314+
lazy n-dimensional slice of the same shape
5315+
+/
5316+
Slice!(kind, packs, MemberIterator!(Iterator, name)) member(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice)
5317+
{
5318+
return typeof(return)(slice._lengths, slice._strides, MemberIterator!(Iterator, name)(slice._iterator));
5319+
}
5320+
}
5321+
5322+
///
5323+
@safe pure unittest
5324+
{
5325+
// struct, union or class
5326+
struct S
5327+
{
5328+
// Property support
5329+
// Getter always must be defined.
5330+
double _x;
5331+
double x() @property
5332+
{
5333+
return x;
5334+
}
5335+
void x(double x) @property
5336+
{
5337+
_x = x;
5338+
}
5339+
5340+
/// Field support
5341+
double y;
5342+
5343+
/// Zero argument function support
5344+
double f()
5345+
{
5346+
return _x * 2;
5347+
}
5348+
}
5349+
5350+
import mir.ndslice.allocation: slice;
5351+
import mir.ndslice.topology: iota;
5352+
5353+
auto matrix = slice!S(2, 3);
5354+
matrix.member!"x"[] = [2, 3].iota;
5355+
matrix.member!"y"[] = matrix.member!"f";
5356+
assert(matrix.member!"y" == [2, 3].iota * 2);
5357+
}

0 commit comments

Comments
 (0)