!>
!> @file bvalue.f90
!>
!> @brief
!>
!> @copyright
!> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
!> SPC (Swiss Plasma Center)
!>
!> SPClibs is free software: you can redistribute it and/or modify it under
!> the terms of the GNU Lesser General Public License as published by the Free
!> Software Foundation, either version 3 of the License, or (at your option)
!> any later version.
!>
!> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY
!> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
!> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
!>
!> You should have received a copy of the GNU Lesser General Public License
!> along with this program. If not, see .
!>
!> @author
!> (in alphabetical order)
!> @author Trach-Minh Tran
!>
function bvalue ( t, bcoef, n, k, x, jderiv )
!*************************************************************************
!
!! BVALUE evaluates a derivative of a spline from its B-spline representation.
!
! Discussion:
!
! The spline is taken to be continuous from the right.
!
! The nontrivial knot interval (T(I),T(I+1)) containing X is
! located with the aid of INTERV. The K B-spline coefficients
! of F relevant for this interval are then obtained from BCOEF,
! or are taken to be zero if not explicitly available, and are
! then differenced JDERIV times to obtain the B-spline
! coefficients of (D**JDERIV)F relevant for that interval.
!
! Precisely, with J = JDERIV, we have from X.(12) of the text that:
!
! (D**J)F = sum ( BCOEF(.,J)*B(.,K-J,T) )
!
! where
! / BCOEF(.), , J == 0
! /
! BCOEF(.,J) = / BCOEF(.,J-1) - BCOEF(.-1,J-1)
! / -----------------------------, 0 < J
! / (T(.+K-J) - T(.))/(K-J)
!
! Then, we use repeatedly the fact that
!
! sum ( A(.)*B(.,M,T)(X) ) = sum ( A(.,X)*B(.,M-1,T)(X) )
!
! with
! (X - T(.))*A(.) + (T(.+M-1) - X)*A(.-1)
! A(.,X) = ---------------------------------------
! (X - T(.)) + (T(.+M-1) - X)
!
! to write (D**J)F(X) eventually as a linear combination of
! B-splines of order 1, and the coefficient for B(I,1,T)(X)
! must then be the desired number (D**J)F(X).
! See x.(17)-(19) of text.
!
! Reference:
!
! Carl DeBoor,
! A Practical Guide to Splines,
! Springer Verlag.
!
! Parameters:
!
! Input, real ( kind = 8 ) T(N+K), the knot sequence. T is assumed
! to be nondecreasing.
!
! Input, real ( kind = 8 ) BCOEF(N), B-spline coefficient sequence.
!
! Input, integer N, the length of BCOEF.
!
! Input, integer K, the order of the spline.
!
! Input, real ( kind = 8 ) X, the point at which to evaluate.
!
! Input, integer JDERIV, the order of the derivative to
! be evaluated. JDERIV is assumed to be zero or positive.
!
! Output, real ( kind = 8 ) BVALUE, the value of the (JDERIV)-th
! derivative of the spline at X.
!
implicit none
integer k
integer n
real ( kind = 8 ) aj(k)
real ( kind = 8 ) bcoef(n)
real ( kind = 8 ) bvalue
real ( kind = 8 ) dl(k)
real ( kind = 8 ) dr(k)
integer i
integer ilo
integer j
integer jc
integer jcmax
integer jcmin
integer jderiv
integer jj
integer mflag
real ( kind = 8 ) t(n+k)
real ( kind = 8 ) x
bvalue = 0.0D+00
if ( k <= jderiv ) then
return
end if
!
! Find I so that 1 <= i < n+k and t(i) < t(i+1) and t(i) <= x < t(i+1).
!
! If no such i can be found, X lies
! outside the support of the spline F and bvalue=0.
! (the asymmetry in this choice of i makes F rightcontinuous)
!
call interv ( t, n+k, x, i, mflag )
if ( mflag /= 0 ) then
return
end if
!
! If K=1 (and jderiv = 0), bvalue = bcoef(i).
!
if ( k <= 1 ) then
bvalue = bcoef(i)
return
end if
!
! Store the K b-spline coefficients relevant for the knot interval
! (T(i),T(i+1)) in aj(1),...,aj(k) and compute dl(j)=x-t(i+1-j),
! dr(j)=T(i+j)-x, j=1,...,k-1 . set any of the aj not obtainable
! from input to zero. Set any T's not obtainable equal to T(1) or
! to T(n+k) appropriately.
!
jcmin = 1
if ( k <= i ) then
do j = 1, k-1
dl(j) = x-t(i+1-j)
end do
else
jcmin = 1-(i-k)
do j = 1, i
dl(j) = x-t(i+1-j)
end do
do j = i, k-1
aj(k-j) = 0.0D+00
dl(j) = dl(i)
end do
end if
jcmax = k
if ( i <= n ) then
go to 90
end if
jcmax = k + n - i
do j = 1, k+n-i
dr(j) = t(i+j)-x
end do
do j = k+n-i, k-1
aj(j+1) = 0.0D+00
dr(j) = dr(k+n-i)
end do
go to 110
90 continue
do j = 1, k-1
dr(j) = t(i+j)-x
end do
110 continue
do jc = jcmin, jcmax
aj(jc) = bcoef(i-k+jc)
end do
!
! Difference the coefficients JDERIV times.
!
do j = 1, jderiv
ilo = k-j
do jj = 1, k-j
aj(jj) = ((aj(jj+1)-aj(jj))/(dl(ilo)+dr(jj))) * real ( k - j, kind = 8 )
ilo = ilo-1
end do
end do
!
! Compute value at X in (t(i),t(i+1)) of jderiv-th derivative,
! given its relevant b-spline coefficients in aj(1),...,aj(k-jderiv).
!
do j = jderiv+1, k-1
ilo = k-j
do jj = 1, k-j
aj(jj) = ( aj(jj+1) * dl(ilo) + aj(jj) * dr(jj) ) &
/ ( dl(ilo) + dr(jj) )
ilo = ilo-1
end do
end do
bvalue = aj(1)
return
end