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

#ifndef PS_SPLINE_H
#define PS_SPLINE_H

/// @addtogroup MathOps Mathematical Operations
/// @{

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

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

#define PS_LEFT_SPLINE_DERIV 0.0
#define PS_RIGHT_SPLINE_DERIV 0.0

/** One-Dimensional Spline */
typedef struct
{
    unsigned 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.
}
psSpline1D;

/** Allocates a psSpline1D structure
 *
 *  Allocator for psSpline1D.
 *
 *  @return psSpline1D*    new 1-D spline struct
 */
psSpline1D *psSpline1DAlloc() PS_ATTR_MALLOC;

/** 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
);

/** 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(
    const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
    const psVector* y                  ///< Coordinates
);

/** 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
);

/*****************************************************************************
    PS_SPLINE macros:
*****************************************************************************/
#define PS_ASSERT_SPLINE(NAME, RVAL) \
if (false == psMemCheckSpline1D(NAME)) { \
    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
            "Unallowable operation: argument %s is not a psSpline1D struct.\n",\
            #NAME); \
    return(RVAL); \
} \

#define PS_ASSERT_SPLINE_NON_NULL(NAME, RVAL) \
if ((NAME) == NULL) { \
    psError(PS_ERR_BAD_PARAMETER_NULL, true, \
            "Unallowable operation: psSpline1D %s is NULL.", \
            #NAME); \
    return(RVAL); \
} \


/// @}
#endif // #ifndef PS_SPLINE_H
