Skip to content

Commit 7db9a4b

Browse files
committed
more purity
1 parent feb42e9 commit 7db9a4b

File tree

6 files changed

+74
-56
lines changed

6 files changed

+74
-56
lines changed

source/mir/internal/memory.d

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ Authors: $(HTTP erdani.com, Andrei Alexandrescu), Ilya Yaroshenko
55
+/
66
module mir.internal.memory;
77

8+
pure nothrow @nogc extern(C)
9+
{
10+
///
11+
void* malloc(size_t size);
12+
///
13+
void* calloc(size_t nmemb, size_t size);
14+
///
15+
void* realloc(void* ptr, size_t size);
16+
///
17+
void free(void* ptr);
18+
}
19+
20+
pure:
21+
822
enum uint platformAlignment = double.alignof > real.alignof ? double.alignof : real.alignof;
923

1024
@nogc nothrow pragma(inline, true):
@@ -42,7 +56,6 @@ version (Windows)
4256

4357
private void* _aligned_malloc()(size_t size, size_t alignment)
4458
{
45-
import core.stdc.stdlib : malloc;
4659
size_t offset = alignment + size_t.sizeof * 2 - 1;
4760

4861
// unaligned chunk
@@ -64,7 +77,6 @@ version (Windows)
6477

6578
private void* _aligned_realloc()(void* ptr, size_t size, size_t alignment)
6679
{
67-
import core.stdc.stdlib : free;
6880
import core.stdc.string : memcpy;
6981

7082
if (!ptr) return _aligned_malloc(size, alignment);
@@ -91,7 +103,6 @@ version (Windows)
91103

92104
private void _aligned_free()(void *ptr)
93105
{
94-
import core.stdc.stdlib : free;
95106
if (!ptr) return;
96107
AlignInfo* head = AlignInfo(ptr);
97108
free(head.basePtr);
@@ -148,7 +159,7 @@ $(D __aligned_free(b.ptr))) on Windows.
148159
*/
149160
version (Posix)
150161
{
151-
public import core.stdc.stdlib : alignedFree = free;
162+
alias alignedFree = free;
152163
}
153164
else
154165
version (Windows)

source/mir/interpolate/constant.d

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ module mir.interpolate.constant;
1515

1616
///
1717
version(mir_test)
18-
@safe unittest
18+
@safe pure unittest
1919
{
2020
import mir.ndslice;
2121
import std.math: approxEqual;
2222

23-
auto x = [0, 1, 2, 3];
24-
auto y = [10, 20, 30, 40];
23+
immutable x = [0, 1, 2, 3];
24+
immutable y = [10, 20, 30, 40];
2525

2626
auto interpolant = constant!int(x.sliced, y.sliced);
2727

@@ -59,7 +59,7 @@ Constraints:
5959
6060
Returns: $(LREF Constant)
6161
+/
62-
template constant(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
62+
template constant(T, size_t N = 1, FirstGridIterator = immutable(T)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
6363
if (is(T == Unqual!T) && N <= 6)
6464
{
6565
static if (N > 1) pragma(msg, "Warning: multivariate constant interplant was not tested.");
@@ -69,8 +69,9 @@ template constant(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = R
6969

7070
/++
7171
Params:
72-
grid = `x` values for interpolant
72+
grid = immutable `x` values for interpolant
7373
values = `f(x)` values for interpolant
74+
forceCopyValues = always copy `values` if set
7475
Constraints:
7576
`grid` and `values` must have the same length >= 3
7677
Returns: $(LREF Spline)
@@ -79,7 +80,7 @@ template constant(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = R
7980
GridVectors grid,
8081
scope Slice!(ykind, [1], yIterator) values,
8182
bool forceCopyValues = false
82-
)
83+
) pure
8384
{
8485
static if (__traits(compiles, typeof(return)(grid, values)))
8586
{
@@ -98,18 +99,16 @@ template constant(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = R
9899
/++
99100
Multivariate constant interpolant with nodes on rectilinear grid.
100101
+/
101-
struct Constant(F, size_t N = 1, FirstGridIterator = F*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
102+
struct Constant(F, size_t N = 1, FirstGridIterator = immutable(F)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
102103
if (N && N <= 6 && NextGridIterators.length == N - 1)
103104
{
104-
import mir.ndslice.internal: ConstIfPointer;
105-
106105
package alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
107-
package alias GridVectors = staticMap!(GridVector, staticMap!(ConstIfPointer, GridIterators));
106+
package alias GridVectors = staticMap!(GridVector, GridIterators);
108107

109108
/// Aligned buffer allocated with `mir.internal.memory`. $(RED For internal use.)
110109
Slice!(Contiguous, [N], F*) _data;
111110
/// Grid iterators. $(RED For internal use.)
112-
staticMap!(ConstIfPointer, GridIterators) _grid;
111+
GridIterators _grid;
113112
///
114113
bool _ownsData;
115114

@@ -170,7 +169,7 @@ struct Constant(F, size_t N = 1, FirstGridIterator = F*, NextGridIterators = Rep
170169

171170
/++
172171
+/
173-
this()(GridVectors grid, Slice!(Contiguous, [N], const(F)*) values) @trusted nothrow @nogc
172+
this()(GridVectors grid, Slice!(Contiguous, [N], immutable(F)*) values) @trusted nothrow @nogc
174173
{
175174
foreach(i, ref x; grid)
176175
{

source/mir/interpolate/linear.d

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,17 @@ Constraints:
3737
3838
Returns: $(LREF Linear)
3939
+/
40-
template linear(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
40+
template linear(T, size_t N = 1, FirstGridIterator = immutable(T)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
4141
// if (isFloatingPoint!T && is(T == Unqual!T) && N <= 6)
4242
{
4343
private alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
4444
private alias GridVectors = Linear!(T, N, GridIterators).GridVectors;
4545

4646
/++
4747
Params:
48-
grid = N `x` values for interpolation
49-
values = `f(x)` values for interpolation
48+
grid = immutable `x` values for interpolant
49+
values = `f(x)` values for interpolant
50+
forceCopyValues = always copy `values` if set
5051
Constraints:
5152
`grid` and `values` must have the same length >= 2
5253
Returns: $(LREF Spline)
@@ -74,13 +75,13 @@ template linear(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Rep
7475

7576
/// R -> R: Linear interpolation
7677
version(mir_test)
77-
@safe unittest
78+
@safe pure unittest
7879
{
7980
import mir.ndslice;
8081
import std.math: approxEqual;
8182

82-
auto x = [0, 1, 2, 3, 5.00274, 7.00274, 10.0055, 20.0137, 30.0192];
83-
auto y = [0.0011, 0.0011, 0.0030, 0.0064, 0.0144, 0.0207, 0.0261, 0.0329, 0.0356,];
83+
immutable x = [0, 1, 2, 3, 5.00274, 7.00274, 10.0055, 20.0137, 30.0192];
84+
immutable y = [0.0011, 0.0011, 0.0030, 0.0064, 0.0144, 0.0207, 0.0261, 0.0329, 0.0356,];
8485
auto xs = [1, 2, 3, 4.00274, 5.00274, 6.00274, 7.00274, 8.00548, 9.00548, 10.0055, 11.0055, 12.0082, 13.0082, 14.0082, 15.0082, 16.011, 17.011, 18.011, 19.011, 20.0137, 21.0137, 22.0137, 23.0137, 24.0164, 25.0164, 26.0164, 27.0164, 28.0192, 29.0192, 30.0192];
8586

8687
auto interpolation = linear!double(x.sliced, y.sliced);
@@ -91,7 +92,7 @@ version(mir_test)
9192
}
9293

9394
/// R^2 -> R: Bilinear interpolaiton
94-
unittest
95+
@safe pure unittest
9596
{
9697
import std.math: approxEqual;
9798
import mir.ndslice;
@@ -106,11 +107,11 @@ unittest
106107
alias f = (x0, x1) => y_x0 * x0 + y_x1 * x1 + y_x0x1 * x0 * x1 - 11;
107108

108109
///// set interpolant ////
109-
auto x0 = [-1.0, 2, 8, 15].sliced;
110-
auto x1 = [-4.0, 2, 5, 10, 13].sliced;
110+
auto x0 = [-1.0, 2, 8, 15].idup.sliced;
111+
auto x1 = [-4.0, 2, 5, 10, 13].idup.sliced;
111112
auto grid = cartesian(x0, x1);
112113

113-
auto interpolant = linear!(double, 2)(x0, x1, grid.map!f.slice);
114+
auto interpolant = linear!(double, 2)(x0, x1, grid.map!f);
114115

115116
///// compute test data ////
116117
auto test_grid = cartesian(x0 + 1.23, x1 + 3.23);
@@ -132,7 +133,7 @@ unittest
132133
}
133134

134135
/// R^3 -> R: Trilinear interpolaiton
135-
unittest
136+
@safe pure unittest
136137
{
137138
import std.math: approxEqual;
138139
import mir.ndslice;
@@ -150,12 +151,12 @@ unittest
150151
+ y_x0x1 * x0 * x1 + y_x0x1x2 * x0 * x1 * x2 - 11;
151152

152153
///// set interpolant ////
153-
auto x0 = [-1.0, 2, 8, 15].sliced;
154-
auto x1 = [-4.0, 2, 5, 10, 13].sliced;
155-
auto x2 = [3, 3.7, 5].sliced;
154+
auto x0 = [-1.0, 2, 8, 15].idup.sliced;
155+
auto x1 = [-4.0, 2, 5, 10, 13].idup.sliced;
156+
auto x2 = [3, 3.7, 5].idup.sliced;
156157
auto grid = cartesian(x0, x1, x2);
157158

158-
auto interpolant = linear!(double, 3)(x0, x1, x2, grid.map!f.slice);
159+
auto interpolant = linear!(double, 3)(x0, x1, x2, grid.map!f);
159160

160161
///// compute test data ////
161162
auto test_grid = cartesian(x0 + 1.23, x1 + 3.23, x2 - 3);
@@ -181,18 +182,16 @@ unittest
181182
/++
182183
Multivariate linear interpolant with nodes on rectilinear grid.
183184
+/
184-
struct Linear(F, size_t N = 1, FirstGridIterator = F*, NextGridIterators...)
185+
struct Linear(F, size_t N = 1, FirstGridIterator = immutable(F)*, NextGridIterators...)
185186
if (N && N <= 6 && NextGridIterators.length == N - 1)
186187
{
187-
import mir.ndslice.internal: ConstIfPointer;
188-
189188
package alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
190-
package alias GridVectors = staticMap!(GridVector, staticMap!(ConstIfPointer, GridIterators));
189+
package alias GridVectors = staticMap!(GridVector, GridIterators);
191190

192191
/// Aligned buffer allocated with `mir.internal.memory`. $(RED For internal use.)
193192
Slice!(Contiguous, [N], F*) _data;
194193
/// Grid iterators. $(RED For internal use.)
195-
staticMap!(ConstIfPointer, GridIterators) _grid;
194+
GridIterators _grid;
196195
///
197196
bool _ownsData;
198197

source/mir/interpolate/package.d

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ unittest
7777
import mir.ndslice.slice: sliced;
7878
import mir.interpolate.linear;
7979

80-
auto x = [0.0, 1, 2].sliced;
81-
auto y = [10.0, 2, 4].sliced;
80+
auto x = [0.0, 1, 2].idup.sliced;
81+
auto y = [10.0, 2, 4].idup.sliced;
8282
auto interpolation = linear!double(x, y);
8383
assert(interpolation.findInterval(1.0) == 1);
8484
}
@@ -182,9 +182,9 @@ version(mir_test)
182182
import mir.ndslice;
183183
import std.math: approxEqual;
184184

185-
auto x = [0, 1, 2, 3, 5.00274, 7.00274, 10.0055, 20.0137, 30.0192];
186-
auto y = [0.0011, 0.0011, 0.0030, 0.0064, 0.0144, 0.0207, 0.0261, 0.0329, 0.0356,];
187-
auto xs = [1, 2, 3, 4.00274, 5.00274, 6.00274, 7.00274, 8.00548, 9.00548, 10.0055, 11.0055, 12.0082, 13.0082, 14.0082, 15.0082, 16.011, 17.011, 18.011, 19.011, 20.0137, 21.0137, 22.0137, 23.0137, 24.0164, 25.0164, 26.0164, 27.0164, 28.0192, 29.0192, 30.0192];
185+
immutable x = [0, 1, 2, 3, 5.00274, 7.00274, 10.0055, 20.0137, 30.0192];
186+
immutable y = [0.0011, 0.0011, 0.0030, 0.0064, 0.0144, 0.0207, 0.0261, 0.0329, 0.0356,];
187+
immutable xs = [1, 2, 3, 4.00274, 5.00274, 6.00274, 7.00274, 8.00548, 9.00548, 10.0055, 11.0055, 12.0082, 13.0082, 14.0082, 15.0082, 16.011, 17.011, 18.011, 19.011, 20.0137, 21.0137, 22.0137, 23.0137, 24.0164, 25.0164, 26.0164, 27.0164, 28.0192, 29.0192, 30.0192];
188188

189189
auto interpolation = linear!double(x.sliced, y.sliced);
190190

@@ -211,7 +211,7 @@ unittest
211211
{
212212
import mir.ndslice.slice;
213213
import mir.interpolate.spline;
214-
auto interpolant = spline!double([0.0, 1, 2].sliced, [3, 4, -10].sliced);
214+
auto interpolant = spline!double([0.0, 1, 2].idup.sliced, [3, 4, -10].idup.sliced);
215215
assert(interpolant(1.3) != interpolant(1.3.atInterval(0)));
216216
assert(interpolant(1.3) == interpolant(1.3.atInterval(1)));
217217
}

source/mir/interpolate/spline.d

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ import mir.ndslice.slice;
3232
import mir.ndslice.traits;
3333

3434
///
35-
@safe nothrow unittest
35+
@safe pure nothrow unittest
3636
{
3737
import std.math: approxEqual;
3838
import mir.ndslice.slice: sliced;
3939
import mir.ndslice.topology: vmap;
4040
import mir.ndslice.algorithm: all;
4141

42-
auto x = [-1.0, 2, 4, 5, 8, 10, 12, 15, 19, 22].sliced;
43-
auto y = [17.0, 0, 16, 4, 10, 15, 19, 5, 18, 6].sliced;
42+
auto x = [-1.0, 2, 4, 5, 8, 10, 12, 15, 19, 22].idup.sliced;
43+
auto y = [17.0, 0, 16, 4, 10, 15, 19, 5, 18, 6].idup.sliced;
4444

4545
auto interpolant = spline!double(x, y); // constructs Spline
4646
auto xs = x + 0.5; // input X values for cubic spline
@@ -84,7 +84,7 @@ import mir.ndslice.traits;
8484
}
8585

8686
///
87-
unittest
87+
@safe pure unittest
8888
{
8989
import std.math: approxEqual;
9090
import mir.ndslice.allocation: uninitSlice;
@@ -93,7 +93,7 @@ unittest
9393
import mir.ndslice.algorithm: all;
9494
import mir.functional: aliasCall;
9595

96-
auto x = [-1.0, 2, 4, 5, 8, 10, 12, 15, 19, 22].sliced;
96+
auto x = [-1.0, 2, 4, 5, 8, 10, 12, 15, 19, 22].idup.sliced;
9797
auto y = [
9898
8.77842512,
9999
7.96429686,
@@ -283,7 +283,7 @@ unittest
283283
Constructs multivariate cubic spline in symmetrical form with nodes on rectilinear grid.
284284
Result has continues second derivatives throughout the curve / nd-surface.
285285
+/
286-
template spline(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
286+
template spline(T, size_t N = 1, FirstGridIterator = immutable(T)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
287287
if (isFloatingPoint!T && is(T == Unqual!T) && N <= 6)
288288
{
289289
static if (N > 1) pragma(msg, "Warning: multivariate cubic spline was not tested!!!");
@@ -293,8 +293,10 @@ template spline(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Rep
293293

294294
/++
295295
Params:
296-
grid = `x` values for interpolant
296+
grid = immutable `x` values for interpolant
297297
values = `f(x)` values for interpolant
298+
typeOfBondaries = $(LREF SplineBoundaryType) for both tails (optional).
299+
valueOfBondaryConditions = value of the boundary type (optional).
298300
Constraints:
299301
`grid` and `values` must have the same length >= 3
300302
Returns: $(LREF Spline)
@@ -311,8 +313,9 @@ template spline(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Rep
311313

312314
/++
313315
Params:
314-
grid = `x` values for interpolant
316+
grid = immutable `x` values for interpolant
315317
values = `f(x)` values for interpolant
318+
bondaries = $(LREF SplineBoundaryCondition) for both tails.
316319
Constraints:
317320
`grid` and `values` must have the same length >= 3
318321
Returns: $(LREF Spline)
@@ -328,8 +331,10 @@ template spline(T, size_t N = 1, FirstGridIterator = T*, NextGridIterators = Rep
328331

329332
/++
330333
Params:
331-
grid = `x` values for interpolant
334+
grid = immutable `x` values for interpolant
332335
values = `f(x)` values for interpolant
336+
rBoundary = $(LREF SplineBoundaryCondition) for left tail.
337+
lBoundary = $(LREF SplineBoundaryCondition) for right tail.
333338
Constraints:
334339
`grid` and `values` must have the same length >= 3
335340
Returns: $(LREF Spline)
@@ -386,16 +391,16 @@ struct SplineBoundaryCondition(T)
386391
/++
387392
Multivariate cubic spline with nodes on rectilinear grid.
388393
+/
389-
struct Spline(F, size_t N = 1, FirstGridIterator = F*, NextGridIterators...)
394+
struct Spline(F, size_t N = 1, FirstGridIterator = immutable(F)*, NextGridIterators...)
390395
if (N && N <= 6 && NextGridIterators.length == N - 1)
391396
{
392397
package alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
393-
package alias GridVectors = staticMap!(GridVector, staticMap!(ConstIfPointer, GridIterators));
398+
package alias GridVectors = staticMap!(GridVector, GridIterators);
394399

395400
/// Aligned buffer allocated with `mir.internal.memory`. $(RED For internal use.)
396401
Slice!(Contiguous, [N], F[2 ^^ N]*) _data;
397402
/// Grid iterators. $(RED For internal use.)
398-
staticMap!(ConstIfPointer, GridIterators) _grid;
403+
GridIterators _grid;
399404

400405
import mir.utility: min, max;
401406
package enum alignment = min(64u, F[2 ^^ N].sizeof).max(size_t.sizeof);
@@ -684,8 +689,11 @@ Params:
684689
values = `f(x)` values for interpolant
685690
slopes = uninitialized ndslice to write slopes into
686691
temp = uninitialized temporary ndslice
692+
lbc = left boundary condition
693+
rbc = right boundary condition
687694
Constraints:
688-
`points`, `values`, `slopes`, and `temp` must have the same length > 3
695+
`points`, `values`, and `slopes`, must have the same length > 3;
696+
`temp` must have length greater or equal to points less minus one.
689697
+/
690698
void splineSlopes(F, T, IP, IV, IS, SliceKind gkind, SliceKind vkind, SliceKind skind)(
691699
scope Slice!(gkind, [1], IP) points,

source/mir/ndslice/topology.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2401,7 +2401,8 @@ Note:
24012401
$(SUBREF dynamic, transposed) and
24022402
$(SUBREF topology, pack) can be used to specify dimensions.
24032403
Params:
2404-
fun = One or more functions.
2404+
slice = ndslice
2405+
callable = callable object, structure, delegate, or function pointer.
24052406
See_Also:
24062407
$(LREF pairwise), $(LREF slide), $(LREF zip),
24072408
$(HTTP en.wikipedia.org/wiki/Map_(higher-order_function), Map (higher-order function))

0 commit comments

Comments
 (0)