/
SplineExtrapolations.jl
91 lines (71 loc) · 2.28 KB
/
SplineExtrapolations.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
module SplineExtrapolations
export
SplineExtrapolation,
extrapolate,
Flat,
Smooth
using ..BSplines
using ..Splines
"""
AbstractExtrapolationMethod
Abstract type representing an extrapolation method.
"""
abstract type AbstractExtrapolationMethod end
"""
Flat <: AbstractExtrapolationMethod
Represents a flat extrapolation: spline values at domain limits are extended to
the left and to the right.
"""
struct Flat <: AbstractExtrapolationMethod end
function extrapolate_at_point(::Flat, S::Spline, x)
a, b = boundaries(basis(S))
x′ = clamp(x, a, b)
S(x′)
end
"""
Smooth <: AbstractExtrapolationMethod
Represents a smooth extrapolation: derivatives up to order ``k - 2`` are
continuous at the boundaries.
"""
struct Smooth <: AbstractExtrapolationMethod end
function extrapolate_at_point(::Smooth, S::Spline, x)
ts = knots(S)
N = length(S)
k = order(S)
# This is the same as the usual spline evaluation except when zone ≠ 0.
n, zone = Splines.find_knot_interval(ts, x)
i = clamp(n, k, N + k)
Splines.evaluate(S, x, i)
end
"""
SplineExtrapolation
Represents a spline which can be evaluated outside of its limits according to a
given extrapolation method.
"""
struct SplineExtrapolation{
S <: Spline,
M <: AbstractExtrapolationMethod,
} <: SplineWrapper{S}
spline :: S
method :: M
SplineExtrapolation(sp::Spline, method::AbstractExtrapolationMethod) =
new{typeof(sp), typeof(method)}(sp, method)
end
method(f::SplineExtrapolation) = f.method
SplineExtrapolation(S::SplineWrapper, args...) = SplineExtrapolation(spline(S), args...)
function Base.show(io::IO, f::SplineExtrapolation)
println(io, nameof(typeof(f)), " containing the ", spline(f))
let io = IOContext(io, :compact => true, :limit => true)
print(io, " extrapolation method: ", method(f))
end
nothing
end
(f::SplineExtrapolation)(x) = extrapolate_at_point(method(f), spline(f), x)
"""
extrapolate(S::Union{Spline, SplineWrapper}, method::AbstractExtrapolationMethod)
Construct a [`SplineExtrapolation`](@ref) from the given spline `S` (which can
also be the result of an interpolation).
"""
extrapolate(sp::Union{Spline, SplineWrapper}, method::AbstractExtrapolationMethod) =
SplineExtrapolation(sp, method)
end