Skip to content

Commit 67049ef

Browse files
authored
Merge pull request #241 from JuliaMath/teh/fix_230
Generalize signatures of convenience constructors
2 parents 25d42a2 + 65db5f3 commit 67049ef

File tree

3 files changed

+117
-79
lines changed

3 files changed

+117
-79
lines changed

README.md

Lines changed: 74 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,22 @@ v = itp(x, y, ...)
5858
Some interpolation objects support computation of the gradient, which
5959
can be obtained as
6060
```julia
61-
g = gradient(itp, x, y, ...)
61+
g = Interpolations.gradient(itp, x, y, ...)
6262
```
63-
or, if you're evaluating the gradient repeatedly, a somewhat more
64-
efficient option is
63+
or as
6564
```julia
66-
gradient!(g, itp, x, y, ...)
65+
Interpolations.gradient!(g, itp, x, y, ...)
6766
```
6867
where `g` is a pre-allocated vector.
6968

7069
Some interpolation objects support computation of the hessian, which
7170
can be obtained as
7271
```julia
73-
h = hessian(itp, x, y, ...)
72+
h = Interpolations.hessian(itp, x, y, ...)
7473
```
75-
or, if you're evaluating the hessian repeatedly, a somewhat more
76-
efficient option is
74+
or
7775
```julia
78-
hessian!(h, itp, x, y, ...)
76+
Interpolations.hessian!(h, itp, x, y, ...)
7977
```
8078
where `h` is a pre-allocated matrix.
8179

@@ -104,71 +102,7 @@ Finally, courtesy of Julia's indexing rules, you can also use
104102
fine = itp(range(1,stop=10,length=1001), range(1,stop=15,length=201))
105103
```
106104

107-
### Quickstart guide
108-
109-
For linear and cubic spline interpolations, `LinearInterpolation` and `CubicSplineInterpolation` can be used to create interpolation objects handily:
110-
```julia
111-
f(x) = log(x)
112-
xs = 1:0.2:5
113-
A = [f(x) for x in xs]
114-
115-
# linear interpolation
116-
interp_linear = LinearInterpolation(xs, A)
117-
interp_linear(3) # exactly log(3)
118-
interp_linear(3.1) # approximately log(3.1)
119-
120-
# cubic spline interpolation
121-
interp_cubic = CubicSplineInterpolation(xs, A)
122-
interp_cubic(3) # exactly log(3)
123-
interp_cubic(3.1) # approximately log(3.1)
124-
```
125-
which support multidimensional data as well:
126-
```julia
127-
f(x,y) = log(x+y)
128-
xs = 1:0.2:5
129-
ys = 2:0.1:5
130-
A = [f(x+y) for x in xs, y in ys]
131-
132-
# linear interpolation
133-
interp_linear = LinearInterpolation((xs, ys), A)
134-
interp_linear(3, 2) # exactly log(3 + 2)
135-
interp_linear(3.1, 2.1) # approximately log(3.1 + 2.1)
136-
137-
# cubic spline interpolation
138-
interp_cubic = CubicSplineInterpolation((xs, ys), A)
139-
interp_cubic(3, 2) # exactly log(3 + 2)
140-
interp_cubic(3.1, 2.1) # approximately log(3.1 + 2.1)
141-
```
142-
For extrapolation, i.e., when interpolation objects are evaluated in coordinates outside of range provided in constructors, the default option for a boundary condition is `Throw` so that they will return an error.
143-
Interested users can specify boundary conditions by providing an extra parameter for `extrapolation_bc`:
144-
```julia
145-
f(x) = log(x)
146-
xs = 1:0.2:5
147-
A = [f(x) for x in xs]
148-
149-
# extrapolation with linear boundary conditions
150-
extrap = LinearInterpolation(xs, A, extrapolation_bc = Line())
151-
152-
@test extrap(1 - 0.2) # ≈ f(1) - (f(1.2) - f(1))
153-
@test extrap(5 + 0.2) # ≈ f(5) + (f(5) - f(4.8))
154-
```
155-
You can also use a "fill" value, which gets returned whenever you ask for out-of-range values:
156-
157-
```julia
158-
extrap = LinearInterpolation(xs, A, extrapolation_bc = NaN)
159-
@test isnan(extrap(5.2))
160-
```
161-
162-
Irregular grids are supported as well; note that presently only `LinearInterpolation` supports irregular grids.
163-
```julia
164-
xs = [x^2 for x = 1:0.2:5]
165-
A = [f(x) for x in xs]
166-
167-
# linear interpolation
168-
interp_linear = LinearInterpolation(xs, A)
169-
interp_linear(1) # exactly log(1)
170-
interp_linear(1.05) # approximately log(1.05)
171-
```
105+
There is also an abbreviated notion [described below](#convenience-notation).
172106

173107
## Control of interpolation algorithm
174108

@@ -323,6 +257,73 @@ etpf = extrapolate(itp, Flat()) # gives 1 on the left edge and 7 on the right
323257
etp0 = extrapolate(itp, 0) # gives 0 everywhere outside [1,7]
324258
```
325259

