/** @file  psMinimizeLMM.c
 *  \brief basic minimization functions
 *  @ingroup Math
 *
 *  This file will contain function prototypes for various Levenberg-Marquadt
 *  minimization routines.
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2006-01-27 20:08:58 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 *
 */

#ifndef PS_MINIMIZE_LMM_H
#define PS_MINIMIZE_LMM_H

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

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

/** A data structure for minimization routines.
 *
 *  Contains numerical analysis parameters/values
 */
typedef struct
{
    const int maxIter;                 ///< Convergence limit
    const float tol;                   ///< Error Tolerance
    float value;                       ///< Value of function at minimum
    int iter;                          ///< Number of iterations to date
    float lastDelta;                   ///< The last difference for the fit
}
psMinimization;


/** A data structure for minimization routines.
 *
 *  
 */
typedef struct
{
    psVector *paramMask;                ///< valid / invalid parameters
    psVector *paramMax;                 ///< max allowed parameters
    psVector *paramMin;                 ///< min allowed parameters
    psVector *paramDelta;               ///< max allowed param swing
}
psMinConstrain;

psMinConstrain *psMinConstrainAlloc();

#define P_PSMINIMIZATION_SET_MAXITER(m,val) *(int*)&m->maxIter = val
        #define P_PSMINIMIZATION_SET_TOL(m,val) *(float*)&m->tol = val

                /** Allocates a psMinimization structure.
                 *
                 *  @return psMinimization* :   a new psMinimization struct
                */
                psMinimization *psMinimizationAlloc(
                    int maxIter,                       ///< Number of minimization iterations to perform.
                    float tol                          ///< Requested error tolerance
                );

/*  Checks the type of a particular pointer.
 *
 *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
 *
 *  @return bool:       True if the pointer matches a psMinimization structure, false otherwise.
 */
bool psMemCheckMinimization(
    psPtr ptr                          ///< the pointer whose type to check
);


/** Specifies the format of a user-defined function that the general Levenberg-
 *  Marquardt minimizer routine will accept.
 *
 *  @return float:   the single float value of the function given the parameters,
 *       positions, and derivatives.
 */
typedef
float (*psMinimizeLMChi2Func)(
    psVector *deriv,                   ///< derivatives of the function
    const psVector *params,            ///< the parameters used to evaluate the function
    const psVector *x                  ///< positions for evaluation
);

/** Minimizes a specified function based on the Levenberg-Marquardt method.
 *
 *  @return bool:   True if successful.
 */
bool psMinimizeLMChi2(
    psMinimization *min,               ///< Minimization specification
    psImage *covar,                    ///< Covariance matrix
    psVector *params,                  ///< "Best Guess" for the parameters that minimize func
    psMinConstrain *constrain,         ///< Constraints on the parameters
    const psArray *x,                  ///< Measurement ordinates of multiple vectors
    const psVector *y,                 ///< Measurement coordinates
    const psVector *yErr,              ///< Errors in the measurement coordinates
    psMinimizeLMChi2Func func          ///< Specified function
);

bool psMinimizeGaussNewtonDelta (
    psVector *delta,
    const psVector *params,
    const psVector *paramMask,
    const psArray  *x,
    const psVector *y,
    const psVector *yErr,
    psMinimizeLMChi2Func func
);

/** Function used to set parameters for generating "best guess" in minimizing Chi-Squared value.
 *
 *  @return psF64:    Chi-squared value for new guess
 */
psF64 p_psMinLM_SetABX (
    psImage  *alpha,                   ///< alpha guess
    psVector *beta,                    ///< beta guess
    const psVector *params,            ///< params guess
    const psVector *paramMask,         ///< param mask
    const psArray  *x,                 ///< Measurement ordinates
    const psVector *y,                 ///< Measurement coordinates
    const psVector *dy,                ///< Weights calculated from y-errors
    psMinimizeLMChi2Func func          ///< Specified function
);


/** Gauss-Jordan numerical solver.
 *
 *  @return bool:   True if successful.
 */
bool psGaussJordan(
    psImage *a,                        ///< Matrix to be solved
    psVector *b                        ///< Vector of values
);

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




#endif // #ifndef PS_MINIMIZE_LMM_H

