From 67fd8f0ce1090b9e93be26761baceaf0efa3d9e6 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 1 Oct 2015 06:04:15 -0500 Subject: [PATCH] Infer the return type for fillvalue based on index types This should promote greater type-stability --- src/b-splines/indexing.jl | 9 +++++++++ src/extrapolation/extrapolation.jl | 3 +-- src/extrapolation/filled.jl | 9 +++------ src/gridded/indexing.jl | 8 ++++++++ test/extrapolation/runtests.jl | 6 ++---- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/b-splines/indexing.jl b/src/b-splines/indexing.jl index 088dfc13..e63c43e8 100644 --- a/src/b-splines/indexing.jl +++ b/src/b-splines/indexing.jl @@ -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) diff --git a/src/extrapolation/extrapolation.jl b/src/extrapolation/extrapolation.jl index edee18d7..77564688 100644 --- a/src/extrapolation/extrapolation.jl +++ b/src/extrapolation/extrapolation.jl @@ -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 diff --git a/src/extrapolation/filled.jl b/src/extrapolation/filled.jl index 535cb899..92639768 100644 --- a/src/extrapolation/filled.jl +++ b/src/extrapolation/filled.jl @@ -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 @@ -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 diff --git a/src/gridded/indexing.jl b/src/gridded/indexing.jl index 68fb439a..16e738a4 100644 --- a/src/gridded/indexing.jl +++ b/src/gridded/indexing.jl @@ -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 diff --git a/test/extrapolation/runtests.jl b/test/extrapolation/runtests.jl index dfea4543..1cda0be1 100644 --- a/test/extrapolation/runtests.jl +++ b/test/extrapolation/runtests.jl @@ -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] @@ -61,4 +59,4 @@ etp2ll = extrapolate(itp2g, Linear) end -include("type-stability.jl") \ No newline at end of file +include("type-stability.jl")