/*                                                                              *
 *   This file is part of the ESO UVES Pipeline                                 *
 *   Copyright (C) 2004,2005 European Southern Observatory                      *
 *                                                                              *
 *   This library 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
 *                                                                              */
 
/*
 * $Author: amodigli $
 * $Date: 2012-01-17 07:53:20 $
 * $Revision: 1.9 $
 * $Name: not supported by cvs2svn $
 * $Log: not supported by cvs2svn $
 * Revision 1.8  2009/06/05 05:49:02  amodigli
 * updated init/end to cpl5
 *
 * Revision 1.7  2007/09/11 17:10:20  amodigli
 * moved test_midas_poly to test_dfs
 *
 * Revision 1.6  2007/06/20 13:04:26  amodigli
 * fix interface to
 *
 * Revision 1.5  2007/05/23 06:43:23  jmlarsen
 * Removed unused variables
 *
 * Revision 1.4  2007/05/03 15:18:22  jmlarsen
 * Added function to add polynomials
 *
 * Revision 1.3  2007/04/24 12:50:29  jmlarsen
 * Replaced cpl_propertylist -> uves_propertylist which is much faster
 *
 * Revision 1.2  2007/03/19 13:51:41  jmlarsen
 * Added test of 2d fitting
 *
 * Revision 1.1  2007/03/15 12:27:18  jmlarsen
 * Moved unit tests to ./uves/tests and ./flames/tests
 *
 * Revision 1.3  2007/02/27 14:04:14  jmlarsen
 * Move unit test infrastructure to IRPLIB
 *
 * Revision 1.2  2007/01/29 12:17:54  jmlarsen
 * Support setting verbosity from command line
 *
 * Revision 1.1  2006/11/24 09:40:17  jmlarsen
 * Added polynomial tests
 *
 * Revision 1.1  2006/11/22 08:04:59  jmlarsen
 * Added uves_dfs unit test module
 *
 * Revision 1.20  2006/11/16 09:49:25  jmlarsen
 * Fixed doxygen bug
 *
 * Revision 1.19  2006/11/08 14:04:03  jmlarsen
 * Doxybugfix
 *
 */

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

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

#include <uves_utils_polynomial.h>
#include <uves_error.h>
#include <uves_utils_wrappers.h>
#include <cpl_test.h>

#include <cpl.h>
/*-----------------------------------------------------------------------------
                                Defines
 -----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/**
 * @defgroup uves_polynomial_test  UVES polynomial unit tests
 */
/*----------------------------------------------------------------------------*/
/**@{*/


/*----------------------------------------------------------------------------*/
/**
   @brief  Test polynomial fitting
 */
/*----------------------------------------------------------------------------*/
static void
test_polynomial_fit_2d(void)
{
    polynomial *pol = NULL;
    cpl_vector *x = NULL;
    cpl_vector *y = NULL;
    cpl_bivector *xy = NULL;
    cpl_vector *z = NULL;
/*    cpl_vector *sigma = NULL;*/
    int degx, degy;

    /* build data */
    double coeff[3] = {43, -0.3, 0.0001};
    double valx, valy, valz;
    int npoints = 0;
    x = cpl_vector_new(1);
    y = cpl_vector_new(1);
    z = cpl_vector_new(1);
    
    for (valx = -10; valx <= 50; valx += 4.7)
        for (valy = 0.001; valy <= 0.002; valy *= 1.1)
            {
                /* z = (2, 4) degree polynomial in x, y */
                valz = coeff[0]*valx*valx + coeff[1]*valy*valx + coeff[2]*valy*valy*valy*valy;
                npoints++;
                cpl_vector_set_size(x, npoints);
                cpl_vector_set_size(y, npoints);
                cpl_vector_set_size(z, npoints);
                cpl_vector_set(x, npoints-1, valx);
                cpl_vector_set(y, npoints-1, valy);
                cpl_vector_set(z, npoints-1, valz);
            }
    
    /* call function */
    for (degx = 0; degx <= 5; degx++)
        for (degy = 0; degy <= 5; degy++) {
            uves_unwrap_bivector_vectors(&xy);
            xy = cpl_bivector_wrap_vectors(x, y);
            
            uves_polynomial_delete(&pol);                    
            check_nomsg( pol = uves_polynomial_fit_2d(xy,
                                                      z,
                                                      NULL, /* sigma */
                                                      degx, degy,
                                                      NULL, NULL, NULL));
            
            /* test results */
            if (degx >= 2 && degy >= 4) {
                /* Then we should have reproduced the input polynomial */
                int i;
                for (i = 0; i < cpl_vector_get_size(x); i++)
                    {
                        cpl_test_rel(uves_polynomial_evaluate_2d(pol, 
                                                                    cpl_vector_get(x, i),
                                                                    cpl_vector_get(y, i)),
                                        cpl_vector_get(z, i), 0.001);
                    }
                
                /* comparing the actual coefficients is less reliable */
#if 0
                for (i = 0; i <= degx; i++)
                    for (j = 0; j <= degy; j++)
                        if (i == 2 && j == 0)
                            cpl_test_rel(uves_polynomial_get_coeff_2d(pol, i, j), coeff[0], 0.0001);
                        else if (i == 1 && j == 1)
                            cpl_test_rel(uves_polynomial_get_coeff_2d(pol, i, j), coeff[1], 0.0001);
                        else if (i == 0 && j == 4)
                            cpl_test_rel(uves_polynomial_get_coeff_2d(pol, i, j), coeff[2], 0.0001);
                        else
                            {
                                uves_msg_warning("%d, %d", i, j);
                                cpl_test_abs(uves_polynomial_get_coeff_2d(pol, i, j), 0, 0.1);
                            }
#endif
            }
        }
    
  cleanup:
    uves_free_vector(&x);
    uves_free_vector(&y);
    uves_free_vector(&z);
    uves_unwrap_bivector_vectors(&xy);
    uves_polynomial_delete(&pol);                    
    return;
}

/*----------------------------------------------------------------------------*/
/**
  @brief   Various tests
**/
/*----------------------------------------------------------------------------*/
static void
test_polynomial(void)
{
    cpl_polynomial *cp1 = cpl_polynomial_new(2);
    cpl_polynomial *cp2 = cpl_polynomial_new(2);
    cpl_size power[2] = {0, 3};
    polynomial *p1;
    polynomial *p2;
    polynomial *p3;

    cpl_polynomial_set_coeff(cp1, power, 7.0);
    cpl_polynomial_set_coeff(cp2, power, 9.0);

    p1 = uves_polynomial_new(cp1);
    p2 = uves_polynomial_new(cp2);

    uves_polynomial_rescale(p1, 0, 2.0);
    uves_polynomial_rescale(p2, 0, 2.0);

    check_nomsg( p3 = uves_polynomial_add_2d(p1, p2) );

    cpl_test_abs(uves_polynomial_get_coeff_2d(p3, 0, 0), 0 , 0.0001);
    cpl_test_abs(uves_polynomial_get_coeff_2d(p3, 0, 3), 7*2+9*2, 0.0001);
    
  cleanup:
    uves_free_polynomial(&cp1);
    uves_free_polynomial(&cp2);
    uves_polynomial_delete(&p1);
    uves_polynomial_delete(&p2);
    uves_polynomial_delete(&p3);
    return;
    
}
   
/*----------------------------------------------------------------------------*/
/**
  @brief   Test of uves_polynomial
**/
/*----------------------------------------------------------------------------*/

int main(void)
{
    cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);

    test_polynomial_fit_2d();

    check_nomsg( test_polynomial() );

  cleanup:
    return cpl_test_end(0);
}


/**@}*/
