Index: trunk/psModules/test/tst_pmImageSubtract.c
===================================================================
--- trunk/psModules/test/tst_pmImageSubtract.c	(revision 4179)
+++ trunk/psModules/test/tst_pmImageSubtract.c	(revision 4179)
@@ -0,0 +1,748 @@
+/** @file tst_pmImageSubtract.c
+ *
+ *  @brief Contains the tests for pmImageSubtract.c:
+ *
+ *  test00: This code will ...
+ *
+ *  @author GLG, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-06-09 05:43:13 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+#include "psTest.h"
+#include "pslib.h"
+//XXX: Why do I need this?
+#include "psConstants.h"
+#include "pmImageSubtract.h"
+#define ERROR_TOLERANCE 1.0
+static int test00(void);
+static int test01(void);
+static int test02(void);
+static int test03(void);
+testDescription tests[] = {
+                              {test00, 000, "pmSubtractionKernelsAllocPOIS()", true, false},
+                              {test01, 000, "pmSubtractionKernelsAllocISIS()", true, false},
+                              {test02, 000, "pmSubtractionFindStamps()", true, false},
+                              {test03, 000, "pmSubtractionCalculateEquation()", true, false},
+                              {NULL}
+                          };
+
+int main(int argc, char* argv[])
+{
+    return !runTestSuite(stderr, "Test Point Driver", tests, argc, argv);
+}
+
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Call with various unallowable input parameters.
+ 
+XXX: Untested: we don't loop through the (u, v, xOrder, yOrder) psVectors and
+ensure that each value is set correctly.
+ ******************************************************************************/
+psBool testPOISAlloc(psS32 size,
+                     psS32 SpatialOrder)
+{
+    printf("Testing pmSubtractionKernelsAllocPOIS(%d, %d)\n", size, SpatialOrder);
+
+    bool testStatus = false;
+    psS32 nBasisFunctions = (2 * size + 1) * (2 * size + 1) * (SpatialOrder + 1) * (SpatialOrder + 2) / 2;
+
+    psSubtractionKernels *kernels = pmSubtractionKernelsAllocPOIS(size, SpatialOrder);
+    if (kernels == NULL) {
+        printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() returned a NULL psSubtractionKernels.\n");
+        testStatus = true;
+    } else {
+        if (kernels->type != PM_SUBTRACTION_KERNEL_POIS) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated the wrong kernels->type.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->u == NULL) ||
+                (kernels->u->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->u member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->u member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->v == NULL) ||
+                (kernels->v->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->v member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->v member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->sigma != NULL) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-NULL ->sigma member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->xOrder == NULL) ||
+                (kernels->xOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->xOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->xOrder member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->yOrder == NULL) ||
+                (kernels->yOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a NULL ->yOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a incorrect length ->yOrder member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->subIndex != 0) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-zero ->subIndex member (%d).\n", kernels->subIndex);
+            testStatus = true;
+        }
+
+        psS32 i = kernels->subIndex;
+        if ((kernels->u->data.F32[i] != 0) ||
+                (kernels->v->data.F32[i] != 0)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS(): the ->subIndex member points to a kernel with (%f, %f) (u, v) basis function.\n",
+                   kernels->u->data.F32[i], kernels->v->data.F32[i]);
+            testStatus = true;
+        }
+
+        if (kernels->preCalc != NULL) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated a non-NULL ->preCalc member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->p_size != size) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated an incorrect ->p_size member (%d).\n", kernels->p_size);
+            testStatus = true;
+        }
+
+        if (kernels->p_spatialOrder != SpatialOrder) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocPOIS() generated an incorrect ->p_spatialOrder member (%d).\n", kernels->p_spatialOrder);
+            testStatus = true;
+        }
+    }
+    psFree(kernels);
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test00( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testPOISAlloc(1, 1);
+    testStatus|= testPOISAlloc(2, 3);
+    testStatus|= testPOISAlloc(3, 4);
+
+    return(!testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Call with various unallowable input parameters.
+ 
+XXX: Untested: we don't loop through the (u, v, xOrder, yOrder) psVectors and
+ensure that each value is set correctly.  We don't ensure that he preCalc
+psImages are set correctly.
+ ******************************************************************************/
+psBool testISISAlloc(psS32 sigmaLength,
+                     psS32 orderLength,
+                     psS32 size,
+                     psS32 SpatialOrder)
+{
+    printf("Testing pmSubtractionKernelsAllocISIS(%d, %d, %d, %d)\n",
+           sigmaLength, orderLength, size, SpatialOrder);
+
+    psVector *sigmas = psVectorAlloc(sigmaLength, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < sigmas->n ; i++) {
+        sigmas->data.F32[i] = 1.0 + (psF32) i;
+    }
+    psVector *orders = psVectorAlloc(orderLength, PS_TYPE_S32);
+    for (psS32 i = 0 ; i < orders->n ; i++) {
+        orders->data.S32[i] = i + 2;
+    }
+
+    bool testStatus = false;
+    psS32 numSigmas = sigmas->n;
+    psS32 nBasisFunctions = 0;
+    for (psS32 s = 0 ; s < numSigmas ; s++) {
+        for (psS32 o = 0 ; o < orders->n ; o++) {
+            nBasisFunctions+= ((orders->data.S32[o] + 1) * (orders->data.S32[o] + 2) / 2);
+        }
+    }
+    nBasisFunctions*= ((SpatialOrder + 1) * (SpatialOrder + 2) / 2);
+
+    psSubtractionKernels *kernels = pmSubtractionKernelsAllocISIS(sigmas, orders, size, SpatialOrder);
+    if (kernels == NULL) {
+        printf("TEST ERROR: pmSubtractionKernelsAllocISIS() returned a NULL psSubtractionKernels.\n");
+        testStatus = true;
+    } else {
+        if (kernels->type != PM_SUBTRACTION_KERNEL_ISIS) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated the wrong kernels->type.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->u == NULL) ||
+                (kernels->u->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->u member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->u member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->v == NULL) ||
+                (kernels->v->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->v member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->v member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->sigma == NULL) ||
+                (kernels->sigma->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->sigma member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->sigma member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->xOrder == NULL) ||
+                (kernels->xOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->xOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->xOrder member.\n");
+            testStatus = true;
+        }
+
+        if ((kernels->yOrder == NULL) ||
+                (kernels->yOrder->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->yOrder member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->yOrder member.\n");
+            testStatus = true;
+        }
+
+        if (kernels->subIndex != 0) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a non-zero ->subIndex member (%d).\n", kernels->subIndex);
+            testStatus = true;
+        }
+
+        //
+        // Ensure that kernels->subIndex points to the correct kernel.
+        //
+        psS32 i = kernels->subIndex;
+        if ((kernels->u->data.F32[i] != 0.0) ||
+                (kernels->v->data.F32[i] != 0.0) ||
+                (kernels->xOrder->data.F32[i] != 0.0) ||
+                (kernels->yOrder->data.F32[i] != 0.0) ||
+                (kernels->sigma->data.F32[i] != sigmas->data.F32[0])) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS(): the ->subIndex member points to the wrong kernel.\n");
+            printf("TEST ERROR: (u, v, xOrder, yOrder, sigma) is (%f, %f, %f, %f, %f).\n",
+                   kernels->u->data.F32[i], kernels->v->data.F32[i],
+                   kernels->xOrder->data.F32[i], kernels->yOrder->data.F32[i],
+                   kernels->sigma->data.F32[i]);
+            testStatus = true;
+        }
+
+        //
+        // Ensure that the preCalc images are allocated correctly.
+        //
+        if ((kernels->preCalc == NULL) ||
+                (kernels->preCalc->n != nBasisFunctions)) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a NULL ->preCalc member or\n");
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated a incorrect length ->preCalc member.\n");
+            testStatus = true;
+        } else {
+            for (psS32 k = 0 ; k < kernels->u->n ; k++) {
+                psImage *kerImg = (psImage *) kernels->preCalc->data[k];
+                if (kerImg == NULL) {
+                    printf("TEST ERROR: the %d-th kernel preCalc image is NULL.\n", k);
+                    testStatus = true;
+                } else {
+                    if (kerImg->type.type != PS_TYPE_F32) {
+                        printf("TEST ERROR: preCalc image %d had ioncorrect type.\n", k);
+                        testStatus = true;
+                    }
+                    if ((kerImg->numRows != (1 + (2 * size))) ||
+                            (kerImg->numCols != (1 + (2 * size)))) {
+                        printf("TEST ERROR: preCalc image %d had incorrect size (%d, %d).\n", k,
+                               kerImg->numRows, kerImg->numCols);
+                        testStatus = true;
+                    }
+                }
+            }
+        }
+
+        if (kernels->p_size != size) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated an incorrect ->p_size member (%d).\n", kernels->p_size);
+            testStatus = true;
+        }
+
+        if (kernels->p_spatialOrder != SpatialOrder) {
+            printf("TEST ERROR: pmSubtractionKernelsAllocISIS() generated an incorrect ->p_spatialOrder member (%d).\n", kernels->p_spatialOrder);
+            testStatus = true;
+        }
+    }
+    psFree(sigmas);
+
+    psFree(kernels->u);
+    psFree(kernels->v);
+    psFree(kernels->sigma);
+    psFree(kernels->xOrder);
+    psFree(kernels->yOrder);
+    psFree(kernels->preCalc);
+    psFree(kernels);
+    psFree(orders);
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test01( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testISISAlloc(1, 1, 1, 1);
+    testStatus|= testISISAlloc(2, 2, 2, 2);
+    testStatus|= testISISAlloc(2, 3, 4, 5);
+    testStatus|= testISISAlloc(3, 4, 5, 6);
+
+    return(!testStatus);
+}
+
+
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: Can we test to ensure that no stamps overlap?
+ 
+XXX: Test stamp alloc/dealloc functions.
+ ******************************************************************************/
+#define TST02_THRESHOLD 3.0
+#define TST02_MASK_VAL 1
+psBool testFindStamps(psS32 numCols,
+                      psS32 numRows,
+                      psS32 xNum,
+                      psS32 yNum,
+                      psS32 border)
+{
+    printf("Testing pmSubtractionFindStamps(%d, %d, %d, %d, %d)\n",
+           numCols, numRows, xNum, yNum, border);
+    bool testStatus = false;
+
+    // Create a test image and set a single pixel in the center of each stamp.
+    psImage *tstImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psS32 numStamps = 0;
+    PS_IMAGE_SET_F32(tstImg, 0.0);
+    for (psS32 j = 0; j < yNum; j++) {
+        for (psS32 i = 0; i < xNum; i++) {
+            psS32 yMin = border + j * (numRows - 2.0 * border) / yNum;
+            psS32 yMax = PS_MIN(numRows-1, (border + (j + 1) * (numRows - 2.0 * border) / yNum) - 1);
+            psS32 xMin = border + i * (numCols - 2.0 * border) / xNum;
+            psS32 xMax = PS_MIN(numCols-1, (border + (i + 1) * (numCols - 2.0 * border) / xNum) - 1);
+
+            tstImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = TST02_THRESHOLD + (psF32) (i + j);
+            numStamps++;
+        }
+    }
+    psImage *tmpMask= psImageAlloc(numCols, numRows, PS_TYPE_U8);
+    PS_IMAGE_SET_U8(tstImg, 0);
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a NULL psImage.  Should generate error, return NULL.\n");
+    psArray *stamps = pmSubtractionFindStamps(NULL, NULL, tmpMask, TST02_MASK_VAL,
+                      TST02_THRESHOLD, xNum, yNum,
+                      border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive xNum.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, 0, yNum,
+                                     border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive yNum.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, 0,
+                                     border);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with a non-positive border.  Should generate error, return NULL.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     0);
+    if (stamps != NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        psFree(stamps);
+        testStatus = true;
+    }
+
+    //-------------------------------------------------------------------------
+    printf("Calling with acceptable input parameters, non-NULL mask.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, tmpMask, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     border);
+    if (stamps == NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        testStatus = true;
+    } else {
+        if (stamps->n != numStamps) {
+            printf("TEST ERROR: %d stamps were found, %d were expected.\n",
+                   stamps->n, numStamps);
+            testStatus = true;
+        }
+        for (psS32 s = 0 ; s < stamps->n ; s++) {
+            pmStamp *stamp = (pmStamp *) stamps->data[s];
+            psS32 row = stamp->y;
+            psS32 col = stamp->x;
+            // printf("Stamp %d at (%d, %d) has a value of %f\n", s, row, col, tstImg->data.F32[row][col]);
+            if (tstImg->data.F32[row][col] < TST02_THRESHOLD) {
+                if (stamp->status != PM_STAMP_NONE) {
+                    printf("TEST ERROR: stamp %d had peak value %f (below theshold) and the status was not set to PM_STAMP_NONE.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            } else {
+                if (stamp->status != PM_STAMP_RECALC) {
+                    printf("TEST ERROR: stamp %d had peak value %f (above theshold) and the status was not set to PM_STAMP_RECALC.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            }
+        }
+    }
+    psFree(stamps);
+
+    //-------------------------------------------------------------------------
+    printf("Calling with acceptable input parameters, NULL mask.\n");
+    stamps = pmSubtractionFindStamps(NULL, tstImg, NULL, TST02_MASK_VAL,
+                                     TST02_THRESHOLD, xNum, yNum,
+                                     border);
+    if (stamps == NULL) {
+        printf("TEST ERROR: pmSubtractionFindStamps returned a non-NULL psArray.\n");
+        testStatus = true;
+    } else {
+        if (stamps->n != numStamps) {
+            printf("TEST ERROR: %d stamps were found, %d were expected.\n",
+                   stamps->n, numStamps);
+            testStatus = true;
+        }
+        for (psS32 s = 0 ; s < stamps->n ; s++) {
+            pmStamp *stamp = (pmStamp *) stamps->data[s];
+            psS32 row = stamp->y;
+            psS32 col = stamp->x;
+            //printf("Stamp %d at (%d, %d) has a value of %f\n", s, row, col, tstImg->data.F32[row][col]);
+            if (tstImg->data.F32[row][col] < TST02_THRESHOLD) {
+                if (stamp->status != PM_STAMP_NONE) {
+                    printf("TEST ERROR: stamp %d had peak value %f (below theshold) and the status was not set to PM_STAMP_NONE.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            } else {
+                if (stamp->status != PM_STAMP_RECALC) {
+                    printf("TEST ERROR: stamp %d had peak value %f (above theshold) and the status was not set to PM_STAMP_RECALC.\n",
+                           s, tstImg->data.F32[row][col]);
+                    testStatus = true;
+                }
+            }
+        }
+    }
+
+    psFree(tstImg);
+    psFree(tmpMask);
+    psFree(stamps);
+
+    return(testStatus);
+}
+
+
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test02( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testFindStamps(100, 100, 2, 2, 2);
+    testStatus|= testFindStamps(100, 100, 10, 10, 2);
+
+    return(!testStatus);
+}
+
+
+psF32 genRanFloat(psF32 low,
+                  psF32 high)
+{
+    psF32 ran1 = (((psF32) (random() % 10000)) / 10000.0);
+    return(low + (ran1 * (high - low)));
+}
+
+#define TST03_THRESHOLD 3.0
+#define TST03_MASK_VAL 1
+#define TST03_KERNEL_SIZE 2
+#define TST03_SPATIAL_ORDER 3
+#define TST03_ORDER_LENGTH 2
+#define TST03_SIGMA_LENGTH 3
+#define TST03_FOOTPRINT 5
+/*******************************************************************************
+NOTE: This function returns FALSE if there were no errors.
+ 
+XXX: We should use a larger variety of input parameter configurations.
+ 
+XXX: I test the following functions here (since they linearly rely on a set of
+data structures that the previoues ones generate):
+    pmSubtractionCalculateEquation()
+    pmSubtractionSolveEquation()
+    pmSubtractionRejectStamps()
+    pmSubtractionKernelImage()
+ 
+XXX: We test that the functions do not seg fault, or generate other errors.
+However, additional work, and further understanding, is required to begin
+testing that the output values are correct as well.
+ ******************************************************************************/
+psBool testSubCalcEqu(psS32 numCols,
+                      psS32 numRows,
+                      psS32 xNum,
+                      psS32 yNum,
+                      psS32 border,
+                      pmSubtractionKernelsType KernelType)
+{
+    printf("Testing pmSubtractionCalculateEquation(): \n");
+    printf("    image size is (%d, %d)\n", numRows, numCols);
+    printf("    num stamps is (%d, %d).  Border is %d\n", yNum, xNum, border);
+    if (KernelType == PM_SUBTRACTION_KERNEL_POIS) {
+        printf("   kernel type is PM_SUBTRACTION_KERNEL_POIS.\n");
+    } else if (KernelType == PM_SUBTRACTION_KERNEL_ISIS) {
+        printf("   kernel type is PM_SUBTRACTION_KERNEL_ISIS.\n");
+    }
+    bool testStatus = false;
+
+    // Create a test image and set a single pixel in the center of each stamp.
+    psImage *tstImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *refImg = psImageAlloc(numCols, numRows, PS_TYPE_F32);
+    psImage *maskImg = psImageAlloc(numCols, numRows, PS_TYPE_U8);
+    PS_IMAGE_SET_F32(tstImg, 0.0);
+    PS_IMAGE_SET_F32(maskImg, 0);
+    for (psS32 j = 0; j < yNum; j++) {
+        for (psS32 i = 0; i < xNum; i++) {
+            psS32 yMin = border + j * (numRows - 2.0 * border) / yNum;
+            psS32 yMax = PS_MIN(numRows-1, (border + (j + 1) * (numRows - 2.0 * border) / yNum) - 1);
+            psS32 xMin = border + i * (numCols - 2.0 * border) / xNum;
+            psS32 xMax = PS_MIN(numCols-1, (border + (i + 1) * (numCols - 2.0 * border) / xNum) - 1);
+
+            // Set the center pixel in the stamp.
+            refImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = TST03_THRESHOLD + (psF32) (i + j);
+            tstImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = TST03_THRESHOLD + (psF32) (i + j);
+            refImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = 100.0;
+            tstImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2] = 100.0;
+
+            // Add some noise for the test image.
+            tstImg->data.F32[(yMax+yMin)/2][(xMax+xMin)/2]+= genRanFloat(0.0, 1.0);
+        }
+    }
+    printf("Generating stamps...\n");
+    psArray *stamps = pmSubtractionFindStamps(NULL, tstImg, NULL, TST03_MASK_VAL,
+                      TST03_THRESHOLD, xNum, yNum,
+                      border);
+
+    //
+    // PsVectors sigmas and orders are for ISIS kernels only.
+    //
+    psVector *sigmas = psVectorAlloc(TST03_SIGMA_LENGTH, PS_TYPE_F32);
+    for (psS32 i = 0 ; i < sigmas->n ; i++) {
+        sigmas->data.F32[i] = 1.0 + (psF32) i;
+    }
+    psVector *orders = psVectorAlloc(TST03_ORDER_LENGTH, PS_TYPE_S32);
+    for (psS32 i = 0 ; i < orders->n ; i++) {
+        orders->data.S32[i] = i + 2;
+    }
+
+    //
+    // Create the subtraction kernels
+    //
+    printf("Generating kernel basis functions...\n");
+    psSubtractionKernels *myKernels = NULL;
+    if (KernelType == PM_SUBTRACTION_KERNEL_POIS) {
+        myKernels = pmSubtractionKernelsAllocPOIS(TST03_KERNEL_SIZE, TST03_SPATIAL_ORDER);
+    } else if (KernelType == PM_SUBTRACTION_KERNEL_ISIS) {
+        myKernels = pmSubtractionKernelsAllocISIS(sigmas, orders, TST03_KERNEL_SIZE, TST03_SPATIAL_ORDER);
+    }
+
+    if ((stamps == NULL) ||
+            (myKernels == NULL)) {
+        printf("TEST ERROR: stamps or myKernels is NULL.\n");
+        testStatus = true;
+    } else {
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL psArray stamps.  Should generate error, return FALSE.\n");
+        psBool rc = pmSubtractionCalculateEquation(NULL, refImg, tstImg, myKernels, TST03_KERNEL_SIZE);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL reference images.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, NULL, tstImg, myKernels, TST03_KERNEL_SIZE);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL input images.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, refImg, NULL, myKernels, TST03_KERNEL_SIZE);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with a NULL kernel basis functions.  Should generate error, return FALSE.\n");
+        rc = pmSubtractionCalculateEquation(stamps, refImg, tstImg, NULL, TST03_KERNEL_SIZE);
+        if (rc == TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned TRUE.\n");
+            testStatus = true;
+        }
+
+        //-------------------------------------------------------------------------
+        printf("Calling with acceptable input parameters.  Should return TRUE.\n");
+
+        rc = pmSubtractionCalculateEquation(stamps, refImg, tstImg, myKernels, TST03_KERNEL_SIZE);
+        if (rc != TRUE) {
+            printf("TEST ERROR: pmSubtractionCalculateEquation() returned FALSE.\n");
+            testStatus = true;
+        } else {
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionSolveEquation() with a NULL stamp argument.  Should generate error, return FALSE.\n");
+            psVector *solution = pmSubtractionSolveEquation(NULL, NULL);
+            if (solution != NULL) {
+                printf("TEST ERROR: pmSubtractionSolveEquation() returned non-NULL.\n");
+                testStatus = true;
+            }
+
+            //-------------------------------------------------------------------------
+            printf("Calling with pmSubtractionSolveEquation() acceptable input parameters.  Should return non-NULL.\n");
+            solution = pmSubtractionSolveEquation(NULL, stamps);
+            if (solution == NULL) {
+                printf("TEST ERROR: pmSubtractionSolveEquation() returned NULL.\n");
+                testStatus = true;
+            }
+
+            //-------------------------------------------------------------------------
+            printf("Calling with pmSubtractionRejectStamps() acceptable input parameters.  Should return TRUE.\n");
+            rc = pmSubtractionRejectStamps(stamps, maskImg, 0xff, TST03_FOOTPRINT, 1.0, refImg, tstImg, solution, myKernels);
+            if (rc != TRUE) {
+                printf("TEST ERROR: pmSubtractionRejectStamps() returned FALSE.\n");
+                testStatus = true;
+            }
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() with NULL solution.  Should generate error, return NULL.\n");
+            psImage *kernelImg = pmSubtractionKernelImage(NULL, NULL, myKernels, 0.0, 0.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() with NULL kernels.  Should generate error, return NULL.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, NULL, 0.0, 0.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() unallowable x value.  Should generate error, return NULL.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, -2.0, 0.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() unallowable x value.  Should generate error, return NULL.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 2.0, 0.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() unallowable y value.  Should generate error, return NULL.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.0, -2.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling pmSubtractionKernelImage() unallowable y value.  Should generate error, return NULL.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.0, 2.0);
+            if (kernelImg != NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned non-NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            //-------------------------------------------------------------------------
+            printf("Calling with pmSubtractionKernelImage() acceptable input parameters.  Should return a psImage.\n");
+            kernelImg = pmSubtractionKernelImage(NULL, solution, myKernels, 0.0, 0.0);
+            if (kernelImg == NULL) {
+                printf("TEST ERROR: pmSubtractionKernelImage() returned NULL.\n");
+                testStatus = true;
+            }
+            free(kernelImg);
+
+            psFree(solution);
+        }
+    }
+    psFree(tstImg);
+    psFree(refImg);
+    psFree(stamps);
+    psFree(myKernels);
+    psFree(orders);
+    psFree(sigmas);
+
+    return(testStatus);
+}
+
+/*******************************************************************************
+NOTE: This function returns TRUE if there were no errors.
+ ******************************************************************************/
+int test03( void )
+{
+    bool testStatus = false;
+
+    testStatus|= testSubCalcEqu(100, 100, 2, 2, 3, PM_SUBTRACTION_KERNEL_POIS);
+    testStatus|= testSubCalcEqu(100, 100, 2, 2, 3, PM_SUBTRACTION_KERNEL_ISIS);
+
+    return(!testStatus);
+}
+// this code will
+
+
+
