Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a fast path for evenly-spaced abscissae #198

Merged
merged 14 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ DataInterpolationsSymbolicsExt = "Symbolics"

[compat]
Aqua = "0.8"
BenchmarkTools = "1"
ChainRulesCore = "1.24"
FindFirstFunctions = "1.1"
FiniteDifferences = "0.12.31"
Expand All @@ -45,6 +46,7 @@ julia = "1.10"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Expand All @@ -58,4 +60,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"

[targets]
test = ["Aqua", "SafeTestsets", "ChainRulesCore", "Optim", "RegularizationTools", "Test", "StableRNGs", "FiniteDifferences", "QuadGK", "ForwardDiff", "Symbolics", "Zygote"]
test = ["Aqua", "BenchmarkTools", "SafeTestsets", "ChainRulesCore", "Optim", "RegularizationTools", "Test", "StableRNGs", "FiniteDifferences", "QuadGK", "ForwardDiff", "Symbolics", "Zygote"]
6 changes: 6 additions & 0 deletions docs/src/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ CubicHermiteSpline
PCHIPInterpolation
QuinticHermiteSpline
```

# Utility Functions

```@docs
DataInterpolations.looks_linear
```
2 changes: 1 addition & 1 deletion ext/DataInterpolationsChainRulesCoreExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ end

function u_tangent(A::LinearInterpolation, t, Δ)
out = zero(A.u)
idx = get_idx(A.t, t, A.idx_prev[])
idx = get_idx(A, t, A.idx_prev[])
t_factor = (t - A.t[idx]) / (A.t[idx + 1] - A.t[idx])
out[idx] = Δ * (one(eltype(out)) - t_factor)
out[idx + 1] = Δ * t_factor
Expand Down
16 changes: 8 additions & 8 deletions src/derivatives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function derivative(A, t, order = 1)
end

function _derivative(A::LinearInterpolation, t::Number, iguess)
idx = get_idx(A.t, t, iguess; idx_shift = -1, ub_shift = -1, side = :first)
idx = get_idx(A, t, iguess; idx_shift = -1, ub_shift = -1, side = :first)
slope = get_parameters(A, idx)
slope, idx
end
Expand Down Expand Up @@ -108,7 +108,7 @@ function _derivative(A::LagrangeInterpolation{<:AbstractMatrix}, t::Number, idx)
end

function _derivative(A::AkimaInterpolation{<:AbstractVector}, t::Number, iguess)
idx = get_idx(A.t, t, iguess; idx_shift = -1, side = :first)
idx = get_idx(A, t, iguess; idx_shift = -1, side = :first)
j = min(idx, length(A.c)) # for smooth derivative at A.t[end]
wj = t - A.t[idx]
(@evalpoly wj A.b[idx] 2A.c[j] 3A.d[j]), idx
Expand All @@ -130,14 +130,14 @@ end

# QuadraticSpline Interpolation
function _derivative(A::QuadraticSpline{<:AbstractVector}, t::Number, iguess)
idx = get_idx(A.t, t, iguess; lb = 2, ub_shift = 0, side = :first)
idx = get_idx(A, t, iguess; lb = 2, ub_shift = 0, side = :first)
σ = get_parameters(A, idx - 1)
A.z[idx - 1] + 2σ * (t - A.t[idx - 1]), idx
end

# CubicSpline Interpolation
function _derivative(A::CubicSpline{<:AbstractVector}, t::Number, iguess)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
Δt₁ = t - A.t[idx]
Δt₂ = A.t[idx + 1] - t
dI = (-A.z[idx] * Δt₂^2 + A.z[idx + 1] * Δt₁^2) / (2A.h[idx + 1])
Expand All @@ -151,7 +151,7 @@ function _derivative(A::BSplineInterpolation{<:AbstractVector{<:Number}}, t::Num
# change t into param [0 1]
t < A.t[1] && return zero(A.u[1]), 1
t > A.t[end] && return zero(A.u[end]), lastindex(t)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
n = length(A.t)
scale = (A.p[idx + 1] - A.p[idx]) / (A.t[idx + 1] - A.t[idx])
t_ = A.p[idx] + (t - A.t[idx]) * scale
Expand All @@ -173,7 +173,7 @@ function _derivative(A::BSplineApprox{<:AbstractVector{<:Number}}, t::Number, ig
# change t into param [0 1]
t < A.t[1] && return zero(A.u[1]), 1
t > A.t[end] && return zero(A.u[end]), lastindex(t)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
scale = (A.p[idx + 1] - A.p[idx]) / (A.t[idx + 1] - A.t[idx])
t_ = A.p[idx] + (t - A.t[idx]) * scale
N = t isa ForwardDiff.Dual ? zeros(eltype(t), A.h) : A.N
Expand All @@ -192,7 +192,7 @@ end
# Cubic Hermite Spline
function _derivative(
A::CubicHermiteSpline{<:AbstractVector{<:Number}}, t::Number, iguess)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
Δt₀ = t - A.t[idx]
Δt₁ = t - A.t[idx + 1]
out = A.du[idx]
Expand All @@ -204,7 +204,7 @@ end
# Quintic Hermite Spline
function _derivative(
A::QuinticHermiteSpline{<:AbstractVector{<:Number}}, t::Number, iguess)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
Δt₀ = t - A.t[idx]
Δt₁ = t - A.t[idx + 1]
out = A.du[idx] + A.ddu[idx] * Δt₀
Expand Down
8 changes: 4 additions & 4 deletions src/integral_inverses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ end

function _interpolate(
A::LinearInterpolationIntInv{<:AbstractVector{<:Number}}, t::Number, iguess)
idx = get_idx(A.t, t, iguess)
idx = get_idx(A, t, iguess)
Δt = t - A.t[idx]
x = A.itp.u[idx]
slope = get_parameters(A.itp, idx)
Expand Down Expand Up @@ -104,13 +104,13 @@ end

function _interpolate(
A::ConstantInterpolationIntInv{<:AbstractVector{<:Number}}, t::Number, iguess)
idx = get_idx(A.t, t, iguess; ub_shift = 0)
idx = get_idx(A, t, iguess; ub_shift = 0)
if A.itp.dir === :left
# :left means that value to the left is used for interpolation
idx_ = get_idx(A.t, t, idx; lb = 1, ub_shift = 0)
idx_ = get_idx(A, t, idx; lb = 1, ub_shift = 0)
else
# :right means that value to the right is used for interpolation
idx_ = get_idx(A.t, t, idx; side = :first, lb = 1, ub_shift = 0)
idx_ = get_idx(A, t, idx; side = :first, lb = 1, ub_shift = 0)
end
A.u[idx] + (t - A.t[idx]) / A.itp.u[idx_], idx
end
4 changes: 2 additions & 2 deletions src/integrals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ function integral(A::AbstractInterpolation, t1::Number, t2::Number)
((t2 < A.t[1] || t2 > A.t[end]) && !A.extrapolate) && throw(ExtrapolationError())
!hasfield(typeof(A), :I) && throw(IntegralNotFoundError())
# the index less than or equal to t1
idx1 = get_idx(A.t, t1, 0)
idx1 = get_idx(A, t1, 0)
# the index less than t2
idx2 = get_idx(A.t, t2, 0; idx_shift = -1, side = :first)
idx2 = get_idx(A, t2, 0; idx_shift = -1, side = :first)

if A.cache_parameters
total = A.I[idx2] - A.I[idx1]
Expand Down
Loading
Loading