Skip to content

Commit

Permalink
Merge pull request #72 from tlycken/teh/typestability_fillvalue
Browse files Browse the repository at this point in the history
Allow manual override of return type for fillvalue
  • Loading branch information
timholy committed Oct 3, 2015
2 parents 1c9ebfb + 67fd8f0 commit 2ba7253
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 12 deletions.
9 changes: 9 additions & 0 deletions src/b-splines/indexing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ function gradient_impl{T,N,TCoefs,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},Pad
end
end

function getindex_return_type{T,N,TCoefs,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},Pad}(::Type{BSplineInterpolation{T,N,TCoefs,IT,GT,Pad}}, argtypes)
Tret = TCoefs
for a in argtypes
Tret = Base.promote_op(Base.MulFun, Tret, a)
end
Tret
end


@generated function gradient!{T,N}(g::AbstractVector, itp::BSplineInterpolation{T,N}, xs::Number...)
length(xs) == N || error("Can only be called with $N indexes")
gradient_impl(itp)
Expand Down
3 changes: 1 addition & 2 deletions src/extrapolation/extrapolation.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export Throw,
FilledExtrapolation # for direct control over typeof(fillvalue)
export Throw

type Extrapolation{T,N,ITPT,IT,GT,ET} <: AbstractInterpolationWrapper{T,N,ITPT,IT,GT}
itp::ITPT
Expand Down
9 changes: 3 additions & 6 deletions src/extrapolation/filled.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ type FilledExtrapolation{T,N,ITP<:AbstractInterpolation,IT,GT,FT} <: AbstractExt
itp::ITP
fillvalue::FT
end
"""
`FilledExtrapolation(itp, fillvalue)` creates an extrapolation object that returns the `fillvalue` any time the indexes in `itp[x1,x2,...]` are out-of-bounds.

By comparison with `extrapolate`, this version lets you control the `fillvalue`'s type directly. It's important for the `fillvalue` to be of the same type as returned by `itp[x1,x2,...]` for in-bounds regions for the index types you are using; otherwise, indexing will be type-unstable (and slow).
"""
function FilledExtrapolation{T,N,IT,GT}(itp::AbstractInterpolation{T,N,IT,GT}, fillvalue)
FilledExtrapolation{T,N,typeof(itp),IT,GT,typeof(fillvalue)}(itp, fillvalue)
end
Expand All @@ -19,15 +15,16 @@ end
"""
extrapolate{T,N,IT,GT}(itp::AbstractInterpolation{T,N,IT,GT}, fillvalue) = FilledExtrapolation(itp, convert(eltype(itp), fillvalue))

@generated function getindex{T,N}(fitp::FilledExtrapolation{T,N}, args::Number...)
@generated function getindex{T,N,ITP,IT,GT,FT}(fitp::FilledExtrapolation{T,N,ITP,IT,GT,FT}, args::Number...)
n = length(args)
n == N || return error("Must index $(N)-dimensional interpolation objects with $(nindexes(N))")
Tret = FT<:Number ? getindex_return_type(ITP, args) : FT
meta = Expr(:meta, :inline)
quote
$meta
# Check to see if we're in the extrapolation region, i.e.,
# out-of-bounds in an index
@nexprs $N d->((args[d] < lbound(fitp,d) || args[d] > ubound(fitp, d)) && return fitp.fillvalue)
@nexprs $N d->((args[d] < lbound(fitp,d) || args[d] > ubound(fitp, d)) && return convert($Tret, fitp.fillvalue))
# In the interpolation region
return getindex(fitp.itp,args...)
end
Expand Down
8 changes: 8 additions & 0 deletions src/gridded/indexing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ function getindex{T,N,TCoefs,IT<:DimSpec{Gridded},K,P}(itp::GriddedInterpolation
dest = Array(T, map(length, x))::Array{T,N}
getindex!(dest, itp, x...)
end

function getindex_return_type{T,N,TCoefs,IT<:DimSpec{Gridded},K,P}(::Type{GriddedInterpolation{T,N,TCoefs,IT,K,P}}, argtypes)
Tret = TCoefs
for a in argtypes
Tret = Base.promote_op(Base.MulFun, Tret, a)
end
Tret
end
6 changes: 2 additions & 4 deletions test/extrapolation/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ etpf = @inferred(extrapolate(itpg, NaN))
@test_throws BoundsError etpf[2.5,2]
@test_throws ErrorException etpf[2.5,2,1] # this will probably become a BoundsError someday

etpf = @inferred(FilledExtrapolation(itpg, 'x'))
@test_approx_eq etpf[2] f(2)
@test etpf[-1.5] == 'x'
@test isa(@inferred(getindex(etpf, dual(-2.5,1))), Dual)

etpl = extrapolate(itpg, Linear)
k_lo = A[2] - A[1]
Expand Down Expand Up @@ -61,4 +59,4 @@ etp2ll = extrapolate(itp2g, Linear)

end

include("type-stability.jl")
include("type-stability.jl")

0 comments on commit 2ba7253

Please sign in to comment.