260+
## Convenience notation
261+
262+
For linear and cubic spline interpolations, `LinearInterpolation` and `CubicSplineInterpolation`
263+
can be used to create interpolating and extrapolating objects handily:
264+
```julia
265+
f(x) = log(x)
266+
xs = 1:0.2:5
267+
A = [f(x) for x in xs]
268+
269+
# linear interpolation
270+
interp_linear = LinearInterpolation(xs, A)
271+
interp_linear(3) # exactly log(3)
272+
interp_linear(3.1) # approximately log(3.1)
273+
274+
# cubic spline interpolation
275+
interp_cubic = CubicSplineInterpolation(xs, A)
276+
interp_cubic(3) # exactly log(3)
277+
interp_cubic(3.1) # approximately log(3.1)
278+
```
279+
which support multidimensional data as well:
280+
```julia
281+
f(x,y) = log(x+y)
282+
xs = 1:0.2:5
283+
ys = 2:0.1:5
284+
A = [f(x,y) for x in xs, y in ys]
285+
286+
# linear interpolation
287+
interp_linear = LinearInterpolation((xs, ys), A)
288+
interp_linear(3, 2) # exactly log(3 + 2)
289+
interp_linear(3.1, 2.1) # approximately log(3.1 + 2.1)
290+
291+
# cubic spline interpolation
292+
interp_cubic = CubicSplineInterpolation((xs, ys), A)
293+
interp_cubic(3, 2) # exactly log(3 + 2)
294+
interp_cubic(3.1, 2.1) # approximately log(3.1 + 2.1)
295+
```
296+
For extrapolation, i.e., when interpolation objects are evaluated in coordinates outside the range provided in constructors, the default option for a boundary condition is `Throw` so that they will return an error.
297+
Interested users can specify boundary conditions by providing an extra parameter for `extrapolation_bc`:
298+
```julia
299+
f(x) = log(x)
300+
xs = 1:0.2:5
301+
A = [f(x) for x in xs]
302+
303+
# extrapolation with linear boundary conditions
304+
extrap = LinearInterpolation(xs, A, extrapolation_bc = Line())
305+
306+
@test extrap(1 - 0.2) # ≈ f(1) - (f(1.2) - f(1))
307+
@test extrap(5 + 0.2) # ≈ f(5) + (f(5) - f(4.8))
308+
```
309+
You can also use a "fill" value, which gets returned whenever you ask for out-of-range values:
310+
311+
```julia
312+
extrap = LinearInterpolation(xs, A, extrapolation_bc = NaN)
313+
@test isnan(extrap(5.2))
314+
```
315+
316+
Irregular grids are supported as well; note that presently only `LinearInterpolation` supports irregular grids.
317+
```julia
318+
xs = [x^2 for x = 1:0.2:5]
319+
A = [f(x) for x in xs]
320+
321+
# linear interpolation
322+
interp_linear = LinearInterpolation(xs, A)
323+
interp_linear(1) # exactly log(1)
324+
interp_linear(1.05) # approximately log(1.05)
325+
```
326+
326327
## Performance shootout
327328

328329
In the `perf` directory, you can find a script that tests

