Skip to content

Commit ed84771

Browse files
committed
Implement extrapolation
1 parent 60862fe commit ed84771

23 files changed

+293
-522
lines changed

src/Interpolations.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,9 @@ end
204204
# getindex is supported only for Integer indices (deliberately)
205205
import Base: getindex
206206
@propagate_inbounds getindex(itp::AbstractInterpolation{T,N}, i::Vararg{Integer,N}) where {T,N} = itp(i...)
207-
@inline function getindex(itp::AbstractInterpolation{T,1}, i::Integer, j::Integer) where T
207+
@propagate_inbounds function getindex(itp::AbstractInterpolation{T,1}, i::Integer, j::Integer) where T
208208
@boundscheck (j == 1 || Base.throw_boundserror(itp, (i, j)))
209-
@inbounds itp(i)
209+
itp(i)
210210
end
211211

212212
# deprecate getindex for other numeric indices
@@ -215,7 +215,7 @@ end
215215
include("nointerp/nointerp.jl")
216216
include("b-splines/b-splines.jl")
217217
# include("gridded/gridded.jl")
218-
# include("extrapolation/extrapolation.jl")
218+
include("extrapolation/extrapolation.jl")
219219
# include("scaling/scaling.jl")
220220
include("utils.jl")
221221
include("io.jl")

src/b-splines/b-splines.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ axes(itp::BSplineInterpolation) = itp.parentaxes
5353

5454
lbounds(itp::BSplineInterpolation) = _lbounds(itp.parentaxes, itpflag(itp), gridflag(itp))
5555
ubounds(itp::BSplineInterpolation) = _ubounds(itp.parentaxes, itpflag(itp), gridflag(itp))
56-
_lbounds(axs::NTuple{N,Any}, itp, gt) where N = ntuple(d->lbound(axs[d], iextract(itp,d), iextract(gt,d)), Val(N))
57-
_ubounds(axs::NTuple{N,Any}, itp, gt) where N = ntuple(d->ubound(axs[d], iextract(itp,d), iextract(gt,d)), Val(N))
56+
_lbounds(axs, itp, gt) = (lbound(axs[1], getfirst(itp), getfirst(gt)), _lbounds(Base.tail(axs), getrest(itp), getrest(gt))...)
57+
_ubounds(axs, itp, gt) = (ubound(axs[1], getfirst(itp), getfirst(gt)), _ubounds(Base.tail(axs), getrest(itp), getrest(gt))...)
58+
_lbounds(::Tuple{}, itp, gt) = ()
59+
_ubounds(::Tuple{}, itp, gt) = ()
5860

5961
# The unpadded defaults
6062
lbound(ax, ::BSpline, ::OnCell) = first(ax) - 0.5

src/b-splines/cubic.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Cubic
2626

2727
function base_rem(::Cubic, bounds, x)
2828
xf = floorbounds(x, bounds)
29-
xf -= ifelse(xf > bounds[2]-1, oneunit(xf), zero(xf))
29+
xf -= ifelse(xf > last(bounds)-1, oneunit(xf), zero(xf))
3030
δx = x - xf
3131
fast_trunc(Int, xf), δx
3232
end
@@ -71,9 +71,9 @@ hessian_weights(::Cubic, δx) = (1-δx, 3*δx-2, 3*(1-δx)-2, δx)
7171
padded_axis(ax::AbstractUnitRange, ::BSpline{<:Cubic}) = first(ax)-1:last(ax)+1
7272
padded_axis(ax::AbstractUnitRange, ::BSpline{Cubic{Periodic}}) = ax
7373

74-
# Due to padding we can extend the bounds
75-
lbound(ax, ::BSpline{Cubic{BC}}, ::OnGrid) where BC = first(ax) - 0.5
76-
ubound(ax, ::BSpline{Cubic{BC}}, ::OnGrid) where BC = last(ax) + 0.5
74+
# # Due to padding we can extend the bounds
75+
# lbound(ax, ::BSpline{Cubic{BC}}, ::OnGrid) where BC = first(ax) - 0.5
76+
# ubound(ax, ::BSpline{Cubic{BC}}, ::OnGrid) where BC = last(ax) + 0.5
7777

