Skip to content
Closed
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
1 change: 1 addition & 0 deletions docs/src/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ QuinticHermiteSpline
```@docs
DataInterpolations.looks_linear
DataInterpolations.output_dim
DataInterpolations.output_size
```
15 changes: 12 additions & 3 deletions src/DataInterpolations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,29 @@ end
"""
output_dim(x::AbstractInterpolation)

Return the number of dimension `ndims(x(t))` of interpolation `x` evaluated at a single value `t`
if `x(t) isa AbstractArray`, or 0 otherwise.
Return the number of dimensions `ndims(x(t))` of interpolation `x` for a scalar `t`.
"""
output_dim(x::AbstractInterpolation) = _output_dim(x.u)
_output_dim(::AbstractVector) = 0 # each value is a scalar
_output_dim(::AbstractVector{<:AbstractArray{<:Any, N}}) where {N} = N # each value is an array but values are not stacked
_output_dim(::AbstractArray{<:Any, N}) where {N} = N - 1 # each value is an array but multiple values are stacked

"""
output_size(x::AbstractInterpolation)

Return the size `size(x(t))` of interpolation `x` for a scalar `t`.
"""
output_size(x::AbstractInterpolation) = _output_size(x.u)
_output_size(::AbstractVector{<:Number}) = ()
_output_size(u::AbstractVector) = size(first(u))
_output_size(u::AbstractArray) = Base.front(size(u))

export LinearInterpolation, QuadraticInterpolation, LagrangeInterpolation,
AkimaInterpolation, ConstantInterpolation, QuadraticSpline, CubicSpline,
BSplineInterpolation, BSplineApprox, CubicHermiteSpline, PCHIPInterpolation,
QuinticHermiteSpline, SmoothArcLengthInterpolation, LinearInterpolationIntInv,
ConstantInterpolationIntInv, ExtrapolationType
export output_dim
export output_dim, output_size

