LCOV - code coverage report
Current view: top level - src - evaluation.jl (source / functions) Hit Total Coverage
Test: on branch (detached from e33c853) Lines: 58 58 100.0 %
Date: 2025-10-07 08:47:25 Functions: 0 0 -

          Line data    Source code
       1        4425 : ev(h::AbstractHermiteSpline{S, V}, t::S, ::X, idx::Int) where {V, S<:Real, X} =
       2             :     interpolate(h, X(), boundedindex(h, t, idx), t)
       3             : 
       4        5863 : ev(h::AbstractHermiteSpline{S, V}, t::S, ::X = Value) where {V, S<:Real, X} =
       5             :     first(ev(h, t, X(), 1))
       6             : 
       7             : 
       8        2498 : function interpolate(hs::AbstractHermiteSpline{S, V},
       9             :                      ::TValueDerivative, idx::Int, t::S) where {S, V}
      10        2498 :     t0, x0, dx0 = hs[idx]
      11        2498 :     t1, x1, dx1 = hs[idx + 1]
      12             : 
      13        2498 :     (t == t0) && return (x0, dx0), idx
      14        2497 :     (t == t1) && return (x1, dx1), idx
      15             : 
      16        2478 :     h = t1 - t0
      17        2478 :     t = (t - t0) / h
      18        2478 :     @assert isfinite(t)
      19             : 
      20        2478 :     cx0, cdx0, cx1, cdx1 = hermitebasis(t)
      21        2478 :     x = x0*cx0 + dx0*(cdx0*h) + x1*cx1 + dx1*(cdx1*h)
      22             : 
      23        2478 :     ex0, edx0, ex1, edx1 = hermitederivativebasis(t)
      24        2478 :     dx = x0*(ex0/h) + dx0*edx0 + x1*(ex1/h) + dx1*edx1
      25             : 
      26        2478 :     (x, dx), idx
      27             : end
      28             : 
      29        2810 : function interpolate(hs::AbstractHermiteSpline{S, V},
      30             :                      ::TValue, idx::Int, t::S) where {S, V}
      31        2810 :     t0, x0, dx0 = hs[idx]
      32        2810 :     t1, x1, dx1 = hs[idx + 1]
      33             : 
      34        2810 :     (t == t0) && return x0, idx
      35        2803 :     (t == t1) && return x1, idx
      36             : 
      37        2796 :     h = t1 - t0
      38        2796 :     t = (t - t0) / h
      39        2796 :     @assert isfinite(t)
      40             : 
      41        2796 :     cx0, cdx0, cx1, cdx1 = hermitebasis(t)
      42        2796 :     x = x0*cx0 + dx0*(cdx0*h) + x1*cx1 + dx1*(cdx1*h)
      43             : 
      44        2796 :     x, idx
      45             : end
      46             : 
      47           9 : function ev(h::AbstractHermiteSpline{S, V},
      48             :             ts::StepRangeLen{S}, ::X = Value) where {S, V, X}
      49           9 :     idx::Int = 1
      50         144 :     function f(t::S)
      51         276 :         out, idx = interpolate(h, X(), boundedindex(h, t, idx), t)
      52         138 :         out
      53             :     end
      54           6 :     (f(t) for t in ts)
      55             : end
      56             : 
      57           3 : _resultype(::TValue, ::Type{V}) where {V} = V
      58           3 : _resultype(::TValueDerivative, ::Type{V}) where {V} = Tuple{V, V}
      59             : 
      60          45 : function ev(h::AbstractHermiteSpline{S, V}, ts::Vector{S}, ::X = Value;
      61             :             sorted::Bool = false) where {S, V, X}
      62          17 :     sorted && return ev(h, Val(:sorted), ts, X())
      63          11 :     issorted(ts, rev=!isascending(h)) && return ev(h, Val(:sorted), ts, X())
      64             : 
      65           6 :     n = length(ts)
      66          12 :     p = sortperm(ts, rev = !isascending(h))
      67             : 
      68          12 :     x = Vector{_resultype(X(), V)}(undef, n)
      69           6 :     idx::Int = 1
      70           6 :     @inbounds for (i, ip) in enumerate(p)
      71         138 :         t = ts[ip]
      72         138 :         x[ip], idx = interpolate(h, X(), boundedindex(h, t, idx), t)
      73         270 :     end
      74             : 
      75           6 :     x
      76             : end
      77             : 
      78          11 : function ev(h::AbstractHermiteSpline{S, V}, ::Val{:sorted}, ts::Vector{S},
      79             :             ::X) where {S, V, X}
      80          11 :     idx::Int = 1
      81         618 :     function f(t::S)
      82         816 :         out, idx = interpolate(h, X(), boundedindex(h, t, idx), t)
      83         607 :         out
      84             :     end
      85             : 
      86          11 :     [ f(t) for t in ts ]
      87             : end
      88             : 
      89             : 
      90             : """
      91             :     (x, dx), idx = ev(h, t, ValueDerivative, idx)  # value and derivative
      92             :     x, dx = ev(h, t, ValueDerivative)
      93             :     x_dx = collect(ev(h, range(t0, t1, length=n))) #   from generator
      94             :     x_dx = ev(h, ts::Vector, ValueDerivative[; issorted=false])
      95             : 
      96             :     x, idx = ev(h, t, Value, idx)                  # value only
      97             :     x = ev(h, t, Value)
      98             :     x = collect(ev(h, range(t0, t1, length=n)))    #   from generator
      99             :     x = ev(h, ts::Vector, Value[; issorted=false])
     100             : 
     101             : Evaluate [`AbstractHermiteSpline`](@ref) `h(t)`, provide (possibly
     102             : reused) knot interval index `idx` from previous evaluation. Compute
     103             : value and derivative `(x, dx)` or only value `x`.
     104             : 
     105             : The evaluation at parameters `ts` in a `Vector` is more efficient if
     106             : `ts` is sorted (w.r.t [`isascending`](@ref)) due to use of caches and
     107             : because the current [`index`](@ref) is stored for lookup. *However*,
     108             : sorting `ts` exclusively for a single pass of evaluation may be more
     109             : expensive than point-location tests for an unsorted `ts`.
     110             : 
     111             : - If `sorted = false` is passed, the `ev` sorts enforces sorting `ts`
     112             :   before evaluation (if `ts` are not already sorted). The returned
     113             :   values apprear in the order of `ts` as for input (i.e., in addition
     114             :   to `sort!` there is an extra overhead for using `sortperm!` and
     115             :   applying the permutation).
     116             : - If `sorted = true` is passed, `ev`
     117             :   evaluates at parameters `ts` without assumptions on order.
     118             : 
     119             : !!! note
     120             :     Passing `sorted = true` is *not an assertion* that parameters `ts`
     121             :     are sorted but rather a hint that `ev` shall not perform any sorting.
     122             : 
     123             : # Alternative syntax
     124             : 
     125             : [`AbstractHermiteSpline`](@ref) `h` is a *callable object*, which delegates
     126             : arguments to `ev(h, t, ...)`.
     127             : 
     128             :     output = h(t, ...)                            # output: see above
     129             :     x = h(t)                                      # default: value only
     130             : 
     131             : """ ev
     132             : 
     133             : """
     134             : Evaluate [`AbstractHermiteSpline`](@ref) `h(t)`, delegates arguments
     135             : to [`ev`](@ref).
     136             : 
     137             : 
     138             : See [`ev`](@ref)
     139             : """
     140        2294 : (h::AbstractHermiteSpline{S, V})(t::S, ::X, args...) where {S, V, X} =
     141             :     ev(h, t, X(), args...)
     142        2131 : (h::AbstractHermiteSpline{S, V})(t::S) where {S, V} = ev(h, t)
     143             : # (h::AbstractHermiteSpline{S, V})(t::S, args...) where {S, V} = ev(h, t, args...) # NOTE: THis is slow!?!
     144          12 : (h::AbstractHermiteSpline{S, V})(t::Vector{S}, ::X; sorted::Bool = false) where {S, V, X} =
     145             :     ev(h, t, X(); sorted)
     146          22 : (h::AbstractHermiteSpline{S, V})(t::Vector{S}; sorted::Bool = false) where {S, V} =
     147             :     ev(h, t; sorted)
     148           3 : (h::AbstractHermiteSpline{S, V})(t::StepRangeLen{S}, ::X) where {S, V, X} =
     149             :     ev(h, t, X())
     150           3 : (h::AbstractHermiteSpline{S, V})(t::StepRangeLen{S}) where {S, V} =
     151             :     ev(h, t)

Generated by: LCOV version 1.16