-
Notifications
You must be signed in to change notification settings - Fork 105
/
linear.jl
58 lines (43 loc) · 1.84 KB
/
linear.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
struct Linear{BC<:Union{Throw{OnGrid},Periodic{OnCell}}} <: DegreeBC{1}
bc::BC
function Linear{BC}(bc::BC=BC()) where BC<:Union{Throw{OnGrid},Periodic{OnCell}}
new{BC}(bc)
end
end
Linear() = Linear(Throw(OnGrid()))
Linear(::Periodic{Nothing}) = Linear(Periodic(OnCell()))
Linear(bc::BC) where BC<:Union{Throw{OnGrid},Periodic{OnCell}} = Linear{BC}(bc)
function Base.show(io::IO, deg::Linear{Throw{OnGrid}})
print(io, nameof(typeof(deg)), '(', ')')
end
"""
Linear()
Indicate that the corresponding axis should use linear interpolation.
# Extended help
Assuming uniform knots with spacing 1, the `i`th piece of linear b-spline
implemented here is defined as follows.
y_i(x) = c p(x) + cp p(1-x)
where
p(δx) = x
and the values `cX` for `X ∈ {_, p}` are the coefficients.
Linear b-splines are naturally interpolating, and require no prefiltering;
there is therefore no need for boundary conditions to be provided.
Also, although the implementation is slightly different in order to re-use
the framework built for general b-splines, the resulting interpolant is just
a piecewise linear function connecting each pair of neighboring data points.
"""
Linear
function positions(deg::Linear, ax::AbstractUnitRange{<:Integer}, x)
f = floor(x)
# When x == last(ax) we want to use the x-1, x pair
f = ifelse(x == last(ax), f - oneunit(f), f)
fi = fast_trunc(Int, f)
expand_index(deg, fi, ax), x-f
end
expand_index(::Linear{Throw{OnGrid}}, fi::Number, ax::AbstractUnitRange) = fi
expand_index(::Linear{Periodic{OnCell}}, fi::Number, ax::AbstractUnitRange) =
(modrange(fi, ax), modrange(fi+1, ax))
value_weights(::Linear, δx) = (1-δx, δx)
gradient_weights(::Linear, δx) = (-oneunit(δx), oneunit(δx))
hessian_weights(::Linear, δx) = (zero(δx), zero(δx))
padded_axis(ax::AbstractUnitRange, ::BSpline{<:Linear}) = ax