@@ -38,6 +38,7 @@ $(T2 as, Convenience function that creates a lazy view,
38
38
where each element of the original slice is converted to a type `T`.)
39
39
$(T2 bitpack, Bitpack slice over an unsigned integral slice.)
40
40
$(T2 bitwise, Bitwise slice over an unsigned integral slice.)
41
+ $(T2 bitwiseField, Bitwise field over an unsigned integral field.)
41
42
$(T2 bytegroup, Groups existing slice into fixed length chunks and uses them as data store for destination type.)
42
43
$(T2 cached, Random access cache. It is usefull in combiation with $(LREF map) and $(LREF vmap).)
43
44
$(T2 cachedGC, Random access cache auto-allocated in GC heap. It is usefull in combiation with $(LREF map) and $(LREF vmap).)
@@ -46,6 +47,7 @@ $(T2 flattened, Contiguous 1-dimensional slice of all elements of a slice.)
46
47
$(T2 map, Multidimensional functional map.)
47
48
$(T2 mapSubSlices, Maps indexes pairs to subslices.)
48
49
$(T2 member, Field (element's member) projection.)
50
+ $(T2 orthogonalReduceField, Functional deep-element wise reduce of a slice composed of fields or iterators.)
49
51
$(T2 pairwise, Pairwise map for vectors.)
50
52
$(T2 pairwiseMapSubSlices, Maps pairwise indexes pairs to subslices.)
51
53
$(T2 retro, Reverses order of iteration for all dimensions.)
@@ -2087,6 +2089,18 @@ version(mir_test) unittest
2087
2089
assert (bits[100 ] == false );
2088
2090
}
2089
2091
2092
+ /+ +
2093
+ Bitwise field over an integral field.
2094
+ Params:
2095
+ field = an integral field.
2096
+ Returns: A bitwise field.
2097
+ +/
2098
+ auto bitwiseField (Field )(Field field)
2099
+ if (isIntegral! (typeof (Field .init[size_t .init])))
2100
+ {
2101
+ return BitwiseField! Field (field);
2102
+ }
2103
+
2090
2104
/+ +
2091
2105
Bitpack slice over an integral slice.
2092
2106
@@ -2275,7 +2289,6 @@ template map(fun...)
2275
2289
auto map (Iterator, size_t N, SliceKind kind)
2276
2290
(Slice! (Iterator, N, kind) slice)
2277
2291
{
2278
- import mir.ndslice.iterator: mapIterator;
2279
2292
auto iterator = mapIterator! f(slice._iterator);
2280
2293
return Slice! (typeof (iterator), N, kind)(slice._lengths, slice._strides, iterator);
2281
2294
}
@@ -2448,7 +2461,6 @@ See_Also:
2448
2461
@optmath auto vmap(Iterator, size_t N, SliceKind kind, Callable)
2449
2462
(Slice! (Iterator, N, kind) slice, auto ref Callable callable)
2450
2463
{
2451
- import mir.ndslice.iterator: VmapIterator;
2452
2464
alias It = VmapIterator! (Iterator, Callable);
2453
2465
return Slice! (It, N, kind)(slice._lengths, slice._strides, It(slice._iterator, callable));
2454
2466
}
@@ -4093,3 +4105,76 @@ template member(string name)
4093
4105
matrix.member! " y" [] = matrix.member! " f" ;
4094
4106
assert (matrix.member! " y" == [2 , 3 ].iota * 2 );
4095
4107
}
4108
+
4109
+
4110
+ version (D_Exceptions)
4111
+ private immutable orthogonalReduceFieldException = new Exception (" orthogonalReduceField: Slice composed of fields must not be empty" );
4112
+
4113
+ /+ +
4114
+ Functional deep-element wise reduce of a slice composed of fields or iterators.
4115
+ +/
4116
+ template orthogonalReduceField (alias fun)
4117
+ {
4118
+ import mir.functional: naryFun;
4119
+ static if (__traits(isSame, naryFun! fun, fun))
4120
+ {
4121
+ @optmath:
4122
+ /+ +
4123
+ Params:
4124
+ slice = Non empty input slice composed of fields or iterators.
4125
+ Returns:
4126
+ a lazy field with each element of which is reduced value of element of the same index of all iterators.
4127
+ +/
4128
+ OrthogonalReduceField! (Iterator, fun) orthogonalReduceField(Iterator)(Slice! Iterator slice)
4129
+ {
4130
+ if (_expect(slice.empty, false ))
4131
+ {
4132
+ version (D_Exceptions)
4133
+ return orthogonalReduceFieldException;
4134
+ else
4135
+ assert (0 );
4136
+ }
4137
+ return typeof (return )(slice);
4138
+ }
4139
+
4140
+ // / ditto
4141
+ auto orthogonalReduceField (T)(T[] array)
4142
+ {
4143
+ return orthogonalReduceField (array.sliced);
4144
+ }
4145
+
4146
+ // / ditto
4147
+ auto orthogonalReduceField (T)(auto ref T withAsSlice)
4148
+ if (hasAsSlice! T)
4149
+ {
4150
+ return orthogonalReduceField (withAsSlice.asSlice);
4151
+ }
4152
+ }
4153
+ else alias orthogonalReduceField = .orthogonalReduceField! (naryFun! fun);
4154
+ }
4155
+
4156
+ // / bit array operations
4157
+ unittest
4158
+ {
4159
+ import mir.ndslice.allocation: bitSlice;
4160
+ import mir.ndslice.dynamic: strided;
4161
+ import mir.ndslice.topology: iota, orthogonalReduceField;
4162
+ auto len = 100 ;
4163
+ auto a = len.bitSlice;
4164
+ auto b = len.bitSlice;
4165
+ auto c = len.bitSlice;
4166
+ a[len.iota.strided! 0 (7 )][] = true ;
4167
+ b[len.iota.strided! 0 (11 )][] = true ;
4168
+ c[len.iota.strided! 0 (13 )][] = true ;
4169
+
4170
+ // this is valid since bitslices above are oroginal slices of allocated memory.
4171
+ auto and = [
4172
+ a.iterator._field._field, // get raw data pointers
4173
+ b.iterator._field._field,
4174
+ c.iterator._field._field]
4175
+ .orthogonalReduceField! " a & b" // operation on size_t
4176
+ .bitwiseField
4177
+ .slicedField(len);
4178
+
4179
+ assert (and == (a & b & c));
4180
+ }
0 commit comments