tautsp Subroutine

subroutine tautsp(tau, gtau, ntau, gamma, s, break, coef, l, k, iflag)

************80

! TAUTSP constructs a cubic spline interpolant to given data.

Discussion:

If 0 < GAMMA, additional knots are introduced where needed to
make the interpolant more flexible locally.  This avoids extraneous
inflection points typical of cubic spline interpolation at knots to
rapidly changing data.

Method:

On the I-th interval, (TAU(I), TAU(I+1)), the interpolant is of the
form:

(*)  F(U(X)) = A + B * U + C * H(U,Z) + D * H(1-U,1-Z),

with

  U = U(X) = ( X - TAU(I) ) / DTAU(I).

Here,

  Z(I) = ADDG(I+1) / ( ADDG(I) + ADDG(I+1) )

but if the denominator vanishes, we set Z(I) = 0.5

Also, we have

  ADDG(J) = abs ( DDG(J) ),
  DDG(J) = DG(J+1) - DG(J),
  DG(J) = DIVDIF(J) = ( GTAU(J+1) - GTAU(J) ) / DTAU(J)

and

  H(U,Z) = ALPHA * U**3
         + ( 1 - ALPHA ) * ( max ( ( ( U - ZETA ) / ( 1 - ZETA ) ), 0 )**3

with

  ALPHA(Z) = ( 1 - GAMMA / 3 ) / ZETA
  ZETA(Z) = 1 - GAMMA * min ( ( 1 - Z ), 1/3 )

Thus, for 1/3 <= Z <= 2/3, F is just a cubic polynomial on
the interval I.  Otherwise, it has one additional knot, at

  TAU(I) + ZETA * DTAU(I).

As Z approaches 1, H(.,Z) has an increasingly sharp bend near 1,
thus allowing F to turn rapidly near the additional knot.

In terms of F(J) = GTAU(J) and FSECND(J) = second derivative of F
at TAU(J), the coefficients for (*) are given as:

  A = F(I) - D
  B = ( F(I+1) - F(I) ) - ( C - D )
  C = FSECND(I+1) * DTAU(I)**2 / HSECND(1,Z)
  D = FSECND(I) * DTAU(I)**2 / HSECND(1,1-Z)

Hence these can be computed once FSECND(1:NTAU) is fixed.

F is automatically continuous and has a continuous second derivative
except when Z=0 or 1 for some I.  We determine FSECND from
the requirement that the first derivative of F be continuous.

In addition, we require that the third derivative be continuous
across TAU(2) and across TAU(NTAU-1).  This leads to a strictly
diagonally dominant tridiagonal linear system for the FSECND(I)
which we solve by Gauss elimination without pivoting.

Modified:

14 February 2007

Author:

Carl DeBoor

Reference:

Carl DeBoor,
A Practical Guide to Splines,
Springer, 2001,
ISBN: 0387953663,
LC: QA1.A647.v27.

Parameters:

Input, real ( kind = 8 ) TAU(NTAU), the sequence of data points.
TAU must be strictly increasing.

Input, real ( kind = 8 ) GTAU(NTAU), the corresponding sequence of
function values.

Input, integer ( kind = 4 ) NTAU, the number of data points.
NTAU must be at least 4.

Input, real ( kind = 8 ) GAMMA, indicates whether additional flexibility
is desired.
GAMMA = 0.0, no additional knots;
GAMMA in (0.0,3.0), under certain conditions on the given data at
points I-1, I, I+1, and I+2, a knot is added in the I-th interval,
for I = 2,...,NTAU-2.  See description of method.  The interpolant
gets rounded with increasing gamma.  A value of 2.5 for GAMMA is typical.
GAMMA in (3.0,6.0), same, except that knots might also be added in
intervals in which an inflection point would be permitted.  A value
of 5.5 for GAMMA is typical.

Output, real ( kind = 8 ) BREAK(L), real ( kind = 8 ) COEF(K,L),
integer ( kind = 4 ) L, integer K, give the piecewise polynomial
representation of the interpolant.  Specifically,
for BREAK(i) <= X <= BREAK(I+1), the interpolant has the form:
  F(X) = COEF(1,I) +  DX    * (
         COEF(2,I) + (DX/2) * (
         COEF(3,I) + (DX/3) *
         COEF(4,I) ) )
with  DX = X - BREAK(I) for I = 1,..., L.

Output, integer ( kind = 4 ) IFLAG, error flag.
1, no error.
2, input was incorrect.

Output, real ( kind = 8 ) S(NTAU,6).  The individual columns of this
array contain the following quantities mentioned in the write up
and below.
S(.,1) = DTAU = TAU(.+1)-TAU;
S(.,2) = DIAG = diagonal in linear system;
S(.,3) = U = upper diagonal in linear system;
S(.,4) = R = right hand side for linear system (initially)
       = FSECND = solution of linear system, namely the second
         derivatives of interpolant at TAU;
S(.,5) = Z = indicator of additional knots;
S(.,6) = 1/HSECND(1,X) with X = Z or 1-Z.

Arguments

Type IntentOptional Attributes Name
real(kind=8) :: tau(ntau)
real(kind=8) :: gtau(ntau)
integer(kind=4) :: ntau
real(kind=8) :: gamma
real(kind=8) :: s(ntau,6)
real(kind=8) :: break(*)
real(kind=8) :: coef(4,*)
integer(kind=4) :: l
integer(kind=4) :: k
integer(kind=4) :: iflag

Source Code

subroutine tautsp ( tau, gtau, ntau, gamma, s, break, coef, l, k, iflag )

  !*****************************************************************************80
  !
  !! TAUTSP constructs a cubic spline interpolant to given data.
  !
  !  Discussion:
  !
  !    If 0 < GAMMA, additional knots are introduced where needed to
  !    make the interpolant more flexible locally.  This avoids extraneous
  !    inflection points typical of cubic spline interpolation at knots to
  !    rapidly changing data.
  !
  !  Method:  
  !
  !    On the I-th interval, (TAU(I), TAU(I+1)), the interpolant is of the
  !    form:
  !
  !    (*)  F(U(X)) = A + B * U + C * H(U,Z) + D * H(1-U,1-Z),
  !
  !    with  
  !
  !      U = U(X) = ( X - TAU(I) ) / DTAU(I). 
  !
  !    Here,
  !
  !      Z(I) = ADDG(I+1) / ( ADDG(I) + ADDG(I+1) )
  !
  !    but if the denominator vanishes, we set Z(I) = 0.5
  !
  !    Also, we have
  !
  !      ADDG(J) = abs ( DDG(J) ), 
  !      DDG(J) = DG(J+1) - DG(J),
  !      DG(J) = DIVDIF(J) = ( GTAU(J+1) - GTAU(J) ) / DTAU(J)
  !
  !    and
  !
  !      H(U,Z) = ALPHA * U**3 
  !             + ( 1 - ALPHA ) * ( max ( ( ( U - ZETA ) / ( 1 - ZETA ) ), 0 )**3
  !
  !    with
  !
  !      ALPHA(Z) = ( 1 - GAMMA / 3 ) / ZETA
  !      ZETA(Z) = 1 - GAMMA * min ( ( 1 - Z ), 1/3 )
  !
  !    Thus, for 1/3 <= Z <= 2/3, F is just a cubic polynomial on
  !    the interval I.  Otherwise, it has one additional knot, at
  !
  !      TAU(I) + ZETA * DTAU(I).
  !
  !    As Z approaches 1, H(.,Z) has an increasingly sharp bend near 1,
  !    thus allowing F to turn rapidly near the additional knot.
  !
  !    In terms of F(J) = GTAU(J) and FSECND(J) = second derivative of F 
  !    at TAU(J), the coefficients for (*) are given as:
  !
  !      A = F(I) - D
  !      B = ( F(I+1) - F(I) ) - ( C - D )
  !      C = FSECND(I+1) * DTAU(I)**2 / HSECND(1,Z)
  !      D = FSECND(I) * DTAU(I)**2 / HSECND(1,1-Z)
  !
  !    Hence these can be computed once FSECND(1:NTAU) is fixed.
  !
  !    F is automatically continuous and has a continuous second derivative
  !    except when Z=0 or 1 for some I.  We determine FSECND from
  !    the requirement that the first derivative of F be continuous.
  !
  !    In addition, we require that the third derivative be continuous
  !    across TAU(2) and across TAU(NTAU-1).  This leads to a strictly
  !    diagonally dominant tridiagonal linear system for the FSECND(I)
  !    which we solve by Gauss elimination without pivoting.
  !
  !  Modified:
  !
  !    14 February 2007
  !
  !  Author:
  !
  !    Carl DeBoor
  !
  !  Reference:
  !
  !    Carl DeBoor,
  !    A Practical Guide to Splines,
  !    Springer, 2001,
  !    ISBN: 0387953663,
  !    LC: QA1.A647.v27.
  !
  !  Parameters:
  !
  !    Input, real ( kind = 8 ) TAU(NTAU), the sequence of data points.  
  !    TAU must be strictly increasing.
  !
  !    Input, real ( kind = 8 ) GTAU(NTAU), the corresponding sequence of
  !    function values.
  !
  !    Input, integer ( kind = 4 ) NTAU, the number of data points.  
  !    NTAU must be at least 4.
  !
  !    Input, real ( kind = 8 ) GAMMA, indicates whether additional flexibility
  !    is desired.
  !    GAMMA = 0.0, no additional knots;
  !    GAMMA in (0.0,3.0), under certain conditions on the given data at
  !    points I-1, I, I+1, and I+2, a knot is added in the I-th interval, 
  !    for I = 2,...,NTAU-2.  See description of method.  The interpolant 
  !    gets rounded with increasing gamma.  A value of 2.5 for GAMMA is typical.
  !    GAMMA in (3.0,6.0), same, except that knots might also be added in
  !    intervals in which an inflection point would be permitted.  A value 
  !    of 5.5 for GAMMA is typical.
  !
  !    Output, real ( kind = 8 ) BREAK(L), real ( kind = 8 ) COEF(K,L), 
  !    integer ( kind = 4 ) L, integer K, give the piecewise polynomial 
  !    representation of the interpolant.  Specifically, 
  !    for BREAK(i) <= X <= BREAK(I+1), the interpolant has the form:
  !      F(X) = COEF(1,I) +  DX    * ( 
  !             COEF(2,I) + (DX/2) * (
  !             COEF(3,I) + (DX/3) *
  !             COEF(4,I) ) )
  !    with  DX = X - BREAK(I) for I = 1,..., L.
  !
  !    Output, integer ( kind = 4 ) IFLAG, error flag.
  !    1, no error.
  !    2, input was incorrect.
  !
  !    Output, real ( kind = 8 ) S(NTAU,6).  The individual columns of this
  !    array contain the following quantities mentioned in the write up
  !    and below.
  !    S(.,1) = DTAU = TAU(.+1)-TAU;
  !    S(.,2) = DIAG = diagonal in linear system;
  !    S(.,3) = U = upper diagonal in linear system;
  !    S(.,4) = R = right hand side for linear system (initially)
  !           = FSECND = solution of linear system, namely the second
  !             derivatives of interpolant at TAU;
  !    S(.,5) = Z = indicator of additional knots;
  !    S(.,6) = 1/HSECND(1,X) with X = Z or 1-Z.
  !
  implicit none

  integer ( kind = 4 ) ntau

  real ( kind = 8 ) alph
  real ( kind = 8 ) alpha
  real ( kind = 8 ) break(*)
  real ( kind = 8 ) c
  real ( kind = 8 ) coef(4,*)
  real ( kind = 8 ) d
  real ( kind = 8 ) del
  real ( kind = 8 ) denom
  real ( kind = 8 ) divdif
  real ( kind = 8 ) entry
  real ( kind = 8 ) entry3
  real ( kind = 8 ) factor
  real ( kind = 8 ) factr2
  real ( kind = 8 ) gam
  real ( kind = 8 ) gamma
  real ( kind = 8 ) gtau(ntau)
  integer ( kind = 4 ) i
  integer ( kind = 4 ) iflag
  integer ( kind = 4 ) k
  integer ( kind = 4 ) l
  integer ( kind = 4 ) method
  real ( kind = 8 ) onemg3
  real ( kind = 8 ) onemzt
  real ( kind = 8 ) ratio
  real ( kind = 8 ) s(ntau,6)
  real ( kind = 8 ) sixth
  real ( kind = 8 ) tau(ntau)
  real ( kind = 8 ) temp
  real ( kind = 8 ) x
  real ( kind = 8 ) z
  real ( kind = 8 ) zeta
  real ( kind = 8 ) zt2

  alph(x) = min ( 1.0D+00, onemg3 / x )
  !
  !  There must be at least 4 interpolation points.
  !
  if ( ntau < 4 ) then
     write ( *, '(a)' ) ' '
     write ( *, '(a)' ) 'TAUTSP - Fatal error!'
     write ( *, '(a)' ) '  Input NTAU must be at least 4.'
     write ( *, '(a,i8)' ) '  NTAU = ', ntau
     iflag = 2
     stop
  end if
  !
  !  Construct delta TAU and first and second (divided) differences of data.
  !
  do i = 1, ntau - 1

     s(i,1) = tau(i+1) - tau(i)

     if ( s(i,1) <= 0.0D+00 ) then
        write ( *, '(a,i3,a,2e15.6,a)' ) &
             '  Point ', i, ' and the next ', tau(i), tau(i+1), ' are disordered.'
        iflag = 2
        return
     end if

     s(i+1,4) = ( gtau(i+1) - gtau(i) ) / s(i,1)

  end do

  do i = 2, ntau - 1
     s(i,4) = s(i+1,4) - s(i,4)
  end do
  !
  !  Construct system of equations for second derivatives at TAU.
  !
  !  At each interior data point, there is one continuity equation.
  !  At the first and last interior data point there is an additional 
  !  equation for a total of NTAU equations in NTAU unknowns.
  !
  i = 2
  s(2,2) = s(1,1) / 3.0D+00
  sixth = 1.0D+00 / 6.0D+00
  method = 2
  gam = gamma

  if ( gam <= 0.0D+00 ) then
     method = 1
  end if

  if ( 3.0D+00 < gam ) then
     method = 3
     gam = gam - 3.0D+00
  end if

  onemg3 = 1.0D+00 - gam / 3.0D+00
  !
  !  Loop over I.
  !
70 continue
  !
  !  Construct Z(I) and ZETA(I).
  !
  z = 0.5D+00

  if ( method == 1 ) then
     go to 100
  end if

  if ( method == 3 ) then
     go to 90
  end if

  if ( s(i,4) * s(i+1,4) < 0.0D+00 ) then
     go to 100
  end if

90 continue

  temp = abs ( s(i+1,4) )
  denom = abs ( s(i,4) ) + temp

  if ( denom /= 0.0D+00 ) then
     z = temp / denom
     if ( abs ( z - 0.5D+00 ) <= sixth ) then
        z = 0.5D+00
     end if
  end if

100 continue

  s(i,5) = z
  !
  !  Set up part of the I-th equation which depends on the I-th interval.
  !
  if ( z < 0.5D+00 ) then

     zeta = gam * z
     onemzt = 1.0D+00 - zeta
     zt2 = zeta**2
     alpha = alph(onemzt)
     factor = zeta / ( alpha * ( zt2 - 1.0D+00 ) + 1.0D+00 )
     s(i,6) = zeta * factor / 6.0D+00
     s(i,2) = s(i,2) + s(i,1) &
          * ( ( 1.0D+00 - alpha * onemzt ) * factor / 2.0D+00 - s(i,6) )
     !
     !  If Z = 0 and the previous Z = 1, then D(I) = 0.  
     !  Since then also U(I-1) = L(I+1) = 0, its value does not matter.  
     !  Reset D(I) = 1 to insure nonzero pivot in elimination.
     !
     if ( s(i,2) <= 0.0D+00 ) then
        s(i,2) = 1.0D+00
     end if

     s(i,3) = s(i,1) / 6.0D+00

  else if ( z == 0.5D+00 ) then

     s(i,2) = s(i,2) + s(i,1) / 3.0D+00
     s(i,3) = s(i,1) / 6.0D+00

  else if ( 0.5D+00 < z ) then

     onemzt = gam * ( 1.0D+00 - z )
     zeta = 1.0D+00 - onemzt
     alpha = alph(zeta)
     factor = onemzt / ( 1.0D+00 - alpha * zeta * ( 1.0D+00 + onemzt ) )
     s(i,6) = onemzt * factor / 6.0D+00
     s(i,2) = s(i,2) + s(i,1) / 3.0D+00
     s(i,3) = s(i,6) * s(i,1)

  end if

  if ( 2 < i ) then
     go to 190
  end if

  s(1,5) = 0.5D+00
  !
  !  The first two equations enforce continuity of the first and of
  !  the third derivative across TAU(2).
  !
  s(1,2) = s(1,1) / 6.0D+00
  s(1,3) = s(2,2)
  entry3 = s(2,3)

  if ( z < 0.5D+00 ) then

     factr2 = zeta * ( alpha * ( zt2 - 1.0D+00 ) + 1.0D+00 ) &
          / ( alpha * ( zeta * zt2 - 1.0D+00 ) + 1.0D+00 )

     ratio = factr2 * s(2,1) / s(1,2)
     s(2,2) = factr2 * s(2,1) + s(1,1)
     s(2,3) = - factr2 * s(1,1)

  else if ( z == 0.5D+00 ) then

     ratio = s(2,1) / s(1,2)
     s(2,2) = s(2,1) + s(1,1)
     s(2,3) = - s(1,1)

  else if ( 0.5D+00 < z ) then

     ratio = s(2,1) / s(1,2)
     s(2,2) = s(2,1) + s(1,1)
     s(2,3) = - s(1,1) * 6.0D+00 * alpha * s(2,6)

  end if
  !
  !  At this point, the first two equations read:
  !
  !              DIAG(1)*X1+U(1)*X2 + ENTRY3*X3 = R(2)
  !       -RATIO*DIAG(1)*X1+DIAG(2)*X2 + U(2)*X3 = 0.0
  !
  !  Eliminate first unknown from second equation.
  !
  s(2,2) = ratio * s(1,3) + s(2,2)
  s(2,3) = ratio * entry3 + s(2,3)
  s(1,4) = s(2,4)
  s(2,4) = ratio * s(1,4)

  go to 200

190 continue
  !
  !  The I-th equation enforces continuity of the first derivative
  !  across TAU(I).  It now reads:
  !
  !    - RATIO * DIAG(I-1) * X(I-1) + DIAG(I) * X(I) + U(I) * X(I+1) = R(I).
  !
  !  Eliminate (I-1)st unknown from this equation
  !
  s(i,2) = ratio * s(i-1,3) + s(i,2)
  s(i,4) = ratio * s(i-1,4) + s(i,4)
  !
  !  Set up the part of the next equation which depends on the I-th interval.
  !
200 continue

  if ( z < 0.5D+00 ) then

     ratio = - s(i,6) * s(i,1) / s(i,2)
     s(i+1,2) = s(i,1) / 3.0D+00

  else if ( z == 0.5D+00 ) then

     ratio = - ( s(i,1) / 6.0D+00 ) / s(i,2)
     s(i+1,2) = s(i,1) / 3.0D+00

  else if ( 0.5D+00 < z ) then

     ratio = - ( s(i,1) / 6.0D+00 ) / s(i,2)
     s(i+1,2) = s(i,1) &
          * ( ( 1.0D+00 - zeta * alpha ) * factor / 2.0D+00 - s(i,6) )

  end if
  !
  !  End of I loop.
  !
  i = i + 1

  if ( i < ntau - 1 ) then
     go to 70
  end if

  s(i,5) = 0.5D+00
  !
  !  The last two equations enforce continuity of third derivative and
  !  of first derivative across TAU(NTAU-1).
  !
  entry = ratio * s(i-1,3) + s(i,2) + s(i,1) / 3.0D+00
  s(i+1,2) = s(i,1) / 6.0D+00
  s(i+1,4) = ratio * s(i-1,4) + s(i,4)

  if ( z < 0.5D+00 ) then

     ratio = s(i,1) * 6.0D+00 * s(i-1,6) * alpha / s(i-1,2)
     s(i,2) = ratio * s(i-1,3) + s(i,1) + s(i-1,1)
     s(i,3) = - s(i-1,1)

  else if ( z == 0.5D+00 ) then

     ratio = s(i,1) / s(i-1,2)
     s(i,2) = ratio * s(i-1,3) + s(i,1) + s(i-1,1)
     s(i,3) = - s(i-1,1)

  else if ( 0.5D+00 < z ) then

     factr2 = onemzt * ( alpha * ( onemzt**2 - 1.0D+00 ) + 1.0D+00 ) &
          / ( alpha * ( onemzt**3 - 1.0D+00 ) + 1.0D+00 )

     ratio = factr2 * s(i,1) / s(i-1,2)
     s(i,2) = ratio * s(i-1,3) + factr2 * s(i-1,1) + s(i,1)
     s(i,3) = - factr2 * s(i-1,1)

  end if
  !
  !  At this point, the last two equations read:
  !
  !           DIAG(I)*XI+     U(I)*XI+1 = R(I)
  !    -RATIO*DIAG(I)*XI+DIAG(I+1)*XI+1 = R(I+1)
  !
  !  Eliminate XI from the last equation.
  !
  s(i,4) = ratio * s(i-1,4)
  ratio = - entry / s(i,2)
  s(i+1,2) = ratio * s(i,3) + s(i+1,2)
  s(i+1,4) = ratio * s(i,4) + s(i+1,4)
  !
  !  Back substitution.
  !
  s(ntau,4) = s(ntau,4) / s(ntau,2)

  do while ( 1 < i )

     s(i,4) = ( s(i,4) - s(i,3) * s(i+1,4) ) / s(i,2)
     i = i - 1

  end do

  s(1,4) = ( s(1,4) - s(1,3) * s(2,4) - entry3 * s(3,4) ) / s(1,2)
  !
  !  Construct polynomial pieces. 
  !
  break(1) = tau(1)
  l = 1

  do i = 1, ntau - 1

     coef(1,l) = gtau(i)
     coef(3,l) = s(i,4)
     divdif = ( gtau(i+1) - gtau(i) ) / s(i,1)
     z = s(i,5)

     if ( z == 0.0D+00 ) then

        coef(2,l) = divdif
        coef(3,l) = 0D+00
        coef(4,l) = 0.0D+00

     else if ( z < 0.5D+00 ) then

        zeta = gam * z
        onemzt = 1.0D+00 - zeta
        c = s(i+1,4) / 6.0D+00
        d = s(i,4) * s(i,6)
        l = l + 1
        del = zeta * s(i,1)
        break(l) = tau(i) + del
        zt2 = zeta**2
        alpha = alph(onemzt)
        factor = onemzt**2 * alpha
        coef(1,l) = gtau(i) + divdif * del &
             + s(i,1)**2 * ( d * onemzt * ( factor - 1.0D+00 ) &
             + c * zeta * ( zt2 - 1.0D+00 ) )
        coef(2,l) = divdif + s(i,1) * ( d * ( 1.0D+00 - 3.0D+00 * factor ) &
             + c * ( 3.0D+00 * zt2 - 1.0D+00 ) )
        coef(3,l) = 6.0D+00 * ( d * alpha * onemzt + c * zeta )
        coef(4,l) = 6.0D+00 * ( c - d * alpha ) / s(i,1)
        coef(4,l-1) = coef(4,l) &
             - 6.0D+00 * d * ( 1.0D+00 - alpha ) / ( del * zt2 )
        coef(2,l-1) = coef(2,l) - del * ( coef(3,l) &
             - ( del / 2.0D+00 ) * coef(4,l-1))

     else if ( z == 0.5D+00 ) then

        coef(2,l) = divdif &
             - s(i,1) * ( 2.0D+00 * s(i,4) + s(i+1,4) ) / 6.0D+00
        coef(4,l) = ( s(i+1,4) - s(i,4) ) / s(i,1)

     else if ( 0.5D+00 <= z ) then

        onemzt = gam * ( 1.0D+00 - z )

        if ( onemzt == 0.0D+00 ) then

           coef(2,l) = divdif
           coef(3,l) = 0D+00
           coef(4,l) = 0.0D+00

        else

           zeta = 1.0D+00 - onemzt
           alpha = alph(zeta)
           c = s(i+1,4) * s(i,6)
           d = s(i,4) / 6.0D+00
           del = zeta * s(i,1)
           break(l+1) = tau(i) + del
           coef(2,l) = divdif - s(i,1) * ( 2.0D+00 * d + c )
           coef(4,l) = 6.0D+00 * ( c * alpha - d ) / s(i,1)
           l = l + 1
           coef(4,l) = coef(4,l-1) + 6.0D+00 * ( 1.0D+00 - alpha ) * c &
                / ( s(i,1) * onemzt**3 )
           coef(3,l) = coef(3,l-1) + del * coef(4,l-1)
           coef(2,l) = coef(2,l-1) + del * ( coef(3,l-1) &
                + ( del / 2.0D+00 ) * coef(4,l-1) )
           coef(1,l) = coef(1,l-1) + del * ( coef(2,l-1) &
                + ( del / 2.0D+00 ) * ( coef(3,l-1) &
                + ( del / 3.0D+00 ) * coef(4,l-1) ) )

        end if

     end if

     l = l + 1
     break(l) = tau(i+1)

  end do

  l = l - 1
  k = 4
  iflag = 1

  return
end subroutine tautsp