/*===========================================================================
  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
===========================================================================*/

/*-------------------------------------------------------------------------*/
/**
 * @defgroup flames_computeback   Substep: Compute background frame  
 *
 */
/*-------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
                          Includes
 --------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <flames_midas_def.h>
#include <flames_uves.h>
#include <flames_newmatrix.h>
#include <flames_computeback.h>

#include <uves_msg.h>

#include <math.h>
#include <stdio.h>
/**@{*/

/*---------------------------------------------------------------------------
                            Implementation
 ---------------------------------------------------------------------------*/
/**
 @name  flames_computeback()  
 @short Compute background frame 
 @author G. Mulas  -  ITAL_FLAMES Consortium. Ported to CPL by A. Modigliani

 @param Frame   input frame
 @param backframe output background frame


 @return success or failure code

 DRS Functions called:          
       dmatrix
                                                                         
 Pseudocode: computes background frame corresponding to determined x,y degrees 
 
@note
*/
flames_err computeback(flames_frame *Frame, frame_data **backframe)
{
 
 int i=0,j=0,k=0,l=0,m=0;

 /* use some buffers to speed up the calculation of coordinate powers */
 double **xpowers, **ypowers;
 double *xbuf, *xbuf1, *ybuf, *ybuf1;
 double xscale, yscale;
 frame_data *fdbuf, fdbuf1;
 double dbuf1, dbuf2;
 uves_msg_debug("computeback 0");
 uves_msg_debug("xdeg=%d subcols=%d\n",Frame->back.xdegree, Frame->subcols);

 xpowers = dmatrix(1, Frame->back.xdegree, 1, Frame->subcols);
 uves_msg_debug("computeback 01");
 ypowers = dmatrix(1, Frame->back.ydegree, 1, Frame->subrows);
 xscale = Frame->subcols>=2 ? (double)Frame->subcols-1 : 1;
 yscale = Frame->subrows>=2 ? (double)Frame->subrows-1 : 1;
 int32_t npar = (int32_t)(Frame->back.xdegree+1)*(Frame->back.ydegree+1);
 
 /* set up the buffers now */
 xbuf1 = xpowers[1];
 ybuf1 = ypowers[1];

 for (i=0; i<=(Frame->subrows-1); i++) ybuf1[i] = ((double) i)/yscale;
 for (j=0; j<=(Frame->subcols-1); j++) xbuf1[j] = ((double) j)/xscale;
 
 for (k=2; k<=Frame->back.ydegree; k++) {
   ybuf = ypowers[k];
   double* ybuf2 = ypowers[k-1];
   for (i=0; i<=(Frame->subrows-1); i++) ybuf[i] = ybuf1[i]*ybuf2[i];
 }

 for (k=2; k<=Frame->back.xdegree; k++) {
   xbuf = xpowers[k];
   double* xbuf2 = xpowers[k-1];
   for (j=0; j<=(Frame->subcols-1); j++) xbuf[j] = xbuf1[j]*xbuf2[j];
 }

 /* compute the fitted points */
 /* xdeg = ydeg = 0 */
 fdbuf1 = (frame_data) Frame->back.coeff[1];
 for (i=0; i<=(Frame->subrows-1); i++) {
   fdbuf = backframe[i];
   for (j=0; j<=(Frame->subcols-1); j++) {
     fdbuf[j] = fdbuf1;
   }
 }

 m=1;
 for (l=1; l<=Frame->back.xdegree; l++) {
   /* ydeg = 0, xdeg>0 */
   m++;
   xbuf = xpowers[l];
   dbuf1 = Frame->back.coeff[m];
   for (i=0; i<=(Frame->subrows-1); i++) {
     fdbuf = backframe[i];
     for (j=0; j<=(Frame->subcols-1); j++) {
       fdbuf[j] += (frame_data) (dbuf1*xbuf[j]);
     }
   }
 }


 for (k=1; k<=Frame->back.ydegree; k++) {
   /* ydeg > 0, xdeg=0 */
   m++;
   ybuf = ypowers[k];
   dbuf1 = Frame->back.coeff[m];
   for (i=0; i<=(Frame->subrows-1); i++) {
     fdbuf = backframe[i];
     fdbuf1 = (frame_data) (dbuf1*ybuf[i]);
     for (j=0; j<=(Frame->subcols-1); j++) {
       fdbuf[j] += fdbuf1;
     }
   }
   /* ydeg > 0, xdeg>0 */
   for (l=1; l<=Frame->back.xdegree; l++) {
     m++;
     xbuf = xpowers[l];
     dbuf1 = Frame->back.coeff[m];
     for (i=0; i<=(Frame->subrows-1); i++) {
       fdbuf = backframe[i];
       dbuf2 = dbuf1*ybuf[i];
       for (j=0; j<=(Frame->subcols-1); j++) {
     fdbuf[j] += (frame_data) (dbuf2*xbuf[j]);
       }
     }
   }
 }

 /* free local temporary buffers */
 free_dmatrix(xpowers, 1, Frame->back.xdegree, 1, Frame->subcols);
 free_dmatrix(ypowers, 1, Frame->back.ydegree, 1, Frame->subrows);

 return NOERR;

}
/**@}*/