7878
"""
7979
`Cubic`: continuity in function value, first and second derivatives yields

src/b-splines/indexing.jl

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
@boundscheck (checkbounds(Bool, itp, x...) || Base.throw_boundserror(itp, x))
55
expand_value(itp, x)
66
end
7-
# @inline function (itp::BSplineInterpolation{T,1})(x::Integer, y::Integer) where T
8-
# @boundscheck (y == 1 || Base.throw_boundserror(itp, (x,y)))
9-
# expand_value(itp, (x,))
10-
# end
7+
@propagate_inbounds function (itp::BSplineInterpolation{T,N})(x::Vararg{Number,M}) where {T,M,N}
8+
inds, trailing = split_trailing(itp, x)
9+
@boundscheck (check1(trailing) || Base.throw_boundserror(itp, x))
10+
@assert length(inds) == N
11+
itp(inds...)
12+
end
1113

1214
@inline function gradient(itp::BSplineInterpolation{T,N}, x::Vararg{Number,N}) where {T,N}
1315
@boundscheck checkbounds(Bool, itp, x...) || Base.throw_boundserror(itp, x)
@@ -46,7 +48,7 @@ Interpolate `itp` at `x`.
4648
function expand_value(itp::AbstractInterpolation, x::Tuple)
4749
coefs = coefficients(itp)
4850
degree = interpdegree(itp)
49-
ixs, rxs = expand_indices_resid(degree, bounds(itp), x)
51+
ixs, rxs = splitgrouped(expand_indices_resid(degree, axes(itp), x))
5052
cxs = expand_weights(value_weights, degree, rxs)
5153
expand(coefs, cxs, ixs)
5254
end
@@ -59,7 +61,7 @@ Calculate the interpolated gradient of `itp` at `x`.
5961
function expand_gradient(itp::AbstractInterpolation, x::Tuple)
6062
coefs = coefficients(itp)
6163
degree = interpdegree(itp)
62-
ixs, rxs = expand_indices_resid(degree, bounds(itp), x)
64+
ixs, rxs = splitgrouped(expand_indices_resid(degree, axes(itp), x))
6365
cxs = expand_weights(value_weights, degree, rxs)
6466
gxs = expand_weights(gradient_weights, degree, rxs)
6567
expand(coefs, (cxs, gxs), ixs)
@@ -68,7 +70,7 @@ end
6870
function expand_gradient!(dest, itp::AbstractInterpolation, x::Tuple)
6971
coefs = coefficients(itp)
7072
degree = interpdegree(itp)
71-
ixs, rxs = expand_indices_resid(degree, bounds(itp), x)
73+
ixs, rxs = splitgrouped(expand_indices_resid(degree, axes(itp), x))
7274
cxs = expand_weights(value_weights, degree, rxs)
7375
gxs = expand_weights(gradient_weights, degree, rxs)
7476
expand!(dest, coefs, (cxs, gxs), ixs)
@@ -82,7 +84,7 @@ Calculate the interpolated hessian of `itp` at `x`.
8284
function expand_hessian(itp::AbstractInterpolation, x::Tuple)
8385
coefs = coefficients(itp)
8486
degree = interpdegree(itp)
85-
ixs, rxs = expand_indices_resid(degree, bounds(itp), x)
87+
ixs, rxs = splitgrouped(expand_indices_resid(degree, axes(itp), x))
8688
cxs = expand_weights(value_weights, degree, rxs)
8789
gxs = expand_weights(gradient_weights, degree, rxs)
8890
hxs = expand_weights(hessian_weights, degree, rxs)
@@ -271,17 +273,16 @@ function expand!(dest, coefs, (vweights, gweights, hweights)::NTuple{3,HasNoInte
271273
dest
272274
end
273275

274-
function expand_indices_resid(degree, bounds, x)
275-
ixbase, δxs = splitpaired(_base_rem(degree, bounds, x))
276-
expand_indices(degree, ixbase, bounds, δxs), δxs
276+
function expand_indices_resid(degree, axs, x)
277+
item = expand_index_resid(getfirst(degree), axs[1], x[1])
278+
(item, expand_indices_resid(getrest(degree), Base.tail(axs), Base.tail(x))...)
277279
end
280+
expand_indices_resid(degree, ::Tuple{}, ::Tuple{}) = ()
278281

279-
@inline _base_rem(degree::Union{Degree,NoInterp}, bounds, x) =
280-
(base_rem(degree, bounds[1], x[1]), _base_rem(degree, Base.tail(bounds), Base.tail(x))...)
281-
@inline _base_rem(degree::Union{Degree,NoInterp}, ::Tuple{}, ::Tuple{}) = ()
282-
@inline _base_rem(degree::Tuple{Vararg{Union{Degree,NoInterp},N}}, bounds::Tuple{Vararg{Any,N}}, x::Tuple{Vararg{Number,N}}) where N =
283-
(base_rem(degree[1], bounds[1], x[1]), _base_rem(Base.tail(degree), Base.tail(bounds), Base.tail(x))...)
284-
@inline _base_rem(::Tuple{}, ::Tuple{}, ::Tuple{}) = ()
282+
function expand_index_resid(degree, ax, x::Number)
283+
ix, δx = base_rem(degree, ax, x)
284+
expand_index(degree, ix, ax, δx), δx
285+
end
285286

286287
expand_weights(f, degree::Union{Degree,NoInterp}, ixs) =
287288
(f(degree, ixs[1]), expand_weights(f, degree, Base.tail(ixs))...)
@@ -290,14 +291,14 @@ expand_weights(f, degree::Union{Degree,NoInterp}, ::Tuple{}) = ()
290291
expand_weights(f, degree::Tuple{Vararg{Union{Degree,NoInterp},N}}, ixs::NTuple{N,Number}) where N =
291292
f.(degree, ixs)
292293

293-
expand_indices(degree::Union{Degree,NoInterp}, ixs, axs, δxs) =
294-
(expand_index(degree, ixs[1], axs[1], δxs[1]), expand_indices(degree, Base.tail(ixs), Base.tail(axs), Base.tail(δxs))...)
295-
expand_indices(degree::Union{Degree,NoInterp}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = ()
294+
# expand_indices(degree::Union{Degree,NoInterp}, ixs, axs, δxs) =
295+
# (expand_index(degree, ixs[1], axs[1], δxs[1]), expand_indices(degree, Base.tail(ixs), Base.tail(axs), Base.tail(δxs))...)
296+
# expand_indices(degree::Union{Degree,NoInterp}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = ()
296297

297-
expand_indices(degree::Tuple{Vararg{Union{Degree,NoInterp},N}}, ixs::NTuple{N,Number}, axs::NTuple{N,Tuple{Real,Real}}, δxs::NTuple{N,Number}) where N =
298-
expand_index.(degree, ixs, axs, δxs)
298+
# expand_indices(degree::Tuple{Vararg{Union{Degree,NoInterp},N}}, ixs::NTuple{N,Number}, axs::NTuple{N,Tuple{Real,Real}}, δxs::NTuple{N,Number}) where N =
299+
# expand_index.(degree, ixs, axs, δxs)
299300

300-
expand_index(degree, ixs, bounds::Tuple{Real,Real}, δxs) = expand_index(degree, ixs, axfrombounds(bounds), δxs)
301+
# expand_index(degree, ixs, bounds::Tuple{Real,Real}, δxs) = expand_index(degree, ixs, axfrombounds(bounds), δxs)
301302

302303
checklubounds(ls, us, xs) = _checklubounds(true, ls, us, xs)
303304
_checklubounds(tf::Bool, ls, us, xs) = _checklubounds(tf & (ls[1] <= xs[1] <= us[1]),
@@ -318,14 +319,19 @@ function getindex_return_type(::Type{BSplineInterpolation{T,N,TCoefs,IT,GT,Pad}}
318319
end
319320

320321
# This handles round-towards-the-middle for points on half-integer edges
321-
roundbounds(x, bounds::Tuple{Integer,Integer}) = round(x)
322-
roundbounds(x, (l, u)) = ifelse(x == l, ceil(l), ifelse(x == u, floor(u), round(x)))
322+
roundbounds(x::Integer, bounds) = x
323+
function roundbounds(x, bounds)
324+
l, u = first(bounds), last(bounds)
325+
h = half(x)
326+
xh = x+h
327+
ifelse(x < u+half(u), floor(xh), ceil(xh)-1)
328+
end
323329

324-
floorbounds(x, bounds::Tuple{Integer,Integer}) = floor(x)
325-
function floorbounds(x, (l, u)::Tuple{Real,Real})
326-
ceill = ceil(l)
327-
ifelse(l <= x <= ceill, ceill, floor(x))
330+
floorbounds(x::Integer, ax) = x
331+
function floorbounds(x, ax)
332+
l = first(ax)
333+
h = half(x)
334+
ifelse(x < l, floor(x+h), floor(x+zero(h)))
328335
end
329336

330-
axfrombounds((l, u)::Tuple{Integer,Integer}) = UnitRange(l, u)
331-
axfrombounds((l, u)) = UnitRange(ceil(Int, l), floor(Int, u))
337+
half(x) = oneunit(x)/2

src/b-splines/linear.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ Linear
2323

2424
function base_rem(::Linear, bounds, x)
2525
xf = floorbounds(x, bounds)
26-
xf -= ifelse(xf >= floor(bounds[2]), oneunit(xf), zero(xf))
26+
xf -= ifelse(xf >= last(bounds), oneunit(xf), zero(xf))
2727
δx = x - xf
2828
fast_trunc(Int, xf), δx
2929
end
3030

31-
expand_index(::Linear, xi::Number, ax::AbstractUnitRange, δx) = (xi, xi+(δx>0))
31+
expand_index(::Linear, xi::Number, ax::AbstractUnitRange, δx) = (xi, xi + ((δx!=0) | (xi < last(ax))))
3232

3333
value_weights(::Linear, δx) = (1-δx, δx)
3434
gradient_weights(::Linear, δx) = (-oneunit(δx), oneunit(δx))

src/b-splines/quadratic.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ expand_index(::Quadratic{BC}, xi::Number, ax::AbstractUnitRange, δx) where BC<:
5050
padded_axis(ax::AbstractUnitRange, ::BSpline{<:Quadratic}) = first(ax)-1:last(ax)+1
5151
padded_axis(ax::AbstractUnitRange, ::BSpline{Quadratic{BC}}) where BC<:Union{Periodic,InPlace,InPlaceQ} = ax
5252

53-
# Due to padding we can extend the bounds
54-
lbound(ax, ::BSpline{Quadratic{BC}}, ::OnGrid) where BC = first(ax) - 0.5
55-
ubound(ax, ::BSpline{Quadratic{BC}}, ::OnGrid) where BC = last(ax) + 0.5
53+
# # Due to padding we can extend the bounds
54+
# lbound(ax, ::BSpline{Quadratic{BC}}, ::OnGrid) where BC = first(ax) - 0.5
55+
# ubound(ax, ::BSpline{Quadratic{BC}}, ::OnGrid) where BC = last(ax) + 0.5
5656

5757
function inner_system_diags(::Type{T}, n::Int, ::Quadratic) where {T}
5858
du = fill(convert(T, SimpleRatio(1,8)), n-1)

src/extrapolation/extrap_prep.jl

Lines changed: 0 additions & 91 deletions
This file was deleted.

src/extrapolation/extrap_prep_gradient.jl

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)