Index: trunk/psLib/test/math/tap_psPolyFit1D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolyFit1D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolyFit1D.c	(revision 10820)
@@ -0,0 +1,514 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 1D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 1D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ 
+XXX: Try null stats.
+ 
+XXX: The tests with "Some Vectors NULL" fail as of 2006/12, they had passed
+previously as of 2006/02.  They are commented out for now.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER 5
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+
+psF32 setData(psF32 x)
+{
+    return(A + (B * x) + (C * x * x) + (D * x * x * x) + (E * x * x * x * x));
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrder,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial1D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 1D Polynomial Fitting Functions");
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf("        performing a clip-fit\n");
+        } else {
+            printf("        performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, polyOrder);
+    }
+
+    if (flags & TS00_POLY_CHEB) {
+        if (VERBOSE)
+            printf(" using chebyshev polynomials\n");
+        myPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_CHEB, polyOrder);
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+        numData = 30;
+    }
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = (flags & TS00_X_NULL) ? i : 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i]);
+    }
+    if (flags & TS00_X_NULL && flags & TS00_POLY_CHEB) {
+        // Renormalise the indices
+        p_psNormalizeVectorRange(xTruth, -1.0, 1.0);
+    }
+    psFree(rng);
+    if (EXTRA_VERBOSE)
+        for (int i = 0; i < numData; i++) {
+            printf("Original %d: %f\t%f\n", i, xTruth->data.F64[i], fTruth->data.F64[i]);
+        }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1, 1);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+
+        #if 0
+
+        if (flags & TS00_POLY_CHEB) {
+            p_psNormalizeVectorRange(x, -1.0, 1.0);
+        }
+        #endif
+
+    }
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial1D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial1D(myPoly, stats, mask, MASK_VALUE, f, fErr, x);
+    } else {
+        rc = psVectorFitPolynomial1D(myPoly, mask, MASK_VALUE, f, fErr, x);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 1D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 1D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrder+1;i++) {
+                printf("Polynomial coefficient %d is %0.1f\n", i, myPoly->coeff[i]);
+            }
+        }
+
+        psVector *result = psPolynomial1DEvalVector(myPoly, xTruth);
+        for (psS32 i=0; i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: %.1f --> %.1f vs %.1f\n",
+                     i, xTruth->data.F64[i], actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: %1.f --> %.1f vs %.1f\n",
+                           i, xTruth->data.F64[i], actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(f);
+    psFree(xTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial1D", 0);
+    psTraceSetLevel("VectorFitPolynomial1DOrd", 0);
+    psTraceSetLevel("VectorFitPolynomial1DCheb", 0);
+    psTraceSetLevel("vectorFitPolynomial1DCheb", 0);
+    psTraceSetLevel("vectorFitPolynomial1DChebSlow", 0);
+    psTraceSetLevel("vectorFitPolynomial1DChebFast", 0);
+    psTraceSetLevel("psVectorFitPolynomial1D", 0);
+    psTraceSetLevel("p_psCreateChebyshevPolys", 0);
+
+    plan_tests(64);
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, F Vector NULL");
+    // Unallowable vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_S32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_S32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_S32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Unallowable vector types");
+
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit, Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit, F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit, Mismatch data type");
+
+
+    //
+    // F32 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL.");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, non-clip fit.  F Vector NULL.");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, non-clip fit.  Mismatch vector types.");
+
+
+    //
+    // F64 tests: Chebyshev polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, non-clip fit.  Mismatch vector types");
+
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+
+    //
+    // F32 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_NULL | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F32 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F32 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+
+
+    //
+    // F64 tests: Chebyshev polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit");
+    // Some Vectors NULL
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    //    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, true), "F64 tests: Chebyshev polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_NULL | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F32 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_F_F64 | TS00_POLY_CHEB | TS00_CLIP_FIT, POLY_ORDER, NUM_DATA, false), "F64 tests: Chebyshev polys, clip fit.  Mismatch vector types");
+
+    // Note: memory leaks tests are performed in the genericTest() subroutine.
+}
+
Index: trunk/psLib/test/math/tap_psPolyFit2D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolyFit2D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolyFit2D.c	(revision 10820)
@@ -0,0 +1,446 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 2D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 2D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 3
+#define A 2.0
+#define B 3.0
+#define C 4.0
+#define D 5.0
+#define E 6.0
+#define F 4.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+
+psF32 setData(psF32 x, psF32 y)
+{
+    return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y));
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial2D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 2D Polynomial Fitting Functions");
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY);
+    }
+
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using an RNG with a known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %d)\n", i, (psF32) i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f %.1f)\n", i, (psF32) i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial2D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial2D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y);
+    } else {
+        rc = psVectorFitPolynomial2D(myPoly, mask, MASK_VALUE, f, fErr, x, y);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 2D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 2D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    printf("Polynomial coefficient [%d][%d] is %0.1f\n", i, j, myPoly->coeff[i][j]);
+                }
+            }
+        }
+
+        psVector *result = psPolynomial2DEvalVector(myPoly, xTruth, yTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF64 actualData = result->data.F64[i];
+            psF64 expectData = fTruth->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(fTruth);
+    psFree(x);
+    psFree(y);
+    psFree(f);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial2D", 0);
+    psTraceSetLevel("VectorFitPolynomial2DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial2D", 0);
+
+    plan_tests(44);
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
Index: trunk/psLib/test/math/tap_psPolyFit3D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolyFit3D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolyFit3D.c	(revision 10820)
@@ -0,0 +1,504 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 3D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 3D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 100
+#define POLY_ORDER_X 2
+#define POLY_ORDER_Y 3
+#define POLY_ORDER_Z 2
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 4.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define ERROR_TOLERANCE 0.10
+#define YERR 10.0
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 4.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (D * y) + (H * z));
+    } else {
+        return(A + (B * x) + (C * x * x) + (D * y) + (E * y * y) + (F * x * y) + (H * z) +
+               (J * z * z) + (K * x * z) + (L * y * z));
+    }
+}
+
+psS32 genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    psS32 testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial3D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 3D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i], zTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY, polyOrderZ);
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4]*= 2.0;
+            f->data.F32[numData/2]*= 2.0;
+            f->data.F32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4]*= 2.0;
+            f->data.S32[numData/2]*= 2.0;
+            f->data.S32[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%d)\n", i, f->data.S32[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4]*= 2.0;
+            f->data.F64[numData/2]*= 2.0;
+            f->data.F64[3*numData/4]*= 2.0;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<numData;i++) {
+                printf("Original data %d: (%.1f)\n", i, f->data.F64[i]);
+            }
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial3D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial3D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z);
+    } else {
+        rc = psVectorFitPolynomial3D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 3D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 3D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        printf("Polynomial coefficient [%d][%d][%d] is %0.1f\n", i, j, k, myPoly->coeff[i][j][k]);
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial3DEvalVector(myPoly, xTruth, yTruth, zTruth);
+        for (psS32 i=0 ;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+psS32 main()
+{
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial3D", 0);
+    psTraceSetLevel("VectorFitPolynomial3DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial3D", 0);
+
+    plan_tests(52);
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
Index: trunk/psLib/test/math/tap_psPolyFit4D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolyFit4D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolyFit4D.c	(revision 10820)
@@ -0,0 +1,700 @@
+/*****************************************************************************
+This routine must ensure that various psLib functions which fit 4D polynomials
+to data work correctly.  There is a function genericTest() which creates
+vectors of data points (x and f), and populates them with the values from an
+arbitrary function setData().  It then calls appropriate 4D fitting function.
+It then evaluates the polynomial with the coefficients generated above and
+determines if they are within an error tolerance of the expected values.
+ 
+XXX: A few tests which previously worked (2006/02) now fail (2006/12).  See
+XXX comment below.
+ *****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define NUM_DATA 200
+#define POLY_ORDER_X 1
+#define POLY_ORDER_Y 1
+#define POLY_ORDER_Z 1
+#define POLY_ORDER_T 1
+#define A 100.0
+#define B 2.0
+#define C 3.0
+#define D 4.0
+#define E 5.0
+#define F 6.0
+#define H 3.0
+#define J 3.0
+#define K 1.0
+#define L 5.0
+#define M 4.0
+#define N 3.0
+#define O 2.0
+#define P 1.0
+#define Q 5.0
+#define ERROR_TOLERANCE 0.05
+#define YERR 0.1
+#define VERBOSE 0
+#define EXTRA_VERBOSE 0
+#define NUM_ITERATIONS 5
+#define CLIP_SIGMA 3.0
+#define OUTLIERS true
+#define MASK_VALUE 1
+
+#define TS00_F_NULL  0x00000001
+#define TS00_F_F32  0x00000002
+#define TS00_F_F64  0x00000004
+#define TS00_F_S32  0x00000008
+#define TS00_X_NULL  0x00000010
+#define TS00_X_F32  0x00000020
+#define TS00_X_F64  0x00000040
+#define TS00_X_S32  0x00000080
+#define TS00_FERR_NULL  0x00000100
+#define TS00_FERR_F32  0x00000200
+#define TS00_FERR_F64  0x00000400
+#define TS00_FERR_S32  0x00000800
+#define TS00_MASK_NULL  0x00001000
+#define TS00_MASK_U8  0x00002000
+#define TS00_MASK_S32  0x00004000
+#define TS00_POLY_ORD  0x00008000
+#define TS00_POLY_CHEB  0x00010000
+#define TS00_CLIP_FIT  0x00020000
+#define TS00_Y_NULL  0x00100000
+#define TS00_Y_F32  0x00200000
+#define TS00_Y_F64  0x00400000
+#define TS00_Y_S32  0x00800000
+#define TS00_Z_NULL  0x01000000
+#define TS00_Z_F32  0x02000000
+#define TS00_Z_F64  0x04000000
+#define TS00_Z_S32  0x08000000
+#define TS00_T_NULL  0x10000000
+#define TS00_T_F32  0x20000000
+#define TS00_T_F64  0x40000000
+#define TS00_T_S32  0x80000000
+
+psF32 setData(psF32 x, psF32 y, psF32 z, psF32 t)
+{
+    if (0) {
+        // Linear case, for testing.
+        return(A + (B * x) + (C * y) + (D * z) + (E * t));
+    } else {
+        #if 0
+        return(A + (B * x) + (C * y) + (D * z) + (E * t) +
+               (F * x * x) + (H * y * y) + (J * z * z) + (K * t * t) +
+               (L * x * y) + (M * x * z) + (N * x * t) + (O * y * z) + (P * y * t) + (Q * z * t));
+        #else
+
+        return A + (B * x) + (C * y) + (D * z) + (E * t) + (F * x * y);
+        #endif
+
+    }
+}
+
+bool genericTest(
+    psU32 flags,
+    psS32 polyOrderX,
+    psS32 polyOrderY,
+    psS32 polyOrderZ,
+    psS32 polyOrderT,
+    psS32 numData,
+    bool expectedRC)
+{
+    psS32 currentId = psMemGetId();
+    bool testStatus = true;
+    psS32 memLeaks = 0;
+    psPolynomial4D *myPoly = NULL;
+    psVector *x = NULL;
+    psVector *y = NULL;
+    psVector *z = NULL;
+    psVector *t = NULL;
+    psVector *f = NULL;
+    psVector *mask = NULL;
+    psVector *fErr = NULL;
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
+    stats->clipSigma = CLIP_SIGMA;
+    stats->clipIter = NUM_ITERATIONS;
+
+    if (VERBOSE)
+        printf("psMinimize functions: 4D Polynomial Fitting Functions");
+
+    psVector *xTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *yTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *zTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *tTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    psVector *fTruth = psVectorAlloc(numData, PS_TYPE_F64);
+    xTruth->n = numData;
+    yTruth->n = numData;
+    zTruth->n = numData;
+    tTruth->n = numData;
+    fTruth->n = numData;
+    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 1); // Using known seed
+    for (int i = 0; i < numData; i++) {
+        xTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        yTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        zTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        tTruth->data.F64[i] = 2.0*psRandomUniform(rng) - 1.0;
+        fTruth->data.F64[i] = setData(xTruth->data.F64[i], yTruth->data.F64[i],
+                                      zTruth->data.F64[i], tTruth->data.F64[i]);
+    }
+    psFree(rng);
+
+    if (expectedRC == false && VERBOSE) {
+        printf("This test should generate an error message, and return NULL.\n");
+    }
+    if (VERBOSE) {
+        if (flags & TS00_CLIP_FIT) {
+            printf(" performing a clip-fit\n");
+        } else {
+            printf(" performing a non clip-fit\n");
+        }
+    }
+
+    if (flags & TS00_POLY_ORD) {
+        if (VERBOSE)
+            printf(" using ordinary polynomials\n");
+        myPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, polyOrderX, polyOrderY,
+                                     polyOrderZ, polyOrderT);
+
+        #if 1
+
+        for (int ix = 0; ix < polyOrderX + 1; ix++) {
+            for (int iy = 0; iy < polyOrderY + 1; iy++) {
+                for (int iz = 0; iz < polyOrderZ + 1; iz++) {
+                    for (int it = 0; it < polyOrderT + 1; it++) {
+                        myPoly->mask[ix][iy][iz][it] = 0xff; // Mask it out
+                    }
+                }
+            }
+        }
+
+        // Put these back in
+        myPoly->mask[0][0][0][0] = 0;   // A
+        myPoly->mask[1][0][0][0] = 0;   // B * x
+        myPoly->mask[0][1][0][0] = 0;   // C * y
+        myPoly->mask[0][0][1][0] = 0;   // D * z
+        myPoly->mask[0][0][0][1] = 0;   // E * t
+        myPoly->mask[1][1][0][0] = 0;   // F * xy
+        #endif
+
+    }
+
+    if (flags & TS00_X_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL x vector\n");
+    }
+
+    if (flags & TS00_X_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_X_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_X_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 x vector\n");
+        x = psVectorCopy(NULL, xTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_Y_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL y vector\n");
+    }
+
+    if (flags & TS00_Y_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Y_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Y_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 y vector\n");
+        y = psVectorCopy(NULL, yTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_Z_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL z vector\n");
+    }
+
+    if (flags & TS00_Z_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_Z_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_Z_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 z vector\n");
+        z = psVectorCopy(NULL, zTruth, PS_TYPE_F64);
+    }
+
+    if (flags & TS00_T_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL t vector\n");
+    }
+
+    if (flags & TS00_T_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F32);
+    }
+
+    if (flags & TS00_T_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_S32);
+    }
+
+    if (flags & TS00_T_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 t vector\n");
+        t = psVectorCopy(NULL, tTruth, PS_TYPE_F64);
+    }
+
+
+    if (flags & TS00_F_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL f vector\n");
+    }
+
+    if (flags & TS00_F_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F32[numData/4] *= 2.0;
+            f->data.F32[numData/2] *= 2.0;
+            f->data.F32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_S32);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.S32[numData/4] *= 2.0;
+            f->data.S32[numData/2] *= 2.0;
+            f->data.S32[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_F_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 f vector\n");
+        f = psVectorCopy(NULL, fTruth, PS_TYPE_F64);
+        // Set a few outliers in the data.
+        if (OUTLIERS && (flags & TS00_CLIP_FIT)) {
+            f->data.F64[numData/4] *= 2.0;
+            f->data.F64[numData/2] *= 2.0;
+            f->data.F64[3*numData/4] *= 2.0;
+        }
+    }
+
+    if (flags & TS00_FERR_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL fErr vector\n");
+    }
+
+    if (flags & TS00_FERR_F32) {
+        if (VERBOSE)
+            printf(" using a psF32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F32[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_S32);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.S32[i] = (psS32) YERR;
+        }
+    }
+
+    if (flags & TS00_FERR_F64) {
+        if (VERBOSE)
+            printf(" using a psF64 fErr vector\n");
+        fErr = psVectorAlloc(numData, PS_TYPE_F64);
+        fErr->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            fErr->data.F64[i] = YERR;
+        }
+    }
+
+    if (flags & TS00_MASK_NULL) {
+        if (VERBOSE)
+            printf(" using a NULL mask vector\n");
+    }
+
+    if (flags & TS00_MASK_U8) {
+        if (VERBOSE)
+            printf(" using a psU8 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_U8);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.U8[i] = 0;
+        }
+    }
+
+    if (flags & TS00_MASK_S32) {
+        if (VERBOSE)
+            printf(" using a psS32 mask vector\n");
+        mask = psVectorAlloc(numData, PS_TYPE_S32);
+        mask->n = numData;
+        for (psS32 i=0;i<numData;i++) {
+            mask->data.S32[i] = 0;
+        }
+    }
+
+    psPolynomial4D *rc = NULL;
+    if (flags & TS00_CLIP_FIT) {
+        rc = psVectorClipFitPolynomial4D(myPoly, stats, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    } else {
+        rc = psVectorFitPolynomial4D(myPoly, mask, MASK_VALUE, f, fErr, x, y, z, t);
+    }
+
+    if (rc == NULL) {
+        if (expectedRC == true) {
+            diag("TEST ERROR: the 4D polynomial fitting function returned NULL.\n");
+            testStatus = false;
+        }
+    } else {
+        if (expectedRC == false) {
+            diag("TEST ERROR: the 4D polynomial fitting function returned non-NULL.\n");
+            testStatus = false;
+        }
+
+        if (EXTRA_VERBOSE) {
+            for (psS32 i=0;i<polyOrderX+1;i++) {
+                for (psS32 j=0;j<polyOrderY+1;j++) {
+                    for (psS32 k=0;k<polyOrderZ+1;k++) {
+                        for (psS32 l=0;l<polyOrderT+1;l++) {
+                            printf("Polynomial coefficient [%d][%d][%d][%d] is %0.1f\n",
+                                   i, j, k, l, myPoly->coeff[i][j][k][l]);
+                        }
+                    }
+                }
+            }
+        }
+
+        psVector *result = psPolynomial4DEvalVector(myPoly, xTruth, yTruth, zTruth, tTruth);
+        for (int i=0;i<numData; i++) {
+            // Skip the outliers.
+            if ((i == numData/4) || (i == numData/2) || (i == 3*numData/4)) {
+                continue;
+            }
+            psF32 expectData = fTruth->data.F64[i];
+            psF32 actualData = result->data.F64[i];
+
+            if (fabs(actualData-expectData) > fabs(ERROR_TOLERANCE * expectData)) {
+                diag("TEST ERROR: Fitted data %d: (%f), expected was (%f)\n",
+                     i, actualData, expectData);
+                testStatus = false;
+            } else {
+                if (EXTRA_VERBOSE) {
+                    printf("GOOD: Fitted data %d: (%.1f), expected was (%.1f)\n",
+                           i, actualData, expectData);
+                }
+            }
+        }
+        psFree(result);
+    }
+
+    psMemCheckCorruption(1);
+    psFree(myPoly);
+    psFree(mask);
+    psFree(x);
+    psFree(y);
+    psFree(z);
+    psFree(t);
+    psFree(f);
+    psFree(xTruth);
+    psFree(yTruth);
+    psFree(zTruth);
+    psFree(tTruth);
+    psFree(fTruth);
+    psFree(fErr);
+    psFree(stats);
+    psMemCheckCorruption(1);
+    memLeaks = psMemCheckLeaks(currentId,NULL,stderr,false);
+    if (0 != memLeaks) {
+        psAbort(__func__,"Memory Leaks! (%d leaks)", memLeaks);
+    }
+
+    return (testStatus);
+}
+
+/*****************************************************************************
+We test a variety of polynomial fitting routines, types, and polynomial types
+here:
+    F32 tests: Ordinary polys, non-clip fit
+    F64 tests: Ordinary polys, non-clip fit
+    F32 tests: Chebyshev polys, non-clip fit
+    F64 tests: Chebyshev polys, non-clip fit
+    F32 tests: Ordinary polys, clip fit
+    F64 tests: Ordinary polys, clip fit
+    F32 tests: Chebyshev polys, clip fit
+    F64 tests: Chebyshev polys, clip fit
+ *****************************************************************************/
+int main()
+{
+    psLogSetFormat("HLNM");
+    psTraceSetLevel(".", 0);
+    psTraceSetLevel("psVectorClipFitPolynomial4D", 0);
+    psTraceSetLevel("VectorFitPolynomial4DOrd", 0);
+    psTraceSetLevel("psVectorFitPolynomial4D", 0);
+
+    plan_tests(60);
+
+    //
+    // F32 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32 | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit");
+
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, non-clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD, POLY_ORDER_X, POLY_ORDER_Y, POLY_ORDER_Z,
+                   POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, non-clip fit.  Mismatch vector types");
+
+    //
+    // F32 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+
+    // XXX: These tests are failing; they shouldn't be.
+    /*
+        ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                                  | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                                  POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit");
+        // Some Vectors NULL
+        ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                                  | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                                  POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    */
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_NULL | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_NULL | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_NULL
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_NULL | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F32 | TS00_X_F32 | TS00_Y_F32 | TS00_Z_F32
+                   | TS00_T_F32 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F32 tests: Ordinary polys, clip fit.  Mismatch vector types");
+
+    //
+    // F64 tests: Ordinary polys, clip fit
+    //
+    // All Vectors non-NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit");
+    // Some Vectors NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_NULL | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, true), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_NULL | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_NULL | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_NULL
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_NULL | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Some Vectors NULL");
+    // F-vector NULL
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_NULL | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    ok(genericTest(TS00_MASK_NULL | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  F Vector NULL");
+    // Mismatch vector types
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F32 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F32 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F32 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F32
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F32 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_U8 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F32 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+    ok(genericTest(TS00_MASK_S32 | TS00_FERR_F64 | TS00_X_F64 | TS00_Y_F64 | TS00_Z_F64
+                   | TS00_T_F64 | TS00_F_F64 | TS00_POLY_ORD | TS00_CLIP_FIT, POLY_ORDER_X, POLY_ORDER_Y,
+                   POLY_ORDER_Z, POLY_ORDER_T, NUM_DATA, false), "F64 tests: Ordinary polys, clip fit.  Mismatch vector types");
+}
+
Index: trunk/psLib/test/math/tap_psPolynomial.c
===================================================================
--- trunk/psLib/test/math/tap_psPolynomial.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolynomial.c	(revision 10820)
@@ -0,0 +1,272 @@
+/** tst_Func00.c
+*
+*    This routine must ensure that the psPolynomial structures are
+*    allocated and deallocated by the psPolynomialXXXlloc() procedures.
+*    It also calls the various psPolynomialXXXEval() procedures.
+*
+*    The F32 and F64 polynomials are tested for all orders (1 - 4) and for
+*    both ordinary and chebyshev polynomials.
+*
+*    NOTE: This test code requries the stdout file to verify that the results
+*    are good.
+*
+*    XXX: Modify these tests so that polynomials with a variety of different
+*    orders are created.
+* 
+*    XXX: Compare to FLT_EPSILON
+* 
+*    @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*    @date $Date: 2006-12-21 20:05:12 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define ORDER    3
+#define VERBOSE  0
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+
+    plan_tests(26);
+
+    // This test will allocate a 1D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial1D* my1DPoly  = NULL;
+
+        // Allocate polynomial
+        my1DPoly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, ORDER);
+        ok(my1DPoly != NULL, "1D polynomial allocated successfully");
+        skip_start(my1DPoly == NULL, 3, "Skipping tests because psPolynomial1DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my1DPoly->nX == ORDER, "psPolynomial1DAlloc(): Number of terms set correctly");
+        ok(my1DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial1DAlloc():  type set correctly");
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            if (my1DPoly->coeff[i] != 0.0) {
+                diag("Coeff[%d] %lg not as expected %lg", i, my1DPoly->coeff[i], 0.0);
+                errorFlag = true;
+            }
+            if (my1DPoly->coeffErr[i] != 0.0) {
+                diag("CoeffErr[%d] %lg not as expected %lg", i, my1DPoly->coeffErr[i], 0.0);
+                errorFlag = true;
+            }
+            if (my1DPoly->mask[i] != 0) {
+                diag("Mask[%d] %d not as expected %d", i, my1DPoly->mask[i], 0);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial1D coefficients set correctly");
+
+        skip_end();
+        psFree(my1DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, -1) != NULL) {
+            diag("psPolynomial1DAlloc() Returned structure but expected NULL");
+        }
+    }
+
+    // This test will allocate a 2D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* my2DPoly = NULL;
+
+        // Allocate polynomial
+        my2DPoly = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1);
+        ok(my2DPoly != NULL, "2D polynomial allocated successfully");
+        skip_start(my2DPoly == NULL, 4, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my2DPoly->nX == ORDER, "psPolynomial2DAlloc(): Number of terms (nX) set correctly");
+        ok(my2DPoly->nY == ORDER+1, "psPolynomial2DAlloc(): Number of terms (nY) set correctly");
+        ok(my2DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial2DAlloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                if (fabs(my2DPoly->coeff[i][j]) > FLT_EPSILON) {
+                    diag("Coeff[%d][%d] %lg not as expected %lg", i, j, my2DPoly->coeff[i][j], 0.0);
+                    errorFlag = true;
+                }
+                if (my2DPoly->coeffErr[i][j] != 0.0) {
+                    diag("CoeffErr[%d][%d] %lg not as expected %lg", i, j, my2DPoly->coeffErr[i][j], 0.0);
+                    errorFlag = true;
+                }
+                if (my2DPoly->mask[i][j] != 0) {
+                    diag("Mask[%d][%d] %d not as expected %d", i, j, my2DPoly->mask[i][j], 0);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial2D coefficients set correctly");
+        skip_end();
+        psFree(my2DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, -1, 1) != NULL) {
+            diag("psPolynomial2DAlloc() returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, 1, -1) != NULL) {
+            diag("psPolynomial2DAlloc() returned structure but expected NULL");
+        }
+    }
+
+    // This test will allocate a 3D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* my3DPoly = NULL;
+
+        // Allocate polynomial
+        my3DPoly = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, ORDER, ORDER+1, ORDER+2);
+        ok(my3DPoly != NULL, "3D polynomial allocated successfully");
+        skip_start(my3DPoly == NULL, 5, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my3DPoly->nX == ORDER, "psPolynomial3DAlloc(): Number of terms (nX) set correctly");
+        ok(my3DPoly->nY == ORDER+1, "psPolynomial3DAlloc(): Number of terms (nY) set correctly");
+        ok(my3DPoly->nZ == ORDER+2, "psPolynomial3DAlloc(): Number of terms (nZ) set correctly");
+        ok(my3DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial3DAlloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                for(psS32 k = 0; k < ORDER+3; k++) {
+                    if (my3DPoly->coeff[i][j][k] != 0.0) {
+                        diag("Coeff[%d][%d][%d] %lg not as expected %lg",
+                             i, j, k, my3DPoly->coeff[i][j][k], 0.0);
+                        errorFlag = true;
+                    }
+                    if (my3DPoly->coeffErr[i][j][k] != 0.0) {
+                        diag("CoeffErr[%d][%d][%d] %lg not as expected %lg",
+                             i, j, k, my3DPoly->coeffErr[i][j][k], 0.0);
+                        errorFlag = true;
+                    }
+                    if (my3DPoly->mask[i][j][k] != 0) {
+                        diag("Mask[%d][%d][%d] %d not as expected %d",
+                             i, j, k, my3DPoly->mask[i][j][k], 0);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial3D coefficients set correctly");
+        skip_end();
+        psFree(my3DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1) != NULL) {
+            diag("psPolynomial3DAlloc(): returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1) != NULL) {
+            diag("psPolynomial3DAlloc() returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1) != NULL) {
+            diag("psPolynomial3DAlloc(): returned structure but expected NULL");
+        }
+    }
+
+    // This test will allocate a 4D polynomial and verify the structure allocated
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D* my4DPoly = NULL;
+
+        // Allocate polynomial
+        my4DPoly = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, ORDER,ORDER+1,ORDER+2,ORDER+3);
+        ok(my4DPoly != NULL, "4D polynomial allocated successfully");
+        skip_start(my4DPoly == NULL, 6, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Verify polynomial structure members set properly
+        ok(my4DPoly->nX == ORDER, "psPolynomial4DAlloc(): Number of terms (nX) set correctly");
+        ok(my4DPoly->nY == ORDER+1, "psPolynomial4DAlloc(): Number of terms (nY) set correctly");
+        ok(my4DPoly->nZ == ORDER+2, "psPolynomial4DAlloc(): Number of terms (nZ) set correctly");
+        ok(my4DPoly->nT == ORDER+3, "psPolynomial4DAlloc(): Number of terms (nT) set correctly");
+        ok(my4DPoly->type == PS_POLYNOMIAL_ORD, "psPolynomial4D    Alloc(): type set correctly");
+
+        bool errorFlag = false;
+        for(psS32 i = 0; i < ORDER+1; i++)
+        {
+            for(psS32 j = 0; j < ORDER+2; j++) {
+                for(psS32 k = 0; k < ORDER+3; k++) {
+                    for(psS32 l = 0; l < ORDER+4; l++) {
+                        if (my4DPoly->coeff[i][j][k][l] != 0.0) {
+                            diag("Coeff[%d][%d][%d][%d] %lg not as expected %lg",
+                                 i, j, k, l, my4DPoly->coeff[i][j][k][l], 0.0);
+                            errorFlag = true;
+                        }
+                        if (my4DPoly->coeffErr[i][j][k][l] != 0.0) {
+                            diag("CoeffErr[%d][%d][%d][%d] %lg not as expected %lg",
+                                 i, j, k, l, my4DPoly->coeffErr[i][j][k][l], 0.0);
+                            errorFlag = true;
+                        }
+                        if (my4DPoly->mask[i][j][k][l] != 0) {
+                            diag("Mask[%d][%d][%d][%d] %d not as expected %d",
+                                 i, j, k, l, my4DPoly->mask[i][j][k][l], 0);
+                            errorFlag = true;
+                        }
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "psPolynomial4D coefficients set correctly");
+        skip_end();
+        psFree(my4DPoly);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    if (0) {
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, -1, 1, 1, 1) != NULL) {
+            diag("psPolynomial4DAlloc(): returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, -1, 1, 1) != NULL) {
+            diag("psPolynomial4DAlloc(): returned structure but expected NULL");
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, -1, 1) != NULL) {
+            diag("psPolynomial4DAlloc(): returned structure but expected NULL");
+            psError(PS_ERR_UNKNOWN,true,"Returned structure but expected NULL");
+        }
+        // Attempt to allocate with negative order
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate error msg for negative terms");
+        if (psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, 1, 1, 1, -1) != NULL) {
+            diag("psPolynomial4DAlloc(): returned structure but expected NULL");
+        }
+    }
+}
+
Index: trunk/psLib/test/math/tap_psPolynomialEval2D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolynomialEval2D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolynomialEval2D.c	(revision 10820)
@@ -0,0 +1,311 @@
+/** tap_psPolynomialEval2D.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-12-21 20:05:12 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly2DCoeff[TERMS][TERMS]   = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF64 Dpoly2DCoeff[TERMS][TERMS]  = {  { -4.3,  2.3, -3.2,  1.9},
+                                       {  1.2,  0.7, -0.3,  1.3},
+                                       {  0.4, -2.9,  0.8, -3.1},
+                                       { -1.1,  2.1,  1.9,  0.6}
+                                    };
+psF32 poly2DMask[TERMS][TERMS]    = {  {  0,    0,    0,    1},
+                                       {  0,    0,    1,    0},
+                                       {  1,    0,    0,    0},
+                                       {  0,    0,    0,    1}
+                                    };
+
+psF32 poly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                        { -0.55,  1.40},
+                                        {  0.00,  2.34},
+                                        { -0.88,  0.00},
+                                        {  3.45, -0.78}
+                                     };
+psF32 Dpoly2DXYValue[TESTPOINTS][2] = {  {  1.40,  0.55},
+                                      { -0.55,  1.40},
+                                      {  0.00,  2.34},
+                                      { -0.88,  0.00},
+                                      {  3.45, -0.78}
+                                      };
+psF32 poly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+psF64 Dpoly2DResult[TESTPOINTS] = {  -3.415938, -14.765687, -16.43992, -4.606381, -22.650702 };
+
+psF32 poly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                         };
+psF32 Dpoly2DXYChebValue[TESTPOINTS][2] = {  {  0.500,  0.500},
+        {  0.000,  0.250},
+        { -0.250,  0.000},
+        {  0.990,  0.150},
+        {  0.333, -0.666}
+                                          };
+psF32 poly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+psF32 Dpoly2DChebResult[TESTPOINTS] = {  0.750000, 1.687500, 0.625000, -0.113040, 0.386786 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(29);
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial2D*  polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial2D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+                polyOrd->mask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial2DEval(polyOrd,Dpoly2DXYValue[i][0],Dpoly2DXYValue[i][1]);
+            if (fabs(Dpoly2DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %f, should be %f\n", result, Dpoly2DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEval() successful (Ordinary)");
+
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate and evaluate Cheby polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial2D*  polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Cheby psPolynomial2D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyCheb->coeff[i][j] = 1.0;
+                polyCheb->mask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial2DEval(polyCheb,Dpoly2DXYChebValue[i][0],Dpoly2DXYChebValue[i][1]);
+            if (fabs(Dpoly2DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %f, should be %f\n", resultCheb, Dpoly2DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEval() successful (Chebyshev)");
+
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* polyOrd = psPolynomial2DAlloc(99, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 2, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Attempt to evaluation invalid polynomial type
+        psF64 result = psPolynomial2DEval(polyOrd,0.0, 0.0);
+        ok(isnan(result), "psPolynomial2DEval() did not return NAN, as expected");
+
+        skip_end();
+        psFree(polyOrd);
+
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial, test the psPolynomial2DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* polyOrd = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 8, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyOrd->coeff[i][j] = poly2DCoeff[i][j];
+                polyOrd->mask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Create input vectors
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdX->data.F64[i]  = poly2DXYValue[i][0];
+            inputOrdY->data.F64[i]  = poly2DXYValue[i][1];
+            inputOrdX->n++;
+            inputOrdY->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial2DEvalVector(polyOrd, inputOrdX, inputOrdY);
+        ok(outputOrd != NULL, "psPolynomial2DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial2DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly2DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                     i, outputOrd->data.F64[i], poly2DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial2DEvalVector(NULL, inputOrdX, inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial2DEvalVector(polyOrd,NULL,inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial2DEvalVector(polyOrd,inputOrdX,NULL) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdX->type.type = PS_TYPE_U8;
+        ok(psPolynomial2DEvalVector(polyOrd,inputOrdX,inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdY->type.type = PS_TYPE_U8;
+        ok(psPolynomial2DEvalVector(polyOrd,inputOrdX, inputOrdY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(outputOrd);
+        psFree(polyOrd);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+
+
+
+    // Allocate polynomial, test the psPolynomial2DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        psPolynomial2D* polyCheb = psPolynomial2DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Cheby polynomial allocation successful");
+        skip_start(polyCheb == NULL, 8, "Skipping tests because psPolynomial2DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                polyCheb->coeff[i][j] = 1.0;
+                polyCheb->mask[i][j]  = poly2DMask[i][j];
+            }
+        }
+
+        // Create input vectors
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebX->data.F64[i] = poly2DXYChebValue[i][0];
+            inputChebY->data.F64[i] = poly2DXYChebValue[i][1];
+            inputChebX->n++;
+            inputChebY->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial2DEvalVector(polyCheb, inputChebX, inputChebY);
+        ok(outputCheb != NULL, "psPolynomial2DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial2DEvalVector() generated correct type");
+
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(poly2DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                     i, outputCheb->data.F64[i], poly2DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial2DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial2DEvalVector(NULL, inputChebX, inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial2DEvalVector(polyCheb,NULL,inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial2DEvalVector(polyCheb,inputChebX,NULL) == NULL, "psPolynomial2DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebX->type.type = PS_TYPE_U8;
+        ok(psPolynomial2DEvalVector(polyCheb,inputChebX,inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebY->type.type = PS_TYPE_U8;
+        ok(psPolynomial2DEvalVector(polyCheb,inputChebX, inputChebY) == NULL, "psPolynomial2DEvalVector() produced NULL when called with non F64 input vector");
+
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(outputCheb);
+        psFree(polyCheb);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: trunk/psLib/test/math/tap_psPolynomialEval3D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolynomialEval3D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolynomialEval3D.c	(revision 10820)
@@ -0,0 +1,392 @@
+/** tap_psPolynomialEval3D.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-12-21 20:05:12 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                            },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                         };
+psF64 Dpoly3DCoeff[TERMS][TERMS][TERMS] = {  { { -1.1,  1.2, -1.3,  1.4},
+        {  1.5, -1.6,  1.7, -1.8},
+        {  0.1, -0.2,  0.3, -0.4},
+        { -0.5,  0.6, -0.7,  0.8}
+                                             },
+        { { -2.1,  2.2, -2.3,  2.4},
+          {  2.5, -2.6,  2.7, -2.8},
+          {  3.1, -3.2,  3.3, -3.4},
+          { -3.5,  3.6, -3.7,  3.8}
+        },
+        { { -4.1,  4.2, -4.3,  4.4},
+          {  4.5, -4.6,  4.7, -4.8},
+          {  5.1, -5.2,  5.3, -5.4},
+          { -5.5,  5.6, -5.7,  5.8}
+        },
+        { { -6.1,  6.2, -6.3,  6.4},
+          {  6.5, -6.6,  6.7, -6.8},
+          {  7.1, -7.2,  7.3, -7.4},
+          { -7.5,  7.6, -7.7,  7.8}
+        }
+                                          };
+
+
+psF32 poly3DMask[TERMS][TERMS][TERMS]    = { {  {  0,    0,    0,    1},
+        {  0,    0,    1,    0},
+        {  1,    0,    0,    0},
+        {  0,    0,    0,    1}
+                                             },
+        {  {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0},
+           {  1,    0,    0,    0}
+        },
+        {  {  0,    1,    0,    0},
+           {  0,    0,    1,    0},
+           {  0,    1,    0,    0},
+           {  0,    0,    1,    0}
+        },
+        {  {  1,    0,    0,    0},
+           {  0,    0,    0,    1},
+           {  1,    0,    0,    0},
+           {  0,    0,    0,    1}
+        },
+                                           };
+
+psF32 poly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                      {  0.297,  0.153, -0.354},
+                                      {  0.000,  0.153, -0.354},
+                                      {  0.297,  0.000, -0.354},
+                                      {  0.297,  0.153,  0.000}
+                                      };
+psF64 Dpoly3DXYZValue[TESTPOINTS][3] = {  {  0.450, -0.780,  0.500},
+                                       {  0.297,  0.153, -0.354},
+                                       {  0.000,  0.153, -0.354},
+                                       {  0.297,  0.000, -0.354},
+                                       {  0.297,  0.153,  0.000}
+                                       };
+psF32 poly3DResult[TESTPOINTS]  = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+psF64 Dpoly3DResult[TESTPOINTS] = { -1.298691, -2.011591, -1.359247, -2.548266, -1.139072};
+
+
+psF32 poly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                          };
+psF64 Dpoly3DXYZChebValue[TESTPOINTS][3] = {  {  0.000,  0.250, -0.250},
+        { -0.250,  0.000,  0.250},
+        {  0.250, -0.250,  0.000},
+        {  0.100, -0.300, -0.400},
+        {  0.990, -0.010,  0.500}
+                                           };
+psF32 poly3DChebResult[TESTPOINTS]  = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+psF64 Dpoly3DChebResult[TESTPOINTS] = {  1.230469, 1.687500, 0.187500, -1.452707, 2.032344 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(33);
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial3D*  polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial3D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                    polyOrd->mask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial3DEval(polyOrd,Dpoly3DXYZValue[i][0],Dpoly3DXYZValue[i][1],
+                                              Dpoly3DXYZValue[i][2]);
+            if (fabs(Dpoly3DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                     result, Dpoly3DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate and evaluate Cheby polynomial structure
+    {
+        psMemId id = psMemGetId();
+
+        // Allocate polynomial structure
+        psPolynomial3D*  polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary psPolynomial3D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyCheb->coeff[i][j][k] = 1.0;
+                    polyCheb->mask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial3DEval(polyCheb,Dpoly3DXYZChebValue[i][0],Dpoly3DXYZChebValue[i][1],
+                                                  Dpoly3DXYZChebValue[i][2]);
+            if (fabs(Dpoly3DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                     resultCheb, Dpoly3DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Cheby)");
+
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* polyOrd = psPolynomial3DAlloc(99, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 2, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Attempt to evaluation invalid polynomial type
+        psF64 result = psPolynomial3DEval(polyOrd,0.0, 0.0, 0.0);
+        ok(isnan(result), "psPolynomial3DEval() did not return NAN, as expected");
+        skip_end();
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+    // Allocate polynomial, test the psPolynomial3DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* polyOrd = psPolynomial3DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 8, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyOrd->coeff[i][j][k] = Dpoly3DCoeff[i][j][k];
+                    polyOrd->mask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Create input vectors
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdX->data.F64[i]  = Dpoly3DXYZValue[i][0];
+            inputOrdY->data.F64[i]  = Dpoly3DXYZValue[i][1];
+            inputOrdZ->data.F64[i]  = Dpoly3DXYZValue[i][2];
+            inputOrdX->n++;
+            inputOrdY->n++;
+            inputOrdZ->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ);
+        ok(outputOrd != NULL, "psPolynomial3DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial3DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly3DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg.\n",
+                     i, outputOrd->data.F64[i], Dpoly3DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial3DEvalVector(NULL,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyOrd,NULL,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,NULL,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,NULL) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdX->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdY->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdY->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdZ->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyOrd,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(inputOrdZ);
+        psFree(outputOrd);
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+
+    // Allocate polynomial, test the psPolynomial3DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        psPolynomial3D* polyCheb = psPolynomial3DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyCheb == NULL, 8, "Skipping tests because psPolynomial3DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    polyCheb->coeff[i][j][k] = 1.0;
+                    polyCheb->mask[i][j][k]  = poly3DMask[i][j][k];
+                }
+            }
+        }
+
+        // Create input vectors
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebX->data.F64[i] = Dpoly3DXYZChebValue[i][0];
+            inputChebY->data.F64[i] = Dpoly3DXYZChebValue[i][1];
+            inputChebZ->data.F64[i] = Dpoly3DXYZChebValue[i][2];
+            inputChebX->n++;
+            inputChebY->n++;
+            inputChebZ->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ);
+        ok(outputCheb != NULL, "psPolynomial3DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial3DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly3DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg.\n",
+                     i, outputCheb->data.F64[i], Dpoly3DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial3DEvalVector(NULL,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyCheb,NULL,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyCheb,inputChebX,NULL,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,NULL) == NULL, "psPolynomial3DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebX->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebY->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebY->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebZ->type.type = PS_TYPE_U8;
+        ok(psPolynomial3DEvalVector(polyCheb,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial3DEvalVector() produced NULL when called with non F64 input vector");
+
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(inputChebZ);
+        psFree(outputCheb);
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: trunk/psLib/test/math/tap_psPolynomialEval4D.c
===================================================================
--- trunk/psLib/test/math/tap_psPolynomialEval4D.c	(revision 10820)
+++ trunk/psLib/test/math/tap_psPolynomialEval4D.c	(revision 10820)
@@ -0,0 +1,662 @@
+/** tst_psFunc11.c
+*
+*  This test driver will exercise the psPolynomialXDEval functions for both
+*  ORD and CHEB type polynomials.
+*
+*  @version  $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2006-12-21 20:05:12 $
+*
+* Copyright 2004-2005 Maui High Performance Computing Center, Univ. of Hawaii
+*
+***************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define  TERMS        4
+#define  TESTPOINTS   5
+#define  ERROR_TOL    0.001
+
+psF32 poly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+psF64 Dpoly4DCoeff[TERMS][TERMS][TERMS][TERMS] = {
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            },
+            {
+                {
+                    { -1.1,  1.2, -1.3,  1.4},
+                    {  1.5, -1.6,  1.7, -1.8},
+                    {  0.1, -0.2,  0.3, -0.4},
+                    { -0.5,  0.6, -0.7,  0.8}
+                },
+                {
+                    { -2.1,  2.2, -2.3,  2.4},
+                    {  2.5, -2.6,  2.7, -2.8},
+                    {  3.1, -3.2,  3.3, -3.4},
+                    { -3.5,  3.6, -3.7,  3.8}
+                },
+                { { -4.1,  4.2, -4.3,  4.4},
+                  {  4.5, -4.6,  4.7, -4.8},
+                  {  5.1, -5.2,  5.3, -5.4},
+                  { -5.5,  5.6, -5.7,  5.8}
+                },
+                { { -6.1,  6.2, -6.3,  6.4},
+                  {  6.5, -6.6,  6.7, -6.8},
+                  {  7.1, -7.2,  7.3, -7.4},
+                  { -7.5,  7.6, -7.7,  7.8}
+                }
+            }
+        };
+
+psF32 poly4DMask[TERMS][TERMS][TERMS][TERMS]    = {
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            },
+            {
+                {
+                    {  0,    0,    0,    1},
+                    {  0,    0,    1,    0},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0},
+                    {  1,    0,    0,    0}
+                },
+                {
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0},
+                    {  0,    1,    0,    0},
+                    {  0,    0,    1,    0}
+                },
+                {
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1},
+                    {  1,    0,    0,    0},
+                    {  0,    0,    0,    1}
+                }
+            }
+        };
+
+psF32 poly4DWXYZValue[TESTPOINTS][4] = {
+                                           {  0.450, -0.780,  0.500, -0.123},
+                                           {  0.297,  0.153, -0.354,  0.000},
+                                           {  0.000,  0.153, -0.354,  0.321},
+                                           {  0.297,  0.000, -0.354,  0.321},
+                                           {  0.297,  0.153,  0.000,  0.321}
+                                       };
+psF64 Dpoly4DWXYZValue[TESTPOINTS][4] = {
+                                            {  0.450, -0.780,  0.500, -0.123},
+                                            {  0.297,  0.153, -0.354,  0.000},
+                                            {  0.000,  0.153, -0.354,  0.321},
+                                            {  0.297,  0.000, -0.354,  0.321},
+                                            {  0.297,  0.153,  0.000,  0.321}
+                                        };
+
+psF32 poly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+psF64 Dpoly4DResult[TESTPOINTS]  = { -3.588753, -2.439566, -1.175955, -1.645497, -1.216915};
+
+psF32 poly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF64 Dpoly4DWXYZChebValue[TESTPOINTS][4] = {
+            {  0.100,  0.000,  0.250, -0.250},
+            {  0.100, -0.250,  0.000,  0.250},
+            {  0.100,  0.250, -0.250,  0.000},
+            {  0.300,  0.200, -0.300, -0.400},
+            { -0.780,  0.990, -0.010,  0.500}
+        };
+psF32 poly4DChebResult[TESTPOINTS]   = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+psF64 Dpoly4DChebResult[TESTPOINTS]  = { -0.216563, -0.297000, -0.033000, 0.432198, 1.785601 };
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(37);
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial structure
+        psPolynomial4D*  polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary psPolynomial4D successfully allocated");
+        skip_start(polyOrd == NULL, 1, "Skipping tests because psPolynomial4DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                        polyOrd->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 result = psPolynomial4DEval(polyOrd, Dpoly4DWXYZValue[i][0], Dpoly4DWXYZValue[i][1],
+                                              Dpoly4DWXYZValue[i][2], Dpoly4DWXYZValue[i][3]);
+            if (fabs(Dpoly4DResult[i]-result) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated value %lg not as expected %lg.\n",
+                     result, Dpoly4DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyOrd);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate and evaluate an ordinary polynomial structure
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial structure
+        psPolynomial4D*  polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary psPolynomial4D successfully allocated");
+        skip_start(polyCheb == NULL, 1, "Skipping tests because psPolynomial4DAlloc() failed");
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyCheb->coeff[i][j][k][l] = 1.0;
+                        polyCheb->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Evaluate test points and verify results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            psF64 resultCheb = psPolynomial4DEval(polyCheb, Dpoly4DWXYZChebValue[i][0], Dpoly4DWXYZChebValue[i][1],
+                                                  Dpoly4DWXYZChebValue[i][2], Dpoly4DWXYZChebValue[i][3]);
+            if (fabs(Dpoly4DChebResult[i]-resultCheb) > ERROR_TOL ) {
+                diag("TEST ERROR: Evaluated Chebyshev value %lg not as expected %lg.\n",
+                     resultCheb, Dpoly4DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial3DEval() successful (Ordinary)");
+
+        psFree(polyCheb);
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Allocate polynomial with unallowed type
+    {
+        psMemId id = psMemGetId();
+        psPolynomial4D* polyOrd = psPolynomial4DAlloc(99, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 2, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Attempt to evaluation invalid polynomial type
+        psF64 result = psPolynomial4DEval(polyOrd,0.0, 0.0, 0.0, 0.0);
+        ok(isnan(result), "psPolynomial3DEval() did not return NAN, as expected");
+        skip_end();
+        psFree(polyOrd);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate polynomial, test the psPolynomial4DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial
+        psPolynomial4D* polyOrd = psPolynomial4DAlloc(PS_POLYNOMIAL_ORD, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyOrd != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyOrd == NULL, 8, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyOrd->coeff[i][j][k][l] = Dpoly4DCoeff[i][j][k][l];
+                        polyOrd->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Create input vectors
+        psVector* inputOrdW  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdX  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdY  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputOrdZ  = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputOrdW->data.F64[i]  = Dpoly4DWXYZValue[i][0];
+            inputOrdX->data.F64[i]  = Dpoly4DWXYZValue[i][1];
+            inputOrdY->data.F64[i]  = Dpoly4DWXYZValue[i][2];
+            inputOrdZ->data.F64[i]  = Dpoly4DWXYZValue[i][3];
+            inputOrdW->n++;
+            inputOrdX->n++;
+            inputOrdY->n++;
+            inputOrdZ->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputOrd = psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ);
+        ok(outputOrd != NULL, "psPolynomial4DEvalVector() generated non-NULL psVector");
+        ok(outputOrd->type.type == PS_TYPE_F64, "psPolynomial4DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly4DResult[i]-outputOrd->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: Result[%d] %lg not equal to expected %lg",
+                     i, outputOrd->data.F64[i], Dpoly4DResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial4DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial4DEvalVector(NULL,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyOrd,NULL,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,NULL,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,NULL,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,NULL) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdX->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdY->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdY->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdZ->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdZ->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputOrdW->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyOrd,inputOrdW,inputOrdX,inputOrdY,inputOrdZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputOrdW->type.type = PS_TYPE_F64;
+
+        psFree(inputOrdX);
+        psFree(inputOrdY);
+        psFree(inputOrdZ);
+        psFree(inputOrdW);
+        psFree(outputOrd);
+        psFree(polyOrd);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Allocate polynomial, test the psPolynomial4DEvalVector() routines
+    {
+        psMemId id = psMemGetId();
+        // Allocate polynomial
+        psPolynomial4D* polyCheb = psPolynomial4DAlloc(PS_POLYNOMIAL_CHEB, TERMS-1, TERMS-1, TERMS-1, TERMS-1);
+        ok(polyCheb != NULL, "Ordinary polynomial allocation successful");
+        skip_start(polyCheb == NULL, 8, "Skipping tests because psPolynomial4DAlloc() failed");
+
+        // Set polynomial members
+        for(psS32 i = 0; i < TERMS; i++)
+        {
+            for(psS32 j = 0; j < TERMS; j++) {
+                for(psS32 k = 0; k < TERMS; k++) {
+                    for(psS32 l = 0; l < TERMS; l++) {
+                        polyCheb->coeff[i][j][k][l] = 1.0;
+                        polyCheb->mask[i][j][k][l]  = poly4DMask[i][j][k][l];
+                    }
+                }
+            }
+        }
+
+        // Create input vectors
+        psVector* inputChebW = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebX = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebY = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        psVector* inputChebZ = psVectorAlloc(TESTPOINTS, PS_TYPE_F64);
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            inputChebW->data.F64[i] = Dpoly4DWXYZChebValue[i][0];
+            inputChebX->data.F64[i] = Dpoly4DWXYZChebValue[i][1];
+            inputChebY->data.F64[i] = Dpoly4DWXYZChebValue[i][2];
+            inputChebZ->data.F64[i] = Dpoly4DWXYZChebValue[i][3];
+            inputChebW->n++;
+            inputChebX->n++;
+            inputChebY->n++;
+            inputChebZ->n++;
+        }
+
+        // Evaluate the vectors
+        psVector* outputCheb = psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ);
+        ok(outputCheb != NULL, "psPolynomial4DEvalVector() generated non-NULL psVector");
+        ok(outputCheb->type.type == PS_TYPE_F64, "psPolynomial4DEvalVector() generated correct type");
+
+        // Verify the results
+        bool errorFlag = false;
+        for(psS32 i = 0; i < TESTPOINTS; i++)
+        {
+            if (fabs(Dpoly4DChebResult[i]-outputCheb->data.F64[i]) > ERROR_TOL) {
+                diag("TEST ERROR: ResultCheb[%d] %lg not equal to expected %lg",
+                     i, outputCheb->data.F64[i], Dpoly4DChebResult[i]);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psPolynomial4DEvalVector() produced the correct answers");
+
+        // Attempt to invoke function with null polynomial
+        ok(psPolynomial4DEvalVector(NULL,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL polynomial");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyCheb,NULL,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,NULL,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,NULL,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with null input vector
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,NULL) == NULL, "psPolynomial4DEvalVector() produced NULL when called with NULL input vector");
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebX->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebX->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebY->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebY->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebZ->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebZ->type.type = PS_TYPE_F64;
+
+        // Attempt to invoke function with a non F64 type input vector
+        inputChebW->type.type = PS_TYPE_U8;
+        ok(psPolynomial4DEvalVector(polyCheb,inputChebW,inputChebX,inputChebY,inputChebZ) == NULL, "psPolynomial4DEvalVector() produced NULL when called with non F64 input vector");
+        inputChebW->type.type = PS_TYPE_F64;
+
+        psFree(inputChebW);
+        psFree(inputChebX);
+        psFree(inputChebY);
+        psFree(inputChebZ);
+        psFree(outputCheb);
+        psFree(polyCheb);
+
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
