/*===========================================================================
  Copyright (C) 2001 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program 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 General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
    Internet e-mail: midas@eso.org
    Postal address: European Southern Observatory
            Data Management Division 
            Karl-Schwarzschild-Strasse 2
            D 85748 Garching bei Muenchen 
            GERMANY
===========================================================================*/
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <flames_newmatrix.h>
#include <flames_mrqcof.h>
/* taken from MIDAS */

void mrqcof(float x[],
            float y[],
            float sig[],
            int   ndata,
            float a[],
            int   ma,
            int   lista[],
            int   mfit,
            float ** alpha,
            float beta[],
            float * chisq,
            void (*funcs)(float,float *,float *,float *,int))
{
    int k,j,i;
    float ymod,wt,sig2i,dy,*dyda;

    dyda=vector(1,ma);
    for (j=1;j<=mfit;j++) {
        for (k=1;k<=j;k++) alpha[j][k]=0.0;
        beta[j]=0.0;
    }
    *chisq=0.0;
    for (i=1;i<=ndata;i++) {
        (*funcs)(x[i],a,&ymod,dyda,ma);
        sig2i=1.0/(sig[i]*sig[i]);
        dy=y[i]-ymod;
        for (j=1;j<=mfit;j++) {
            wt=dyda[lista[j]]*sig2i;
            for (k=1;k<=j;k++)
                alpha[j][k] += wt*dyda[lista[k]];
            beta[j] += dy*wt;
        }
        (*chisq) += dy*dy*sig2i;
    }
    for (j=2;j<=mfit;j++)
        for (k=1;k<=j-1;k++) alpha[k][j]=alpha[j][k];
    free_vector(dyda,1,ma);
}



/* mrq_cof() is the same as mrqcof() except for that x is assumed to be
   an array starting at 1 and having a step size of 1: 1,2,3,4,...,ndata
 */
void mrq_cof(float y[],
             float sig[],
             int ndata,
             float a[],
             int ma,
             int lista[],
             int mfit,
             float** alpha,
             float beta[],
             float * chisq,
             void (*funcs)(float,float *,float *,float *,int))
{
    int k,j,i;
    float x;
    float ymod,wt,sig2i,dy,*dyda;

    dyda=vector(1,ma);
    for (j=1;j<=mfit;j++) {
        for (k=1;k<=j;k++) alpha[j][k]=0.0;
        beta[j]=0.0;
    }
    *chisq=0.0;
    for (i=1;i<=ndata;i++) {
        x = i;
        (*funcs)(x,a,&ymod,dyda,ma);
        sig2i=1.0/(sig[i]*sig[i]);
        dy=y[i]-ymod;
        for (j=1;j<=mfit;j++) {
            wt=dyda[lista[j]]*sig2i;
            for (k=1;k<=j;k++)
                alpha[j][k] += wt*dyda[lista[k]];
            beta[j] += dy*wt;
        }
        (*chisq) += dy*dy*sig2i;
    }
    for (j=2;j<=mfit;j++)
        for (k=1;k<=j-1;k++) alpha[k][j]=alpha[j][k];
    free_vector(dyda,1,ma);
}
