@@ -30,10 +30,10 @@ export
3030 # scaling/scaling.jl
3131
3232using LinearAlgebra, SparseArrays
33- using WoodburyMatrices, Ratios, AxisAlgorithms, OffsetArrays
33+ using StaticArrays, WoodburyMatrices, Ratios, AxisAlgorithms, OffsetArrays
3434
35- import Base: convert, size, axes, getindex, promote_rule,
36- ndims, eltype, checkbounds
35+ using Base: @propagate_inbounds
36+ import Base : convert, size, axes, promote_rule, ndims, eltype, checkbounds
3737
3838abstract type Flag end
3939abstract type InterpolationType <: Flag end
@@ -48,57 +48,183 @@ abstract type AbstractInterpolation{T,N,IT<:DimSpec{InterpolationType},GT<:DimSp
4848abstract type AbstractInterpolationWrapper{T,N,ITPT,IT,GT} <: AbstractInterpolation{T,N,IT,GT} end
4949abstract type AbstractExtrapolation{T,N,ITPT,IT,GT} <: AbstractInterpolationWrapper{T,N,ITPT,IT,GT} end
5050
51- struct Throw <: Flag end
52- struct Flat <: Flag end
53- struct Line <: Flag end
54- struct Free <: Flag end
55- struct Periodic <: Flag end
56- struct Reflect <: Flag end
57- struct InPlace <: Flag end
51+ """
52+ BoundaryCondition
53+
54+ An abstract type with one of the following values (see the help for each for details):
55+
56+ - `Throw()`
57+ - `Flat()`
58+ - `Line()`
59+ - `Free()`
60+ - `Periodic()`
61+ - `Reflect()`
62+ - `InPlace()`
63+ - `InPlaceQ()`
64+ """
65+ abstract type BoundaryCondition <: Flag end
66+ struct Throw <: BoundaryCondition end
67+ struct Flat <: BoundaryCondition end
68+ struct Line <: BoundaryCondition end
69+ struct Free <: BoundaryCondition end
70+ struct Periodic <: BoundaryCondition end
71+ struct Reflect <: BoundaryCondition end
72+ struct InPlace <: BoundaryCondition end
5873# InPlaceQ is exact for an underlying quadratic. This is nice for ground-truth testing
5974# of in-place (unpadded) interpolation.
60- struct InPlaceQ <: Flag end
75+ struct InPlaceQ <: BoundaryCondition end
6176const Natural = Line
6277
63- @generated size (itp:: AbstractInterpolation{T,N} ) where {T, N} = Expr (:tuple , [:(size (itp, $ i)) for i in 1 : N]. .. )
64- size (exp:: AbstractExtrapolation , d) = size (exp. itp, d)
65- bounds (itp:: AbstractInterpolation{T,N} ) where {T,N} = tuple (zip (lbounds (itp), ubounds (itp))... )
66- bounds (itp:: AbstractInterpolation{T,N} , d) where {T,N} = (lbound (itp,d),ubound (itp,d))
67- @generated lbounds (itp:: AbstractInterpolation{T,N} ) where {T,N} = Expr (:tuple , [:(lbound (itp, $ i)) for i in 1 : N]. .. )
68- @generated ubounds (itp:: AbstractInterpolation{T,N} ) where {T,N} = Expr (:tuple , [:(ubound (itp, $ i)) for i in 1 : N]. .. )
69- lbound (itp:: AbstractInterpolation{T,N} , d) where {T,N} = 1
70- ubound (itp:: AbstractInterpolation{T,N} , d) where {T,N} = size (itp, d)
78+ Base. IndexStyle (:: Type{<:AbstractInterpolation} ) = IndexCartesian ()
79+
80+ size (itp:: AbstractInterpolation ) = map (length, itp. parentaxes)
81+ size (exp:: AbstractExtrapolation ) = size (exp. itp)
82+ axes (itp:: AbstractInterpolation ) = itp. parentaxes
83+ axes (exp:: AbstractExtrapolation ) = axes (exp. itp)
84+
85+ bounds (itp:: AbstractInterpolation ) = map (twotuple, lbounds (itp), ubounds (itp))
86+ twotuple (r:: AbstractUnitRange ) = (first (r), last (r))
87+ twotuple (x, y) = (x, y)
88+ bounds (itp:: AbstractInterpolation , d) = bounds (itp)[d]
89+ lbounds (itp:: AbstractInterpolation ) = _lbounds (itp. parentaxes, itpflag (itp), gridflag (itp))
90+ ubounds (itp:: AbstractInterpolation ) = _ubounds (itp. parentaxes, itpflag (itp), gridflag (itp))
91+ _lbounds (axs:: NTuple{N,Any} , itp, gt) where N = ntuple (d-> lbound (axs[d], iextract (itp,d), iextract (gt,d)), Val (N))
92+ _ubounds (axs:: NTuple{N,Any} , itp, gt) where N = ntuple (d-> ubound (axs[d], iextract (itp,d), iextract (gt,d)), Val (N))
93+
7194itptype (:: Type{AbstractInterpolation{T,N,IT,GT}} ) where {T,N,IT<: DimSpec{InterpolationType} ,GT<: DimSpec{GridType} } = IT
7295itptype (:: Type{ITP} ) where {ITP<: AbstractInterpolation } = itptype (supertype (ITP))
73- itptype (itp:: AbstractInterpolation ) = itptype (typeof (itp))
96+ itptype (itp:: AbstractInterpolation ) = itptype (typeof (itp))
97+ itpflag (itp:: AbstractInterpolation ) = itp. it
7498gridtype (:: Type{AbstractInterpolation{T,N,IT,GT}} ) where {T,N,IT<: DimSpec{InterpolationType} ,GT<: DimSpec{GridType} } = GT
7599gridtype (:: Type{ITP} ) where {ITP<: AbstractInterpolation } = gridtype (supertype (ITP))
76100gridtype (itp:: AbstractInterpolation ) = gridtype (typeof (itp))
101+ gridflag (itp:: AbstractInterpolation ) = itp. gt
77102ndims (:: Type{AbstractInterpolation{T,N,IT,GT}} ) where {T,N,IT<: DimSpec{InterpolationType} ,GT<: DimSpec{GridType} } = N
78103ndims (:: Type{ITP} ) where {ITP<: AbstractInterpolation } = ndims (supertype (ITP))
79104ndims (itp:: AbstractInterpolation ) = ndims (typeof (itp))
80105eltype (:: Type{AbstractInterpolation{T,N,IT,GT}} ) where {T,N,IT<: DimSpec{InterpolationType} ,GT<: DimSpec{GridType} } = T
81106eltype (:: Type{ITP} ) where {ITP<: AbstractInterpolation } = eltype (supertype (ITP))
82107eltype (itp:: AbstractInterpolation ) = eltype (typeof (itp))
83- count_interp_dims (:: Type{T} , N) where {T<: AbstractInterpolation } = N
84108
85- # Generic indexing methods (fixes #183)
86- Base. to_index (:: AbstractInterpolation , i:: Real ) = i
109+ """
110+ n = count_interp_dims(ITP)
111+
112+ Count the number of dimensions along which type `ITP` is interpolating.
113+ `NoInterp` dimensions do not contribute to the sum.
114+ """
115+ count_interp_dims (:: Type{ITP} ) where {ITP<: AbstractInterpolation } = count_interp_dims (itptype (ITP), ndims (ITP))
116+ count_interp_dims (:: Type{IT} , n) where {IT<: InterpolationType } = n * count_interp_dims (IT)
117+ count_interp_dims (it:: Type{IT} , n) where IT<: Tuple{Vararg{InterpolationType,N}} where N =
118+ _count_interp_dims (0 , it... )
119+ @inline _count_interp_dims (c, :: IT1 , args... ) where IT1 =
120+ _count_interp_dims (c + count_interp_dims (IT1), args... )
121+ _count_interp_dims (c) = c
122+
123+ """
124+ w = value_weights(degree, δx)
125+
126+ Compute the weights for interpolation of the value at an offset `δx` from the "base" position.
127+ `degree` describes the interpolation scheme.
128+
129+ # Example
130+
131+ ```jldoctest
132+ julia> Interpolations.value_weights(Linear(), 0.2)
133+ (0.8, 0.2)
134+ ```
135+
136+ This corresponds to the fact that linear interpolation at `x + 0.2` is `0.8*y[x] + 0.2*y[x+1]`.
137+ """
138+ function value_weights end
139+
140+ """
141+ w = gradient_weights(degree, δx)
142+
143+ Compute the weights for interpolation of the gradient at an offset `δx` from the "base" position.
144+ `degree` describes the interpolation scheme.
145+
146+ # Example
147+
148+ ```jldoctest
149+ julia> Interpolations.gradient_weights(Linear(), 0.2)
150+ (-1.0, 1.0)
151+ ```
152+
153+ This defines the gradient of a linear interpolation at 3.2 as `y[4] - y[3]`.
154+ """
155+ function gradient_weights end
156+
157+ """
158+ w = hessian_weights(degree, δx)
159+
160+ Compute the weights for interpolation of the hessian at an offset `δx` from the "base" position.
161+ `degree` describes the interpolation scheme.
87162
88- @inline function Base. _getindex (:: IndexCartesian , A:: AbstractInterpolation{T,N} , I:: Vararg{Int,N} ) where {T,N} # ambiguity resolution
89- @inbounds r = getindex (A, I... )
90- r
163+ # Example
164+
165+ ```jldoctest
166+ julia> Interpolations.hessian_weights(Linear(), 0.2)
167+ (0.0, 0.0)
168+ ```
169+
170+ Linear interpolation uses straight line segments, so the second derivative is zero.
171+ """
172+ function hessian_weights end
173+
174+
175+ gradient1 (itp:: AbstractInterpolation{T,1} , x) where {T} = gradient (itp, x)[1 ]
176+ hessian1 (itp:: AbstractInterpolation{T,1} , x) where {T} = hessian (itp, x)[1 ]
177+
178+ # ## Supporting expansion of CartesianIndex
179+
180+ const UnexpandedIndexTypes = Union{Number, AbstractVector, CartesianIndex}
181+ const ExpandedIndexTypes = Union{Number, AbstractVector}
182+
183+ Base. to_index (:: AbstractInterpolation , x:: Number ) = x
184+
185+ # Commented out because you can't add methods to an abstract type.
186+ # @inline function (itp::AbstractInterpolation)(x::Vararg{UnexpandedIndexTypes})
187+ # itp(to_indices(itp, x))
188+ # end
189+ function gradient (itp:: AbstractInterpolation , x:: Vararg{UnexpandedIndexTypes} )
190+ gradient (itp, to_indices (itp, x))
91191end
92- @inline function Base. _getindex (:: IndexCartesian , A:: AbstractInterpolation{T,N} , I:: Vararg{Real,N} ) where {T,N}
93- @inbounds r = getindex (A, I... )
94- r
192+ function gradient! (dest, itp:: AbstractInterpolation , x:: Vararg{UnexpandedIndexTypes} )
193+ gradient! (dest, itp, to_indices (itp, x))
95194end
195+ function hessian (itp:: AbstractInterpolation , x:: Vararg{UnexpandedIndexTypes} )
196+ hessian (itp, to_indices (itp, x))
197+ end
198+ function hessian! (dest, itp:: AbstractInterpolation , x:: Vararg{UnexpandedIndexTypes} )
199+ hessian! (dest, itp, to_indices (itp, x))
200+ end
201+
202+ # @inline function (itp::AbstractInterpolation)(x::Vararg{ExpandedIndexTypes})
203+ # itp.(Iterators.product(x...))
204+ # end
205+ function gradient (itp:: AbstractInterpolation , x:: Vararg{ExpandedIndexTypes} )
206+ map (y-> gradient (itp, y), Iterators. product (x... ))
207+ end
208+ function hessian (itp:: AbstractInterpolation , x:: Vararg{ExpandedIndexTypes} )
209+ map (y-> hessian (itp, y), Iterators. product (x... ))
210+ end
211+
212+ # getindex is supported only for Integer indices (deliberately)
213+ import Base: getindex
214+ @propagate_inbounds getindex (itp:: AbstractInterpolation{T,N} , i:: Vararg{Integer,N} ) where {T,N} = itp (i... )
215+ @propagate_inbounds function getindex (itp:: AbstractInterpolation{T,1} , i:: Integer , j:: Integer ) where T
216+ @boundscheck (j == 1 || Base. throw_boundserror (itp, (i, j)))
217+ itp (i)
218+ end
219+
220+ # deprecate getindex for other numeric indices
221+ @deprecate getindex (itp:: AbstractInterpolation{T,N} , i:: Vararg{Number,N} ) where {T,N} itp (i... )
96222
97223include (" nointerp/nointerp.jl" )
98224include (" b-splines/b-splines.jl" )
99- include (" gridded/gridded.jl" )
100- include (" extrapolation/extrapolation.jl" )
101- include (" scaling/scaling.jl" )
225+ # include("gridded/gridded.jl")
226+ # include("extrapolation/extrapolation.jl")
227+ # include("scaling/scaling.jl")
102228include (" utils.jl" )
103229include (" io.jl" )
104230include (" convenience-constructors.jl" )
0 commit comments