@@ -23,6 +23,77 @@ static Slice!(N, V*) emptySlice(size_t N, V)() pure @safe nothrow
23
23
return Slice! (N, V* )();
24
24
}
25
25
26
+ package (dcv) @nogc pure nothrow
27
+ {
28
+ /**
29
+ Pack and unpack (N, T*) slices to (N-1, T[M]*).
30
+ */
31
+ auto staticPack (size_t CH , size_t N, T)(Slice! (N, T* ) slice)
32
+ {
33
+ ulong [N- 1 ] shape = slice.shape[0 .. N- 1 ];
34
+ long [N- 1 ] strides = [slice.structure.strides[0 ] / CH , slice.structure.strides[1 ] / CH ];
35
+ T[CH ]* ptr = cast (T[CH ]* )slice.ptr;
36
+ return Slice! (N- 1 , T[CH ]* )(shape, strides, ptr);
37
+ }
38
+
39
+ // / ditto
40
+ auto staticUnpack (size_t CH , size_t N, T)(Slice! (N, T[CH ]* ) slice)
41
+ {
42
+ ulong [N+ 1 ] shape = [slice.shape[0 ], slice.shape[1 ], CH ];
43
+ long [N+ 1 ] strides = [slice.structure.strides[0 ] * CH , slice.structure.strides[1 ] * CH , 1 ];
44
+ T* ptr = cast (T* )slice.ptr;
45
+ return Slice! (N+ 1 , T* )(shape, strides, ptr);
46
+ }
47
+
48
+ @safe @nogc nothrow pure auto borders(Shape)(Shape shape, size_t ks)
49
+ in
50
+ {
51
+ static assert (Shape.length == 2 , " Non-matrix border extraction is not currently supported." );
52
+ }
53
+ body
54
+ {
55
+ import std.typecons : Tuple ;
56
+ import std.algorithm.comparison : max;
57
+ import std.range : iota;
58
+ import std.traits : ReturnType;
59
+
60
+ struct Range (Iota)
61
+ {
62
+ Iota rows;
63
+ Iota cols;
64
+ @disable this ();
65
+ this (Iota rows, Iota cols)
66
+ {
67
+ this .rows = rows;
68
+ this .cols = cols;
69
+ }
70
+ }
71
+
72
+ auto range (Iota)(Iota rows, Iota cols)
73
+ {
74
+ return Range ! Iota(rows, cols);
75
+ }
76
+
77
+ // forced size_t cast...
78
+ auto _iota (B, E, S)(B begin, E end, S step = 1 )
79
+ {
80
+ return iota (size_t (begin), size_t (end), size_t (step));
81
+ }
82
+
83
+ size_t kh = max(1 , ks / 2 );
84
+ alias Iota = ReturnType! (iota! (size_t , size_t , size_t ));
85
+
86
+ Range ! (Iota)[4 ] borders = [
87
+ range(_iota(0 , shape[0 ]), _iota(0 , kh)),
88
+ range(_iota(0 , shape[0 ]), _iota(shape[1 ] - kh, shape[1 ])),
89
+ range(_iota(0 , kh), _iota(0 , shape[1 ])),
90
+ range(_iota(shape[0 ] - kh, shape[0 ]), _iota(0 , shape[1 ]))
91
+ ];
92
+
93
+ return borders;
94
+ }
95
+ }
96
+
26
97
/**
27
98
Take another typed Slice. Type conversion for the Slice object.
28
99
@@ -185,43 +256,39 @@ static if (__VERSION__ >= 2071)
185
256
// / Check if given function can perform boundary condition test.
186
257
template isBoundaryCondition (alias bc)
187
258
{
188
- import std.typetuple ;
259
+ enum bool isBoundaryCondition = true ;
260
+ }
261
+
262
+ nothrow @nogc pure
263
+ {
189
264
190
- alias Indices = TypeTuple! (int , int );
191
- alias bct = bc! (2 , float , Indices);
192
- static if (isCallable! (bct) && is (Parameters! bct[0 ] == Slice! (2 , float * ))
193
- && is (Parameters! bct[1 ] == int ) && is (Parameters! bct[2 ] == int ) && is (ReturnType! bct == float ))
265
+ // / $(LINK2 https://en.wikipedia.org/wiki/Neumann_boundary_condition, Neumann) boundary condition test
266
+ auto neumann (Tensor, Indices... )(Tensor tensor, Indices indices)
267
+ if (isSlice! Tensor && allSameType! Indices && allSatisfy! (isIntegral, Indices))
194
268
{
195
- enum bool isBoundaryCondition = true ;
269
+ immutable N = ReturnType! (Tensor.shape).length;
270
+ static assert (indices.length == N, " Invalid index dimension" );
271
+ return tensor.bcImpl! _neumann(indices);
196
272
}
197
- else
273
+
274
+ // / $(LINK2 https://en.wikipedia.org/wiki/Periodic_boundary_conditions,Periodic) boundary condition test
275
+ auto periodic (Tensor, Indices... )(Tensor tensor, Indices indices)
276
+ if (isSlice! Tensor && allSameType! Indices && allSatisfy! (isIntegral, Indices))
198
277
{
199
- enum bool isBoundaryCondition = false ;
278
+ immutable N = ReturnType! (Tensor.shape).length;
279
+ static assert (indices.length == N, " Invalid index dimension" );
280
+ return tensor.bcImpl! _periodic(indices);
200
281
}
201
- }
202
282
203
- // / $(LINK2 https://en.wikipedia.org/wiki/Neumann_boundary_condition, Neumann) boundary condition test
204
- ref T neumann (size_t N, T, Indices... )(ref Slice! (N, T* ) slice, Indices indices)
205
- if (allSameType! Indices && allSatisfy! (isIntegral, Indices))
206
- {
207
- static assert (indices.length == N, " Invalid index dimension" );
208
- return slice.bcImpl! _neumann(indices);
209
- }
210
-
211
- // / $(LINK2 https://en.wikipedia.org/wiki/Periodic_boundary_conditions,Periodic) boundary condition test
212
- ref T periodic (size_t N, T, Indices... )(ref Slice! (N, T* ) slice, Indices indices)
213
- if (allSameType! Indices && allSatisfy! (isIntegral, Indices))
214
- {
215
- static assert (indices.length == N, " Invalid index dimension" );
216
- return slice.bcImpl! _periodic(indices);
217
- }
283
+ // / Symmetric boundary condition test
284
+ auto symmetric (Tensor, Indices... )(Tensor tensor, Indices indices)
285
+ if (isSlice! Tensor && allSameType! Indices && allSatisfy! (isIntegral, Indices))
286
+ {
287
+ immutable N = ReturnType! (Tensor.shape).length;
288
+ static assert (indices.length == N, " Invalid index dimension" );
289
+ return tensor.bcImpl! _symmetric(indices);
290
+ }
218
291
219
- // / Symmetric boundary condition test
220
- ref T symmetric (size_t N, T, Indices... )(ref Slice! (N, T* ) slice, Indices indices)
221
- if (allSameType! Indices && allSatisfy! (isIntegral, Indices))
222
- {
223
- static assert (indices.length == N, " Invalid index dimension" );
224
- return slice.bcImpl! _symmetric(indices);
225
292
}
226
293
227
294
// / Alias for generalized boundary condition test function.
@@ -264,30 +331,33 @@ unittest
264
331
265
332
private :
266
333
267
- ref auto bcImpl (alias bcfunc, size_t N, T, Indices... )(ref Slice! (N, T* ) slice, Indices indices)
334
+ nothrow @nogc pure :
335
+
336
+ auto bcImpl (alias bcfunc, Tensor, Indices... )(Tensor tensor, Indices indices)
268
337
{
338
+ immutable N = ReturnType! (Tensor.shape).length;
269
339
static if (N == 1 )
270
340
{
271
- return slice [bcfunc(cast (int )indices[0 ], cast (int )slice .length)];
341
+ return tensor [bcfunc(cast (int )indices[0 ], cast (int )tensor .length)];
272
342
}
273
343
else static if (N == 2 )
274
344
{
275
- return slice [bcfunc(cast (int )indices[0 ], cast (int )slice .length! 0 ),
276
- bcfunc(cast (int )indices[1 ], cast (int )slice .length! 1 )];
345
+ return tensor [bcfunc(cast (int )indices[0 ], cast (int )tensor .length! 0 ),
346
+ bcfunc(cast (int )indices[1 ], cast (int )tensor .length! 1 )];
277
347
}
278
348
else static if (N == 3 )
279
349
{
280
- return slice [bcfunc(cast (int )indices[0 ], cast (int )slice .length! 0 ),
281
- bcfunc(cast (int )indices[1 ], cast (int )slice .length! 1 ), bcfunc(cast (int )indices[2 ],
282
- cast (int )slice .length! 2 )];
350
+ return tensor [bcfunc(cast (int )indices[0 ], cast (int )tensor .length! 0 ),
351
+ bcfunc(cast (int )indices[1 ], cast (int )tensor .length! 1 ), bcfunc(cast (int )indices[2 ],
352
+ cast (int )tensor .length! 2 )];
283
353
}
284
354
else
285
355
{
286
356
foreach (i, ref id; indices)
287
357
{
288
- id = bcfunc(cast (int )id, cast (int )slice .shape[i]);
358
+ id = bcfunc(cast (int )id, cast (int )tensor .shape[i]);
289
359
}
290
- return slice [indices];
360
+ return tensor [indices];
291
361
}
292
362
}
293
363
0 commit comments