src/convenience-constructors.jl

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
# convenience copnstructors for linear / cubic spline interpolations
22
# 1D version
3-
LinearInterpolation(range::T, vs; extrapolation_bc = Throw()) where {T <: AbstractRange} = extrapolate(scale(interpolate(vs, BSpline(Linear())), range), extrapolation_bc)
4-
LinearInterpolation(range::T, vs; extrapolation_bc = Throw()) where {T <: AbstractArray} = extrapolate(interpolate((range, ), vs, Gridded(Linear())), extrapolation_bc)
5-
CubicSplineInterpolation(range::T, vs; bc = Line(OnGrid()), extrapolation_bc = Throw()) where {T <: AbstractRange} = extrapolate(scale(interpolate(vs, BSpline(Cubic(bc))), range), extrapolation_bc)
3+
LinearInterpolation(range::AbstractRange, vs::AbstractVector; extrapolation_bc = Throw()) =
4+
extrapolate(scale(interpolate(vs, BSpline(Linear())), range), extrapolation_bc)
5+
LinearInterpolation(range::AbstractVector, vs::AbstractVector; extrapolation_bc = Throw()) =
6+
extrapolate(interpolate((range, ), vs, Gridded(Linear())), extrapolation_bc)
7+
CubicSplineInterpolation(range::AbstractRange, vs::AbstractVector;
8+
bc = Line(OnGrid()), extrapolation_bc = Throw()) =
9+
extrapolate(scale(interpolate(vs, BSpline(Cubic(bc))), range), extrapolation_bc)
610

711
# multivariate versions
8-
LinearInterpolation(ranges::NTuple{N,T}, vs; extrapolation_bc = Throw()) where {N,T <: AbstractRange} = extrapolate(scale(interpolate(vs, BSpline(Linear())), ranges...), extrapolation_bc)
9-
LinearInterpolation(ranges::NTuple{N,T}, vs; extrapolation_bc = Throw()) where {N,T <: AbstractArray} = extrapolate(interpolate(ranges, vs, Gridded(Linear())), extrapolation_bc)
10-
CubicSplineInterpolation(ranges::NTuple{N,T}, vs; bc = Line(OnGrid()), extrapolation_bc = Throw()) where {N,T <: AbstractRange} = extrapolate(scale(interpolate(vs, BSpline(Cubic(bc))), ranges...), extrapolation_bc)
12+
LinearInterpolation(ranges::NTuple{N,AbstractRange}, vs::AbstractArray{T,N};
13+
extrapolation_bc = Throw()) where {N,T} =
14+
extrapolate(scale(interpolate(vs, BSpline(Linear())), ranges...), extrapolation_bc)
15+
LinearInterpolation(ranges::NTuple{N,AbstractVector}, vs::AbstractArray{T,N};
16+
extrapolation_bc = Throw()) where {N,T} =
17+
extrapolate(interpolate(ranges, vs, Gridded(Linear())), extrapolation_bc)
18+
CubicSplineInterpolation(ranges::NTuple{N,AbstractRange}, vs::AbstractArray{T,N};
19+
bc = Line(OnGrid()), extrapolation_bc = Throw()) where {N,T} =
20+
extrapolate(scale(interpolate(vs, BSpline(Cubic(bc))), ranges...), extrapolation_bc)
21+
22+
"""
23+
etp = LinearInterpolation(knots, A; extrapolation_bc=Throw())
24+
25+
A shorthand for `extrapolate(interpolate(knots, A, scheme), extrapolation_bc)`,
26+
where `scheme` is either `BSpline(Linear())` or `Gridded(Linear())` depending on whether
27+
`knots` are ranges or vectors.
28+
"""
29+
LinearInterpolation
30+
31+
"""
32+
etp = CubicSplineInterpolation(knots, A; bc=Line(OnGrid()), extrapolation_bc=Throw())
33+
34+
A shorthand for `extrapolate(interpolate(knots, A, BSpline(Cubic(bc))), extrapolation_bc)`.
35+
"""
36+
CubicSplineInterpolation

test/convenience-constructors.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ end
178178
@test extrap(x_lower, y_lower) A[1, 1] - ΔA_l
179179
@test extrap(x_higher, y_higher) A[end, end] + ΔA_h
180180
end
181+
182+
@testset "issue #230" begin # at least, I think this is what issue #230 is really about
183+
f(x,y) = log(x+y)
184+
xs = 1:5
185+
ys = 2:0.1:5
186+
A = [f(x,y) for x in xs, y in ys]
187+
itp = LinearInterpolation((xs, ys), A)
188+
for (i, j) in zip(Iterators.product(xs, ys), eachindex(A))
189+
@test itp(i...) A[j]
190+
end
191+
end
181192
end
182193

183194
end

0 commit comments

Comments
 (0)