/** @file  psMinimize.c
 *  \brief basic minimization functions
 *  @ingroup Math
 *
 *  This file will contain function prototypes for various minimization,
 *  chi-squared minimization, and 1-D polynomial fitting routines.
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.29 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2004-10-06 23:38:49 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 *
 */

#if !defined(PS_MINIMIZE_H)
#define PS_MINIMIZE_H

#include <stdio.h>
#include <float.h>
#include <math.h>

#include "psMemory.h"
#include "psVector.h"
#include "psArray.h"
#include "psImage.h"
#include "psMatrix.h"
#include "psFunctions.h"
#include "psStats.h"
#include "psTrace.h"
#include "psLogMsg.h"
#include "psError.h"
#include "psAbort.h"
#include "psConstants.h"


/** \file psMinimize.h
 *  \brief minimization operations
 *  \ingroup Stats
 */
/** \addtogroup Stats
 *  \{
 */

typedef struct
{
    int maxIter;                       ///< Convergence limit
    float tol;                         ///< Error Tolerance
    float value;                       ///< Value of function at minimum
    int iter;                          ///< Number of iterations required
    float lastDelta;                   ///< The last difference for the fit
}
psMinimization;

psMinimization *psMinimizationAlloc(int maxIter,
                                    float tol);

/** Derive a polynomial fit.
 *
 *  psVectorFitPolynomial1d returns the polynomial that best fits the 
 *  observations. The input parameters are a polynomial that specifies the 
 *  fit order, myPoly, which will be altered and returned with the best-fit 
 *  coefficients; and the observations, x, y and yErr. The independent 
 *  variable list, x may be NULL, in which case the vector index is used. 
 *  The dependent variable error, yErr may be null, in which case the solution 
 *  is determined in the assumption that all data errors are equal. This 
 *  function must be valid only for types psF32, psF64.
 *
 *  @return psPolynomial1D*    polynomial fit
 */
psPolynomial1D* psVectorFitPolynomial1D(
    psPolynomial1D* myPoly,            ///< Polynomial to fit
    const psVector* restrict x,        ///< Ordinates (or NULL to just use the indices)
    const psVector* restrict y,        ///< Coordinates
    const psVector* restrict yErr      ///< Errors in coordinates, or NULL
);

psSpline1D *psVectorFitSpline1D(psSpline1D *mySpline,              ///< The spline which will be generated.
                                const psVector* restrict x,        ///< Ordinates (or NULL to just use the indices)
                                const psVector* restrict y,        ///< Coordinates
                                const psVector* restrict yErr      ///< Errors in coordinates, or NULL
                               );


// XXX: What if any of these arguments are NULL?
typedef
float (*psMinimizeLMChi2Func)(psVector *deriv,
                              const psVector *params,
                              const psVector *coords);

bool psMinimizeLMChi2(psMinimization *min,
                      psVector *params,
                      const psVector *paramMask,
                      psImage *covar,
                      const psArray *coords,
                      const psVector *value,
                      psMinimizeLMChi2Func func);

typedef
float (*psMinimizePowellFunc)(const psVector *params,
                              const psArray *coords);

bool psMinimizePowell(psMinimization *min,
                      psVector *params,
                      const psVector *paramMask,
                      const psArray *coords,
                      psMinimizePowellFunc func);

typedef
psVector *(*psMinimizeChi2PowellFunc)(const psVector *params,
                                      const psArray *coords);

bool psMinimizeChi2Powell(psMinimization *min,
                          psVector *params,
                          const psVector *paramMask,
                          const psArray *coords,
                          const psVector *value,
                          const psVector *error,
                          psMinimizeChi2PowellFunc func);



/* \} */// End of MathGroup Functions

#endif

