dbintk Subroutine

private subroutine dbintk(x, y, t, n, k, bcoef, q, work, iflag)

dbintk produces the b-spline coefficients, bcoef, of the b-spline of order k with knots t(i), i=1,…,n+k, which takes on the value y(i) at x(i), i=1,…,n. the spline or any of its derivatives can be evaluated by calls to dbvalu.

the i-th equation of the linear system a*bcoef = b for the coefficients of the interpolant enforces interpolation at x(i), i=1,…,n. hence, b(i) = y(i), for all i, and a is a band matrix with 2k-1 bands if a is invertible. the matrix a is generated row by row and stored, diagonal by diagonal, in the rows of q, with the main diagonal going into row k. the banded system is then solved by a call to dbnfac (which constructs the triangular factorization for a and stores it again in q), followed by a call to dbnslv (which then obtains the solution bcoef by substitution). dbnfac does no pivoting, since the total positivity of the matrix a makes this unnecessary. the linear system to be solved is (theoretically) invertible if and only if t(i) < x(i) < t(i+k), for all i. equality is permitted on the left for i=1 and on the right for i=n when k knots are used at x(1) or x(n). otherwise, violation of this condition is certain to lead to an error.

Error conditions

  • improper input
  • singular system of equations

History

  • splint written by carl de boor [5]
  • dbintk author: amos, d. e., (snla) : date written 800901
  • revision date 820801
  • 000330 modified array declarations. (jec)
  • Jacob Williams, 5/10/2015 : converted to free-form Fortran.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in), dimension(n) :: x

vector of length n containing data point abscissa in strictly increasing order.

real(kind=wp), intent(in), dimension(n) :: y

corresponding vector of length n containing data point ordinates.

real(kind=wp), intent(in), dimension(*) :: t

knot vector of length n+k since t(1),..,t(k) <= x(1) and t(n+1),..,t(n+k)

= x(n), this leaves only n-k knots (not necessarily x(i) values) interior to (x(1),x(n))

integer, intent(in) :: n

number of data points, n >= k

integer, intent(in) :: k

order of the spline, k >= 1

real(kind=wp), intent(out), dimension(n) :: bcoef

a vector of length n containing the b-spline coefficients

real(kind=wp), intent(out), dimension(*) :: q

a work vector of length (2k-1)n, containing the triangular factorization of the coefficient matrix of the linear system being solved. the coefficients for the interpolant of an additional data set (x(i),yy(i)), i=1,…,n with the same abscissa can be obtained by loading yy into bcoef and then executing call dbnslv(q,2k-1,n,k-1,k-1,bcoef)

real(kind=wp), intent(out), dimension(*) :: work

work vector of length 2*k

integer, intent(out) :: iflag

if 0: no errors. if 100: k does not satisfy k>=1. if 101: n does not satisfy n>=k. if 102: x(i) does not satisfy x(i)<x(i+1) for some i. if 103: some abscissa was not in the support of the. corresponding basis function and the system is singular. if 104: the system of solver detects a singular system. although the theoretical conditions for a solution were satisfied.


Calls

proc~~dbintk~~CallsGraph proc~dbintk dbintk proc~dbnfac dbnfac proc~dbintk->proc~dbnfac proc~dbnslv dbnslv proc~dbintk->proc~dbnslv proc~dbspvn dbspvn proc~dbintk->proc~dbspvn

Called by

proc~~dbintk~~CalledByGraph proc~dbintk dbintk proc~dbtpcf dbtpcf proc~dbtpcf->proc~dbintk proc~db1ink db1ink proc~db1ink->proc~dbtpcf proc~db2ink db2ink proc~db2ink->proc~dbtpcf proc~interp_surf interp_surf proc~interp_surf->proc~db2ink program~test_bspline test_bspline program~test_bspline->proc~interp_surf

