subroutine lfit(x,y,weight,ndata,a,ma,covar,ncvm,chisq,funcs,error)
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! CLASS internal routine
  ! Given a set of NDATA points X(I),Y(I) with individual weights WEIGHT(I),
  ! use Chi2 minimization to determine the MA coefficients A
  ! of a function that depends linearly on A.
  !---------------------------------------------------------------------
  integer,                    intent(in)  :: ndata   ! Size of data arrays
  real, dimension(ndata),     intent(in)  :: x       ! Abscissa of input values
  real, dimension(ndata),     intent(in)  :: y       ! Ordinates of input values
  real, dimension(ndata),     intent(in)  :: weight  ! Weights
  integer,                    intent(in)  :: ma      ! Approx. polynom number
  real, dimension(ma),        intent(out) :: a       ! Output coefficients
  integer,                    intent(in)  :: ncvm    ! Size of covariance matrix
  real, dimension(ncvm,ncvm), intent(out) :: covar   ! Covariance matrix (pivot)
  real,                       intent(out) :: chisq   ! Chi2 value
  external                                :: funcs   ! Approx. function
  logical,                    intent(out) :: error   ! Error flag
  ! Local
  integer, parameter :: mmax=50
  real :: beta(mmax),afunc(mmax)
  integer :: i,j,k
  real :: sig2i,sum,ym,wt
  !
  if (ma.gt.mmax) then
     call class_message(seve%f,'LFIT','Incoherent array dimensions')
     error = .true.
     return
  endif
  !
  do j=1,ma
     do k=1,ma
        covar(j,k)=0.
     enddo
     beta(j)=0.
  enddo
  do i=1,ndata
     call funcs(x(i),afunc,ma)
     ym=y(i)
     sig2i=weight(i)
     do j=1,ma
        wt=afunc(j)*sig2i
        do k=1,j
           covar(j,k)=covar(j,k)+wt*afunc(k)
        enddo
        beta(j)=beta(j)+ym*wt
     enddo
  enddo
  if (ma.gt.1) then
     do j=2,ma
        do k=1,j-1
           covar(k,j)=covar(j,k)
        enddo
     enddo
  endif
  call gaussj(covar,ma,ncvm,beta,1,1)
  do j=1,ma
     a(j)=beta(j)
  enddo
  chisq=0.
  do i=1,ndata
     call funcs(x(i),afunc,ma)
     sum=0.
     do j=1,ma
        sum=sum+a(j)*afunc(j)
     enddo
     chisq=chisq+((y(i)-sum)*weight(i))**2
  enddo
  return
end subroutine lfit
!
subroutine gaussj(a,n,np,b,m,mp)
  use gbl_message
  !---------------------------------------------------------------------
  ! @ private
  ! CLASS internal routine
  ! Gauss Jordan elimination with full pivoting
  ! Solve A.X = B by computing inv(A) : X = inv(A).B
  !---------------------------------------------------------------------
  integer, intent(in)    ::  np        ! Size
  real,    intent(inout) ::  a(np,np)  ! On input A ; on output inv(A)
  integer, intent(in)    ::  n         ! Size of X vectors
  integer, intent(in)    ::  mp        ! Size
  real,    intent(inout) ::  b(np,mp)  ! On input, RHS ; on output, X vectors
  integer, intent(in)    ::  m         ! Number of X vectors
  ! Local
  character(len=*), parameter :: rname='GAUSSJ'
  integer, parameter :: nmax=50
  real :: big,dum,pivinv
  integer, dimension(nmax) :: ipiv,indxr,indxc
  integer :: i,j,k,l,ll,irow,icol
  !
  do j=1,n
     ipiv(j)=0
  enddo
  do i=1,n
     big=0.
     do j=1,n
        if(ipiv(j).ne.1)then
           do k=1,n
              if (ipiv(k).eq.0) then
                 if (abs(a(j,k)).ge.big)then
                    big=abs(a(j,k))
                    irow=j
                    icol=k
                 endif
              elseif  (ipiv(k).gt.1) then
                 call class_message(seve%r,rname,'Singular matrix')
                 return
              endif
           enddo
        endif
     enddo
     ipiv(icol)=ipiv(icol)+1
     if (irow.ne.icol) then
        do l=1,n
           dum=a(irow,l)
           a(irow,l)=a(icol,l)
           a(icol,l)=dum
        enddo
        do l=1,m
           dum=b(irow,l)
           b(irow,l)=b(icol,l)
           b(icol,l)=dum
        enddo
     endif
     indxr(i)=irow
     indxc(i)=icol
     if (a(icol,icol).eq.0.) then
        call class_message(seve%r,rname,'Singular matrix')
        return
     endif
     pivinv=1./a(icol,icol)
     a(icol,icol)=1.
     do l=1,n
        a(icol,l)=a(icol,l)*pivinv
     enddo
     do l=1,m
        b(icol,l)=b(icol,l)*pivinv
     enddo
     do ll=1,n
        if(ll.ne.icol)then
           dum=a(ll,icol)
           a(ll,icol)=0.
           do l=1,n
              a(ll,l)=a(ll,l)-a(icol,l)*dum
           enddo
           do  l=1,m
              b(ll,l)=b(ll,l)-b(icol,l)*dum
           enddo
        endif
     enddo
  enddo
  do l=n,1,-1
     if(indxr(l).ne.indxc(l))then
        do k=1,n
           dum=a(k,indxr(l))
           a(k,indxr(l))=a(k,indxc(l))
           a(k,indxc(l))=dum
        enddo
     endif
  enddo
  return
end subroutine gaussj
