Skip to content

Commit 00c34ee

Browse files
committed
Add parentaxes, it, and gt fields to BSplineInterpolation
Storing parentaxes will allow us to do padding via OffsetArrays, which has the major advantage of keeping the indices of the padded array in-register with those of the original array. This should simplify a lot of code.
1 parent 8f027e8 commit 00c34ee

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

src/b-splines/b-splines.jl

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,27 @@ BSpline(::D) where {D<:Degree} = BSpline{D}()
1414

1515
bsplinetype(::Type{BSpline{D}}) where {D<:Degree} = D
1616

17-
struct BSplineInterpolation{T,N,TCoefs<:AbstractArray,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},pad} <: AbstractInterpolation{T,N,IT,GT}
17+
struct BSplineInterpolation{T,N,TCoefs<:AbstractArray,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},Axs<:Tuple{Vararg{AbstractUnitRange,N}}} <: AbstractInterpolation{T,N,IT,GT}
1818
coefs::TCoefs
19+
parentaxes::Axs
20+
it::IT
21+
gt::GT
1922
end
20-
function BSplineInterpolation(::Type{TWeights}, A::AbstractArray{Tel,N}, ::IT, ::GT, ::Val{pad}) where {N,Tel,TWeights<:Real,IT<:DimSpec{BSpline},GT<:DimSpec{GridType},pad}
21-
isconcretetype(IT) || error("The b-spline type must be a leaf type (was $IT)")
22-
isconcretetype(typeof(A)) || warn("For performance reasons, consider using an array of a concrete type (typeof(A) == $(typeof(A)))")
23+
function BSplineInterpolation(::Type{TWeights}, A::AbstractArray{Tel,N}, it::IT, gt::GT, axs) where {N,Tel,TWeights<:Real,IT<:DimSpec{BSpline},GT<:DimSpec{GridType}}
24+
# String interpolation causes allocation, noinline avoids that unless they get called
25+
@noinline err_concrete(IT) = error("The b-spline type must be a concrete type (was $IT)")
26+
@noinline warn_concrete(A) = @warn("For performance reasons, consider using an array of a concrete type (typeof(A) == $(typeof(A)))")
2327

24-
c = zero(TWeights)
25-
for _ in 2:N
26-
c *= c
27-
end
28+
isconcretetype(IT) || err_concrete(IT)
29+
isconcretetype(typeof(A)) || warn_concrete(A)
30+
31+
# Compute the output element type when positions have type TWeights
2832
if isempty(A)
29-
T = Base.promote_op(*, typeof(c), eltype(A))
33+
T = Base.promote_op(*, TWeights, eltype(A))
3034
else
31-
T = typeof(c * first(A))
35+
T = typeof(zero(TWeights) * first(A))
3236
end
33-
BSplineInterpolation{T,N,typeof(A),IT,GT,pad}(A)
37+
BSplineInterpolation{T,N,typeof(A),IT,GT,typeof(axs)}(A, fix_axis.(axs), it, gt)
3438
end
3539

3640
# Utilities for working either with scalars or tuples/tuple-types
@@ -68,13 +72,17 @@ end
6872
@inline axes(itp::BSplineInterpolation{T,N,TCoefs,IT,GT,pad}) where {T,N,TCoefs,IT,GT,pad} =
6973
indices_removepad.(axes(itp.coefs), pad)
7074

75+
fix_axis(r::Base.OneTo) = r
76+
fix_axis(r::Base.Slice) = r
77+
fix_axis(r::UnitRange) = Base.Slice(r)
78+
fix_axis(r::AbstractUnitRange) = fix_axis(UnitRange(r))
7179
function axes(itp::BSplineInterpolation{T,N,TCoefs,IT,GT,pad}, d) where {T,N,TCoefs,IT,GT,pad}
7280
d <= N ? indices_removepad(axes(itp.coefs, d), padextract(pad, d)) : axes(itp.coefs, d)
7381
end
7482

7583
function interpolate(::Type{TWeights}, ::Type{TC}, A, it::IT, gt::GT) where {TWeights,TC,IT<:DimSpec{BSpline},GT<:DimSpec{GridType}}
76-
Apad, Pad = prefilter(TWeights, TC, A, IT, GT)
77-
BSplineInterpolation(TWeights, Apad, it, gt, Pad)
84+
Apad = prefilter(TWeights, TC, A, it, gt)
85+
BSplineInterpolation(TWeights, Apad, it, gt, axes(A))
7886
end
7987
function interpolate(A::AbstractArray, it::IT, gt::GT) where {IT<:DimSpec{BSpline},GT<:DimSpec{GridType}}
8088
interpolate(tweight(A), tcoef(A), A, it, gt)
@@ -91,7 +99,12 @@ tcoef(A::AbstractArray{Float32}) = Float32
9199
tcoef(A::AbstractArray{Rational{Int}}) = Rational{Int}
92100
tcoef(A::AbstractArray{T}) where {T<:Integer} = typeof(float(zero(T)))
93101

94-
interpolate!(::Type{TWeights}, A, it::IT, gt::GT) where {TWeights,IT<:DimSpec{BSpline},GT<:DimSpec{GridType}} = BSplineInterpolation(TWeights, prefilter!(TWeights, A, IT, GT), it, gt, Val{0}())
102+
function interpolate!(::Type{TWeights}, A, it::IT, gt::GT) where {TWeights,IT<:DimSpec{BSpline},GT<:DimSpec{GridType}}
103+
# Set the bounds of the interpolant inward, if necessary
104+
axsA = axes(A)
105+
axspad = padded_axes(axsA, it)
106+
BSplineInterpolation(TWeights, prefilter!(TWeights, A, it, gt), it, gt, fix_axis.(padinset.(axsA, axspad)))
107+
end
95108
function interpolate!(A::AbstractArray, it::IT, gt::GT) where {IT<:DimSpec{BSpline},GT<:DimSpec{GridType}}
96109
interpolate!(tweight(A), A, it, gt)
97110
end

0 commit comments

Comments
 (0)