# added for RegularizationSmooth, JJS 11/27/21
### Regularization data smoothing and interpolation
Expand Down
45 changes: 44 additions & 1 deletion test/interpolation_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ end
@test A(5.5) == 11.0
@test A(11) == 22
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = vcat(2.0collect(1:10)', 3.0collect(1:10)')
@test @inferred(LinearInterpolation(
Expand All @@ -60,6 +61,7 @@ end
@test A(5.5) == [11.0, 16.5]
@test A(11) == [22, 33]
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)

x = 1:10
y = 2:4
Expand All @@ -76,6 +78,7 @@ end
@test A(5.5) == [11.0, 16.5, 22.0]
@test A(11) == [22.0, 33.0, 44.0]
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (3,)
end

x = 1:10
Expand All @@ -92,6 +95,7 @@ end
@test A(5) == [8.0 10.0; 12.0 15.0; 16.0 20.0]
test_cached_index(A)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (3, 2)

# with NaNs (#113)
u = [NaN, 1.0, 2.0, 3.0]
Expand All @@ -103,6 +107,7 @@ end
@test A(3.0) == 2.0
@test A(4.0) == 3.0
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = [0.0, NaN, 2.0, 3.0]
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
Expand All @@ -112,6 +117,7 @@ end
@test A(3.0) == 2.0
@test A(4.0) == 3.0
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = [0.0, 1.0, NaN, 3.0]
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
Expand All @@ -121,6 +127,7 @@ end
@test isnan(A(3.0))
@test A(4.0) == 3.0
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = [0.0, 1.0, 2.0, NaN]
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
Expand All @@ -130,6 +137,7 @@ end
@test isnan(A(3.5))
@test isnan(A(4.0))
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = [0.0, 1.0, 2.0, NaN]
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
Expand All @@ -139,6 +147,7 @@ end
@test isnan(A(3.5))
@test isnan(A(4.0))
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Test type stability
u = Float32.(1:5)
Expand Down Expand Up @@ -170,11 +179,12 @@ end
end

# NaN time value for Unitful arrays: issue #365
t = (0:3)u"s" # Unitful quantities
t = (0:3)u"s" # Unitful quantities
u = [0, -2, -1, -2]u"m"
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
@test isnan(A(NaN * u"s"))
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Nan time value:
t = 0.0:3 # Floats
Expand All @@ -183,13 +193,15 @@ end
dA = t -> ForwardDiff.derivative(A, t)
@test isnan(dA(NaN))
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

t = 0:3 # Integers
u = [0, -2, -1, -2]
A = @inferred(LinearInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
dA = t -> ForwardDiff.derivative(A, t)
@test isnan(dA(NaN))
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Test derivative at point gives derivative to the right (except last is to left):
ts = t[begin:(end - 1)]
Expand All @@ -205,6 +217,7 @@ end
@test A(5.5) == fill(11.0)
@test A(11) == fill(22)
@test @inferred(output_dim(A)) == 0 # values are 0-dimensional arrays!
@test @inferred(output_size(A)) == ()

# Test constant -Inf interpolation
u = [-Inf, -Inf]
Expand Down Expand Up @@ -242,6 +255,7 @@ end
@test A(5.0) == 25
test_cached_index(A)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# backward-looking interpolation
u = [1.0, 4.0, 9.0, 16.0]
Expand Down Expand Up @@ -299,6 +313,7 @@ end
@test A(3.5) == [12.25, 12.25]
@test A(5.0) == [25.0, 25.0]
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)

u_ = [1.0, 4.0, 9.0, 16.0]' .* ones(5)
u = [u_[:, i] for i in 1:size(u_, 2)]
Expand All @@ -309,6 +324,7 @@ end
@test A(3.5) == 12.25 * ones(5)
@test A(5.0) == 25.0 * ones(5)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (5,)

u = [repeat(u[i], 1, 3) for i in 1:4]
@test_broken @inferred(QuadraticInterpolation(
Expand All @@ -320,6 +336,7 @@ end
@test A(3.5) == 12.25 * ones(5, 3)
@test A(5.0) == 25.0 * ones(5, 3)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (5, 3)

# Test extrapolation
u = [1.0, 4.5, 6.0, 2.0]
Expand All @@ -342,6 +359,7 @@ end
@test A(2.0) == 4.0
@test A(1.5) == 2.25
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u = [1.0, 8.0, 27.0, 64.0]
t = [1.0, 2.0, 3.0, 4.0]
Expand All @@ -358,6 +376,7 @@ end
@test A(1.5) ≈ [2.25, 2.25]
@test A(3.5) ≈ [12.25, 12.25]
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)

u_ = [1.0, 4.0, 9.0]' .* ones(4)
u = [u_[:, i] for i in 1:size(u_, 2)]
Expand All @@ -367,6 +386,7 @@ end
@test A(2.0) == 4.0 * ones(4)
@test A(1.5) == 2.25 * ones(4)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (4,)

u_ = [1.0, 8.0, 27.0, 64.0]' .* ones(4)
u = [u_[:, i] for i in 1:size(u_, 2)]
Expand All @@ -377,6 +397,7 @@ end
@test A(1.5) ≈ 3.375 * ones(4)
@test A(3.5) ≈ 42.875 * ones(4)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (4,)

u = [repeat(u[i], 1, 3) for i in 1:4]
A = @inferred(LagrangeInterpolation(u, t))
Expand All @@ -385,6 +406,7 @@ end
@test A(1.5) ≈ 3.375 * ones(4, 3)
@test A(3.5) ≈ 42.875 * ones(4, 3)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (4, 3)

# Test extrapolation
u = [1.0, 4.0, 9.0]
Expand Down Expand Up @@ -419,6 +441,7 @@ end
@test A(10.0) ≈ 3.0
test_cached_index(A)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Test extrapolation
A = @inferred(AkimaInterpolation(u, t; extrapolation = ExtrapolationType.Extension))
Expand Down Expand Up @@ -513,6 +536,7 @@ end
@test A(4.5) == u[4]
test_cached_index(A)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)

A = @inferred(ConstantInterpolation(
u, t; extrapolation = ExtrapolationType.Extension)) # dir=:left is default
Expand All @@ -527,6 +551,7 @@ end
@test A(4.5) == u[4]
test_cached_index(A)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)
end

