/*****************************************************************************
    This routine must ensure that the psSpline1DEval() function works
    properly.  It creates a spline with psSpline1DAlloc(), creates a set of
    data values, sets the spline polynomials with psVectorFitSpline1D(), then
    calls psSpline1DEval() on new data values and ensures that the results
    are correct.
 
    XXX: figure out the memory deallocator
 *****************************************************************************/
#include <stdio.h>
#include <math.h>
#include "pslib_strict.h"
#include "psTest.h"
#include "psMemory.h"
#include "psSpline.h"

#define N 8

psS32 t00()
{
    psS32 testStatus = true;
    psS32 memLeaks=0;
    psS32 i;
    float x;
    float y;
    psS32  currentId = psMemGetId();
    psSpline1D *tmpSpline;
    psVector *data;

    psTraceSetLevel(".", 0);

    /****************************************************************************/
    /****************************************************************************/
    testStatus = true;
    printPositiveTestHeader(stdout,
                            "psFunction functions",
                            "psSpline1DAlloc()");
    data = psVectorAlloc(N+1, PS_TYPE_F32);
    tmpSpline = psSpline1DAlloc(N, 1, 1.0, 10.0);

    for (i=0;i<N+1;i++) {
        data->data.F32[i] = tmpSpline->knots->data.F32[i];
    }
    psVectorFitSpline1D(tmpSpline, data, data, NULL);

    for (i=0;i<N+1;i++) {
        x = 0.5 + (float) i+1;
        y = psSpline1DEval(
                tmpSpline,
                x
            );
        if (fabs(x-y) > FLT_EPSILON) {
            printf("ERROR: f(%f) is %f\n", x, y);
            testStatus = true;
        }
    }

    psFree(tmpSpline);
    psMemCheckCorruption(1);
    psFree(data);
    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
    if (0 != memLeaks) {
        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
    }

    printFooter(stdout,
                "psSpline functions",
                "psSpline1DAlloc()",
                testStatus);

    return (!testStatus);
}

psS32 t01()
{
    psS32 testStatus = true;
    psS32 memLeaks=0;
    psS32 i;
    float x;
    float y;
    psS32  currentId = psMemGetId();
    psSpline1D *tmpSpline;
    psVector *data;

    psTraceSetLevel(".", 0);

    /****************************************************************************/
    /****************************************************************************/
    testStatus = true;
    printPositiveTestHeader(stdout,
                            "psFunction functions",
                            "psSpline1DAlloc()");
    data = psVectorAlloc(N+1, PS_TYPE_F32);
    tmpSpline = psSpline1DAlloc(N, 1, 1.0, 10.0);

    for (i=0;i<N+1;i++) {
        data->data.F32[i] = tmpSpline->knots->data.F32[i];
    }
    psVectorFitSpline1D(tmpSpline, data, data, NULL);

    for (i=0;i<N+1;i++) {
        x = 0.5 + (float) i+1;
        y = psSpline1DEval(
                tmpSpline,
                x
            );
        if (fabs(x-y) > FLT_EPSILON) {
            printf("ERROR: f(%f) is %f\n", x, y);
            testStatus = true;
        }
    }

    psFree(tmpSpline);
    psMemCheckCorruption(1);
    psFree(data);
    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
    if (0 != memLeaks) {
        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
    }

    printFooter(stdout,
                "psSpline functions",
                "psSpline1DAlloc()",
                testStatus);

    return (!testStatus);
}

psS32 main()
{
    psLogSetFormat("HLNM");
    t00();
    // XXX: Why is this commented?
    //    t01();
}
