Skip to content

Commit 4316c04

Browse files
authored
Implement inplace GriddedInterpolation (#496)
* Implement inplace GriddedInterpolation * Fix io test * Add inplace gridded example to doc * Bump version to 0.14.0
1 parent 9dbcb64 commit 4316c04

File tree

5 files changed

+95
-74
lines changed

5 files changed

+95
-74
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Interpolations"
22
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
3-
version = "0.13.7"
3+
version = "0.14.0"
44

55
[deps]
66
AxisAlgorithms = "13072b0f-2c55-5437-9ae7-d433b7a33950"

docs/src/control.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ Af = [a for a in A if !ismissing(a)]
123123
itp = interpolate((xf, ), Af, Gridded(Linear()))
124124
```
125125

126+
In-place gridded interpolation is also possible:
127+
```julia
128+
x = 1:4
129+
y = view(rand(4), :)
130+
itp = interpolate!((x,), y, Gridded(Linear()))
131+
y .= 0
132+
@show itp(2.5) # 0
133+
```
134+
126135
## Parametric splines
127136

128137
Given a set a knots with coordinates `x(t)` and `y(t)`, a parametric spline `S(t) = (x(t),y(t))` parametrized by `t in [0,1]` can be constructed with the following code adapted from a [post](http://julia-programming-language.2336112.n4.nabble.com/Parametric-splines-td37794.html#a37818) by Tomas Lycken:

src/gridded/gridded.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const GridIndex{T} = Union{AbstractVector{T}, Tuple}
1616

1717
struct GriddedInterpolation{T,N,TCoefs,IT<:DimSpec{Gridded},K<:Tuple{Vararg{AbstractVector}}} <: AbstractInterpolation{T,N,IT}
1818
knots::K
19-
coefs::Array{TCoefs,N}
19+
coefs::TCoefs
2020
it::IT
2121
end
2222

@@ -29,12 +29,12 @@ end
2929
"""
3030
GriddedInterpolation(typeOfWeights::Type{<:Real},
3131
knots::NTuple{N, Union{ AbstractVector{T}, Tuple } },
32-
array::AbstractArray{TCoefs,N},
32+
array::AbstractArray{Tel,N},
3333
interpolationType::DimSpec{<:Gridded})
3434
3535
Construct a GriddedInterpolation for generic knots from an AbstractArray
3636
"""
37-
function GriddedInterpolation(::Type{TWeights}, knots::NTuple{N,GridIndex}, A::AbstractArray{TCoefs,N}, it::IT) where {N,TCoefs,TWeights<:Real,IT<:DimSpec{Gridded},pad}
37+
function GriddedInterpolation(::Type{TWeights}, knots::NTuple{N,GridIndex}, A::AbstractArray{Tel,N}, it::IT) where {N,Tel,TWeights<:Real,IT<:DimSpec{Gridded},pad}
3838
isconcretetype(IT) || error("The b-spline type must be a leaf type (was $IT)")
3939

4040
check_gridded(it, knots, axes(A))
@@ -44,7 +44,7 @@ function GriddedInterpolation(::Type{TWeights}, knots::NTuple{N,GridIndex}, A::A
4444
else
4545
T = typeof(c * first(A))
4646
end
47-
GriddedInterpolation{T,N,TCoefs,IT,typeof(knots)}(knots, A, it)
47+
GriddedInterpolation{T,N,typeof(A),IT,typeof(knots)}(knots, A, it)
4848
end
4949

5050
"""
@@ -146,7 +146,7 @@ axes(A::GriddedInterpolation) = axes(A.coefs)
146146
itpflag(A::GriddedInterpolation) = A.it
147147

148148
function interpolate(::Type{TWeights}, ::Type{TCoefs}, knots::NTuple{N,GridIndex}, A::AbstractArray{Tel,N}, it::IT) where {TWeights,TCoefs,Tel,N,IT<:DimSpec{Gridded}}
149-
GriddedInterpolation(TWeights, knots, A, it)
149+
GriddedInterpolation(TWeights, knots, copy(A), it)
150150
end
151151
"""
152152
itp = interpolate((nodes1, nodes2, ...), A, interpmode)
@@ -169,7 +169,7 @@ end
169169
interpolate!(::Type{TWeights}, knots::NTuple{N,GridIndex}, A::AbstractArray{Tel,N}, it::IT) where {TWeights,Tel,N,IT<:DimSpec{Gridded}} =
170170
GriddedInterpolation(TWeights, knots, A, it)
171171
function interpolate!(knots::NTuple{N,GridIndex}, A::AbstractArray{Tel,N}, it::IT) where {Tel,N,IT<:DimSpec{Gridded}}
172-
interpolate!(tweight(A), tcoef(A), knots, A, it)
172+
interpolate!(tweight(A), knots, A, it)
173173
end
174174

175175
lbounds(itp::GriddedInterpolation) = first.(itp.knots)

test/gridded/gridded.jl

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,75 +5,78 @@ using Interpolations, Test
55
front(r::AbstractRange) = range(first(r), step=step(r), length=length(r)-1)
66

77
for D in (Constant, Linear)
8-
## 1D
9-
a = rand(5)
10-
knots = (range(1, stop=length(a), length=length(a)),)
11-
itp = @inferred(interpolate(knots, a, Gridded(D())))
12-
@inferred(itp(2))
13-
@inferred(itp(CartesianIndex(2)))
14-
for i = 1:length(a)
15-
@test itp(i) a[i]
16-
@test itp(CartesianIndex(i)) a[i]
17-
end
18-
@inferred(itp(knots...))
19-
@test itp(knots...) a
20-
# compare scalar indexing and vector indexing
21-
x = front(knots[1] .+ 0.1)
22-
v = itp(x)
23-
for i = 1:length(x)
24-
@test v[i] itp(x[i])
25-
end
26-
x = [2.3,2.2] # non-increasing order
27-
v = itp(x)
28-
for i = 1:length(x)
29-
@test v[i] itp(x[i])
30-
end
31-
# compare against BSpline
32-
itpb = @inferred(interpolate(a, BSpline(D())))
33-
for x in range(1.1, stop=4.9, length=101)
34-
@test itp(x) itpb(x)
35-
end
8+
for constructor in (interpolate, interpolate!)
9+
isinplace = constructor == interpolate!
10+
## 1D
11+
a = rand(5)
12+
knots = (range(1, stop=length(a), length=length(a)),)
13+
itp = @inferred(constructor(knots, a, Gridded(D())))
14+
@inferred(itp(2))
15+
@inferred(itp(CartesianIndex(2)))
16+
for i = 1:length(a)
17+
@test itp(i) a[i]
18+
@test itp(CartesianIndex(i)) a[i]
19+
end
20+
@inferred(itp(knots...))
21+
@test itp(knots...) a
22+
# compare scalar indexing and vector indexing
23+
x = front(knots[1] .+ 0.1)
24+
v = itp(x)
25+
for i = 1:length(x)
26+
@test v[i] itp(x[i])
27+
end
28+
x = [2.3,2.2] # non-increasing order
29+
v = itp(x)
30+
for i = 1:length(x)
31+
@test v[i] itp(x[i])
32+
end
33+
# compare against BSpline
34+
itpb = @inferred(constructor(a, BSpline(D())))
35+
for x in range(1.1, stop=4.9, length=101)
36+
@test itp(x) itpb(x)
37+
end
3638

37-
knots = (range(0.0, stop=1.0, length=length(a)),)
38-
itp = @inferred(interpolate(knots, a, Gridded(D())))
39-
@test itp([0.1, 0.2, 0.3]) == [itp(0.1), itp(0.2), itp(0.3)]
39+
knots = (range(0.0, stop=1.0, length=length(a)),)
40+
itp = @inferred(constructor(knots, a, Gridded(D())))
41+
@test itp([0.1, 0.2, 0.3]) == [itp(0.1), itp(0.2), itp(0.3)]
4042

41-
## 2D
42-
A = rand(6,5)
43-
knots = (range(1, stop=size(A,1), length=size(A,1)), range(1, stop=size(A,2), length=size(A,2)))
44-
itp = @inferred(interpolate(knots, A, Gridded(D())))
45-
@test parent(itp) === A
46-
@inferred(itp(2, 2))
47-
@inferred(itp(CartesianIndex((2,2))))
48-
for j = 2:size(A,2)-1, i = 2:size(A,1)-1
49-
@test itp(i,j) A[i,j]
50-
@test itp(CartesianIndex((i,j))) A[i,j]
51-
end
52-
@test itp(knots...) A
53-
@inferred(itp(knots...))
54-
# compare scalar indexing and vector indexing
55-
x, y = front(knots[1] .+ 0.1), front(knots[2] .+ 0.6)
56-
v = itp(x,y)
57-
for j = 1:length(y), i = 1:length(x)
58-
@test v[i,j] itp(x[i],y[j])
59-
end
60-
# check the fallback vector indexing
61-
x = [2.3,2.2] # non-increasing order
62-
y = [3.5,2.8]
63-
v = itp(x,y)
64-
for j = 1:length(y), i = 1:length(x)
65-
@test v[i,j] itp(x[i],y[j])
66-
end
67-
# compare against BSpline
68-
itpb = @inferred(interpolate(A, BSpline(D())))
69-
for x in range(1.1, stop=5.9, length=101), y in range(1.1, stop=4.9, length=101)
70-
@test itp(x,y) itpb(x,y)
71-
end
43+
## 2D
44+
A = rand(6,5)
45+
knots = (range(1, stop=size(A,1), length=size(A,1)), range(1, stop=size(A,2), length=size(A,2)))
46+
itp = @inferred(constructor(knots, A, Gridded(D())))
47+
isinplace && @test parent(itp) === A
48+
@inferred(itp(2, 2))
49+
@inferred(itp(CartesianIndex((2,2))))
50+
for j = 2:size(A,2)-1, i = 2:size(A,1)-1
51+
@test itp(i,j) A[i,j]
52+
@test itp(CartesianIndex((i,j))) A[i,j]
53+
end
54+
@test itp(knots...) A
55+
@inferred(itp(knots...))
56+
# compare scalar indexing and vector indexing
57+
x, y = front(knots[1] .+ 0.1), front(knots[2] .+ 0.6)
58+
v = itp(x,y)
59+
for j = 1:length(y), i = 1:length(x)
60+
@test v[i,j] itp(x[i],y[j])
61+
end
62+
# check the fallback vector indexing
63+
x = [2.3,2.2] # non-increasing order
64+
y = [3.5,2.8]
65+
v = itp(x,y)
66+
for j = 1:length(y), i = 1:length(x)
67+
@test v[i,j] itp(x[i],y[j])
68+
end
69+
# compare against BSpline
70+
itpb = @inferred(constructor(A, BSpline(D())))
71+
for x in range(1.1, stop=5.9, length=101), y in range(1.1, stop=4.9, length=101)
72+
@test itp(x,y) itpb(x,y)
73+
end
7274

73-
A = rand(8,20)
74-
knots = ([x^2 for x = 1:8], [0.2y for y = 1:20])
75-
itp = interpolate(knots, A, Gridded(D()))
76-
@test itp(4,1.2) A[2,6]
75+
A = rand(8,20)
76+
knots = ([x^2 for x = 1:8], [0.2y for y = 1:20])
77+
itp = constructor(knots, A, Gridded(D()))
78+
@test itp(4,1.2) A[2,6]
79+
end
7780
end
7881

7982
# issue #248
@@ -101,4 +104,13 @@ using Interpolations, Test
101104
successive_knots_warning = "Successive repeated knots detected. Consider using `move_knots` keyword to Interpolations.deduplicate_knots!"
102105
@test_logs (:warn, successive_knots_warning) Interpolations.deduplicate_knots!(duplicated_knots)
103106
@test allunique(duplicated_knots)
107+
108+
# inplace gridded interpolation, issue #495
109+
knots = ([0., 1.],)
110+
y = view([1., 2.], :)
111+
f1 = interpolate(knots, y, Gridded(Linear()))
112+
f2 = interpolate!(knots, y, Gridded(Linear()))
113+
y .= 0
114+
@test f1(0.5) 1.5
115+
@test f2(0.5) 0
104116
end

test/io.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ using Test
5151
summary(itp) == "8×20 interpolate((::Array{Int64,1},::Array{Float64,1}), ::Array{Float64,2}, (Gridded(Linear()), Gridded(Constant{Nearest}()))) with element type Float64"
5252

5353
# issue #260
54-
A = (1:4)/4
54+
A = collect((1:4)/4)
5555
itp = interpolate((range(0.0, stop=0.3, length=4),), A, Gridded(Linear()))
5656
io = IOBuffer()
5757
show(io, MIME("text/plain"), itp)

0 commit comments

Comments
 (0)