Skip to content

Commit 753a1d3

Browse files
Merge pull request #58 from ljubobratovicrelja/optimization-patch-2
Optimization pass
2 parents 7b97737 + d88c786 commit 753a1d3

File tree

14 files changed

+1314
-919
lines changed

14 files changed

+1314
-919
lines changed

source/dcv/core/algorithm.d

+29-12
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,21 @@ import std.traits : isNumeric, isFloatingPoint;
2525
import mir.ndslice.slice : Slice, sliced, DeepElementType;
2626
import mir.ndslice.algorithm : ndReduce, ndEach, Yes;
2727

28+
import dcv.core.utils : isSlice;
29+
2830
version(LDC)
2931
{
30-
import ldc.intrinsics : sqrt = llvm_sqrt, fabs = llvm_fabs, min = llvm_minnum, max = llvm_maxnum;
32+
import ldc.intrinsics : sqrt = llvm_sqrt, fabs = llvm_fabs;
3133
}
3234
else
3335
{
3436
import std.math : sqrt, fabs;
35-
import std.algorithm.comparison : min, max;
3637
}
3738

3839
version(unittest)
3940
{
4041
import std.math : approxEqual;
42+
import ldc.intrinsics : min = llvm_minnum, max = llvm_maxnum;
4143
}
4244

4345
/**
@@ -170,10 +172,14 @@ Returns:
170172
Scaled input tensor.
171173
172174
*/
173-
@nogc nothrow auto scaled(Scalar, Range, size_t N)(auto ref Slice!(N, Range) tensor, Scalar alpha = 1, Scalar beta = 0)
174-
if (isNumeric!Scalar)
175+
nothrow @nogc auto scaled(Scalar, Tensor)(Tensor tensor, Scalar alpha = 1, Scalar beta = 0) if (isNumeric!Scalar)
176+
in
177+
{
178+
static assert(isSlice!Tensor, "Input tensor has to be of type mir.ndslice.slice.Slice.");
179+
}
180+
body
175181
{
176-
tensor.ndEach!((ref v) { v = alpha * (v) + beta; }, Yes.vectorized);
182+
tensor.ndEach!((ref v) { v = cast(DeepElementType!Tensor)(alpha * (v) + beta); }, Yes.vectorized);
177183
return tensor;
178184
}
179185

@@ -198,21 +204,32 @@ Params:
198204
maxValue = Maximal value output tensor should contain.
199205
200206
*/
201-
@nogc auto ranged(Scalar, Range, size_t N)(auto ref Slice!(N, Range) tensor,
207+
nothrow @nogc auto ranged(Scalar, Tensor)(Tensor tensor,
202208
Scalar minValue = 0, Scalar maxValue = 1) if (isNumeric!Scalar)
209+
in
210+
{
211+
static assert(isSlice!Tensor, "Input tensor has to be of type mir.ndslice.slice.Slice.");
212+
}
213+
body
203214
{
204-
alias RangeElementType = DeepElementType!(typeof(tensor));
215+
alias T = DeepElementType!Tensor;
205216

206-
auto _min = ndReduce!(min, Yes.vectorized)(RangeElementType.max, tensor);
207-
static if (isFloatingPoint!RangeElementType)
208-
auto _max = ndReduce!(max, Yes.vectorized)(RangeElementType.min_normal, tensor);
217+
static if (isFloatingPoint!T)
218+
{
219+
import ldc.intrinsics : min = llvm_minnum, max = llvm_maxnum;
220+
auto _max = ndReduce!(max, Yes.vectorized)(T.min_normal, tensor);
221+
}
209222
else
210-
auto _max = ndReduce!(max, Yes.vectorized)(RangeElementType.min, tensor);
223+
{
224+
import std.algorithm.comparison : min, max;
225+
auto _max = ndReduce!(max, Yes.vectorized)(T.min, tensor);
226+
}
211227

228+
auto _min = ndReduce!(min, Yes.vectorized)(T.max, tensor);
212229
auto rn_val = _max - _min;
213230
auto sc_val = maxValue - minValue;
214231

215-
tensor.ndEach!((ref a) { a = sc_val * ((a - _min) / rn_val) + minValue; }, Yes.vectorized);
232+
tensor.ndEach!((ref a) { a = cast(T)(sc_val * ((a - _min) / rn_val) + minValue); }, Yes.vectorized);
216233

217234
return tensor;
218235
}

source/dcv/core/utils.d

+109-39
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,77 @@ static Slice!(N, V*) emptySlice(size_t N, V)() pure @safe nothrow
2323
return Slice!(N, V*)();
2424
}
2525

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+
2697
/**
2798
Take another typed Slice. Type conversion for the Slice object.
2899
@@ -185,43 +256,39 @@ static if (__VERSION__ >= 2071)
185256
/// Check if given function can perform boundary condition test.
186257
template isBoundaryCondition(alias bc)
187258
{
188-
import std.typetuple;
259+
enum bool isBoundaryCondition = true;
260+
}
261+
262+
nothrow @nogc pure
263+
{
189264

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))
194268
{
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);
196272
}
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))
198277
{
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);
200281
}
201-
}
202282

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+
}
218291

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);
225292
}
226293

227294
/// Alias for generalized boundary condition test function.
@@ -264,30 +331,33 @@ unittest
264331

265332
private:
266333

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)
268337
{
338+
immutable N = ReturnType!(Tensor.shape).length;
269339
static if (N == 1)
270340
{
271-
return slice[bcfunc(cast(int)indices[0], cast(int)slice.length)];
341+
return tensor[bcfunc(cast(int)indices[0], cast(int)tensor.length)];
272342
}
273343
else static if (N == 2)
274344
{
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)];
277347
}
278348
else static if (N == 3)
279349
{
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)];
283353
}
284354
else
285355
{
286356
foreach (i, ref id; indices)
287357
{
288-
id = bcfunc(cast(int)id, cast(int)slice.shape[i]);
358+
id = bcfunc(cast(int)id, cast(int)tensor.shape[i]);
289359
}
290-
return slice[indices];
360+
return tensor[indices];
291361
}
292362
}
293363

0 commit comments

Comments
 (0)