Source Code

    subroutine dbintk(x,y,t,n,k,bcoef,q,work,iflag)

    implicit none

    integer,intent(in)                :: n      !! number of data points, n >= k
    real(wp),dimension(n),intent(in)  :: x      !! vector of length n containing data point abscissa
                                                !! in strictly increasing order.
    real(wp),dimension(n),intent(in)  :: y      !! corresponding vector of length n containing data
                                                !! point ordinates.
    real(wp),dimension(*),intent(in)  :: t      !! knot vector of length n+k
                                                !! since t(1),..,t(k) <= x(1) and t(n+1),..,t(n+k)
                                                !! >= x(n), this leaves only n-k knots (not
                                                !! necessarily x(i) values) interior to (x(1),x(n))
    integer,intent(in)                :: k      !! order of the spline, k >= 1
    real(wp),dimension(n),intent(out) :: bcoef  !! a vector of length n containing the b-spline coefficients
    real(wp),dimension(*),intent(out) :: q      !! a work vector of length (2*k-1)*n, containing
                                                !! the triangular factorization of the coefficient
                                                !! matrix of the linear system being solved.  the
                                                !! coefficients for the interpolant of an
                                                !! additional data set (x(i),yy(i)), i=1,...,n
                                                !! with the same abscissa can be obtained by loading
                                                !! yy into bcoef and then executing
                                                !! call dbnslv(q,2k-1,n,k-1,k-1,bcoef)
    real(wp),dimension(*),intent(out) :: work   !! work vector of length 2*k
    integer,intent(out)               :: iflag  !! if   0: no errors.
                                                !! if 100: k does not satisfy k>=1.
                                                !! if 101: n does not satisfy n>=k.
                                                !! if 102: x(i) does not satisfy x(i)<x(i+1) for some i.
                                                !! if 103: some abscissa was not in the support of the.
                                                !! corresponding basis function and the system is singular.
                                                !! if 104: the system of solver detects a singular system.
                                                !! although the theoretical conditions for a solution were satisfied.

    integer :: iwork, i, ilp1mx, j, jj, km1, kpkm2, left,lenq, np1
    real(wp) :: xi

    if (k<1) then
        write(error_unit,'(A)') 'dbintk - k does not satisfy k>=1'
        iflag = 100
        return
    endif

    if (n<k) then
        write(error_unit,'(A)') 'dbintk - n does not satisfy n>=k'
        iflag = 101
        return
    endif

    jj = n - 1
    if (jj/=0) then
        do i=1,jj
            if (x(i)>=x(i+1)) then
                write(error_unit,'(A)') 'dbintk - x(i) does not satisfy x(i)<x(i+1) for some i'
                iflag = 102
                return
            endif
        enddo
    endif

    np1 = n + 1
    km1 = k - 1
    kpkm2 = 2*km1
    left = k
    ! zero out all entries of q
    lenq = n*(k+km1)
    do i=1,lenq
        q(i) = 0.0_wp
    enddo

    ! loop over i to construct the n interpolation equations
    do i=1,n

        xi = x(i)
        ilp1mx = min(i+k,np1)
        ! *** find  left  in the closed interval (i,i+k-1) such that
        !         t(left) <= x(i) < t(left+1)
        ! matrix is singular if this is not possible
        left = max(left,i)
        if (xi<t(left)) then
            write(error_unit,'(A)') 'dbintk - some abscissa was not in the support of the'//&
                         ' corresponding basis function and the system is singular'
            iflag = 103
            return
        endif
        do
            if (xi<t(left+1)) go to 30
            left = left + 1
            if (left>=ilp1mx) exit
        enddo
        left = left - 1
        if (xi>t(left+1)) then
            write(error_unit,'(A)') 'dbintk - some abscissa was not in the support of the'//&
                         ' corresponding basis function and the system is singular'
            iflag = 103
            return
        endif

        ! *** the i-th equation enforces interpolation at xi, hence
        ! a(i,j) = b(j,k,t)(xi), all j. only the  k  entries with  j =
        ! left-k+1,...,left actually might be nonzero. these  k  numbers
        ! are returned, in  bcoef (used for temp.storage here), by the
        ! following
 30     call dbspvn(t, k, k, 1, xi, left, bcoef, work, iwork, iflag)
        if (iflag/=0) return

        ! we therefore want  bcoef(j) = b(left-k+j)(xi) to go into
        ! a(i,left-k+j), i.e., into  q(i-(left+j)+2*k,(left+j)-k) since
        ! a(i+j,j)  is to go into  q(i+k,j), all i,j,  if we consider  q
        ! as a two-dim. array , with  2*k-1  rows (see comments in
        ! dbnfac). in the present program, we treat  q  as an equivalent
        ! one-dimensional array (because of fortran restrictions on
        ! dimension statements) . we therefore want  bcoef(j) to go into
        ! entry
        !     i -(left+j) + 2*k + ((left+j) - k-1)*(2*k-1)
        !            = i-left+1 + (left -k)*(2*k-1) + (2*k-2)*j
        ! of q.
        jj = i - left + 1 + (left-k)*(k+km1)
        do j=1,k
            jj = jj + kpkm2
            q(jj) = bcoef(j)
        enddo

    enddo

    ! obtain factorization of a, stored again in q.
    call dbnfac(q, k+km1, n, km1, km1, iflag)

    if (iflag==1) then !success
        ! *** solve  a*bcoef = y  by backsubstitution
        do i=1,n
            bcoef(i) = y(i)
        enddo
        call dbnslv(q, k+km1, n, km1, km1, bcoef)
        iflag = 0
    else  !failure
        write(error_unit,'(A)') 'dbintk - the system of solver detects a singular system'//&
                     ' although the theoretical conditions for a solution were satisfied'
        iflag = 104
    endif

    endsubroutine dbintk