@@ -107,15 +107,15 @@ end
107
107
Monotonic interpolation up to third order represented by type, knots and
108
108
coefficients.
109
109
"""
110
- struct MonotonicInterpolation{T, TCoeffs , TEl, TInterpolationType<: MonotonicInterpolationType ,
110
+ struct MonotonicInterpolation{T, TCoeffs1, TCoeffs2, TCoeffs3 , TEl, TInterpolationType<: MonotonicInterpolationType ,
111
111
TKnots<: AbstractVector{<:Number} , TACoeff <: AbstractArray{TEl,1} } <: AbstractInterpolation{T,1,DimSpec{TInterpolationType}}
112
112
113
113
it:: TInterpolationType
114
114
knots:: TKnots
115
115
A:: TACoeff # constant parts of piecewise polynomials
116
- m:: Vector{TCoeffs } # coefficients of linear parts of piecewise polynomials
117
- c:: Vector{TCoeffs } # coefficients of quadratic parts of piecewise polynomials
118
- d:: Vector{TCoeffs } # coefficients of cubic parts of piecewise polynomials
116
+ m:: Vector{TCoeffs1 } # coefficients of linear parts of piecewise polynomials
117
+ c:: Vector{TCoeffs2 } # coefficients of quadratic parts of piecewise polynomials
118
+ d:: Vector{TCoeffs3 } # coefficients of cubic parts of piecewise polynomials
119
119
end
120
120
121
121
function Base.:(== )(o1:: MonotonicInterpolation , o2:: MonotonicInterpolation )
@@ -134,10 +134,10 @@ itpflag(A::MonotonicInterpolation) = A.it
134
134
coefficients (A:: MonotonicInterpolation ) = A. A
135
135
136
136
function MonotonicInterpolation (:: Type{TWeights} , it:: TInterpolationType , knots:: TKnots , A:: AbstractArray{TEl,1} ,
137
- m:: Vector{TCoeffs } , c:: Vector{TCoeffs } , d:: Vector{TCoeffs } ) where {TWeights, TCoeffs , TEl, TInterpolationType<: MonotonicInterpolationType , TKnots<: AbstractVector{<:Number} }
137
+ m:: Vector{TCoeffs1 } , c:: Vector{TCoeffs2 } , d:: Vector{TCoeffs3 } ) where {TWeights, TCoeffs1, TCoeffs2, TCoeffs3 , TEl, TInterpolationType<: MonotonicInterpolationType , TKnots<: AbstractVector{<:Number} }
138
138
139
139
isconcretetype (TInterpolationType) || error (" The spline type must be a leaf type (was $TInterpolationType )" )
140
- isconcretetype (TCoeffs ) || warn (" For performance reasons, consider using an array of a concrete type (eltype(A) == $(eltype (A)) )" )
140
+ isconcretetype (tcoef (A) ) || warn (" For performance reasons, consider using an array of a concrete type (eltype(A) == $(eltype (A)) )" )
141
141
142
142
check_monotonic (knots, A)
143
143
@@ -148,22 +148,23 @@ function MonotonicInterpolation(::Type{TWeights}, it::TInterpolationType, knots:
148
148
T = typeof (cZero * first (A))
149
149
end
150
150
151
- MonotonicInterpolation {T, TCoeffs , TEl, TInterpolationType, TKnots, typeof(A)} (it, knots, A, m, c, d)
151
+ MonotonicInterpolation {T, TCoeffs1, TCoeffs2, TCoeffs3 , TEl, TInterpolationType, TKnots, typeof(A)} (it, knots, A, m, c, d)
152
152
end
153
153
154
- function interpolate (:: Type{TWeights} , :: Type{TCoeffs } , knots:: TKnots ,
155
- A:: AbstractArray{TEl,1} , it:: TInterpolationType ) where {TWeights,TCoeffs ,TEl,TKnots<: AbstractVector{<:Number} ,TInterpolationType<: MonotonicInterpolationType }
154
+ function interpolate (:: Type{TWeights} , :: Type{TCoeffs1} , :: Type{TCoeffs2} , :: Type{TCoeffs3 } , knots:: TKnots ,
155
+ A:: AbstractArray{TEl,1} , it:: TInterpolationType ) where {TWeights,TCoeffs1,TCoeffs2,TCoeffs3 ,TEl,TKnots<: AbstractVector{<:Number} ,TInterpolationType<: MonotonicInterpolationType }
156
156
157
157
check_monotonic (knots, A)
158
158
159
159
# first we need to determine tangents (m)
160
160
n = length (knots)
161
- m, Δ = calcTangents (TCoeffs , knots, A, it)
162
- c = Vector {TCoeffs } (undef, n- 1 )
163
- d = Vector {TCoeffs } (undef, n- 1 )
161
+ m, Δ = calcTangents (TCoeffs1 , knots, A, it)
162
+ c = Vector {TCoeffs2 } (undef, n- 1 )
163
+ d = Vector {TCoeffs3 } (undef, n- 1 )
164
164
for k ∈ 1 : n- 1
165
165
if TInterpolationType == LinearMonotonicInterpolation
166
- c[k] = d[k] = zero (TCoeffs)
166
+ c[k] = zero (TCoeffs2)
167
+ d[k] = zero (TCoeffs3)
167
168
else
168
169
xdiff = knots[k+ 1 ] - knots[k]
169
170
c[k] = (3 * Δ[k] - 2 * m[k] - m[k+ 1 ]) / xdiff
177
178
function interpolate (knots:: AbstractVector{<:Number} , A:: AbstractArray{TEl,1} ,
178
179
it:: TInterpolationType ) where {TEl,TInterpolationType<: MonotonicInterpolationType }
179
180
180
- interpolate (tweight (A), tcoef (A), knots, A, it)
181
+ interpolate (tweight (A),typeof (oneunit (eltype (A)) / oneunit (eltype (knots))),
182
+ typeof (oneunit (eltype (A)) / oneunit (eltype (knots))^ 2 ),
183
+ typeof (oneunit (eltype (A)) / oneunit (eltype (knots))^ 3 ),knots,A,it)
181
184
end
182
185
183
186
function (itp:: MonotonicInterpolation )(x:: Number )
@@ -282,6 +285,7 @@ function calcTangents(::Type{TCoeffs}, x::AbstractVector{<:Number},
282
285
n = length (x)
283
286
Δ = Vector {TCoeffs} (undef, n- 1 )
284
287
m = Vector {TCoeffs} (undef, n)
288
+ buff = Vector {typeof(first(Δ)^2)} (undef, n)
285
289
for k in 1 : n- 1
286
290
Δk = (y[k+ 1 ] - y[k]) / (x[k+ 1 ] - x[k])
287
291
Δ[k] = Δk
@@ -290,10 +294,10 @@ function calcTangents(::Type{TCoeffs}, x::AbstractVector{<:Number},
290
294
else
291
295
# If any consecutive secant lines change sign (i.e. curve changes direction), initialize the tangent to zero.
292
296
# This is needed to make the interpolation monotonic. Otherwise set tangent to the average of the secants.
293
- if Δk <= zero (Δk)
297
+ if Δ[k - 1 ] * Δk <= zero (Δk^ 2 )
294
298
m[k] = zero (TCoeffs)
295
299
else
296
- m[k] = Δ[k - 1 ] * (Δ[k- 1 ] + Δk) / 2.0
300
+ m[k] = (Δ[k- 1 ] + Δk) / 2.0
297
301
end
298
302
end
299
303
end
@@ -317,8 +321,8 @@ function calcTangents(::Type{TCoeffs}, x::AbstractVector{<:Number},
317
321
end
318
322
α = m[k] / Δk
319
323
β = m[k+ 1 ] / Δk
320
- τ = 3.0 / sqrt (α^ 2 + β^ 2 )
321
- if τ < 1.0 # if we're outside the circle with radius 3 then move onto the circle
324
+ τ = 3.0 * oneunit (α) / sqrt (α^ 2 + β^ 2 )
325
+ if τ < 1.0 # if we're outside the circle with radius 3 then move onto the circle
322
326
m[k] = τ * α * Δk
323
327
m[k+ 1 ] = τ * β * Δk
324
328
end
@@ -341,7 +345,7 @@ function calcTangents(::Type{TCoeffs}, x::AbstractVector{<:Number},
341
345
Δ[k] = Δk
342
346
if k == 1 # left endpoint
343
347
m[k] = Δk
344
- elseif Δ[k- 1 ] * Δk <= zero (TCoeffs )
348
+ elseif Δ[k- 1 ] * Δk <= zero (Δk ^ 2 )
345
349
m[k] = zero (TCoeffs)
346
350
else
347
351
α = (1.0 + (x[k+ 1 ] - x[k]) / (x[k+ 1 ] - x[k- 1 ])) / 3.0
0 commit comments