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

}
/**@}*/

