!>
!> @file bsplvb.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
!>
subroutine bsplvb ( t, jhigh, index, x, left, biatx )
!*************************************************************************
!
!! BSPLVB evaluates B-splines at a point X with a given knot sequence.
!
! Discusion:
!
! BSPLVB evaluates all possibly nonzero B-splines at X of order
!
! JOUT = MAX ( JHIGH, (J+1)*(INDEX-1) )
!
! with knot sequence T.
!
! The recurrence relation
!
! X - T(I) T(I+J+1) - X
! B(I,J+1)(X) = ----------- * B(I,J)(X) + --------------- * B(I+1,J)(X)
! T(I+J)-T(I) T(I+J+1)-T(I+1)
!
! is used to generate B(LEFT-J:LEFT,J+1)(X) from B(LEFT-J+1:LEFT,J)(X)
! storing the new values in BIATX over the old.
!
! The facts that
!
! B(I,1)(X) = 1 if T(I) <= X < T(I+1)
!
! and that
!
! B(I,J)(X) = 0 unless T(I) <= X < T(I+J)
!
! are used.
!
! The particular organization of the calculations follows
! algorithm 8 in chapter X of the text.
!
! Reference:
!
! Carl DeBoor,
! A Practical Guide to Splines,
! Springer Verlag.
!
! Parameters:
!
! Input, real ( kind = 8 ) T(LEFT+JOUT), the knot sequence. T is assumed to
! be nondecreasing, and also, T(LEFT) must be strictly less than
! T(LEFT+1).
!
! Input, integer JHIGH, INDEX, determine the order
! JOUT = MAX(JHIGH,(J+1)*(INDEX-1))
! of the B-splines whose values at X are to be returned.
! INDEX is used to avoid recalculations when several
! columns of the triangular array of B-spline values are
! needed, for example, in BVALUE or in BSPLVD.
!
! If INDEX = 1, the calculation starts from scratch and the entire
! triangular array of B-spline values of orders
! 1, 2, ...,JHIGH is generated order by order, i.e.,
! column by column.
!
! If INDEX = 2, only the B-spline values of order J+1, J+2, ..., JOUT
! are generated, the assumption being that BIATX, J,
! DELTAL, DELTAR are, on entry, as they were on exit
! at the previous call. In particular, if JHIGH = 0,
! then JOUT = J+1, i.e., just the next column of B-spline
! values is generated.
!
! WARNING: the restriction JOUT <= JMAX (= 20) is
! imposed arbitrarily by the dimension statement for DELTAL
! and DELTAR, but is nowhere checked for.
!
! Input, real ( kind = 8 ) X, the point at which the B-splines
! are to be evaluated.
!
! Input, integer LEFT, an integer chosen so that
! T(LEFT) <= X <= T(LEFT+1).
!
! Output, real ( kind = 8 ) BIATX(JOUT), with BIATX(I) containing the
! value at X of the polynomial of order JOUT which agrees
! with the B-spline B(LEFT-JOUT+I,JOUT,T) on the interval
! (T(LEFT),T(LEFT+1)).
!
implicit none
integer, parameter :: jmax = 20
integer jhigh
real ( kind = 8 ) biatx(jhigh)
!!$ real ( kind = 8 ), save, dimension ( jmax ) :: deltal
!!$ real ( kind = 8 ), save, dimension ( jmax ) :: deltar
real ( kind = 8 ), dimension ( jmax ) :: deltal
real ( kind = 8 ), dimension ( jmax ) :: deltar
integer i
integer index
!!$ integer, save :: j = 1
integer :: j
integer left
real ( kind = 8 ) saved
real ( kind = 8 ) t(left+jhigh)
real ( kind = 8 ) term
real ( kind = 8 ) x
! Forces starting always from scratch!
!!$ if ( index == 1 ) then
j = 1
biatx(1) = 1.0D+00
if ( jhigh <= j ) then
return
end if
!!$ end if
if ( t(left+1) <= t(left) ) then
write ( *, '(a)' ) ' '
write ( *, '(a)' ) 'BSPLVB - Fatal error!'
write ( *, '(a)' ) ' It is required that T(LEFT) < T(LEFT+1).'
write ( *, '(a,i6)' ) ' But LEFT = ', left
write ( *, '(a,g14.6)' ) ' T(LEFT) = ', t(left)
write ( *, '(a,g14.6)' ) ' T(LEFT+1) = ', t(left+1)
stop
end if
do
deltar(j) = t(left+j) - x
deltal(j) = x - t(left+1-j)
saved = 0.0D+00
do i = 1, j
term = biatx(i) / ( deltar(i) + deltal(j+1-i) )
biatx(i) = saved + deltar(i) * term
saved = deltal(j+1-i) * term
end do
biatx(j+1) = saved
j = j + 1
if ( jhigh <= j ) then
exit
end if
end do
return
end