@@ -40,6 +40,99 @@ alias fuse(Dimensions...) = fuseImpl!(false, void, Dimensions);
4040// / ditto
4141alias rcfuse (Dimensions... ) = fuseImpl! (true , void , Dimensions);
4242
43+ // /
44+ @safe pure nothrow version(mir_test) unittest
45+ {
46+ import mir.ndslice.fuse;
47+ import mir.ndslice.slice : Contiguous, Slice;
48+ import mir.ndslice.topology: iota;
49+ import mir.rc.array: RCI ;
50+
51+ enum ror = [
52+ [0 , 1 , 2 , 3 ],
53+ [4 , 5 , 6 , 7 ],
54+ [8 , 9 ,10 ,11 ]];
55+
56+ // 0 1 2 3
57+ // 4 5 6 7
58+ // 8 9 10 11
59+ auto matrix = ror.fuse;
60+
61+ auto rcmatrix = ror.rcfuse; // nogc version
62+
63+ assert (matrix == [3 , 4 ].iota);
64+ assert (rcmatrix == [3 , 4 ].iota);
65+ static assert (ror.fuse == [3 , 4 ].iota); // CTFE-able
66+
67+ // matrix is contiguos
68+ static assert (is (typeof (matrix) == Slice! (int * , 2 )));
69+ static assert (is (typeof (rcmatrix) == Slice! (RCI ! int , 2 )));
70+ }
71+
72+ // / Transposed
73+ @safe pure nothrow version(mir_test) unittest
74+ {
75+ import mir.ndslice.fuse;
76+ import mir.ndslice.topology: iota;
77+ import mir.ndslice.dynamic: transposed;
78+ import mir.ndslice.slice : Contiguous, Slice;
79+
80+ enum ror = [
81+ [0 , 1 , 2 , 3 ],
82+ [4 , 5 , 6 , 7 ],
83+ [8 , 9 ,10 ,11 ]];
84+
85+ // 0 4 8
86+ // 1 5 9
87+ // 2 6 10
88+ // 3 7 11
89+
90+ // `!1` brings dimensions under index 1 to the front (0 index).
91+ auto matrix = ror.fuse! 1 ;
92+
93+ assert (matrix == [3 , 4 ].iota.transposed! 1 );
94+ // TODO: CTFE
95+ // static assert(ror.fuse!1 == [3, 4].iota.transposed!1); // CTFE-able
96+ // matrix is contiguos
97+ static assert (is (typeof (matrix) == Slice! (int * , 2 )));
98+ }
99+
100+
101+ // / 3D
102+ @safe pure nothrow version(mir_test) unittest
103+ {
104+ import mir.ndslice.fuse;
105+ import mir.ndslice.topology: iota;
106+ import mir.ndslice.dynamic: transposed;
107+
108+ auto ror =
109+ [[[ 0 , 1 , 2 , 3 ],
110+ [ 4 , 5 , 6 , 7 ]],
111+ [[ 8 , 9 ,10 ,11 ],
112+ [12 ,13 ,14 ,15 ]]];
113+
114+ auto nd = [2 , 2 , 4 ].iota;
115+
116+ assert (ror.fuse == nd);
117+ assert (ror.fuse! 2 == nd.transposed! 2 );
118+ assert (ror.fuse! (1 , 2 ) == nd.transposed! (1 , 2 ));
119+ assert (ror.fuse! (2 , 1 ) == nd.transposed! (2 , 1 ));
120+ }
121+
122+ // / Work with RC Arrays of RC Arrays
123+ @safe pure nothrow version(mir_test) unittest
124+ {
125+ import mir.ndslice.fuse;
126+ import mir.ndslice.slice;
127+ import mir.ndslice.topology: map;
128+ import mir.rc.array;
129+
130+ Slice! (const (double )* , 2 ) conv(RCArray! (const RCArray! (const double )) a)
131+ {
132+ return a[].map! " a[]" .fuse;
133+ }
134+ }
135+
43136/+ +
44137Fuses ndrange `r` into GC-allocated ($(LREF fuseAs)) or RC-allocated ($(LREF rcfuseAs)) ndslice.
45138Can be used to join rows or columns into a matrix.
@@ -54,6 +147,35 @@ alias fuseAs(T, Dimensions...) = fuseImpl!(false, T, Dimensions);
54147// / ditto
55148alias rcfuseAs (T, Dimensions... ) = fuseImpl! (true , T, Dimensions);
56149
150+ // /
151+ @safe pure nothrow version(mir_test) unittest
152+ {
153+ import mir.ndslice.fuse;
154+ import mir.ndslice.slice : Contiguous, Slice;
155+ import mir.ndslice.topology: iota;
156+ import mir.rc.array: RCI ;
157+
158+ enum ror = [
159+ [0 , 1 , 2 , 3 ],
160+ [4 , 5 , 6 , 7 ],
161+ [8 , 9 ,10 ,11 ]];
162+
163+ // 0 1 2 3
164+ // 4 5 6 7
165+ // 8 9 10 11
166+ auto matrix = ror.fuseAs! double ;
167+
168+ auto rcmatrix = ror.rcfuseAs! double ; // nogc version
169+
170+ assert (matrix == [3 , 4 ].iota);
171+ assert (rcmatrix == [3 , 4 ].iota);
172+ static assert (ror.fuseAs! double == [3 , 4 ].iota); // CTFE-able
173+
174+ // matrix is contiguos
175+ static assert (is (typeof (matrix) == Slice! (double * , 2 )));
176+ static assert (is (typeof (rcmatrix) == Slice! (RCI ! double , 2 )));
177+ }
178+
57179// /
58180template fuseImpl (bool RC , T_ , Dimensions... )
59181{
@@ -157,99 +279,6 @@ template fuseImpl(bool RC, T_, Dimensions...)
157279 alias fuseImpl = .fuseImpl! (RC , T_ , staticMap! (toSize_t, Dimensions));
158280}
159281
160- // /
161- @safe pure nothrow version(mir_test) unittest
162- {
163- import mir.ndslice.fuse;
164- import mir.ndslice.slice : Contiguous, Slice;
165- import mir.ndslice.topology: iota;
166- import mir.rc.array: RCI ;
167-
168- enum ror = [
169- [0 , 1 , 2 , 3 ],
170- [4 , 5 , 6 , 7 ],
171- [8 , 9 ,10 ,11 ]];
172-
173- // 0 1 2 3
174- // 4 5 6 7
175- // 8 9 10 11
176- auto matrix = ror.fuse;
177-
178- auto rcmatrix = ror.rcfuse; // nogc version
179-
180- assert (matrix == [3 , 4 ].iota);
181- assert (rcmatrix == [3 , 4 ].iota);
182- static assert (ror.fuse == [3 , 4 ].iota); // CTFE-able
183-
184- // matrix is contiguos
185- static assert (is (typeof (matrix) == Slice! (int * , 2 )));
186- static assert (is (typeof (rcmatrix) == Slice! (RCI ! int , 2 )));
187- }
188-
189- // / Transposed
190- @safe pure nothrow version(mir_test) unittest
191- {
192- import mir.ndslice.fuse;
193- import mir.ndslice.topology: iota;
194- import mir.ndslice.dynamic: transposed;
195- import mir.ndslice.slice : Contiguous, Slice;
196-
197- enum ror = [
198- [0 , 1 , 2 , 3 ],
199- [4 , 5 , 6 , 7 ],
200- [8 , 9 ,10 ,11 ]];
201-
202- // 0 4 8
203- // 1 5 9
204- // 2 6 10
205- // 3 7 11
206-
207- // `!1` brings dimensions under index 1 to the front (0 index).
208- auto matrix = ror.fuse! 1 ;
209-
210- assert (matrix == [3 , 4 ].iota.transposed! 1 );
211- // TODO: CTFE
212- // static assert(ror.fuse!1 == [3, 4].iota.transposed!1); // CTFE-able
213- // matrix is contiguos
214- static assert (is (typeof (matrix) == Slice! (int * , 2 )));
215- }
216-
217-
218- // / 3D
219- @safe pure nothrow version(mir_test) unittest
220- {
221- import mir.ndslice.fuse;
222- import mir.ndslice.topology: iota;
223- import mir.ndslice.dynamic: transposed;
224-
225- auto ror =
226- [[[ 0 , 1 , 2 , 3 ],
227- [ 4 , 5 , 6 , 7 ]],
228- [[ 8 , 9 ,10 ,11 ],
229- [12 ,13 ,14 ,15 ]]];
230-
231- auto nd = [2 , 2 , 4 ].iota;
232-
233- assert (ror.fuse == nd);
234- assert (ror.fuse! 2 == nd.transposed! 2 );
235- assert (ror.fuse! (1 , 2 ) == nd.transposed! (1 , 2 ));
236- assert (ror.fuse! (2 , 1 ) == nd.transposed! (2 , 1 ));
237- }
238-
239- // / Work with RC Arrays of RC Arrays
240- @safe pure nothrow version(mir_test) unittest
241- {
242- import mir.ndslice.fuse;
243- import mir.ndslice.slice;
244- import mir.ndslice.topology: map;
245- import mir.rc.array;
246-
247- Slice! (const (double )* , 2 ) conv(RCArray! (const RCArray! (const double )) a)
248- {
249- return a[].map! " a[]" .fuse;
250- }
251- }
252-
253282private template fuseDimensionCount (R)
254283{
255284 static if (is (typeof (R.init.shape) : size_t [N], size_t N) && (isDynamicArray! R || __traits(hasMember, R, " front" )))
@@ -279,7 +308,9 @@ size_t[fuseDimensionCount!Range] fuseShape(Range)(Range r)
279308 typeof (return ) ret;
280309 ret[0 .. N] = r.shape;
281310 if (! ret[0 .. N].anyEmptyShape)
311+ {
282312 ret[N .. $] = fuseShape(mixin (" r" ~ " .front" .repeat(N).fuseCells.field));
313+ }
283314 return ret;
284315 }
285316}
0 commit comments