Skip to content

Commit 1201501

Browse files
timholysglyon
authored andcommitted
Fix/improve construction of NoInterp objects (#177)
This might seem strange, but it's a convenient way of doing *extrapolation* on arrays at integer coordinates.
1 parent d7ab993 commit 1201501

File tree

5 files changed

+50
-17
lines changed

5 files changed

+50
-17
lines changed

src/b-splines/indexing.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ function getindex_return_type(::Type{BSplineInterpolation{T,N,TCoefs,IT,GT,Pad}}
9494
_promote_mul(eltype(TCoefs), I)
9595
end
9696

97+
@noinline function getindex_return_type(::Type{Tel}, ::Type{BSplineInterpolation{T,N,TCoefs,IT,GT,Pad}}, argtypes::Tuple) where {Tel,T,N,TCoefs,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},Pad}
98+
reduce(_promote_mul, eltype(TCoefs), (Tel, argtypes...))
99+
end
100+
97101
@generated function gradient!(g::AbstractVector, itp::BSplineInterpolation{T,N}, xs::Number...) where {T,N}
98102
length(xs) == N || error("Can only be called with $N indexes")
99103
gradient_impl(itp)

src/extrapolation/filled.jl

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,32 @@ mutable struct FilledExtrapolation{T,N,ITP<:AbstractInterpolation,IT,GT,FT} <: A
66
end
77

88
function FilledExtrapolation(itp::AbstractInterpolation{T,N,IT,GT}, fillvalue) where {T,N,IT,GT}
9-
FilledExtrapolation{T,N,typeof(itp),IT,GT,typeof(fillvalue)}(itp, fillvalue)
9+
Te = promote_type(T,typeof(fillvalue))
10+
FilledExtrapolation{Te,N,typeof(itp),IT,GT,typeof(fillvalue)}(itp, fillvalue)
1011
end
1112

1213
Base.parent(A::FilledExtrapolation) = A.itp
1314

1415
"""
1516
`extrapolate(itp, fillvalue)` creates an extrapolation object that returns the `fillvalue` any time the indexes in `itp[x1,x2,...]` are out-of-bounds.
1617
"""
17-
extrapolate(itp::AbstractInterpolation{T,N,IT,GT}, fillvalue) where {T,N,IT,GT} = FilledExtrapolation(itp, convert(eltype(itp), fillvalue))
18+
extrapolate(itp::AbstractInterpolation{T,N,IT,GT}, fillvalue) where {T,N,IT,GT} = FilledExtrapolation(itp, fillvalue)
1819

1920
function getindex_impl(fitp::Type{FilledExtrapolation{T,N,ITP,IT,GT,FT}}, args) where {T,N,ITP,IT,GT,FT}
20-
n = length(args)
21-
n == N || return error("Must index $(N)-dimensional interpolation objects with $(nindexes(N))")
22-
23-
Tret = FT<:Number ? getindex_return_type(ITP, args) : FT
24-
meta = Expr(:meta, :inline)
25-
quote
26-
$meta
27-
# Check to see if we're in the extrapolation region, i.e.,
28-
# out-of-bounds in an index
29-
inds_etp = indices(fitp)
30-
@nexprs $N d->((args[d] < lbound(fitp, d, inds_etp[d]) || args[d] > ubound(fitp, d, inds_etp[d]))) && return convert($Tret, fitp.fillvalue)::$Tret
31-
# In the interpolation region
32-
return convert($Tret, getindex(fitp.itp,args...))::$Tret
33-
end
21+
n = length(args)
22+
n == N || return error("Must index $(N)-dimensional interpolation objects with $(nindexes(N))")
23+
24+
Tret = FT<:Number ? getindex_return_type(T, ITP, args) : FT
25+
meta = Expr(:meta, :inline)
26+
quote
27+
$meta
28+
# Check to see if we're in the extrapolation region, i.e.,
29+
# out-of-bounds in an index
30+
inds_etp = indices(fitp)
31+
@nexprs $N d->((args[d] < lbound(fitp, d, inds_etp[d]) || args[d] > ubound(fitp, d, inds_etp[d]))) && return convert($Tret, fitp.fillvalue)::$Tret
32+
# In the interpolation region
33+
return convert($Tret, getindex(fitp.itp,args...))::$Tret
34+
end
3435
end
3536

3637

src/nointerp/nointerp.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
function interpolate(A::AbstractArray, ::NoInterp, gt::GT) where {GT<:DimSpec{GridType}}
2+
interpolate(Int, eltype(A), A, NoInterp(), gt)
3+
end
4+
5+
iextract(::Type{NoInterp}, d) = NoInterp
6+
17
function define_indices_d(::Type{NoInterp}, d, pad)
28
symix, symx = Symbol("ix_",d), Symbol("x_",d)
39
:($symix = convert(Int, $symx))
@@ -27,4 +33,6 @@ function count_interp_dims(it::Type{IT}, N) where IT<:Tuple{Vararg{Interpolation
2733
n += count_interp_dims(p, 1)
2834
end
2935
n
30-
end
36+
end
37+
38+
prefilter(::Type{TWeights}, ::Type{TC}, A, ::Type{IT},::Type{GT}) where {TWeights, TC, IT<:NoInterp, GT<:GridType} = A, Val{0}()

test/nointerp.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module NoInterpTests
2+
println("Testing NoInterp...")
3+
using Interpolations, Base.Test
4+
5+
a = reshape(1:12, 3, 4)
6+
ai = interpolate(a, NoInterp(), OnGrid())
7+
@test eltype(ai) == Int
8+
@test ai[1,1] == 1
9+
@test ai[3, 3] == 9
10+
@test_throws InexactError ai[2.2, 2]
11+
@test_throws InexactError ai[2, 2.2]
12+
13+
ae = extrapolate(ai, NaN)
14+
@test eltype(ae) == Float64
15+
@test ae[1,1] === 1.0
16+
@test ae[0,1] === NaN
17+
@test_throws InexactError ae[1.5,2]
18+
19+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using Interpolations
88
include("extrapolation/runtests.jl")
99
# b-spline interpolation tests
1010
include("b-splines/runtests.jl")
11+
include("nointerp.jl")
1112

1213
# scaling tests
1314
include("scaling/runtests.jl")

0 commit comments

Comments
 (0)