@testset "Vector of Matrices case" for u in [
Expand All @@ -545,6 +570,7 @@ end
@test A(4.5) == u[4]
test_cached_index(A)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (2, 2)

A = @inferred(ConstantInterpolation(
u, t; extrapolation = ExtrapolationType.Extension)) # dir=:left is default
Expand All @@ -559,6 +585,7 @@ end
@test A(4.5) == u[4]
test_cached_index(A)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (2, 2)
end

# Test extrapolation
Expand Down Expand Up @@ -611,6 +638,7 @@ end
@test A(2.0) == P₁(2.0)
test_cached_index(A)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u_ = [0.0, 1.0, 3.0]' .* ones(4)
u = [u_[:, i] for i in 1:size(u_, 2)]
Expand All @@ -620,6 +648,7 @@ end
@test A(0.7) == P₁(0.7) * ones(4)
@test A(2.0) == P₁(2.0) * ones(4)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (4,)

u = [repeat(u[i], 1, 3) for i in 1:3]
A = @inferred(QuadraticSpline(u, t; extrapolation = ExtrapolationType.Extension))
Expand All @@ -628,6 +657,7 @@ end
@test A(0.7) == P₁(0.7) * ones(4, 3)
@test A(2.0) == P₁(2.0) * ones(4, 3)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (4, 3)

# Test extrapolation
u = [0.0, 1.0, 3.0]
Expand Down Expand Up @@ -663,6 +693,7 @@ end
@test A(x) ≈ P₂(x)
end
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

u_ = [0.0, 1.0, 3.0]' .* ones(4)
u = [u_[:, i] for i in 1:size(u_, 2)]
Expand All @@ -676,6 +707,7 @@ end
@test A(x) ≈ P₂(x) * ones(4)
end
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (4,)

u = [repeat(u[i], 1, 3) for i in 1:3]
@test_broken @inferred(CubicSpline(
Expand All @@ -688,6 +720,7 @@ end
@test A(x) ≈ P₂(x) * ones(4, 3)
end
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (4, 3)

# Test extrapolation
u = [0.0, 1.0, 3.0]
Expand Down Expand Up @@ -737,6 +770,7 @@ end
@test [A(t[1]), A(t[end])] == [u[1], u[end]]
test_cached_index(A)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Test extrapolation
A = @inferred(BSplineInterpolation(
Expand Down Expand Up @@ -777,12 +811,14 @@ end
@test isapprox(u_test[1, :], sin.(t_test), atol = 1e-3)
@test isapprox(u_test[2, :], cos.(t_test), atol = 1e-3)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)

A = @inferred(BSplineInterpolation(u2d, t, 2, :ArcLen, :Average))
u_test = reduce(hcat, A.(t_test))
@test isapprox(u_test[1, :], sin.(t_test), atol = 1e-3)
@test isapprox(u_test[2, :], cos.(t_test), atol = 1e-3)
@test @inferred(output_dim(A)) == 1
@test @inferred(output_size(A)) == (2,)
end
@testset "AbstractArray{T, 3}" begin
f3d(t) = [sin(t) cos(t);
Expand All @@ -795,12 +831,14 @@ end
f_test = reduce(hcat, f3d.(t_test))
@test isapprox(u_test, f_test, atol = 1e-2)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (2, 2)

A = @inferred(BSplineInterpolation(u3d, t, 2, :ArcLen, :Average))
t_test = 0.1:0.05:1.0
u_test = reduce(hcat, A.(t_test))
@test isapprox(u_test, f_test, atol = 1e-2)
@test @inferred(output_dim(A)) == 2
@test @inferred(output_size(A)) == (2, 2)
end
end

Expand Down Expand Up @@ -874,6 +912,7 @@ end
@test A(100.0)≈10.106770 rtol=1e-5
@test A(300.0)≈9.901542 rtol=1e-5
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()
test_cached_index(A)
push!(u, 1.0)
@test_throws AssertionError CubicHermiteSpline(du, u, t)
Expand All @@ -890,6 +929,7 @@ end
@test all(maximum(u) .>= us)
@test all(A.du[3:4] .== 0.0)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()
end

@testset "Quintic Hermite Spline" begin
Expand All @@ -906,9 +946,11 @@ end
@test A(300.0)≈11.364162 rtol=1e-5
test_cached_index(A)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()
push!(u, 1.0)
@test_throws AssertionError QuinticHermiteSpline(ddu, du, u, t)
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()
end

@testset "Smooth Arc Length Interpolation" begin
Expand Down Expand Up @@ -955,6 +997,7 @@ end
us = A.(ts)
@test vs ≈ us
@test @inferred(output_dim(A)) == 0
@test @inferred(output_size(A)) == ()

# Test extrapolation
A = Curvefit(u, t, model, p0, LBFGS(); extrapolate = true)
Expand Down
Loading