      subroutine l2appr ( t, n, k, q, diag, bcoef )
c  from  * a practical guide to splines *  by c. de boor
c  to be called in main program  l 2 m a i n .
calls subprograms  bsplvb, bchfac/slv
c
constructs the (weighted discrete) l2-approximation by splines of order
c  k  with knot sequence  t(1), ..., t(n+k)  to given data points
c  ( tau(i), gtau(i) ), i=1,...,ntau. the b-spline coefficients
c  b c o e f   of the approximating spline are determined from the
c  normal equations using cholesky's method.
c
c******  i n p u t  ******
c  t(1), ..., t(n+k)  the knot sequence
c  n.....the dimension of the space of splines of order k with knots t.
c  k.....the order
c
c  w a r n i n g  . . .  the restriction   k .le. kmax (= 20)   is impo-
c        sed by the arbitrary dimension statement for  biatx  below, but
c        is  n o w h e r e   c h e c k e d   for.
c
c******  w o r k  a r r a y s  ******
c  q....a work array of size (at least) k*n. its first  k  rows are used
c       for the  k  lower diagonals of the gramian matrix  c .
c  diag.....a work array of length  n  used in bchfac .
c
c******  i n p u t  via  c o m m o n  /data/  ******
c  ntau.....number of data points
c  (tau(i),gtau(i)), i=1,...,ntau     are the  ntau  data points to be
c        fitted .
c  weight(i), i=1,...,ntau    are the corresponding weights .
c
c******  o u t p u t  ******
c  bcoef(1), ..., bcoef(n)  the b-spline coeffs. of the l2-appr.
c
c******  m e t h o d  ******
c  the b-spline coefficients of the l2-appr. are determined as the sol-
c  ution of the normal equations
c     sum ( (b(i),b(j))*bcoef(j) : j=1,...,n)  = (b(i),g),
c                                               i = 1, ..., n .
c  here,  b(i)  denotes the i-th b-spline,  g  denotes the function to
c  be approximated, and the  i n n e r   p r o d u c t  of two funct-
c  ions  f  and  g  is given by
c      (f,g)  :=  sum ( f(tau(i))*g(tau(i))*weight(i) : i=1,...,ntau) .
c  the arrays  t a u  and  w e i g h t  are given in common block
c   d a t a , as is the array  g t a u  containing the sequence
c  g(tau(i)), i=1,...,ntau.
c  the relevant function values of the b-splines  b(i), i=1,...,n, are
c  supplied by the subprogram  b s p l v b .
c     the coeff.matrix  c , with
c           c(i,j)  :=  (b(i), b(j)), i,j=1,...,n,
c  of the normal equations is symmetric and (2*k-1)-banded, therefore
c  can be specified by giving its k bands at or below the diagonal. for
c  i=1,...,n,  we store
c   (b(i),b(j))  =  c(i,j)  in  q(i-j+1,j), j=i,...,min0(i+k-1,n)
c  and the right side
c   (b(i), g )  in  bcoef(i) .
c  since b-spline values are most efficiently generated by finding sim-
c  ultaneously the value of  e v e r y  nonzero b-spline at one point,
c  the entries of  c  (i.e., of  q ), are generated by computing, for
c  each ll, all the terms involving  tau(ll)  simultaneously and adding
c  them to all relevant entries.
c
      integer k,n,   i,j,jj,kmax,left,leftmk,ll,mm,ntau,ntmax
      parameter (kmax=20,ntmax=200)
      real bcoef(n),diag(n),q(k,n),t(n+k),  biatx(kmax),dw,gtau,tau,weight
      common / data / ntau, tau(ntmax),gtau(ntmax),weight(ntmax)
c
      do 7 j=1,n
         bcoef(j) = 0.
         do 7 i=1,k
    7       q(i,j) = 0.
      left = k
      leftmk = 0
      do 20 ll=1,ntau
c                   locate  l e f t  s.t. tau(ll) in (t(left),t(left+1))
   10       if (left .eq. n)            go to 15
            if (tau(ll) .lt. t(left+1)) go to 15
            left = left+1
            leftmk = leftmk + 1
                                        go to 10
   15    call bsplvb ( t, k, 1, tau(ll), left, biatx )
c        biatx(mm) contains the value of b(left-k+mm) at tau(ll).
c        hence, with  dw := biatx(mm)*weight(ll), the number dw*gtau(ll)
c        is a summand in the inner product
c           (b(left-k+mm), g)  which goes into  bcoef(left-k+mm)
c        and the number biatx(jj)*dw is a summand in the inner product
c           (b(left-k+jj), b(left-k+mm)), into  q(jj-mm+1,left-k+mm)
c        since  (left-k+jj) - (left-k+mm) + 1  =  jj - mm + 1 .
         do 20 mm=1,k
            dw = biatx(mm)*weight(ll)
            j = leftmk + mm
            bcoef(j) = dw*gtau(ll) + bcoef(j)
            i = 1
            do 20 jj=mm,k
               q(i,j) = biatx(jj)*dw + q(i,j)
   20          i = i + 1
c
c             construct cholesky factorization for  c  in  q , then use
c             it to solve the normal equations
c                    c*x  =  bcoef
c             for  x , and store  x  in  bcoef .
      call bchfac ( q, k, n, diag )
      call bchslv ( q, k, n, bcoef )
                                        return
      end