I am working with splines, and I would like to evaluate polynomials along with their derivatives using all sorts of nice tricks like @evalpoly and @SArray. The function below gives an idea. It does not look great, though. What are my options to turn this into something where I can be sure the resulting code can be nicely inlined and optimized, with no “if dev==…” after compilation, and also avoiding code duplication? It would also be cool to make it generic on the polynomial order, for instance. Is this a situation where macros or @generated might help me? Or is this code perhaps already the best conceivably possible?
using StaticArrays
function calc_spline(t, a, dev=0)
N = size(a, 2)
i = convert(Int, min(max(1, floor(t)), N)) :: Int
u = t - i
p = a[:, i]
if dev==0
@evalpoly(u, p[1], p[2], p[3], p[4])
elseif dev==1
@SArray [
@evalpoly(u, p[1], p[2], p[3], p[4]),
@evalpoly(u, p[2], 2 * p[3], 3 * p[4])
]
elseif dev==2
@SArray [
@evalpoly(u, p[1], p[2], p[3], p[4]),
@evalpoly(u, p[2], 2 * p[3], 3 * p[4]),
@evalpoly(u, 2 * p[3], 2 * (3 * p[4]))
]
elseif dev==3
@SArray [
@evalpoly(u, p[1], p[2], p[3], p[4]),
@evalpoly(u, p[2], 2 * p[3], 3 * p[4]),
@evalpoly(u, 2 * p[3], 2 * (3 * p[4])),
2 * (3 * p[4])
]
end
end
julia> a = 0.10 * reshape(1:40, 4,:)
4×10 Array{Float64,2}:
0.1 0.5 0.9 1.3 1.7 2.1 2.5 2.9 3.3 3.7
0.2 0.6 1.0 1.4 1.8 2.2 2.6 3.0 3.4 3.8
0.3 0.7 1.1 1.5 1.9 2.3 2.7 3.1 3.5 3.9
0.4 0.8 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0
julia> calc_spline(3.4, a, 0)
1.5527999999999997
julia> calc_spline(3.4, a, 1)
2-element SArray{Tuple{2},Float64,1,2}:
1.5527999999999997
2.4559999999999995
julia> calc_spline(3.4, a, 2)
3-element SArray{Tuple{3},Float64,1,3}:
1.5527999999999997
2.4559999999999995
5.08
julia> calc_spline(3.4, a, 3)
4-element SArray{Tuple{4},Float64,1,4}:
1.5527999999999997
2.4559999999999995
5.08
7.200000000000001