/** @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.39 $ $Name:  $
 *  @date $Date: 2005/02/17 19:26:23 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 *
 */

#if !defined(PS_MINIMIZE_H)
#define PS_MINIMIZE_H

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

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

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

psMinimization *psMinimizationAlloc(psS32 maxIter,
                                    psF32 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* x,                 ///< Ordinates (or NULL to just use the indices)
    const psVector* y,                 ///< Coordinates
    const psVector* yErr               ///< Errors in coordinates, or NULL
);

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

typedef
psF64 (*psMinimizeLMChi2Func)(psVector *deriv,
                                  psVector *params,
                                  psVector *x);

psBool psMinimizeLMChi2(psMinimization *min,
                        psImage *covar,
                        psVector *params,
                        const psVector *paramMask,
                        const psArray *x,
                        const psVector *y,
                        const psVector *yErr,
                        psMinimizeLMChi2Func func);

psBool p_psMinLM_GuessABP (psImage  *Alpha,
			   psVector *Beta,
			   psVector *Params,
			   psImage  *alpha,
			   psVector *beta,
			   psVector *params,
			   psF64 lambda);

psF64 p_psMinLM_SetABX (psImage  *alpha,
			psVector *beta,
			psVector *params,
			const psArray  *x,
			const psVector *y,
                        const psVector *dy,
			psMinimizeLMChi2Func func);

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

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

psVector *psMinimizeLMChi2Gauss1D(psImage *deriv,
                                  const psVector *params,
                                  const psArray *coords);

psVector *psMinimizePowellChi2Gauss1D(const psVector *params,
                                      const psArray *coords);

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

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

// XXX EAM : psGaussJordan provided as an alternate to LU Decomp for psMinimizeLMChi2
bool psGaussJordan (psImage *a, psVector *b);

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

#endif

