@@ -70,7 +70,7 @@ function quadratic_spline_params(t::AbstractVector, sc::AbstractVector)
7070
7171 # Create linear system Ac = u, where:
7272 # - A consists of basis function evaulations in t
73- # - c are 1D control points
73+ # - c are 1D control points
7474 n = length (t)
7575 dtype_sc = typeof (t[1 ] / t[1 ])
7676
@@ -235,6 +235,19 @@ function du_PCHIP(u, t)
235235 δ = diff (u) ./ h
236236 s = sign .(δ)
237237
238+ # Special handling of the slope at the endpoints, see
239+ # Cleve Moler, Numerical Computing with MATLAB, Chap 3.6 (file pchiptx.m, function pchipend())
240+ function _edge_case (h₁, h₂, δ₁, δ₂)
241+ d = ((2 * h₁ + h₂) * δ₁ - h₁ * δ₂) / (h₁ + h₂)
242+ if sign (d) != sign (δ₁)
243+ zero (eltype (δ))
244+ elseif sign (δ₁) != sign (δ₂) && abs (d) > 3 * abs (δ₁)
245+ 3 * δ₁
246+ else
247+ d
248+ end
249+ end
250+
238251 function _du (k)
239252 sₖ₋₁, sₖ = if k == 1
240253 s[1 ], s[2 ]
@@ -248,17 +261,22 @@ function du_PCHIP(u, t)
248261 zero (eltype (δ))
249262 elseif sₖ₋₁ == sₖ
250263 if k == 1
251- (( 2 * h[1 ] + h[2 ]) * δ[1 ] - h[ 1 ] * δ[ 2 ]) / (h[ 1 ] + h [2 ])
264+ _edge_case ( h[1 ], h[2 ], δ[1 ], δ [2 ])
252265 elseif k == lastindex (t)
253- ((2 * h[end ] + h[end - 1 ]) * δ[end ] - h[end ] * δ[end - 1 ]) /
254- (h[end ] + h[end - 1 ])
266+ _edge_case (h[end ], h[end - 1 ], δ[end ], δ[end - 1 ])
255267 else
256268 w₁ = 2 h[k] + h[k - 1 ]
257269 w₂ = h[k] + 2 h[k - 1 ]
258270 (w₁ + w₂) / (w₁ / δ[k - 1 ] + w₂ / δ[k])
259271 end
260272 else
261- zero (eltype (δ))
273+ if k == 1
274+ _edge_case (h[1 ], h[2 ], δ[1 ], δ[2 ])
275+ elseif k == lastindex (t)
276+ _edge_case (h[end ], h[end - 1 ], δ[end ], δ[end - 1 ])
277+ else
278+ zero (eltype (δ))
279+ end
262280 end
263281 end
264282
0 commit comments