/** @file psSpline.h
 *  @brief Standard Mathematical Functions.
 *  @ingroup GROUP00
 *
 *  This file will hold the prototypes for procedures which allocate, free,
 *  and evaluate splines.
 *
 *  @ingroup GROUP00
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2005-09-11 22:18:40 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */

#ifndef PS_SPLINE_H
#define PS_SPLINE_H

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

#include "psVector.h"
#include "psScalar.h"
#include "psPolynomial.h"

/** \addtogroup GROUP00
 *  \{
 */

/** One-Dimensional Spline */
typedef struct
{
    int n;                             ///< The number of spline pieces
    psPolynomial1D **spline;           ///< An array of n pointers to the spline polynomials
    psVector *knots;                   ///< The boundaries between each spline piece.  Size is n+1.
    psF32 *p_psDeriv2;                 ///< For cubic splines, the second derivative at each domain point.  Size is n+1.
    psF32 *p_psDomains;                ///< The boundaries between each spline piece.  Size is n+1.
}
psSpline1D;

/** Allocates a psSpline1D structure
 *
 *  Allocator for psSpline1D where the bounds are implicitly specified through specifying
 *  min and max values along with the number of splines.
 *
 *  @return psSpline1D*    new 1-D spline struct
 */
psSpline1D *psSpline1DAlloc(
    int n,                             ///< Number of spline polynomials
    int order,                         ///< Order of spline polynomials
    float min,                         ///< Lower boundary value of spline polynomials
    float max                          ///< Upper boundary value of spline polynomials
);

/** Allocates a psSpline1D structure
 *
 *  Allocator for psSpline1D where the bounds are explicitly specified.
 *
 *  @return psSpline1D*    new 1-D spline struct
 */
psSpline1D *psSpline1DAllocGeneric(
    const psVector *bounds,            ///< Bounds for spline polynomials
    int order                          ///< Order of spline polynomials
);

/** Evaluates 1-D spline polynomials at a specific coordinate.
 *
 *  @return float    result of spline polynomials evaluated at given location
 */
float psSpline1DEval(
    const psSpline1D *spline,          ///< Coefficients for spline polynomials
    float x                            ///< location at which to evaluate
);

/** Evaluates 1-D spline polynomials at a set of specific coordinates.
 *
 *  @return psVector*    results of spline polynomials evaluated at given locations
 */
psVector *psSpline1DEvalVector(
    const psSpline1D *spline,          ///< Coefficients of spline polynomials
    const psVector *x                  ///< locations at which to evaluate
);

/** Performs a binary disection on a given vector.
 *  Searches through an array of data for a specified value.
 *
 *  @return psS32    corresponding index number of specified value
 */
psS32 p_psVectorBinDisect(
    psVector *bins,                    ///< Array of non-decreasing values
    psScalar *x                        ///< Target value to find
);

/** Interpolates a series of data points for evaluation at a specific coordinate.  Uses a
 *  Lagrange interpolation method.
 *
 *  @return psScalar*    Lagrange interpolation value at given location
 */
psScalar *p_psVectorInterpolate(
    psVector *domain,                  ///< Domain (x coords) for interpolation
    psVector *range,                   ///< Range (y coords) for interpolation
    int order,                         ///< Order of interpolation function
    psScalar *x                        ///< Location at which to evaluate
);

/** 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 psSpline1D structure, false otherwise.
 */
bool psMemCheckSpline1D(
    psPtr ptr                          ///< the pointer whose type to check
);

/** Derive a one-dimensional spline fit.
 *
 *  Given a psSpline1D data structure and a set of x,y vectors, this routine
 *  generates the linear splines which satisfy those data points.
 *
 *  @return psSpline1D*:  the calculated one-dimensional splines
 */
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
);

psSpline1D *psVectorFitSpline1DNEW(
    const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
    const psVector* y,                 ///< Coordinates
    int nKnots
);

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

#endif // #ifndef PS_SPLINE_H

