Skip to content

Commit 2d4e41f

Browse files
authored
Rework mir.interpolate (#213)
* rework constant and linear interpolations * update spline implementation * update polynomial interpolation * add C++ interpolate header * fix docs * fix build * remove DIPS configuration support from unittests * fix unittest * improve parabolaDerivatives * improve unittests
1 parent a34100c commit 2d4e41f

File tree

11 files changed

+426
-440
lines changed

11 files changed

+426
-440
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ matrix:
2222
- {d: gdc}
2323
script:
2424
- travis_wait 100 dub test --arch "$ARCH" --build=unittest-cov
25-
- travis_wait 100 dub test --arch "$ARCH" -c dips
25+
# - travis_wait 100 dub test --arch "$ARCH" -c dips
2626
- ./test_examples.sh
2727
# - travis_wait 100 dub test --arch "$ARCH" --build=unittest-release
2828

cpp_example/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cstdlib>
44
#include <vector>
55
#include <map>
6+
#include "mir/interpolate.h"
67
#include "mir/series.h"
78
#include "mir/rcarray.h"
89
#include "mir/rcptr.h"

include/mir/interpolate.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
namespace mir {
3+
namespace interpolate
4+
{
5+
enum class SplineType
6+
{
7+
c2,
8+
cardinal,
9+
monotone,
10+
doubleQuadratic,
11+
akima
12+
};
13+
14+
enum class SplineBoundaryType
15+
{
16+
periodic = -1,
17+
notAKnot,
18+
firstDerivative,
19+
secondDerivative,
20+
parabolic,
21+
monotone,
22+
akima
23+
};
24+
25+
template<class T>
26+
struct SplineBoundaryCondition
27+
{
28+
SplineBoundaryType type = SplineBoundaryType::notAKnot;
29+
T value = 0;
30+
};
31+
}
32+
}

source/mir/interpolate/constant.d

Lines changed: 42 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ module mir.interpolate.constant;
1717

1818
///
1919
version(mir_test)
20-
@safe pure unittest
20+
@safe pure @nogc unittest
2121
{
2222
import mir.ndslice;
2323
import mir.math.common: approxEqual;
2424

25-
immutable x = [0, 1, 2, 3];
26-
immutable y = [10, 20, 30, 40];
25+
static immutable x = [0, 1, 2, 3];
26+
static immutable y = [10, 20, 30, 40];
2727

28-
auto interpolant = constant!int(x.sliced, y.sliced);
28+
auto interpolant = constant!int(x.rcslice, y.rcslice!(const int));
2929

3030
assert(interpolant(-1) == 10);
3131
assert(interpolant(0) == 10);
@@ -38,15 +38,18 @@ version(mir_test)
3838
}
3939

4040

41-
42-
import std.traits;
43-
import mir.primitives;
44-
import mir.ndslice.slice;
41+
import core.lifetime: move;
4542
import mir.internal.utility;
43+
import mir.functional;
44+
import mir.interpolate;
4645
import mir.math.common: optmath;
47-
46+
import mir.ndslice.slice;
47+
import mir.primitives;
48+
import mir.rc.array;
49+
import mir.utility: min, max;
50+
import std.meta: AliasSeq, staticMap;
51+
import std.traits;
4852
public import mir.interpolate: atInterval;
49-
import mir.interpolate;
5053

5154
/++
5255
Constructs multivariate constant interpolant with nodes on rectilinear grid.
@@ -60,97 +63,66 @@ Constraints:
6063
6164
Returns: $(LREF Constant)
6265
+/
63-
template constant(T, size_t N = 1, FirstGridIterator = immutable(T)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
64-
if (is(T == Unqual!T) && N <= 6)
66+
Constant!(F, N, X) constant(F, size_t N = 1, X = F)
67+
(Repeat!(N, Slice!(RCI!(immutable X))) grid, Slice!(RCI!(const F), N) values)
6568
{
66-
static if (N > 1) pragma(msg, "Warning: multivariate constant interpolant was not tested.");
67-
68-
import std.meta: AliasSeq;
69-
70-
@optmath:
71-
72-
private alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
73-
private alias GridVectors = Constant!(T, N, GridIterators).GridVectors;
74-
75-
/++
76-
Params:
77-
grid = immutable `x` values for interpolant
78-
values = `f(x)` values for interpolant
79-
Constraints:
80-
`grid` and `values` must have the same length >= 3
81-
Returns: $(LREF Spline)
82-
+/
83-
Constant!(T, N, GridIterators) constant(yIterator, SliceKind ykind)(
84-
GridVectors grid,
85-
Slice!(yIterator, 1, ykind) values
86-
) pure @trusted
87-
{
88-
static if (__VERSION__ >= 2085) import core.lifetime: move; else import std.algorithm.mutation: move;
89-
auto ret = typeof(return)(grid);
90-
ret._data[] = values;
91-
return ret.move;
92-
}
69+
return typeof(return)(forward!grid, values.move);
9370
}
9471

9572
/++
9673
Multivariate constant interpolant with nodes on rectilinear grid.
9774
+/
98-
struct Constant(F, size_t N = 1, FirstGridIterator = immutable(F)*, NextGridIterators = Repeat!(N - 1, FirstGridIterator))
99-
if (N && N <= 6 && NextGridIterators.length == N - 1)
75+
extern(C++, "mir", "interpolate")
76+
struct Constant(F, size_t N = 1, X = F)
77+
if (N && N <= 6)
10078
{
101-
import mir.rc.array;
102-
import std.meta: AliasSeq, staticMap;
103-
104-
package alias GridIterators = AliasSeq!(FirstGridIterator, NextGridIterators);
105-
package alias GridVectors = staticMap!(GridVector, GridIterators);
106-
10779
@optmath:
10880

10981
/// Aligned buffer allocated with `mir.internal.memory`. $(RED For internal use.)
110-
mir_slice!(mir_rci!F, N) _data;
82+
Slice!(RCI!(const F), N) _data;
11183
/// Grid iterators. $(RED For internal use.)
112-
GridIterators _grid;
84+
RCI!(immutable X)[N] _grid;
11385

114-
import mir.utility: min, max;
86+
extern(D):
11587

11688
/++
11789
+/
118-
this(GridVectors grid) @safe @nogc
90+
this(Repeat!(N, Slice!(RCI!(immutable X))) grid, Slice!(RCI!(const F), N) data) @safe @nogc
11991
{
120-
size_t length = 1;
121-
size_t[N] shape;
122-
enum msg = "constant interpolant: minimal allowed length for the grid equals 1.";
92+
enum msg_min = "constant interpolant: minimal allowed length for the grid equals 1.";
93+
enum msg_eq = "constant interpolant: X and Y values length should be equal.";
12394
version(D_Exceptions)
124-
static immutable exc = new Exception(msg);
95+
{
96+
static immutable exc_min = new Exception(msg_min);
97+
static immutable exc_eq = new Exception(msg_eq);
98+
}
12599
foreach(i, ref x; grid)
126100
{
127101
if (x.length < 1)
128102
{
129-
version(D_Exceptions)
130-
throw exc;
131-
else
132-
assert(0, msg);
103+
version(D_Exceptions) throw exc_min;
104+
else assert(0, msg_min);
105+
}
106+
if (x.length != data._lengths[i])
107+
{
108+
version(D_Exceptions) throw exc_eq;
109+
else assert(0, msg_eq);
133110
}
134-
length *= shape[i] = x.length;
111+
_grid[i] = x._iterator;
135112
}
136-
137-
auto rca = mir_rcarray!F(length);
138-
this._data = rca.asSlice.sliced(shape);
139-
this._grid = staticMap!(iter, grid);
113+
_data = data;
140114
}
141115

142116
@trusted:
143117

144118
///
145119
Constant lightConst()() const @property { return *cast(Constant*)&this; }
146-
///
147-
Constant lightImmutable()() immutable @property { return *cast(Constant*)&this; }
148120

149121
///
150-
GridVectors[dimension] grid(size_t dimension = 0)() scope return const @property
122+
Slice!(RCI!(immutable X)) grid(size_t dimension = 0)() scope return const @property
151123
if (dimension < N)
152124
{
153-
return _grid[dimension].sliced(_data._lengths[dimension]);
125+
return _grid[dimension].lightConst.sliced(_data._lengths[dimension]);
154126
}
155127

156128
/++
@@ -175,19 +147,15 @@ struct Constant(F, size_t N = 1, FirstGridIterator = immutable(F)*, NextGridIter
175147
template opCall(uint derivative = 0)
176148
if (derivative <= derivativeOrder)
177149
{
178-
@trusted:
179150
/++
180-
`(x)` and `[x]` operators.
151+
`(x)` operator.
181152
Complexity:
182153
`O(log(grid.length))`
183154
+/
184-
auto opCall(X...)(in X xs) scope const
155+
auto opCall(X...)(in X xs) scope const @trusted
185156
if (X.length == N)
186-
// @FUTURE@
187-
// X.length == N || derivative == 0 && X.length && X.length <= N
188157
{
189158
size_t[N] indexes = void;
190-
191159
foreach(i; Iota!N)
192160
{
193161
static if (isInterval!(typeof(xs[i])))

0 commit comments

Comments
 (0)