Index: /trunk/psLib/test/imageops/tap_psFits.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psFits.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psFits.c	(revision 11398)
@@ -0,0 +1,1255 @@
+/** @file  tst_psFits.c
+*
+*  @brief Contains the tests for psFits.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-30 00:13:01 $
+*
+*  XXXX: All of the makeTable() tests are failing, as well as one additional one.
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+#include <unistd.h>
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+//static bool makeMulti(void);  // implicitly tests psFitsSetExtName
+//static bool makeTable(void);
+const char* multiFilename = "multi.fits";
+const char* tableFilename = "table.fits";
+const int tableNumRows = 10;
+
+
+// N.B., the tests to Image read/write was liberally taken from the now
+// deprecated psImageReadSection/psImageWriteSection function tests.
+
+bool makeMulti(void)
+{
+    psFits* fitsFile = psFitsOpen(multiFilename,"w");
+
+    if (fitsFile == NULL) {
+        diag("Could not create 'multi' FITS file");
+        return false;
+    }
+
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    char extname[80];
+    for (int lcv = 0; lcv < 8; lcv++) {
+        snprintf(extname,80,"ext-%d", lcv);
+
+        psMetadata* header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item", (psS32)lcv);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item", (float)(1.0f/(float)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item", (double)(1.0/(double)(1+lcv)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (lcv%2 == 0));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "String Item",
+                      extname);
+
+        // set the pixels in the image
+        psImageInit(image, (float)lcv);
+        if (!psFitsWriteImage(fitsFile,header,image,0,extname)) {
+            diag("Could not write image");
+        }
+        psFree(header);
+    }
+    psFree(image);
+    psFree(fitsFile);
+
+    return true;
+}
+
+bool makeTable(void)
+{
+    psFits* fitsFile = psFitsOpen(tableFilename, "w");
+    if (fitsFile == NULL) {
+        diag("Could not create 'table' FITS file");
+        return false;
+    }
+
+    // make the PHU an image (per FITS standard, it must be)
+    psImage* image = psImageAlloc(16,16,PS_TYPE_F32);
+
+    if (!psFitsWriteImage(fitsFile,NULL,image,1,NULL)) {
+        diag("Could not write PHU image");
+        return false;
+    }
+
+    psFree(image);
+
+    // build a table structure
+    psArray* table = psArrayAlloc(tableNumRows);
+    psMetadata* header = NULL;
+    for (int row = 0; row < tableNumRows; row++) {
+        header = psMetadataAlloc();
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYINT",
+                      PS_DATA_S32,
+                      "psS32 Item",
+                      (psS32)row);
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYFLT",
+                      PS_DATA_F32,
+                      "psF32 Item",
+                      (float)(1.0f/(float)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYDBL",
+                      PS_DATA_F64,
+                      "psF64 Item",
+                      (double)(1.0/(double)(1+row)));
+
+        psMetadataAdd(header,PS_LIST_TAIL, "MYBOOL",
+                      PS_DATA_BOOL,
+                      "psBool Item",
+                      (row%2 == 0));
+
+        char* str = NULL;
+        psStringAppend(&str,"row=%d",row+1);
+        psMetadataAdd(header,PS_LIST_TAIL, "MYSTR",
+                      PS_DATA_STRING,
+                      "psString Item",
+                      str);
+        psFree(str);
+
+        psVector* vec = psVectorAlloc(5,PS_TYPE_S32);
+        for (int x=0; x < 4; x++) {
+            vec->data.S32[x] = x*10+row;
+            vec->n++;
+        }
+        psMetadataAdd(header,PS_LIST_TAIL, "MYVEC",
+                      PS_DATA_VECTOR,
+                      "psVector Item",
+                      vec);
+        psFree(vec);
+
+        table->data[row] = header;
+        table->n++;
+    }
+
+    printf("XXX: The following call to psFitsWriteTable() seg faults\n");
+    psFitsWriteTable(fitsFile, NULL, table, NULL);
+
+    psFree(table);
+    psFree(fitsFile);
+    return (!psMemCheckLeaks(15,NULL,stderr,false));
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetLevel(PS_LOG_INFO);
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(509);
+
+    // tst_psFitsOpen()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+        psFits* fitsFile = psFitsOpen(multiFilename,"r");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on existing file");
+        int extNum = psFitsGetExtNum(fitsFile);
+        ok(extNum == 0, "psFitsOpen was queued to the PHU");
+        psFitsClose(fitsFile);
+
+        // make sure the file doesn't already exist.
+        // XXX: What is F_OK?
+        //        if (access("new.fits", F_OK) == 0) {
+        //            if (remove
+        //                    ("new.fits") != 0) {
+        //                psError(PS_ERR_UNKNOWN, false,
+        //                        "Couldn't delete the new.fits file");
+        //                return 3;
+        //            }
+        //        }
+
+        fitsFile = psFitsOpen("new.fits","w");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on w mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psImage* img = psImageAlloc(16,16,PS_TYPE_F32);
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        // psFree should be equivalent to psFitsClose
+        psFree(fitsFile);
+
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        fitsFile = psFitsOpen("new.fits","w+");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on w+ mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        psFitsClose(fitsFile);
+
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        fitsFile = psFitsOpen("new.fits","a");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on a mode");
+
+        // write something to the file, otherwise CFITSIO will complain on close
+        psFitsWriteImage(fitsFile,NULL,img,1,NULL);
+        psFitsClose(fitsFile);
+        fitsFile = psFitsOpen("new.fits","a+");
+        ok(fitsFile != NULL, "psFitsOpen returned non-NULL on a+ mode");
+
+        psFitsClose(fitsFile);
+        // now, if psFitsOpen actually created the file, I shouldn't error in removing it.
+        ok(remove
+           ("new.fits") == 0, "psFitsOpen seemed to have created a new file");
+
+        // Attempt to allocate with NULL filename
+        // Following should generate an error message
+        // XXX: Verify error
+        fitsFile = psFitsOpen(NULL,"r");
+        ok(fitsFile == NULL, "psFitsOpen returned NULL for NULL input");
+
+        // Attempt to use an unallowed mode
+        // Following should generate an error message
+        // XXX: Verify error
+        fitsFile = psFitsOpen("new.fits","b+");
+        ok(fitsFile == NULL, "psFitsOpen returned NULL for NULL input");
+
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsMoveExtName()
+    {
+        psMemId id = psMemGetId();
+
+        ok(makeMulti(), "Created 'multi' FITS file");
+        if (! makeMulti() )
+        {
+            return 1;
+        }
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+
+        if (fits == NULL)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "psFitsOpen returned NULL on existing file");
+            return 1;
+        }
+
+        int numHDUs = psFitsGetSize(fits);
+
+        if (numHDUs < 2)
+        {
+            psError(PS_ERR_UNKNOWN,true,
+                    "The 'multi' FITS file does not have multiple HDUs");
+            return 2;
+        }
+
+        char extName[80];
+        psRegion region = {0,0,0,0};
+
+        for (int lcv = 0; lcv < numHDUs; lcv++)
+        {
+            snprintf(extName,80,"ext-%d",lcv);
+            // try to move to the named extension.
+            if (! psFitsMoveExtName(fits, extName) ) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to move to ext-%d",
+                        lcv);
+                return 3;
+            }
+
+            // check to see if I can retrieve the name back from the psFits object.
+            char* nameFromFile = psFitsGetExtName(fits);
+            if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to retrieve the extension name back ('%s' vs '%s'",
+                        nameFromFile, extName);
+                return 3;
+            }
+            psFree(nameFromFile);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            if (image == NULL || abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "The image pixel 0,0 of ext-%d was %g, expected %d",
+                        lcv,image->data.F32[0][0],lcv);
+                return 4;
+            }
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-1; lcv >= 0; lcv--)
+        {
+            snprintf(extName,80,"ext-%d",lcv);
+            // try to move to the named extension.
+            if (! psFitsMoveExtName(fits, extName) ) {
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to move to ext-%d",
+                        lcv);
+                return 5;
+            }
+
+            // check to see if I can retrieve the name back from the psFits object.
+            char* nameFromFile = psFitsGetExtName(fits);
+            if (strcmp(nameFromFile,extName) != 0) { // hey, it didn't move?
+                psError(PS_ERR_UNKNOWN, false,
+                        "Failed to retrieve the extension name back ('%s' vs '%s'",
+                        nameFromFile, extName);
+                return 5;
+            }
+            psFree(nameFromFile);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            if (abs(image->data.F32[0][0] - (float)lcv) > FLT_EPSILON) {
+                psError(PS_ERR_UNKNOWN, true,
+                        "The image pixel 0,0 of ext-%d was %g, expected %d",
+                        lcv,image->data.F32[0][0],lcv);
+                return 6;
+            }
+            psFree(image);
+        }
+
+        // check to see if given a bogus extension name, it errors.
+        psLogMsg(__func__,PS_LOG_INFO, "Following should be an error");
+        // XXX: Verify error
+        if (psFitsMoveExtName(fits, "bogus") || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Moving to non-existant HDU didn't fail");
+            return 7;
+        }
+
+        // check to see if given a NULL psFits, it errors.
+        psLogMsg(__func__,PS_LOG_INFO, "Following should be an error");
+        // XXX: Verify error
+        if (psFitsMoveExtName(NULL, "bogus") || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Operation of NULL psFits didn't fail");
+            return 8;
+        }
+
+        // check to see if given a NULL extname, it errors.
+        psLogMsg(__func__,PS_LOG_INFO, "Following should be an error");
+        // XXX: Verify error
+        if (psFitsMoveExtName(fits, NULL) || psErrorGetStackSize() != 1)
+        {
+            psError(PS_ERR_UNKNOWN, false,
+                    "Operation of NULL extname didn't fail");
+            return 9;
+        }
+
+        psFree(fits);
+
+        // Attempt to get ext name from null fits file
+        psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL fits file");
+        if(psFitsGetExtName(NULL) != NULL)
+        {
+            psError(PS_ERR_UNKNOWN,true,"Expected NULL return from psFitsGetExtName with NULL fits file");
+            return 10;
+        }
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsMoveExtNum()
+    {
+        psMemId id = psMemGetId();
+
+        ok(makeMulti(), "Created 'multi' FITS file");
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        // as a side test, let's make sure psFitsGetSize can handle NULL.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsGetSize(NULL) == 0 && psErrorGetStackSize() == 1,
+           "The 'multi' FITS file has multiple HDUs");
+
+        ok(numHDUs == 8, "The 'multi' FITS file does not have multiple HDUs");
+
+        psRegion region = {0,0,0,0};
+        // test absolute positioning
+        for (int lcv = 0; lcv < numHDUs; lcv++)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, lcv, false), "Moved to extension %d", lcv);
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv, "Retrieved the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+            ok(image != NULL && abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-1; lcv >= 0; lcv--)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, lcv, false), "Moved to extension %d", lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv, image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        // test relative positioning
+        psFitsMoveExtNum(fits,0,false);
+        for (int lcv = 1; lcv < numHDUs; lcv++)
+        {
+            // try to move to the extension
+            if (psFitsMoveExtNum(fits, 1, true), "Failed to move to extension %d", lcv)
+                ;
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv,
+               "Failed to retrieve the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(image != NULL && abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+        for (int lcv = numHDUs-2; lcv >= 0; lcv--)
+        {
+            // try to move to the extension
+            ok(psFitsMoveExtNum(fits, -1, true), "Failed to move to extension %d", lcv);
+
+            // check to see if I can retrieve the number back from the psFits object.
+            ok(psFitsGetExtNum(fits) == lcv,
+               "Failed to retrieve the extension number back (%d vs %d)",
+               psFitsGetExtNum(fits), lcv);
+
+            // check that the image is associated to the extension moved, i.e.,
+            // did we really move to the proper extension?
+            psImage* image = NULL;
+            image = psFitsReadImage(fits,region,0);
+
+            ok(abs(image->data.F32[0][0] - (float)lcv) <= FLT_EPSILON,
+               "The image pixel 0,0 of ext-%d was %g, expected %d",
+               lcv,image->data.F32[0][0],lcv);
+            psFree(image);
+        }
+
+
+        // check to see if given a negative extension number, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, -1, false) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if relative positioning beyond PHU, it errors.
+        psFitsMoveExtNum(fits,0,false);
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, -1, true) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if given a extension greater than the total #HDUs, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, numHDUs, false) && psErrorGetStackSize() == 1,
+           "Moving to a HDU beyond the file's contents did fail");
+
+        // check to see if relative positioning beyond PHU, it errors.
+        psFitsMoveExtNum(fits,numHDUs-1,false);
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(fits, 1, true) && psErrorGetStackSize() == 1,
+           "Moving to negative HDU did fail");
+
+        // check to see if given a NULL psFits, it errors.
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(!psFitsMoveExtNum(NULL, 0, false) && psErrorGetStackSize() == 1,
+           "Operation of NULL psFits didt fail");
+        psFitsClose(fits);
+
+        // Attempt to get ext name from null fits file
+        // Following should generate an error for NULL fits file
+        // XXX: Verify error
+        ok(psFitsGetExtNum(NULL) == PS_FITS_TYPE_NONE,
+           "Expected NULL return from psFitsGetExtNum with NULL fits file");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+
+    }
+
+
+    // tst_psFitsReadHeader()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        ok(numHDUs >= 8, "The 'multi' FITS file has multiple HDUs");
+
+        char extname[80];
+        for (int hdunum = 0; hdunum < numHDUs; hdunum++)
+        {
+            snprintf(extname,80,"ext-%d",hdunum);
+            psFitsMoveExtNum(fits,hdunum,false);
+
+            psMetadata* header = psFitsReadHeader(NULL,fits);
+            ok(header != NULL, "Read header");
+
+            psMetadata* header2 = psMetadataAlloc();
+            header2 = psFitsReadHeader(header2,fits);
+            ok(header2 != NULL, "Read header");
+
+            ok(header->list->n >= 1 && header->list->n == header2->list->n,
+               "Reading the header given a NULL input psMetadata did not differ from giving an existing psMetadata");
+
+            // check for the extra metadata items
+            psS32 intItem = psMetadataLookupS32(NULL,header, "MYINT");
+            psF32 fltItem = psMetadataLookupF32(NULL,header, "MYFLT");
+            psF64 dblItem = psMetadataLookupF64(NULL,header, "MYDBL");
+            psMetadataItem* boolItem = psMetadataLookup(header, "MYBOOL");
+            psString strItem = psMetadataLookupStr(NULL, header, "MYSTR");
+
+            ok(intItem == hdunum, "Retrieved psS32 metadata item from file");
+
+            ok(fabsf(fltItem - 1.0f/(float)(1+hdunum)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file.  Got %f vs %f",
+               fltItem,1.0f/(float)(1+hdunum));
+
+            ok(abs(dblItem - 1.0/(double)(1+hdunum)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file.  Got %g vs %g",
+               dblItem, 1.0/(double)(1+hdunum));
+
+            ok(boolItem != NULL && boolItem->type == PS_DATA_BOOL,
+               "Retrieved psBool metadata item from file");
+
+            ok(strItem != NULL && strncmp(strItem,extname,strlen(extname)) == 0,
+               "Retrieved string metadata item from file.  Got '%s' vs '%s' (%d)",
+               strItem,extname,strlen(extname));
+
+            psFree(header);
+            psFree(header2);
+        }
+
+        // Following should be an error (input psFits = NULL)
+        // XXX: Verify error
+        psMetadata* header = psFitsReadHeader(NULL,NULL);
+        ok(header == NULL && psErrorGetStackSize() == 1,
+           "psFitsReadHeader didn't error on a NULL psFits");
+
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadHeaderSet()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psFits* fits = psFitsOpen(multiFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        int numHDUs = psFitsGetSize(fits);
+        ok(numHDUs >= 8, "The 'multi' FITS file has multiple HDUs");
+
+        // move to the middle
+        psFitsMoveExtNum(fits,numHDUs/2, false);
+        psMetadata* headerSet = psFitsReadHeaderSet(NULL,fits);
+        ok(headerSet != NULL, "psFitsReadHeaderSet returned non-NULL");
+
+        ok(psFitsGetExtNum(fits) == numHDUs/2, "psFitsReadHeaderSet did not change the CHU");
+
+        char extname[80];
+        for (int i = 0; i < numHDUs; i++)
+        {
+            if (i == 0) {
+                snprintf(extname, 80, "PHU");
+            } else {
+                snprintf(extname, 80, "ext-%d", i);
+            }
+
+            psMetadata* header = psMetadataLookupPtr(NULL,headerSet, extname);
+
+            ok(header != NULL, "psFitsReadHeader returned non-NULL for HDU#%d", i);
+
+            psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+            ok(intItem == i, "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d",
+               intItem, i);
+        }
+
+        psMetadata* set3 = psFitsReadHeaderSet(NULL,fits);
+        ok(set3 != NULL, "psFitsReadHeaderSet returned non-NULL");
+
+        for (int i = 0; i < numHDUs; i++)
+        {
+            if (i == 0) {
+                snprintf(extname, 80, "PHU");
+            } else {
+                snprintf(extname, 80, "ext-%d", i);
+            }
+
+            psMetadata* header = psMetadataLookupPtr(NULL, set3, extname);
+            ok(header != NULL, "psFitsReadHeader returned non-NULL for HDU#%d", i);
+
+            psS32 intItem = psMetadataLookupS32(NULL, header, "MYINT");
+            ok(intItem == i, "psFitsReadHeader for HDU#%d had a MYINT of %d, expected %d",
+               intItem, i);
+        }
+
+        set3 = psFitsReadHeaderSet(set3,NULL);
+        ok(set3 == NULL, "psFitsReadHeaderSet returned NULL given a NULL psFits");
+
+
+        psFree(headerSet);
+        psFitsClose(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadTable()
+    // XXXX: This is if'ed out because the call to makeTable() is seg faulting
+    if (0) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename, "r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        psArray* table = psFitsReadTable(fits);
+        ok(table != NULL, "psFitsReadTable returned non-NULL");
+        ok(table->n == tableNumRows, "Expected %d rows, read %d",
+           tableNumRows, table->n);
+
+        for (int row = 0; row < table->n; row++) {
+            psMetadata* rowData = table->data[row];
+
+            psS32 intItem = psMetadataLookupS32(NULL, rowData, "MYINT");
+            psF32 fltItem = psMetadataLookupF32(NULL, rowData, "MYFLT");
+            psF64 dblItem = psMetadataLookupF64(NULL, rowData, "MYDBL");
+            psBool boolItem = psMetadataLookupBool(NULL, rowData, "MYBOOL");
+            psString strItem = psMetadataLookupStr(NULL, rowData, "MYSTR");
+            psVector* vecItem = psMetadataLookupPtr(NULL, rowData, "MYVEC");
+
+            ok(intItem == row,
+               "Failed to retrieve psS32 metadata item from file (row=%d).  Got %d vs %d",
+               row, intItem, row);
+
+            ok(fabsf(fltItem - 1.0f/(float)(1+row)) <= FLT_EPSILON,
+               "Retrieved psF32 metadata item from file (row=%d).  Got %f vs %f",
+               row, fltItem,1.0f/(float)(1+row));
+
+            ok(abs(dblItem - 1.0/(double)(1+row)) <= DBL_EPSILON,
+               "Retrieved psF64 metadata item from file (row=%d).  Got %g vs %g",
+               row, dblItem, 1.0/(double)(1+row));
+
+            ok(!(boolItem != ((row&0x01) == 0)),
+               "Retrieved psBool metadata item from file (row=%d). Got %d vs %d",
+               row, boolItem, ((row&0x01) == 0));
+
+            char strValue[16];
+            snprintf(strValue,16,"row=%d",row+1);
+            ok(strncmp(strItem,strValue,strlen(strValue)) == 0,
+               "Retrieved psString metadata item from file (row=%d). Got '%s' vs '%s'",
+               row, strItem, strValue);
+
+            ok(vecItem != NULL, "Retrieved psVector metadata item from file (row=%d)", row);
+
+            ok(vecItem->type.type == PS_DATA_S32 &&
+               vecItem->data.S32[0] == row &&
+               vecItem->data.S32[3] == row+30,
+               "Retrieved psVector (row=%d) had expected values [%d,%d,%d,%d] vs [%d,%d,%d,%d]",
+               row,vecItem->data.S32[0], vecItem->data.S32[1],
+               vecItem->data.S32[2], vecItem->data.S32[3],
+               row,row+10,row+20,row+30);
+        }
+
+        psFree(table);
+        psFree(fits);
+
+        psArray* nullTest = psFitsReadTable(NULL);
+        ok(nullTest == NULL && psErrorGetStackSize() == 1,
+           "psFitsReadTable returned NULL when given NULL");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadTableColumnNum()
+    // XXXX: This is if'ed out because the call to makeTable() is seg faulting
+    if (0) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        // read the column data via number
+        psVector* colData;
+        psElemType type[4] = {PS_TYPE_S32, PS_TYPE_F32, PS_TYPE_F32, PS_TYPE_BOOL};
+        psElemType altType[4] = {PS_TYPE_S64, PS_TYPE_F64, PS_TYPE_F64, PS_TYPE_BOOL};
+        char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+        psF64 expectedValues[4][10] = {
+                                          {0,1,2,3,4,5,6,7,8,9},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}
+                                      };
+
+        for (int col = 0; col < 4; col++) {
+            colData = psFitsReadTableColumnNum(fits,colname[col]);
+            ok(colData != NULL, "psFitsReadTableColumnNum returned non-NULL for col=%d");
+
+            if (colData->type.type != type[col] &&
+                    colData->type.type != altType[col]) {
+                char* typeRead;
+                char* typeExpected;
+                PS_TYPE_NAME(typeRead, colData->type.type);
+                PS_TYPE_NAME(typeExpected, type[col]);
+
+                ok(false, "psFitsReadTableColumnNum returned different type, %s vs %s, for col=%d",
+                   typeRead, typeExpected, col);
+            } else {
+                ok(true, "psFitsReadTableColumnNum returned same type");
+            }
+            ok(colData->n == tableNumRows,
+               "psFitsReadTableColumnNum returned same number of rows, %d vs %d, for col=%d",
+               colData->n, tableNumRows, col);
+            for (int row = 0; row < tableNumRows; row++) {
+                ok(abs(p_psVectorGetElementF64(colData,row) - expectedValues[col][row]) <= FLT_EPSILON,
+                   "psFitsReadTableColumnNum returned values (%g vs %g) for col=%d",
+                   p_psVectorGetElementF64(colData,row), expectedValues[col][row], col);
+            }
+            psFree(colData);
+        }
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        psVector* data = psFitsReadTableColumnNum(NULL,colname[0]);
+        psErr* err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumnNum did return NULL with NULL psFits");
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psFitsReadTableColumnNum did return error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        data = psFitsReadTableColumnNum(fits,"BOGUS");
+        err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumnNum did return NULL with bogus column name");
+        ok(err->code == PS_ERR_IO, "psFitsReadTableColumnNum did return error with bogus column name");
+        psFree(err);
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsReadTableColumn()
+    // XXXX: This is if'ed out because the call to makeTable() is seg faulting
+    if (0) {
+        psMemId id = psMemGetId();
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"r");
+        ok(fits != NULL, "psFitsOpen returned non-NULL on existing file");
+
+        psFitsMoveExtNum(fits,1,false);
+        // read the column data via number
+        psArray* colData;
+        char* colname[4] = {"MYINT","MYFLT","MYDBL","MYBOOL"};
+        psF64 expectedValues[3][10] = {
+                                          {0,1,2,3,4,5,6,7,8,9},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0},
+                                          {1.0,1.0/2.0,1.0/3.0,1.0/4.0,1.0/5.0,1.0/6.0,1.0/7.0,1.0/8.0,1.0/9.0}
+                                      };
+        char* expectedBoolValues[10] = {"T","F","T","F","T","F","T","F","T","F"};
+        char* expectedStrValues[10] = {"row=1","row=2","row=3","row=4","row=5","row=6","row=7","row=8","row=9","row=10"};
+
+        bool errorFlag = false;
+        for (int col = 0; col < 4; col++) {
+            colData = psFitsReadTableColumn(fits,colname[col]);
+            if (colData == NULL) {
+                diag("psFitsReadTableColumn returned NULL for col=%d", col);
+                errorFlag = true;
+            }
+            if (colData->n != tableNumRows) {
+                diag("psFitsReadTableColumn returned different number of rows, %d vs %d, for col=%d",
+                     colData->n, tableNumRows, col);
+                errorFlag = true;
+            }
+            if (col < 3) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (abs(atof((char*)colData->data[row]) - expectedValues[col][row]) > 0.0001) {
+                        diag("psFitsReadTableColumn returned unexpected values (%g vs %g) for col=%d",
+                             atof((char*)colData->data[row]), expectedValues[col][row], col);
+                        errorFlag = true;
+                    }
+                }
+            } else if (col == 3) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (strncmp(colData->data[row],expectedBoolValues[row],
+                                strlen(expectedBoolValues[row])) != 0) {
+                        diag("psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                             (char*)colData->data[row], expectedBoolValues[row], col);
+                        errorFlag = true;
+                    }
+                }
+            } else if (col == 4) {
+                for (int row = 0; row < tableNumRows; row++) {
+                    if (strncmp(colData->data[row],expectedStrValues[row],
+                                strlen(expectedStrValues[row])) != 0) {
+                        diag("psFitsReadTableColumn returned unexpected values ('%s' vs '%s') for col=%d",
+                             (char*)colData->data[row], expectedStrValues[row], col);
+                        errorFlag = true;
+                    }
+                }
+            }
+            psFree(colData);
+        }
+        ok(!errorFlag, "psFitsReadTableColumn() produced the correct data");
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        psArray* data = psFitsReadTableColumn(NULL,"MYINT");
+        psErr* err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumn did return NULL with NULL psFits");
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psFitsReadTableColumn did error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        data = psFitsReadTableColumn(fits,"BOGUS");
+        err = psErrorLast();
+        ok(data == NULL, "psFitsReadTableColumn did return NULL with col=\"BOGUS\"");
+        ok(err->code == PS_ERR_IO, "psFitsReadTableColumn did error with col=\"BOGUS\"");
+        psFree(err);
+
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsUpdateTable()
+    // XXXX: This is if'ed out because the call to makeTable() is seg faulting
+    if (0) {
+        psMemId id = psMemGetId();
+        psErr* err;
+        char* strValue[] = {
+                               "row A",
+                               "row B",
+                               "row C",
+                               "row D",
+                               "row E",
+                               "row F",
+                               "row G",
+                               "row H",
+                               "row I",
+                               "row J",
+                               "row K"
+                           };
+        ok(makeTable(), "Created 'table' FITS file");
+        psFits* fits = psFitsOpen(tableFilename,"rw");
+        ok(fits != NULL, "psFitsOpen returned NULL on existing file");
+        psFitsMoveExtNum(fits,1,false);
+        // change the data in the file, going past by one (implicit new row of data)
+        bool errorFlag = false;
+        for (int row = 0; row < tableNumRows+1; row++) {
+            psMetadata* md = psMetadataAlloc();
+            psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",(float)row/-10.0);
+            psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",(double)row/-100.0);
+            psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-row);
+            psMetadataAddBool(md,PS_LIST_TAIL,"MYBOOL", 0,"",((row & 1) == 1));
+            psMetadataAddStr(md,PS_LIST_TAIL,"MYSTR", 0,"",strValue[row]);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+            if (!psFitsUpdateTable(fits,md,row)) {
+                diag("psFitsUpdateTable returned false, but expected true for row=%d", row);
+                errorFlag = true;
+            }
+            psFree(md);
+        }
+        ok(!errorFlag, "psFitsUpdateTable() produced the correct data");
+
+        for (int row = 0; row < tableNumRows+1; row++) {
+            psMetadata* md = psFitsReadTableRow(fits, row);
+            if (abs(psMetadataLookupF32(NULL,md,"MYFLT") - (float)row/-10.0) > FLT_EPSILON) {
+                diag("psFitsUpdateTable did not change the float value for row=%d", row);
+                errorFlag = true;
+            }
+            if (abs(psMetadataLookupF64(NULL,md,"MYDBL") - (float)row/-100.0) > FLT_EPSILON) {
+                diag("psFitsUpdateTable did not change the double value for row=%d", row);
+                errorFlag = true;
+            }
+            if (psMetadataLookupS32(NULL,md,"MYINT") != -row) {
+                diag("psFitsUpdateTable did not change the integer value for row=%d", row);
+                errorFlag = true;
+            }
+            if (psMetadataLookupBool(NULL,md,"MYBOOL") != ((row &1) == 1)) {
+                diag("psFitsUpdateTable did not change the boolean value for row=%d", row);
+                errorFlag = true;
+            }
+            psString mystr = psMetadataLookupStr(NULL,md,"MYSTR");
+            if (strncmp(mystr,strValue[row], strlen(strValue[row])) != 0) {
+                diag("psFitsUpdateTable did not change the string value for row=%d", row);
+                errorFlag = true;
+            }
+            psFree(md);
+        }
+        ok(!errorFlag, "psFitsUpdateTable() produced the correct data");
+
+        psMetadata* md = psMetadataAlloc();
+        psMetadataAddF32(md,PS_LIST_TAIL,"BOGUS", 0,"",-1.0f);
+        // Following should be a warning
+        // XXX: Verify warning
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,md,0), "psFitsUpdateTable did return false with bogus column data");
+        psFree(md);
+
+        md = psMetadataAlloc();
+        psMetadataAddF32(md,PS_LIST_TAIL,"MYFLT", 0,"",-1.0f);
+        psMetadataAddF64(md,PS_LIST_TAIL,"MYDBL", 0,"",-2.0);
+        psMetadataAddS32(md,PS_LIST_TAIL,"MYINT", 0,"",-3);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(NULL,md,0), "psFitsUpdateTable did return false with NULL psFits");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psFitsUpdateTable did error with NULL psFits");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,NULL,0), "psFitsUpdateTable did return false with NULL psMetadata");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psFitsUpdateTable did error with NULL psMetadata");
+        psFree(err);
+
+        // Following should be an error
+        // XXX: Verify error
+        psErrorClear();
+        ok(psFitsUpdateTable(fits,md,-1), "psFitsUpdateTable did return false with row=-1");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_IO, "psFitsUpdateTable did error with row=-1");
+
+        psFree(err);
+        psFree(md);
+        psFitsClose(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRead()
+    {
+        psS32 N = 256;
+        psS32 M = 128;
+
+        // This function shall open the specified FITS file, read the specified data
+        // and place the data into a psImage structure. This function shall generate
+        // an error message and return NULL if any of the input parameters are out of
+        // range, image file doesn't exist or image is zero or one dimensional.
+        // Verify the returned psImage structure contains expected values, if the input
+        // parameter filename specifies an available FITS file with known 2dimensional
+        // data, input parameters col, row, ncol, nrow, z specify data range with the
+        // FITS file. Cases should include 1x1, Nx1, 1xN, NxN and MxN sub images and
+        // total FITS file image. (done in macro)
+        // Verify the returned psImage structure is equal to the input parameter
+        // 'output', if specified. (done in macro)
+
+        #define testReadTypeSize(m, n, readM0, readN0, readM, readN, TYP, filename) \
+        { \
+            psMemId id = psMemGetId(); \
+            psImage* img = NULL; \
+            psImage* img2 = NULL; \
+            psImage* img3 = NULL; \
+            psImage* img4 = NULL; \
+            \
+            GENIMAGE(img,m,n,TYP,row+2*col); \
+            img2 = psImageCopy(img2,img,PS_TYPE_##TYP); \
+            GENIMAGE(img3,m,n,TYP,row+2*col); \
+            psImageClip(img3,32.0,32.0,120.0,120.0); \
+            img4 = psImageCopy(img4,img3,PS_TYPE_##TYP); \
+            psFits* fits = psFitsOpen(filename, "w"); \
+            ok(psFitsWriteImage(fits, NULL, img, 2, NULL), "Wrote test image %s",filename); \
+            ok(psFitsUpdateImage(fits,img3, 0,0, 1), "Wrote test image %s",filename); \
+            ok(psFitsWriteImage(fits,NULL, img3, 2, NULL), "Wrote test image %s",filename); \
+            ok(psFitsUpdateImage(fits,img, 0, 0, 1), "Wrote test image %s",filename); \
+            psFree(img); \
+            psFree(fits); \
+            img = NULL; \
+            psFree(img3); \
+            img3 = NULL; \
+            fits = psFitsOpen(filename,"r"); \
+            psRegion reg = {readM0, readM, readN0, readN}; \
+            img = psFitsReadImage(fits, reg, 0); \
+            img3 = psFitsReadImage(fits, reg, 1); \
+            ok(img3 != NULL, "Read test image %s",filename); \
+            bool errorFlag = false; \
+            for (psU32 row = readN0; row < readN; row++) { \
+                ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+                ps##TYP* img2Row = img2->data.TYP[row]; \
+                ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+                ps##TYP* img4Row = img4->data.TYP[row]; \
+                for (psU32 col = readM0; col < readM; col++) { \
+                    if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                    if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psFitsReadImage() produced the correct data"); \
+            psFree(img); \
+            img = NULL; \
+            psFree(img3); \
+            img3 = NULL; \
+            psFitsMoveExtNum(fits,1, false); \
+            img3 = psFitsReadImage(fits, reg, 0); \
+            img = psFitsReadImage(fits, reg, 1); \
+            ok(img != NULL, "Read test image %s",filename); \
+            errorFlag = false; \
+            for (psU32 row = readN0; row < readN; row++) { \
+                ps##TYP* imgRow = img->data.TYP[row-readN0]; \
+                ps##TYP* img2Row = img2->data.TYP[row]; \
+                ps##TYP* img3Row = img3->data.TYP[row-readN0]; \
+                ps##TYP* img4Row = img4->data.TYP[row]; \
+                for (psU32 col = readM0; col < readM; col++) { \
+                    if (fabsf(imgRow[col-readM0]-img2Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,0 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)imgRow[col-readM0],(psF32)img2Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                    if (fabsf(img3Row[col-readM0]-img4Row[col]) > FLT_EPSILON) { \
+                        diag("Image changed in I/O operation at %d,%d,1 (%.2f vs %.2f) for %s", \
+                             col,row,(psF32)img3Row[col-readM0],(psF32)img4Row[col],filename); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psFitsReadImage() produced the correct data"); \
+            psFree(img); \
+            psFree(img2); \
+            psFree(img3); \
+            psFree(img4); \
+            psFree(fits); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        #define testReadType(TYP,filename) \
+        testReadTypeSize(1,1,0,0,0,0,TYP,"tmpImages/1x1_" filename); \
+        testReadTypeSize(M,1,M/4,0,M*3/4,0,TYP,"tmpImages/Mx1_" filename); \
+        testReadTypeSize(1,N,0,N/4,0,N*3/4,TYP,"tmpImages/1xN_" filename); \
+        testReadTypeSize(M,N,M/4,N/4,M*3/4,N*3/4,TYP,"tmpImages/MxN_" filename);
+
+        system("mkdir tmpImages");
+
+        testReadType(U8,"U8.fits");
+        testReadType(S8,"S8.fits");   // Not a requirement
+        testReadType(S16,"S16.fits");
+        testReadType(U16,"U16.fits"); // Not a requirement
+        testReadType(S32,"S32.fits");
+        testReadType(U32,"U32.fits"); // Not a requirement
+        testReadType(F32,"F32.fits");
+        testReadType(F64,"F64.fits");
+
+        // Attempt to read from NULL fits object
+        // Following should generate error message for NULL psFits
+        // XXX: Verify error
+        // XXXX: This is seg-faulting
+        if (0)
+        {
+            psMemId id = psMemGetId();
+            psRegion region = {
+                                  0,0,0,0
+                              };
+            ok(psFitsReadImage(NULL,region,0) == NULL, "Did return NULL for NULL psFits");
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+            \
+        }
+    }
+
+
+    // testImageWrite()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psS32 m = 64;
+        psS32 n = 96;
+
+        // This function shall write the specified section within a psImage structure
+        // to a FITS file. If the specifiedfile exists, then data should overwrite the
+        // section to write. If the specified file doesn't exist, it shall be created.
+        // If an extenstion is specified, then a basic primary header data unit shall
+        //  be created.
+        //
+        // Verify a FITS file named filename is generated and contains expected
+        // values, if the input parameter input contains known data values, input
+        // parameters col, row, ncol, nrow specify a valid data region within psImage
+        // structure.
+        //
+        // Verify a FITS file named filename is generated and contains a primary
+        // header data unit with extension with expected values, if the input
+        // parameter input contains known data values, input parameters col, row,
+        // ncol, nrow specify a valid data region within psImage structure and
+        // extname and/or extnum specify an extenstion to write.
+        //
+        // N.B. : these are done in testImageRead tests, see above.
+        //
+        // Verify a FITS file named filename is overwritten and contains
+        // expected values, if the input parameter input contains known data values,
+        // input parameters col, row, ncol, nrow specify a valid data region within
+        // psImage structure.
+
+        GENIMAGE(img,m,n,F32,0);
+        GENIMAGE(img2,m,n,F32,row+2*col);
+        system("mkdir tmpImages");
+        psFits* fits = psFitsOpen("tmpImages/writeTest.fits","w");
+
+        ok(psFitsWriteImage(fits, NULL, img,1, NULL), "Wrote writeTest.fits");
+        ok(psFitsUpdateImage(fits, img2, 0, 0, 0), "Updated writeTest.fits");
+        psFree(img);
+        psFree(img2);
+
+        // Did it really overwrite the pixel values?  Let's read it in and see.
+        psFitsClose(fits);
+
+        psRegion region = {0,0,0,0};
+        fits = psFitsOpen("tmpImages/writeTest.fits","r");
+        img = NULL;
+        img = psFitsReadImage(fits, region, 0);
+        ok(img != NULL, "Read in writeTest.fits");
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(imgRow[col] - (row+2*col)) > FLT_EPSILON) {
+                    diag("The image values were not overwritten at %d,%d (%.2f vs %.2f)",
+                         col,row,imgRow[col],(row+2*col));
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psFitsReadImage() produced the correct data");
+
+        psFree(img);
+
+        // Verify false is returned and program execution is not stopped, if the input image
+        // is null.
+        // Following should generate an error message because input image is null
+        // XXX: Verify error
+        ok(!psFitsWriteImage(fits,NULL,NULL, 1, NULL),
+           "psImageWriteSection did return false when input image is NULL");
+        psFree(fits);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // tst_psFitsWriteHeader()
+    {
+        psMemId id = psMemGetId();
+        ok(makeMulti(), "Created 'multi' FITS file");
+
+        psMetadata* header   = psMetadataAlloc();
+        psFits*     fitsFile = psFitsOpen(multiFilename,"a+");
+
+        // Test psFitsReadWrite generates files from psFitsWriteImage which calls psFitsWriteHeader
+        // so these additional tests check for error conditions
+        // Attempt call function with NULL metadata
+        ok(!psFitsWriteHeader(fitsFile, NULL), "Expected return of true for NULL metadata pointer");
+        psFree(fitsFile);
+
+        // Attempt to call function with NULL fits
+        ok(!psFitsWriteHeader(NULL, header), "Expected return of true for NULL fits file pointer");
+        psFree(header);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /trunk/psLib/test/imageops/tap_psImageFFT.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psImageFFT.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psImageFFT.c	(revision 11398)
@@ -0,0 +1,566 @@
+/** @file  tst_psImageFFT.c
+ *
+ *  @brief Contains the tests for psFFT.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-30 00:13:01 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(68);
+
+    // psImageFFT(void)
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* img3 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+        psImage* img4 = NULL;
+        psImage* img5 = NULL;
+
+        // 1. assign a image to a radial sinisoid
+        // 2. perform forward transform
+        // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+        // 4. perform reverse transform
+        // 5. compare to original (should be equal to within a reasonable error)
+
+        // 1. assign a image to a radial sinisoid
+        GENIMAGE(img,m,n,F32, sinf((32.0f-row)/32.0f*M_PI)+sinf((64.0f-col)/64.0f*M_PI));
+
+        // 2. perform forward transform
+        img2 = psImageFFT(img2,img,PS_FFT_FORWARD);
+        ok(img2 != NULL, "psImageFFT() returned non-NULL");
+        skip_start(img2 == NULL, 1, "Skipping tests because psImageFFT() returned NULL");
+        ok(img2->type.type == PS_TYPE_C32, "FFT produced complex values");
+        ok(img2->numCols == m && img2->numRows == n, "FFT produced proper size result (%dx%d vs. expected %dx%d).",
+           img2->numCols,img2->numRows,m,n);
+
+        // 3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psC32* img2Row = img2->data.C32[row];
+            for (psU32 col=0;col<m;col++) {
+                psF32 mag = cabsf(img2Row[col])/m/n;
+                if (mag > 0.1f) {
+                    // must be (0,1) or (0,n-1) or (1,0) or (m-1,0)
+                    if (! (col == 0 && (row == 1 || row == n-1))
+                            && ! (row == 0 && (col==1 || col == m-1)) ) {
+                        diag("Result incorrect at %d,%d (%.2f)",col,row,mag);
+                        errorFlag = true;
+                    }
+                } else {
+                    if ( (col == 0 && (row == 1 || row == n-1))
+                            || (row == 0 && (col==1 || col == m-1)) ) {
+                        diag("Result incorrect at %d,%d (%.2f)",col,row,mag);
+                        errorFlag = true;
+                    }
+                }
+            }
+        }
+        ok(!errorFlag, "FFT produced correct data values");
+
+
+
+        // 4. perform reverse transform
+        img3 = psImageFFT(img3,img2,PS_FFT_REVERSE);
+        ok(img3 != NULL, "psImageFFT() returned non-NULL");
+        skip_start(img3 == NULL, 1, "Skipping tests because psImageFFT() returned NULL");
+        ok(img3->type.type == PS_TYPE_C32, "FFT produced complex values");
+
+        ok(img3->numCols == m && img3->numRows == n, "FFT didt produce proper size result (%dx%d vs. expected %dx%d).",
+           img3->numCols,img3->numRows,m,n);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psC32* img3Row = img3->data.C32[row];
+            psF32* imgRow = img->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                psF32 pixel = creal(img3Row[col])/m/n;
+                if (fabsf(pixel-imgRow[col]) > 0.1) {
+                    diag("Reverse FFT gave original image back (%d,%d %.2f vs %.2f)",
+                         col,row,pixel,imgRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "FFT produced correct data values");
+        ok(!errorFlag, "FFT produced correct data values");
+
+
+
+        // 4. perform reverse transform to real result
+        img3 = psImageFFT(img3,img2,PS_FFT_REVERSE|PS_FFT_REAL_RESULT);
+        ok(img3 != NULL, "psImageFFT() returned non-NULL");
+        skip_start(img3 == NULL, 1, "Skipping tests because psImageFFT() returned NULL");
+        ok(img3->type.type == PS_TYPE_F32, "FFT asked to make real result");
+        ok(img3->numCols == m && img3->numRows == n, "FFT produced proper size result (%dx%d vs. expected %dx%d).",
+           img3->numCols,img3->numRows,m,n);
+
+        errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psF32* img3Row = img3->data.F32[row];
+            psF32* imgRow = img->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                psF32 pixel = img3Row[col]/m/n;
+                if (fabsf(pixel-imgRow[col]) > 0.1) {
+                    diag("Reverse FFT gave original image back (%d,%d %.2f vs %.2f)",
+                         col,row,pixel,imgRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "FFT produced correct data values");
+        ok(!errorFlag, "FFT produced correct data values");
+
+
+
+        // check if error occurs if FORWARD and REVERSE are both given.
+        // Following should be an error
+        // XXX: werify error
+        ok(psImageFFT(NULL,img2,PS_FFT_REVERSE|PS_FFT_FORWARD) == NULL,
+           "PS_FFT_REVERSE|PS_FFT_FORWARD returned NULL");
+
+        // Following should be an error
+        // XXX: werify error
+        ok(psImageFFT(NULL,img2,PS_FFT_FORWARD|PS_FFT_REAL_RESULT) == NULL,
+           "PS_FFT_FORWARD|PS_FFT_REAL_RESULT returned NULL");
+
+        // Verify return null and program execution doesn't stop if input image is null
+        img4 = psImageFFT(NULL,NULL,PS_FFT_FORWARD);
+        ok(img4 == NULL, "psImageFFT should return null for a null input image");
+
+        // Verify return null and program execution doesn't stop if input image is incorrect direction
+        // Following should generate error for incorrect direction
+        // XXX: werify error
+        GENIMAGE(img4,8,8,S8,row+col);
+        img5 = psImageFFT(NULL,img4,PS_FFT_REAL_RESULT);
+        ok(img5 == NULL, "psImageFFT should return null for an incorrect FFT direction");
+
+        psFree(img4);
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        skip_end();
+        skip_end();
+        skip_end();
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // 1. create a C64 complex vector with distinctly different real and imaginary parts.
+    // 2. call psImageReal and psImageImaginary
+    // 3. compare results to the real/imaginary components of input
+    {
+        psMemId id = psMemGetId();
+        psImage* c64Img = NULL;
+        psImage* c64Img2 = NULL;
+        psImage* c64Img3 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+
+        // XXX: What is I?
+        GENIMAGE(c64Img,m,n,C64, row + I * col);
+        c64Img2 = psImageReal(c64Img2,c64Img);
+        ok(c64Img2 != NULL, "psImageReal() returned non-NULL");
+        ok(c64Img2->type.type == PS_TYPE_F64, "psImageReal() returned the correct type");
+        c64Img3 = psImageImaginary(c64Img3,c64Img);
+        ok(c64Img3 != NULL, "psImageImaginary() returned non-NULL");
+        ok(c64Img3->type.type == PS_TYPE_F64, "psImageImaginary() returned the correct type");
+
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psF64* img2Row = c64Img2->data.F64[row];
+            psF64* img3Row = c64Img3->data.F64[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(img2Row[col] - row) > FLT_EPSILON) {
+                    diag("psImageReal didn't return the real portion at n=%d", n);
+                    errorFlag = true;
+                }
+                if (fabsf(img3Row[col] - col) > FLT_EPSILON) {
+                    diag("psImageImaginary didn't return the imag portion at n=%d", n);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageReal() and psImageImaginary() returned the correct data");
+        psFree(c64Img);
+        psFree(c64Img2);
+        psFree(c64Img3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    {
+        psMemId id = psMemGetId();
+        psImage* ncImg = NULL;
+        psImage* ncImg2 = NULL;
+        psImage* ncImg3 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+
+        GENIMAGE(ncImg,m,n,F32,row+col);
+        ncImg2 = psImageReal(ncImg2,ncImg);
+        ncImg3 = psImageImaginary(ncImg3,ncImg);
+        ok(ncImg2 != NULL, "psImageReal() returned non-NULL");
+        ok(ncImg2->type.type == PS_TYPE_F32, "psImageReal() returned the correct type");
+        ok(ncImg3 != NULL, "psImageImaginary() returned non-NULL");
+        ok(ncImg3->type.type == PS_TYPE_F32, "psImageImaginary() returned the correct type");
+
+        bool errorFlag = false;
+        for(psU32 row=0; row<n; row++)
+        {
+            psF32* ncImg2Row = ncImg2->data.F32[row];
+            psF32* ncImg3Row = ncImg3->data.F32[row];
+            for(psU32 col=0; col<m; col++) {
+                if(fabsf(ncImg2Row[col] - (row+col)) > FLT_EPSILON) {
+                    diag("psImageReal didn't return the real portion");
+                    errorFlag = true;
+                }
+                if(fabsf(ncImg3Row[col] - 0) > FLT_EPSILON) {
+                    diag("psImageImaginary didn't return the imaginary portion");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageReal() and psImageImaginary() returned the correct data");
+        psFree(ncImg);
+        psFree(ncImg2);
+        psFree(ncImg3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+
+    // Perform psImageReal with null input
+    {
+        psMemId id = psMemGetId();
+        ok(psImageReal(NULL,NULL) == NULL, "psImageReal() returned NULL with NULL inputs");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform psImageImaginary with null input
+    {
+        psMemId id = psMemGetId();
+        ok(psImageImaginary(NULL,NULL) == NULL, "psImageImaginary() returned NULL with NULL inputs");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageComplex()
+    // 1. create two unique psF32 vectors of the same size
+    // 2. call psImageComplex
+    // 3. verify that the result is a psC32
+    // 4. use crealf and cimagf on step 2 results
+    // 5. compare step 4 results to input.
+    // 6. create a psF32 and a psF64 vector of the same size
+    // 7. call psImageComplex
+    // 8. verify that an appropriate error occurred.
+    // 9. create two psf32 vectors of different sizes
+    // 10. call psImageComplex
+    // 11. verify thet an appropriate error occurred.
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* img3 = NULL;
+        psImage* c64Img = NULL;
+        psImage* c64Img2 = NULL;
+        psImage* c64Img3 = NULL;
+        psImage* pImg = NULL;
+        psImage* pImg2 = NULL;
+        psImage* pImg3 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+        GENIMAGE(img,m,n,F32,row);
+        GENIMAGE(img2,m,n,F32,col);
+        GENIMAGE(c64Img,m,n,F64,row);
+        GENIMAGE(c64Img2,m,n,F64,col);
+        GENIMAGE(pImg,m,n,S16,row);
+        GENIMAGE(pImg2,m,n,S16,col);
+        img3 = psImageComplex(img3,img,img2);
+        ok(img3 != NULL, "psImageComplex() returned non-NULL");
+        ok(img3->type.type == PS_TYPE_C32, "psImageComplex() returned the correct type");
+        c64Img3 = psImageComplex(c64Img3,c64Img,c64Img2);
+        ok(c64Img3 != NULL, "psImageComplex() returned non-NULL");
+        ok(c64Img3->type.type == PS_TYPE_C64, "psImageComplex() returned the correct type");
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psC32* img3Row = img3->data.C32[row];
+            psC64* c64Img3Row = c64Img3->data.C64[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(crealf(img3Row[col]) - row) > FLT_EPSILON ||
+                        fabsf(cimagf(img3Row[col]) - col) > FLT_EPSILON) {
+                    diag("psImageComplex result is incorrect (%d,%d, %.2f+%.2fi)",
+                         col,row,crealf(img3Row[col]),cimagf(img3Row[col]));
+                    errorFlag = true;
+                }
+                if (fabsf(crealf(c64Img3Row[col]) - row) > FLT_EPSILON ||
+                        fabsf(cimagf(c64Img3Row[col]) - col) > FLT_EPSILON) {
+                    diag("psImageComplex result is incorrect");
+                    errorFlag = true;
+
+                }
+            }
+        }
+        ok(!errorFlag, "psImageComplex() returned correct results");
+
+        img2 = psImageRecycle(img2,m,n,PS_TYPE_F64);
+
+        // Following should be an error (type mismatch)
+        // Verify that an appropriate error occurred
+        img3 = psImageComplex(img3,img,img2);
+        ok(img3 == NULL, "psImageComplex() returned NULL when input types mismatched.");
+
+        // Following should be an error (size mismatch)
+        img2 = psImageRecycle(img2,m/2,n,PS_TYPE_F32);
+        img3 = psImageComplex(img3,img,img2);
+        ok(img3 == NULL, "psImageComplex() returned a NULL when input sizes mismatched");
+
+        // Perform psImageComplex with incorrect type
+        // Following should generate an error message.");
+        pImg3 = psImageComplex(pImg3,pImg,pImg2);
+        ok(pImg3 == NULL, "psImageComplex returned NULL with incorrect type input");
+
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        psFree(c64Img);
+        psFree(c64Img2);
+        psFree(c64Img3);
+        psFree(pImg);
+        psFree(pImg2);
+
+        // Perform psImageComplex with null input
+        ok(psImageComplex(NULL,NULL,NULL) == NULL, "psImageComplex() returned NULL with null input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // 1. create a psC32 with unique real and imaginary values.
+    // 2. call psImageConjugate
+    // 3. verify result is psC32
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    // testImageConjugate()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* c64Img = NULL;
+        psImage* c64Img2 = NULL;
+        psImage* pImg = NULL;
+        psImage* pImg2 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+        GENIMAGE(img,m,n,C32, row + I * col);
+        GENIMAGE(c64Img,m,n,C64,row + I*col);
+        GENIMAGE(pImg,m,n,F32,row+col);
+
+
+        img2 = psImageConjugate(img2,img);
+        ok(img2 != NULL, "psImageConjugate() returned non-NULL");
+        c64Img2 = psImageConjugate(c64Img2,c64Img);
+        ok(c64Img2 != NULL, "psImageConjugate() returned non-NULL");
+        pImg2 = psImageConjugate(pImg2,pImg);
+        ok(pImg2 != NULL, "psImageConjugate() returned non-NULL");
+
+        ok(img2->type.type == PS_TYPE_C32, "psImageConjugate() returned the correct type");
+        ok(c64Img2->type.type == PS_TYPE_C64, "psImageConjugate() returned the correct type");
+        ok(pImg2->type.type == PS_TYPE_F32, "psImageConjugate() returned the correct type");
+
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psC32* img2Row = img2->data.C32[row];
+            psC64* c64Img2Row = c64Img2->data.C64[row];
+            psF32* pImg2Row = pImg2->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(crealf(img2Row[col]) - row) > FLT_EPSILON ||
+                        fabsf(cimagf(img2Row[col]) + col) > FLT_EPSILON) {
+                    diag("psImageComplex result is incorrect (%d,%d, %.2f+%.2fi)",
+                         col,row,crealf(img2Row[col]),cimagf(img2Row[col]));
+                    errorFlag = true;
+                }
+                if (fabsf(crealf(c64Img2Row[col]) - row) > FLT_EPSILON ||
+                        fabsf(cimagf(c64Img2Row[col]) + col) > FLT_EPSILON) {
+                    diag("psImageComplex result is incorrect");
+                    errorFlag = true;
+                }
+                if (fabsf(pImg2Row[col] - (row+col)) > FLT_EPSILON) {
+                    diag("psImageComplex result is incorrect");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageConjugate() generated the correct data values");
+        psFree(img);
+        psFree(img2);
+        psFree(c64Img);
+        psFree(c64Img2);
+        psFree(pImg);
+        psFree(pImg2);
+
+        // Perform psImageConjugate with null input
+        ok(psImageConjugate(NULL,NULL) == NULL, "psImageConjugate() returned NULL with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // testImagePowerSpectrum()
+    // 1. create a psC32 vector with unique real and imaginary components
+    // 2. call psImagePowerSpectrum
+    // 3. verify result is psF32
+    // 4. verify the values are the square of the absolute values of the original
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* c64Img = NULL;
+        psImage* c64Img2 = NULL;
+        psImage* pImg = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+
+        GENIMAGE(img,m,n,C32, row + I * col);
+        GENIMAGE(c64Img,m,n,C64,row+I*col);
+        GENIMAGE(pImg,m,n,F32,row+col);
+
+        img2 = psImagePowerSpectrum(img2,img);
+        c64Img2 = psImagePowerSpectrum(c64Img2, c64Img);
+        ok(img2 != NULL, "psImagePowerSpectrum() returned non-NULL");
+        ok(c64Img2 != NULL, "psImagePowerSpectrum() returned non-NULL");
+        ok(img2->type.type == PS_TYPE_F32, "psImagePowerSpectrum() returned the correct type");
+        ok(c64Img2->type.type == PS_TYPE_F64, "psImagePowerSpectrum() returned the correct type");
+
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psC32* imgRow = img->data.C32[row];
+            psF32* img2Row = img2->data.F32[row];
+            psC64* c64ImgRow = c64Img->data.C64[row];
+            psF64* c64Img2Row = c64Img2->data.F64[row];
+            for (psU32 col=0;col<m;col++) {
+                psF32 power = cabs(imgRow[col]);
+                psF64 power64 = cabs(c64ImgRow[col]);
+                power *= power/n/n/m/m;
+                power64 *= power64/n/n/m/m;
+
+                if (fabsf(img2Row[col] - power) > 2.0f*FLT_EPSILON) {
+                    diag("psImagePowerSpectrum result is incorrect (%d,%d, %.2f vs %.2f)",
+                         col,row,img2Row[col],power);
+                    errorFlag = true;
+                }
+                if (fabsf(c64Img2Row[col] - power64) > 2.0f*FLT_EPSILON) {
+                    diag("psImagePowerSpectrum result is incorrect");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImagePowerSPectrum() generated the correct data values");
+        psFree(img);
+        psFree(img2);
+        psFree(c64Img);
+        psFree(c64Img2);
+
+        // Perform psImagePowerSpectrum with incorrect input
+        // Following should generate error message
+        // XXX: Verify error
+        ok(psImagePowerSpectrum(NULL,pImg) == NULL, "psImagePowerSpectrum() returned NULL with incorrect type");
+        psFree(pImg);
+
+        // Perform psImagePowerSpectrum with NULL input
+        ok(psImagePowerSpectrum(NULL,NULL) == NULL, "psImagePowerSpectrum() returned NULL with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRealImaginary()
+    // 1. create a C32 complex image with distinctly different real and imaginary parts
+    // 2. call psImageReal and psImageImaginary
+    // 3. compare results to the real/imaginary components of input
+    // XXX: If we put this block above the previous 2 blocks, then we get memory errors
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img3 = NULL;
+        psU32 m = 128;
+        psU32 n = 64;
+        GENIMAGE(img,m,n,C32, row + I * col);
+        psImage* img2 = psImageReal(img2,img);
+        ok(img2 != NULL, "psImageReal returned non-NULL");
+        skip_start(img2 == NULL, 4, "Skipping tests because psImageReal() returned NULL");
+        ok(img2->type.type == PS_TYPE_F32, "psImageReal returned the correct type");
+        img3 = psImageImaginary(img3,img);
+        ok(img3 != NULL, "psImageImaginary() returned non-NULL");
+        skip_start(img3 == NULL, 2, "Skipping tests because psImageImaginary() returned NULL");
+        ok(img3->type.type == PS_TYPE_F32, "psImageImaginary() returned the correct type");
+
+        bool errorFlag = false;
+        for (psU32 row=0;row<n;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            psF32* img3Row = img3->data.F32[row];
+            for (psU32 col=0;col<m;col++) {
+                if (fabsf(img2Row[col] - row) > FLT_EPSILON) {
+                    diag("psImageReal didn't return the real portion at n=%d", n);
+                    errorFlag = true;
+                }
+                if (fabsf(img3Row[col] - col) > FLT_EPSILON) {
+                    diag("psImageImaginary didn't return the imag portion at n=%d", n);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageReal(), psImageImaginary() returned the correct data");
+        skip_end();
+        skip_end();
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+}
Index: /trunk/psLib/test/imageops/tap_psImageGeomManip.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psImageGeomManip.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psImageGeomManip.c	(revision 11398)
@@ -0,0 +1,1001 @@
+/** @file  tst_psImageGeomManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-30 00:13:01 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+
+bool testImageShiftCase(psS32 cols,
+                        psS32 rows,
+                        float colShift,
+                        float rowShift)
+{
+    psImage *fOut = NULL;
+    psImage *sOut = NULL;
+    psImage *fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage *sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+    psImage *fBiOut = psImageAlloc(cols,rows,PS_TYPE_F32);
+    psImage *sBiOut = psImageAlloc(cols,rows,PS_TYPE_S16);
+    bool errorFlag = false;
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32 *fRow = fImg->data.F32[row];
+        psS16 *sRow = sImg->data.S16[row];
+        for (psS32 col=0;col<cols;col++) {
+            fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+            sRow[col] = row-2*col;
+        }
+    }
+
+    fOut = psImageShift(fOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_FLAT);
+    sOut = psImageShift(sOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_FLAT);
+    fBiOut = psImageShift(fBiOut, fImg, colShift, rowShift, NAN, PS_INTERPOLATE_BILINEAR);
+    sBiOut = psImageShift(sBiOut, sImg, colShift, rowShift, -1, PS_INTERPOLATE_BILINEAR);
+
+    for(psS32 row=0;row<rows;row++) {
+        psF32 *fRow = fOut->data.F32[row];
+        psS16 *sRow = sOut->data.S16[row];
+        psF32 *fBiRow = fBiOut->data.F32[row];
+        psS16 *sBiRow = sBiOut->data.S16[row];
+
+        for (psS32 col=0;col<cols;col++) {
+            psF32 fValue = psImagePixelInterpolate(fImg,col+colShift,
+                                                   row+rowShift,NULL,0,NAN,PS_INTERPOLATE_FLAT);
+            psS16 sValue = (psS16)psImagePixelInterpolate(sImg,col+colShift,
+                           row+rowShift,NULL,0,-1,PS_INTERPOLATE_FLAT);
+
+            psF32 fBiValue = psImagePixelInterpolate(fImg,col+colShift,
+                             row+rowShift,NULL,0,NAN,PS_INTERPOLATE_BILINEAR);
+            psS16 sBiValue = (psS16)psImagePixelInterpolate(sImg,col+colShift,
+                             row+rowShift,NULL,0,-1,PS_INTERPOLATE_BILINEAR);
+
+            if (fabsf(fRow[col] - fValue) > FLT_EPSILON) {
+                diag("Float image not shifted correctly at %d,%d (%g vs %g)",
+                     col,row,fRow[col],fValue);
+                errorFlag = true;
+            }
+            if (sRow[col] != sValue) {
+                diag("Short image not shifted correctly at %d,%d (%d vs %d)",
+                     col,row,sRow[col],sValue);
+                errorFlag = true;
+            }
+            if (fabsf(fBiRow[col] - fBiValue) > FLT_EPSILON) {
+                diag("Float image not shifted correctly at %d,%d (%g vs %g)",
+                     col,row,fBiRow[col],fBiValue);
+                errorFlag = true;
+            }
+            if (sBiRow[col] != sBiValue) {
+                diag("Short image not shifted correctly at %d,%d (%d vs %d)",
+                     col,row,sBiRow[col],sBiValue);
+                errorFlag = true;
+            }
+        }
+    }
+
+    psFree(fImg);
+    psFree(sImg);
+    psFree(fOut);
+    psFree(sOut);
+    psFree(fBiOut);
+    psFree(sBiOut);
+
+    return !errorFlag;
+}
+
+
+psS32 main(psS32 argc, char *argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(178);
+
+    // testImageRebin()
+    // This function shall generate a rescaled version of a psImage structure
+    // derived from a specified statistics method.
+    {
+        psMemId id = psMemGetId();
+        psImage *in = NULL;
+        psImage *out = NULL;
+        psImage *out2 = NULL;
+        psImage *out3 = NULL;
+        psImage *mask = NULL;
+        psImage *meanTruth = NULL;
+        psImage *meanTruthWMask = NULL;
+        psImage *maxTruth = NULL;
+        psStats stats;
+
+        //        Verify the returned psImage structure contains expected values, if the
+        //        input parameter input contains known data, the input scale is a known
+        //        value with a known statistical method specified in stats. Cases should
+        //        include at least two different scales and statistical methods. Comparison
+        //        of expected values should include a delta to allow testing on different
+        //        platforms.
+        #define testRebinType(DATATYPE)  \
+        { \
+            psMemId id = psMemGetId();\
+            in = psImageAlloc(16,16,PS_TYPE_##DATATYPE); \
+            mask = psImageAlloc(16,16,PS_TYPE_U8); \
+            meanTruth = psImageAlloc(4,4,PS_TYPE_F32); \
+            meanTruthWMask = psImageAlloc(4,4,PS_TYPE_F32); \
+            maxTruth = psImageAlloc(6,6,PS_TYPE_F32); \
+            memset(meanTruth->data.F32[0],0,sizeof(psF32)*4*4); \
+            memset(meanTruthWMask->data.F32[0],0,sizeof(psF32)*4*4); \
+            memset(maxTruth->data.F32[0],0,sizeof(psF32)*6*6); \
+            for (psS32 row = 0; row<16; row++) { \
+                ps##DATATYPE *inRow = in->data.DATATYPE[row]; \
+                psF32 *meanTruthRow = meanTruth->data.F32[row/4]; \
+                psF32 *meanTruthWMaskRow = meanTruthWMask->data.F32[row/4]; \
+                psF32 *maxTruthRow = maxTruth->data.F32[row/3]; \
+                psU8 *maskRow = mask->data.U8[row]; \
+                for (psS32 col = 0; col<16; col++) { \
+                    if(col != 15) { \
+                        maskRow[col] = 0; \
+                    } else { \
+                        maskRow[col] = 1; \
+                    } \
+                    inRow[col] = row + col; \
+                    meanTruthRow[col/4] += row + col; \
+                    if (maxTruthRow[col/3] < row + col) { \
+                        maxTruthRow[col/3] = row+col; \
+                    } \
+                    if(maskRow[col] == 0 ) { \
+                        meanTruthWMaskRow[col/4] += row + col; \
+                    } \
+                } \
+            } \
+            for (psS32 row = 0; row<4; row++) { \
+                psF32 *meanTruthRow = meanTruth->data.F32[row]; \
+                psF32 *meanTruthWMaskRow = meanTruthWMask->data.F32[row]; \
+                for (psS32 col = 0; col<4; col++) { \
+                    meanTruthRow[col] /= 16; \
+                    if ( col == 3 ) { \
+                        meanTruthWMaskRow[col] /= 12; \
+                    } else { \
+                        meanTruthWMaskRow[col] /= 16; \
+                    } \
+                } \
+            } \
+            stats.options = PS_STAT_SAMPLE_MEAN; \
+            ok(false, "XXXX: Skipping test because of a known seg fault"); \
+            if (0) { \
+                out = psImageRebin(NULL,in,NULL,0,4,&stats); \
+                ok(out != NULL, "psImageRebin returned non-NULL"); \
+                ok(out->numRows == 4 && out->numCols == 4, \
+                   "psImageRebin did produce the proper size image"); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<4; row++) { \
+                    ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+                    psF32 *truthRow = meanTruth->data.F32[row]; \
+                    for (psS32 col = 0; col<4; col++) { \
+                        if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin didn't produce the proper mean " \
+                                 "result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageRebin() produced the correct data"); \
+            } \
+            ok(false, "XXXX: Skipping test because of a known seg fault"); \
+            if (0) { \
+                stats.options = PS_STAT_SAMPLE_MEAN; \
+                out3 = psImageRebin(NULL,in,mask,1,4,&stats); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<4; row++) { \
+                    ps##DATATYPE *outRow = out3->data.DATATYPE[row]; \
+                    psF32 *truthRow = meanTruthWMask->data.F32[row]; \
+                    for ( psS32 col = 0; col<4; col++) { \
+                        if(abs((psS32)outRow[col]-(psS32)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin with mask didn't produce the proper mean " \
+                                 "result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                    ok(!errorFlag, "psImageRebin() produced the correct data"); \
+                } \
+            } \
+            stats.options = PS_STAT_MAX; \
+            ok(false, "XXXX: Skipping test because of a known seg fault"); \
+            if (0) { \
+                out2 = psImageRebin(out,in,NULL,0,3,&stats); \
+                ok(out == out2, "psImageRebin didt recycle a psImage properly"); \
+                ok(out != NULL, "psImageRebin returned non-NULL"); \
+                ok(out->numRows == 6 && out->numCols == 6, \
+                   "psImageRebin did produce the proper size image"); \
+                bool errorFlag = false; \
+                for (psS32 row = 0; row<6; row++) { \
+                    ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+                    psF32 *truthRow = maxTruth->data.F32[row]; \
+                    for (psS32 col = 0; col<6; col++) { \
+                        if (fabsf((float)outRow[col]-(float)truthRow[col]) > FLT_EPSILON) { \
+                            diag("psImageRebin didn't produce the proper " \
+                                 "max result at (%d,%d) [%f vs %f]", \
+                                 col,row,outRow[col],truthRow[col]); \
+                            errorFlag = true;\
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageRebin() produced the correct data"); \
+            } \
+            psFree(in); \
+            psFree(out); \
+            psFree(out3); \
+            psFree(mask); \
+            psFree(meanTruth); \
+            psFree(meanTruthWMask); \
+            psFree(maxTruth); \
+            ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testRebinType(F32);
+        testRebinType(F64);
+        testRebinType(U16);
+        testRebinType(S8);
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input image type is not supported.
+        // Following should be an error for unsupported type
+        // XXX: Verify error
+        in = psImageAlloc(16,16,PS_TYPE_U8);
+        mask = psImageAlloc(16,16,PS_TYPE_F32);
+        stats.options = PS_STAT_SAMPLE_MEAN;
+        out = psImageRebin(NULL,in,NULL,0,4,&stats);
+        ok(out == NULL, "psImageRebin returned NULL for unsupported type");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the mask type is not U8
+        // Following should be an error for invallid mask type
+        // XXX: Verify error
+        out = psImageRebin(NULL,in,mask,1,4,&stats);
+        ok(out == NULL, "psImageRebin returned NULL for incorrect mask");
+        psFree(mask);
+        psFree(in);
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input parameter input is null.
+        out2 = psImageRebin(NULL,NULL,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned NULL with NULL input");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input parameter scale is less than or equal to zero.
+        in = psImageAlloc(16, 16, PS_TYPE_F32);
+        // Following should be an error for scale < 0
+        // XXX: Verify error
+        out2 = psImageRebin(NULL,in,NULL,0,0,&stats);
+        ok(out2 == NULL, "psImageRebin returned NULL when the scale was zero");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input parameter stats is null.
+        // Following should be an error for stats null
+        // XXX: Verify error
+        out2 = psImageRebin(NULL,in,NULL,0,1,NULL);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats was NULL");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input parameter psStats structure member options
+        // is zero or any value which doesn't correspond to a valid statistical
+        // method.
+        // Following should be an error for stats options 0
+        // XXX: Verify error
+        stats.options = 0;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats options was zero");
+
+        //Following should be an error for stat options use range");
+        // XXX: Verify error
+        stats.options = PS_STAT_USE_RANGE;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an image though the stats options was PS_STAT_USE_RANGE");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the input parameter psStats structure member options
+        // specifies more than one valid statistical method.
+        // Following should be an error for stats with multiple options
+        // XXX: Verify error
+        stats.options = PS_STAT_SAMPLE_MEAN + PS_STAT_MAX;
+        out2 = psImageRebin(NULL,in,NULL,0,1,&stats);
+        ok(out2 == NULL, "psImageRebin returned an NULL when the stats options was PS_STAT_SAMPLE_MEAN+PS_STAT_MAX");
+
+        psFree(in);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRoll()
+    {
+        psMemId id = psMemGetId();
+        psImage *in;
+        psImage *out;
+        psImage *out2;
+        psS32 rows = 64;
+        psS32 cols = 64;
+        psS32 rows1 = 8;
+        psS32 cols1 = 8;
+
+        // The function psImageRoll shall generate a new psImage structure by
+        // rolling the input image the correponding number of pixels in the vertical
+        // and/or horizontal direction. The image output image shall be the same size
+        // as the input image. Values which roll off the image are wrapped to the
+        // other side.
+        //
+        // Verify the returned psImage structure contains expected values, if the
+        // input image contains known values and the roll performed is known.
+        // Cases should include no roll, vertical roll, horizontal roll and
+        // combination vertical/horizontal rolls. Positive and negative rolls
+        // should be performed.
+
+        in = psImageAlloc(cols,rows,PS_TYPE_F32);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                inRow[col] = (psF32)row+(psF32)col/1000.0f;
+            }
+        }
+
+        out = psImageRoll(NULL,in,0,0);
+        bool errorFlag = false;
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[row];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[col] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=0, dy=0",
+                         col,row,inRow[col],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        errorFlag = false;
+        out2 = psImageRoll(out,in,cols/4,0);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[row];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=cols/4, dy=0",
+                         col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        // Verify the returned psImage structure pointer is equal to the input
+        // parameter out if provided.
+        ok(out2 == out, "psImageRoll didt recycle the out psImage");
+
+        errorFlag = false;
+        out = psImageRoll(out,in,0,rows/4);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[(row+rows/4)%rows];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[col] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=0, dy=rows/4",
+                         col,row,inRow[col],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        errorFlag = false;
+        out = psImageRoll(out,in,cols/4,rows/4);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[(row+rows/4)%rows];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[(col+cols/4) % cols] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4",
+                         col,row,inRow[(col+cols/4) % cols],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        errorFlag = false;
+        out = psImageRoll(out,in,-cols/4,0);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[row];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[(col+(cols-cols/4)) % cols] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=-cols/4, dy=0",
+                         col,row,inRow[(col+(cols-cols/4)) % cols],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        errorFlag = false;
+        out = psImageRoll(out,in,0,-rows/4);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[(row+rows-rows/4)%rows];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[col] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=0, dy=-rows/4",
+                         col,row,inRow[col],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        errorFlag = false;
+        out = psImageRoll(out,in,-cols/4,-rows/4);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[(row+rows-rows/4)%rows];
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                if (inRow[(col+cols-cols/4) % cols] != outRow[col]) {
+                    diag("psImageRoll didn't produce expected result "
+                         "at %d,%d (%f vs %f) for dx=cols/4, dy=rows/4",
+                         col,row,inRow[(col+cols-cols/4) % cols],outRow[col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if input parameter input is null.
+        out2 = psImageRoll(NULL,NULL,0,0);
+        if (out2 != NULL)
+        {
+            psError(PS_ERR_UNKNOWN, true,"psImageRoll did not return NULL though input image was NULL!?");
+            return 2;
+        }
+
+        psFree(in);
+        psFree(out);
+
+        #define testRollType(DATATYPE) \
+        in = psImageAlloc(rows1,cols1,PS_TYPE_##DATATYPE); \
+        \
+        for (psS32 row=0;row<rows1;row++) { \
+            ps##DATATYPE *inRow = in->data.DATATYPE[row]; \
+            for (psS32 col=0;col<cols1;col++) { \
+                inRow[col] = (ps##DATATYPE)row+(ps##DATATYPE)col; \
+            } \
+        } \
+        \
+        errorFlag = false; \
+        out = psImageRoll(NULL,in,rows1/4,cols1/4); \
+        for (psS32 row=0;row<rows1;row++) { \
+            ps##DATATYPE *inRow = in->data.DATATYPE[(row+rows1/4)%rows1]; \
+            ps##DATATYPE *outRow = out->data.DATATYPE[row]; \
+            for (psS32 col=0;col<cols1;col++) { \
+                if (inRow[(col+cols1/4)%cols1] != outRow[col]) { \
+                    diag("psImageRoll didn't produce expected result " \
+                         "at %d,%d (%f vs %f) for dx=0, dy=0", \
+                         col,row,(float)inRow[col],(float)outRow[col]); \
+                    errorFlag = true; \
+                } \
+            } \
+        } \
+        psFree(in); \
+        psFree(out); \
+        ok(!errorFlag, "psImageRoll() produced the correct data values");
+
+        testRollType(U8);
+        testRollType(U16);
+        testRollType(S8);
+        testRollType(S16);
+        testRollType(F64);
+        testRollType(C32);
+        testRollType(C64);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageRotate()
+    {
+        psMemId id = psMemGetId();
+        // This function shall calculate a new psImage structure based upon the
+        // rotation of a given psImage structure. The center of rotation shall be the
+        // center pixel of the input image.
+        //
+        // The following steps of the testpoint are done manually via inspection of
+        // fOut.fits & sOut.fits.
+        //
+        //  * Verify the returned psImage structure contains expected values, if
+        //    the input parameter psImage contains known values. Cases should
+        //    include rotations of 0, 45, 90, 135, 180, 225, 270, 315, 360 and at leat one
+        //    other arbitrary angle. Cases of the input image should include image
+        //    with a center pixel and an image without a center pixel.
+        //  * Verify the returned psImage structure contains pixels set to exposed value, if
+        //    the rotation and input psImage to not correspond to the output image.
+
+        psImage *fOut = NULL;
+        psImage *sOut = NULL;
+        psImage *fBiOut = NULL;
+        psImage *sBiOut = NULL;
+        psImage *fTruth = NULL;
+        psImage *sTruth = NULL;
+        psImage *fBiTruth = NULL;
+        psImage *sBiTruth = NULL;
+        psS32 rows = 64;
+        psS32 cols = 64;
+        psImage *fImg = psImageAlloc(cols,rows,PS_TYPE_F32);
+        psImage *sImg = psImageAlloc(cols,rows,PS_TYPE_S16);
+
+        for(psS32 row=0;row<rows;row++)
+        {
+            psF32 *fRow = fImg->data.F32[row];
+            psS16 *sRow = sImg->data.S16[row];
+            for (psS32 col=0;col<cols;col++) {
+                fRow[col] = (psF32)(row)+(psF32)(col)/100.0f;
+                sRow[col] = row-2*col;
+            }
+        }
+
+        // since interpolation is involved, etc., the simplist way to verify things
+        // is to verify the results manually and bless it for automated comparison
+        // thereafter
+
+
+        // write results of various rotates to a file and verify with truth images
+        system("mkdir temp");
+        psS32 index = 0;
+        psBool fail = false;
+        psF32 radianRot;
+
+        psFits *fOutFile = psFitsOpen("fOut.fits","w");
+        psFits *sOutFile = psFitsOpen("sOut.fits","w");
+        psFits *fBiOutFile = psFitsOpen("fBiOut.fits","w");
+        psFits *sBiOutFile = psFitsOpen("sBiOut.fits","w");
+        ok(fOutFile != NULL && sOutFile != NULL && fBiOutFile != NULL && sBiOutFile != NULL,
+           "psFitsOpen() created the output files");
+
+        psFits *fTruthFile = psFitsOpen("verified/fOut.fits","r");
+        psFits *sTruthFile = psFitsOpen("verified/sOut.fits","r");
+        psFits *fBiTruthFile = psFitsOpen("verified/fBiOut.fits","r");
+        psFits *sBiTruthFile = psFitsOpen("verified/sBiOut.fits","r");
+        ok(fTruthFile != NULL && sTruthFile != NULL && fBiTruthFile != NULL && sBiTruthFile != NULL,
+           "psFitsOpen() opened the truth files");
+
+        psRegion regionAll = psRegionSet(0,0,0,0);
+        for (psS32 rot=-180;rot<=180;rot+=45)
+        {
+            psImage *oldOut = fOut;
+            psImage *oldBiOut = fBiOut;
+            if (rot == 90) {
+                radianRot = M_PI_2;
+            } else if (rot == -90) {
+                radianRot = M_PI+M_PI_2;
+            } else if (rot == 180 || rot == -180) {
+                radianRot = M_PI;
+            } else {
+                radianRot = ((float)rot)*M_PI/180.0;
+            }
+
+            fOut = psImageRotate(fOut,fImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+            fBiOut = psImageRotate(fBiOut,fImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+            // Verify the returned psImage structure is equal to the input
+            // parameter out if provided.
+            ok(fOut != NULL, "psImageRotate() returned non-NULL");
+            ok(oldOut == fOut, "psImageRotate(): the output recycle functionality was successful");
+            ok(fBiOut != NULL, "psImageRotate() returned non-NULL");
+            ok(oldBiOut == fBiOut, "psImageRotate(): the output recycle functionality was successful");
+            sOut = psImageRotate(sOut,sImg,radianRot,-1.0,PS_INTERPOLATE_FLAT);
+            sBiOut = psImageRotate(sBiOut,sImg,radianRot,-1.0,PS_INTERPOLATE_BILINEAR);
+            ok(psFitsWriteImage(fOutFile, NULL, fOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(sOutFile, NULL, sOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(fBiOutFile, NULL, fBiOut, 1, NULL), "psFitsWriteImage() successful");
+            ok(psFitsWriteImage(sBiOutFile, NULL, sBiOut, 1, NULL), "psFitsWriteImage() successful");
+
+            // now, let's compare this with the verified file
+            psFitsMoveExtNum(fTruthFile, index, false);
+            psFitsMoveExtNum(sTruthFile, index, false);
+            psFitsMoveExtNum(fBiTruthFile, index, false);
+            psFitsMoveExtNum(sBiTruthFile, index, false);
+            psFree(fTruth);
+            psFree(sTruth);
+            psFree(fBiTruth);
+            psFree(sBiTruth);
+            fTruth = NULL;
+            sTruth = NULL;
+            fBiTruth = NULL;
+            sBiTruth = NULL;
+            fTruth = psFitsReadImage(fTruthFile, regionAll, 0);
+            sTruth = psFitsReadImage(sTruthFile, regionAll, 0);
+            fBiTruth = psFitsReadImage(fBiTruthFile, regionAll, 0);
+            sBiTruth = psFitsReadImage(sBiTruthFile, regionAll, 0);
+            bool errorFlag = false;
+            if (fTruth == NULL) {
+                diag("verified psF32 image failed to be read (%d deg. rotation)", rot);
+                errorFlag = true;
+                fail = true;
+            } else {
+                if(fTruth->numRows != fOut->numRows || fTruth->numCols != fOut->numCols) {
+                    diag("Rotated float image size did not equal truth image for %d deg rotation (%dx%d vs %dx%d)",
+                         rot,fOut->numCols,fOut->numRows,fTruth->numCols,fTruth->numRows);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<fTruth->numRows;row++) {
+                        psF32 *truthRow = fTruth->data.F32[row];
+                        psF32 *outRow = fOut->data.F32[row];
+                        for (psS32 col=0;col<fTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                diag("Float Image mismatch (%f vs %f) at %d,%d",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation)", rot);
+
+
+            errorFlag = false;
+            if (sTruth == NULL) {
+                diag("verified psS16 image failed to be read (%d deg. rotation)",rot);
+                errorFlag = true;
+            } else {
+                if (sTruth->numRows != sOut->numRows ||
+                        sTruth->numCols != sOut->numCols) {
+                    diag("Rotated psS16 image size did not match truth image for %d deg rotation",rot);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<sTruth->numRows;row++) {
+                        psS16 *truthRow = sTruth->data.S16[row];
+                        psS16 *outRow = sOut->data.S16[row];
+                        for (psS32 col=0;col<sTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                diag("Short Image mismatch (%d vs %d) at %d,%d",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation)", rot);
+
+
+            errorFlag = false;
+            if (fBiTruth == NULL) {
+                diag("verified psF32 Bi image failed to be read (%d deg. rotation)",
+                     rot);
+                errorFlag = true;
+            } else {
+                if (fBiTruth->numRows != fBiOut->numRows || fBiTruth->numCols != fBiOut->numCols) {
+                    diag("Rotated float image size did not match truth "
+                         "image for %d deg rotation (%dx%d vs %dx%d). BILINEAR",
+                         rot,fBiOut->numCols,fBiOut->numRows,fBiTruth->numCols,fBiTruth->numRows);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<fBiTruth->numRows;row++) {
+                        psF32 *truthRow = fBiTruth->data.F32[row];
+                        psF32 *outRow = fBiOut->data.F32[row];
+                        for (psS32 col=0;col<fBiTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                diag("Float Image mismatch (%f vs %f) at %d,%d. BILINEAR",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation)", rot);
+
+
+            if (sBiTruth == NULL) {
+                diag("verified psS16 image failed to be read "
+                     "(%d deg. rotation) BILINEAR",rot);
+                errorFlag = true;
+                fail = true;
+            } else {
+                if (sBiTruth->numRows != sBiOut->numRows ||
+                        sBiTruth->numCols != sBiOut->numCols) {
+                    diag("Rotated psS16 image size did not match truth "
+                         "image for %d deg rotation. BILINEAR",rot);
+                    errorFlag = true;
+                } else {
+                    for (psS32 row=0;row<sBiTruth->numRows;row++) {
+                        psS16 *truthRow = sBiTruth->data.S16[row];
+                        psS16 *outRow = sBiOut->data.S16[row];
+                        for (psS32 col=0;col<sBiTruth->numCols;col++) {
+                            if (fabsf(truthRow[col]-outRow[col]) > 1) {
+                                diag("Short Image mismatch (%d vs %d) "
+                                     "at %d,%d. BILINEAR",
+                                     outRow[col], truthRow[col],col,row);
+                                errorFlag = true;
+                            }
+                        }
+                    }
+                }
+            }
+            ok(!errorFlag, "psImageRotate() produced the correct data values (%d degree rotation)", rot);
+
+            index++;
+        }
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameter input is null.
+        // Following should be an error
+        // XXX: Verify error
+        fOut = psImageRotate(fOut,NULL,0,0,PS_INTERPOLATE_FLAT);
+        ok(fOut == NULL, "NULL was returned when the input image was NULL");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the specified interpolation mode is unallowed
+        // Following should be an error for unallowed interpolation type
+        // XXX: Verify error
+        fOut = psImageRotate(fOut, fImg, 33, 0, -1);
+        ok(fOut == NULL, "NULL was returned when the interpolation mode is unallowed");
+
+        psFree(sOut);
+        psFree(fImg);
+        psFree(sImg);
+        psFree(fTruth);
+        psFree(sTruth);
+        psFree(sBiOut);
+        psFree(fBiTruth);
+        psFree(sBiTruth);
+        psFree(fBiOut);
+
+        psFree(fOutFile);
+        psFree(sOutFile);
+        psFree(fBiOutFile);
+        psFree(sBiOutFile);
+
+        psFree(fTruthFile);
+        psFree(sTruthFile);
+        psFree(fBiTruthFile);
+        psFree(sBiTruthFile);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageShift()
+    {
+        psMemId id = psMemGetId();
+        // This functions shall generate a new psImage structure by shifting the
+        // input psImage structure a specified number of pixels in the horizontal
+        // and/or vertical directions.
+        //
+        // Verify the returned psImage structure contains expected values, if the
+        // input psImage structure contains known values and a know shift in the
+        // vertical and/or horizontal directions. Cases should include no shift,
+        // vertical only(up,down), horizontal only(right, left), and combination
+        // shift. Cases should include fractional shifts. Comparison of expected
+        // values should include a delta to allow for testing on different
+        // platforms.
+        //
+        // Verify the returned psImage structure contains values for pixels not in
+        // the original image set to the input parameter exposed.
+
+        // integer shift
+        // XXXX: These fail
+        ok(false, "XXXX: Skipping psImageShift() tests because of known failures");
+        if (0)
+        {
+            ok(testImageShiftCase(64,128,0.0f,0.0f), "psImageShift (0, 0)");
+            ok(testImageShiftCase(64,128,0.0f,16.0f), "psImageShift (0, 16)");
+            ok(testImageShiftCase(64,128,0.0f,-16.0f), "psImageShift (0, -16)");
+            ok(testImageShiftCase(64,128,32.0f,0.0f), "psImageShift (32, 0)");
+            ok(testImageShiftCase(64,128,-32.0f,0.0f), "psImageShift (-32, 0)");
+            ok(testImageShiftCase(64,128,32.0f,16.0f), "psImageShift (32, 16)");
+            ok(testImageShiftCase(64,128,32.0f,-16.0f), "psImageShift (32, -16)");
+            ok(testImageShiftCase(64,128,-32.0f,16.0f), "psImageShift (-32, 16)");
+            ok(testImageShiftCase(64,128,-32.0f,-16.0f), "psImageShift (-32, -16)");
+
+            // fractional shift
+            ok(testImageShiftCase(64,128,0.0f,16.4f), "psImageShift (0, 16.4)");
+            ok(testImageShiftCase(64,128,0.0f,-16.4f), "psImageShift (0, -16.4)");
+            ok(testImageShiftCase(64,128,32.7f,0.0f), "psImageShift (32.7, 0)");
+            ok(testImageShiftCase(64,128,-32.7f,0.0f), "psImageShift (-32.7, 0)");
+            ok(testImageShiftCase(64,128,32.6f,16.2f), "psImageShift (32.6, 16.2)");
+            ok(testImageShiftCase(64,128,32.6f,-16.2f), "psImageShift (32.6, -16.2)");
+            ok(testImageShiftCase(64,128,-32.6f,16.2f), "psImageShift (-32.6, 16.2)");
+            ok(testImageShiftCase(64,128,-32.6f,-16.2f), "psImageShift (-32.6, -16.2)");
+        }
+
+        // Verify the returned psImage structure pointer is equal to the input
+        // parameter out if provided.
+        psImage *fImg = psImageAlloc(32,32,PS_TYPE_F32);
+        psImage *fRecycle = psImageAlloc(32,32,PS_TYPE_F32);
+        psImage *fOut = psImageShift(fRecycle, fImg, 8,8, NAN, PS_INTERPOLATE_FLAT);
+        ok(fRecycle == fOut, "psImageShift did recycle my image");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input psImage structure pointer is null.
+        // Following should be an error
+        // XXX: Verify error
+        fOut = psImageShift(fOut,NULL,8,8,NAN,PS_INTERPOLATE_FLAT);
+        ok(fOut == NULL, "psImageShift did return NULL given a NULL input image");
+
+        // Verify the returned psImage structure is null and program execution
+        // doesn't stop, if the specified interpolation mode is unallowed.
+        // Following should be an error for unallowed interpolation mode
+        // XXX: Verify error
+        fOut = psImageShift(fOut,fImg,8,8,NAN,-1);
+        ok(fOut == NULL, "psImageShift did return NULL given an unallowed interpolation mode");
+
+        psFree(fImg);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageResample()
+    {
+        psMemId id = psMemGetId();
+
+        psS32 rows = 60;
+        psS32 cols = 80;
+        psImage *result = NULL;
+        psS32 scale = 4;
+        psErr *err;
+
+        psImage *image = psImageAlloc(cols,rows,PS_TYPE_F32);
+        for(psS32 row=0;row<rows;row++)
+        {
+            psF32 *imageRow = image->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                imageRow[col] = row+2*col;
+            }
+        }
+        result = psImageCopy(NULL,image,PS_TYPE_F64);
+        psImage *orig = result;
+        result = psImageResample(result,image,scale,PS_INTERPOLATE_FLAT);
+        ok(result != NULL, "psImageResample() returned non-NULL");
+        ok(result == orig, "psImageResample() recycled image");
+        ok(result->type.type == PS_TYPE_F32, "psImageResample() produced the correct type");
+
+
+        ok(result->numCols == image->numCols*scale && result->numRows == image->numRows*scale,
+           "psImageResample() produced the correct size");
+
+
+        bool errorFlag = false;
+        psF32 truthValue;
+        for(psS32 row=0;row<result->numRows;row++)
+        {
+            for (psS32 col=0;col<result->numCols;col++) {
+                truthValue = psImagePixelInterpolate(image,
+                                                     (float)col/(float)scale,(float)row/(float)scale,
+                                                     NULL,0,-1,PS_INTERPOLATE_FLAT);
+                if (fabs(truthValue - result->data.F32[row][col]) > FLT_EPSILON) {
+                    diag("value bad at (%d,%d).  Got %g, expected %g",
+                         col,row,result->data.F32[row][col], truthValue);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageResample() produced the correct data values");
+
+        // verify that image=null is handled properly.
+        psErrorClear();
+        result = psImageResample(result,NULL,scale,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with NULL input");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_NULL, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // verify that scale < 1 is handled properly
+        psErrorClear();
+        result = psImageResample(result,image,0,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with scale < 1");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // verify that unallowed interpolation mode is handled properly
+        psErrorClear();
+        result = psImageResample(result,image,2,-1);
+        ok(result == NULL, "psImageResample() returned NULL with unallowed interpolation mode");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_VALUE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        // Verify that that an unallowed image type is handled properly
+        psErrorClear();
+        psImage *invImage = psImageAlloc(cols,rows,PS_TYPE_BOOL);
+        memset(invImage->p_rawDataBuffer,0,cols*rows*PSELEMTYPE_SIZEOF(PS_TYPE_BOOL)); // make sure the image is of all NULLs
+        result = psImageResample(result,invImage,2,PS_INTERPOLATE_FLAT);
+        ok(result == NULL, "psImageResample() returned NULL with unallowed image type");
+        err = psErrorLast();
+        ok(err->code == PS_ERR_BAD_PARAMETER_TYPE, "psImageResample() produced the correct error message");
+        psFree(err);
+
+        psFree(image);
+        psFree(result);
+        psFree(invImage);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageTransform()
+    {
+        psMemId id = psMemGetId();
+        int cols = 16;
+        int rows = 32;
+
+        psPlaneTransform *trans = psPlaneTransformAlloc(2,2);
+        trans->x->coeff[1][0] = 0.5;
+        trans->y->coeff[0][1] = 1.5;
+
+        psImage *in = psImageAlloc(cols,rows,PS_TYPE_F32);
+        for (psS32 row=0;row<rows;row++)
+        {
+            psF32 *inRow = in->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                inRow[col] = (psF32)row+(psF32)col/1000.0f;
+            }
+        }
+        in->col0 = 1;
+        psImage *out = psImageTransform(NULL,
+                                        NULL,
+                                        in,
+                                        NULL,
+                                        0,
+                                        trans,
+                                        psRegionSet(1,1+cols*2,0,rows*2),
+                                        NULL,
+                                        PS_INTERPOLATE_FLAT,
+                                        -1);
+
+        ok(out != NULL, "psImageTransform() returned non-NULL");
+        ok(out->type.type == PS_TYPE_F32, "psImageTransform() produced the correct type");
+        ok(out->numRows == rows*2 && out->numCols == cols*2, "psImageTransform() produced the correct size");
+
+        bool errorFlag = false;
+        for (psS32 row=0;row<out->numRows;row++)
+        {
+            psF32 *outRow = out->data.F32[row];
+            for (psS32 col=0;col<cols;col++) {
+                float inValue = p_psImagePixelInterpolateFLAT_F32(in,
+                                col*trans->x->coeff[1][0]+trans->x->coeff[0][0]+1,
+                                row*trans->y->coeff[0][1]+trans->y->coeff[0][0],
+                                NULL, 0,
+                                -1);
+                if (fabsf(outRow[col] - inValue) > 0.01) {
+                    diag("out at %d,%d was %g, expected %g", col,row,outRow[col], inValue);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTransform() produced the correct data values");
+
+        psFree(out);
+        psFree(in);
+        psFree(trans);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /trunk/psLib/test/imageops/tap_psImageInterpolate.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psImageInterpolate.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psImageInterpolate.c	(revision 11398)
@@ -0,0 +1,329 @@
+/** @file tst_psImageInterpolate.c
+ *
+ * @brief Contains the tests for psImagePixelInterpolate
+ *
+ * @author Eric Van Alst, MHPCC
+ *
+ * @version $Revision: 1.1 $
+ *          $Name: not supported by cvs2svn $
+ * @date $Date: 2007-01-30 00:13:01 $
+ *
+ * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define GENIMAGE(img,c,r,TYP,valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for(psU32 row=0; row<r; row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for(psU32 col=0; col<c; col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+#define CHECK_INTERP_VALUE(img,x,y,mask,maskval,exposed,TYPE,expected) \
+{ \
+    psF32 val = (psF32)psImagePixelInterpolate(img,x,y,mask,maskval,exposed,PS_INTERPOLATE_##TYPE); \
+    ok(fabsf(val-expected)<FLT_EPSILON, "psImagePixelInterpolate() correct"); \
+}
+
+#define CHECK_INTERP_BY_TYPE(TYPE) \
+{ \
+    psImage* img1; \
+    GENIMAGE(img1,10,10,TYPE,row+col) \
+    CHECK_INTERP_VALUE(img1,1.9,1.6,NULL,0,0,FLAT,2.0) \
+    CHECK_INTERP_VALUE(img1,4.0,2.0,NULL,0,0,BILINEAR,5.0) \
+    psFree(img1); \
+}
+
+#define CHECK_INTERP_BY_TYPE_ORIG(TYPE) \
+{ \
+    psImage* img1; \
+    GENIMAGE(img1,10,10,TYPE,row+col) \
+    CHECK_INTERP_VALUE(img1,1.9,1.6,NULL,0,0,FLAT,2.0) \
+}
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(57);
+
+    // testInterpolateFlatBilinear(void)
+    // Perform simple(four neighbor) FLAT interpolation for all types
+    // Perform bilinear interpolation for all types
+    CHECK_INTERP_BY_TYPE(S8)
+    CHECK_INTERP_BY_TYPE(S16)
+    CHECK_INTERP_BY_TYPE(S32)
+    CHECK_INTERP_BY_TYPE(S64)
+    CHECK_INTERP_BY_TYPE(U8)
+    CHECK_INTERP_BY_TYPE(U16)
+    CHECK_INTERP_BY_TYPE(U32)
+    CHECK_INTERP_BY_TYPE(U64)
+    CHECK_INTERP_BY_TYPE(F32)
+    CHECK_INTERP_BY_TYPE(F64)
+    CHECK_INTERP_BY_TYPE(C32)
+    CHECK_INTERP_BY_TYPE(C64)
+
+    // testInterpolateError(void)
+    // Perform interpolation with NULL input image
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psF32 val = psImagePixelInterpolate(NULL,1.2,1.2,NULL,0,5.0,PS_INTERPOLATE_FLAT);
+        ok(val == 5.0, "psImagePixelInterpolate() returned the unexposed value (NULL image)");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation with unallowed input image type
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psImage *img1 = psImageAlloc(10,10,PS_TYPE_BOOL);
+        psF32 val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_FLAT);
+        ok(val == 10.0, "psImagePixelInterpolate() returned the unexposed value (unallowed image type)");
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation with unallowed method
+    // Following should generate an error message
+    // XXX: we do not test the error generation
+    {
+        psMemId id = psMemGetId();
+        psImage *img1 = psImageAlloc(10,10,PS_TYPE_BOOL);
+        psF32 val = psImagePixelInterpolate(img1,1.2,1.2,NULL,0,10.0,PS_INTERPOLATE_BILINEAR+1);
+        ok(val == 10.0, "psImagePixelInterpolate() returned the unexposed value (unallowed interpolation method)");
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // The following assumptions about the test image are:
+    //
+    //                     col
+    //             0   1   2   3   4   5   6   7  ...
+    //
+    // row 0       0   1   2   3   4   5   6   7
+    // row 1       1   2   3   4   5   6   7   8
+    // row 2       2   3   4   5   6   7   8   9
+    // ...
+    // testInterpolateMaskFlatBilinear(void)
+    psImage* img1 = NULL;
+    psImage* msk1 = NULL;
+
+    // Perform interpolate with mask and mask value set at nearest pixel to verify
+    // the unexposed value is return
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][1] = 1;
+        CHECK_INTERP_VALUE(img1,1.9,1.6,msk1,1,10.0,FLAT,10.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper left pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper right pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower left pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.25)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower right pixel)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.75)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (upper pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (lower pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (left pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask and one mask value for bilinear (right pixels)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.5)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (upper left)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,4.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (upper right)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (lower left)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,5.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask only one valid pixel (lower right)
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,6.0)
+        psFree(msk1);
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Perform interpolate with mask no valid pixels
+    {
+        psMemId id = psMemGetId();
+        GENIMAGE(img1,10,10,F32,row+col)
+        GENIMAGE(msk1,10,10,U8,0)
+        msk1->data.U8[1][3] = 1;
+        msk1->data.U8[1][4] = 1;
+        msk1->data.U8[2][3] = 1;
+        msk1->data.U8[2][4] = 1;
+        CHECK_INTERP_VALUE(img1,4.0,2.0,msk1,1,0,BILINEAR,0.0)
+        psFree(msk1);
+        psFree(img1);
+        return 0;
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // Perform interpolation for a 1D image
+    {
+        psMemId id = psMemGetId();
+        psImage* img1 = NULL;
+        GENIMAGE(img1,10,1,F32,row+col)
+        CHECK_INTERP_VALUE(img1,4.0,0.0,NULL,0,100.0,BILINEAR,3.5)
+        psFree(img1);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
+
Index: /trunk/psLib/test/imageops/tap_psImagePixelManip.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psImagePixelManip.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psImagePixelManip.c	(revision 11398)
@@ -0,0 +1,704 @@
+/** @file  tst_psImageManip.c
+ *
+ *  @brief Contains the tests for psImageManip.[ch]
+ *
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-01-30 00:13:01 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+psS32 main(psS32 argc, char* argv[])
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(85);
+
+    // testImageClip()
+    {
+        psMemId id = psMemGetId();
+
+        //psImageClip shall limit the minimum and maximum data value within a psImage structure
+
+        // psImageClip shall limit the minimum and maximum data value within a
+        // psImage structure to a specified min and max value.
+        //
+        // Verify the returned integer is equal to the number of pixels clipped,
+        // if the input psImage structure contains known values and input parameters
+        // min and max have know values.
+        //
+        // Verify the psImage structure specified by the input parameter input is
+        // modified to contain the expected values, if the input psImage structure
+        // contains known values, min and max are specified and vmin and vmax
+        // parameters are known.
+        //
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is null.
+        //
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter min is larger than max.
+        // create image
+        #define testImageClipByType(datatype) \
+        { \
+            psU32 c = 128; \
+            psU32 r = 256; \
+            psF64 min; \
+            psF64 max; \
+            psS32 numClipped = 0; \
+            psS32 retVal; \
+            psMemId id = psMemGetId(); \
+            psImage *img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    imgRow[col] = (ps##datatype)(row+col); \
+                } \
+            } \
+            min = (psF64)r/2.0; \
+            max = (psF64)r; \
+            \
+            retVal = psImageClip(img,min,(double)PS_MIN_##datatype,max,(double)PS_MAX_##datatype); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    ps##datatype value = (ps##datatype)(row+col); \
+                    if (value < min) { \
+                        numClipped++; \
+                        value = PS_MIN_##datatype; \
+                    } else if (value > max) { \
+                        numClipped++; \
+                        value = PS_MAX_##datatype; \
+                    } \
+                    if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%g vs %g) at %u,%u", \
+                             (psF64)imgRow[col],(psF64)value,col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        #define testImageClipByComplexType(datatype) \
+        { \
+            psU32 c = 128; \
+            psU32 r = 256; \
+            psF64 min; \
+            psF64 max; \
+            psS32 numClipped = 0; \
+            psS32 retVal; \
+            psMemId id = psMemGetId(); \
+            psImage *img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    imgRow[col] = (ps##datatype)(row+I*col); \
+                } \
+            } \
+            min = (float)r/2.0f; \
+            max = (float)r; \
+            \
+            retVal = psImageClip(img,min,-1.0f,max,-2.0f); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (psU32 row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (psU32 col=0;col<c;col++) { \
+                    ps##datatype value = row+I*col; \
+                    if (cabs(value) < min) { \
+                        numClipped++; \
+                        value = -1.0f; \
+                    } else if (cabs(value) > max) { \
+                        numClipped++; \
+                        value = -2.0f; \
+                    } \
+                    if (fabsf(creal(imgRow[col])-creal(value)) > FLT_EPSILON || \
+                            fabsf(cimag(imgRow[col])-cimag(value)) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%.2f+%.2fi vs %.2f+%.2fi) at %u,%u", \
+                             creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testImageClipByType(F64);
+        testImageClipByType(F32);
+        testImageClipByType(S32);
+        testImageClipByType(S16);
+        testImageClipByType(S8);
+        testImageClipByType(U32);
+        testImageClipByType(U16);
+        testImageClipByType(U8);
+        testImageClipByComplexType(C32);
+        testImageClipByComplexType(C64);
+
+
+        psF64 min;
+        psF64 max;
+        psS32 retVal;
+        psImage *img = NULL;
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is null.
+        retVal = psImageClip(NULL,min,-1.0f,max,-2.0f);
+        ok(retVal == 0, "Expected zero return for clips of a NULL image");
+
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter min is larger than max.
+        // Following should be an error (max<min)
+        // XXX: Verify error
+        retVal = psImageClip(img,max,-1.0f,min,-2.0f);
+        ok(retVal == 0, "Expected zero return for clips when max < min");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageClipNAN()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psU32 c = 128;
+        psU32 r = 256;
+        psS32 numClipped = 0;
+        psS32 retVal;
+
+        // psImageClipNaN shall modified pixel values of NaN with a specified value");
+
+        // psImageClipNaN shall modify a psImage structure with pixel values set
+        // to NaN to a value specified as an input parameter.
+        //
+        // Verify the returned integer is equal to the number of pixels modified
+        // and the psImage is modified at locations where NaN pixels where
+        // located to the value specified in the input parameter value.
+        //
+        // Verify the returned integer is zero and program execution doesn't stop,
+        // if the input parameter psImage structure pointer is null.
+        // create image
+        #define testImageClipNaNByType(datatype) \
+        { \
+            psMemId id = psMemGetId(); \
+            img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    if (row == col) { \
+                        imgRow[col] = NAN; \
+                    } else if (row+1 == col) { \
+                        imgRow[col] = INFINITY; \
+                    } else { \
+                        imgRow[col] = (ps##datatype)(row+col); \
+                    } \
+                } \
+            } \
+            \
+            retVal = psImageClipNaN(img,-1.0f); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    ps##datatype value = (ps##datatype)(row+col); \
+                    if ( (row == col) || (row+1 == col) ) { \
+                        numClipped++; \
+                        value = -1.0; \
+                    } \
+                    if (fabsf(imgRow[col]-value) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%f vs %f) at %d,%d", \
+                             imgRow[col],value,col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        testImageClipNaNByType(F32);
+        testImageClipNaNByType(F64);
+        testImageClipNaNByType(C32);
+        testImageClipNaNByType(C64);
+
+        // Verify the retuned integer is zero, psImage structure input is unmodified
+        // and program executions doesn't stop, if input parameter psImage structure
+        // pointer is null.
+        retVal = psImageClipNaN(NULL,-1.0f);
+        ok(retVal == 0, "Expected zero return for clips of a NULL image");
+
+        // Verify program execution doesn't stop if the input image type is something
+        // other than F32, F64, C32, C64.
+        img = psImageAlloc(c,r,PS_TYPE_S32);
+        // Following should be an error (incorrect type)
+        // XXX: Verify error
+        retVal = psImageClipNaN(img,2.0f);
+        ok(retVal == 0, "Expected zero return for clip of incorrect image type");
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageClipComplexRegion()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psU32 c = 1024;
+        psU32 r = 2048;
+        psS32 numClipped = 0;
+        psS32 retVal;
+
+        // psImageClipNaN shall modified pixel values of NaN with a specified value
+
+        // 1. Create a complex image with a wide range of complex values
+        //
+        // 2. call psImageClipComplexRegion with min and max where there is at least
+        //    2 pixels in the image above) that is:
+        //   a) real(p) < real(min) && complex(p) < complex(min),
+        //   b) real(p) < real(min) && complex(min) < complex(p) < complex(max)
+        //   c) real(min) < real(p) < real(max) && complex(p) < complex(min)
+        //   d) real(min) < real(p) < real(max) && complex(min) < complex(p) < complex(max)
+        //   e) real(p) > real(max) && complex(min) < complex(p) < complex(max)
+        //   f) real(pmin) < real(p) < real(max) && complex(p) > complex(max)
+        //   g) real(p) > real(max) && complex(p) > complex(max)
+        //   h) real(p) < real(min) && complex(p) > complex(max)
+        //   i) real(p) > real(max) && complex(p) < complex(min)
+        //
+        // 3. verify that All pixels in case (a), (b), and (c) have the value vmin
+        //
+        // 4. verify that all pixels in case (d) are unchanged from input
+        //
+        // 5. verify that all pixels in case (e), (f), (g), (h), and (i) have the
+        //    value vmax
+        #define testImageClipComplexByType(datatype,MIN,MAX) \
+        { \
+            psMemId id = psMemGetId(); \
+            img = psImageAlloc(c,r,PS_TYPE_##datatype); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    imgRow[col] = row+I*col; \
+                } \
+            } \
+            \
+            retVal = psImageClipComplexRegion(img,MIN,-1.0-1.0*I,MAX,-2.0-2.0*I); \
+            \
+            numClipped = 0; \
+            bool errorFlag = false; \
+            for (unsigned row=0;row<r;row++) { \
+                ps##datatype* imgRow = img->data.datatype[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    ps##datatype value = (ps##datatype)(row+I*col); \
+                    if ( (row > creal(MAX)) || (col > cimag(MAX)) ) { \
+                        numClipped++; \
+                        value = -2.0-2.0*I; \
+                    } else if ((row < creal(MIN)) || (col < cimag(MIN)) ) { \
+                        numClipped++; \
+                        value = -1.0-1.0*I; \
+                    } \
+                    if (cabs(imgRow[col]-value) > FLT_EPSILON) { \
+                        diag("Pixel value is not as expected (%g%+gi vs %g%+gi) at %d,%d", \
+                             creal(imgRow[col]),cimag(imgRow[col]),creal(value),cimag(value),col,row); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageClip() produced the correct data values"); \
+            ok(retVal == numClipped, "Got the expected number of clips"); \
+            psFree(img); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        complex double min = ((double)r)/5.0+I*((double)c)/4.0;
+        complex double max = ((double)r)/3.0+I*((double)c)/2.0;
+
+        // Testing clipping at %g%+gi to %g%+gi for psC32, creal(min),cimag(min),creal(max),cimag(max));
+
+        testImageClipComplexByType(C32,min,max);
+
+        // Testing clipping at %g%+gi to %g%+gi for psC64, creal(min),cimag(min),creal(max),cimag(max));
+        testImageClipComplexByType(C64,min,max);
+
+        //  6. Call psImageClipComplexRegion with NULL input parameter; should error
+        //     but not stop execution.
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(NULL,0,0,0,0);
+        ok(retVal == 0, "Expected zero return for clips of a NULL image");
+
+        img = psImageAlloc(c,r,PS_TYPE_C32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psC32* imgRow = img->data.C32[row];
+            for (unsigned col=0;col<c;col++) {
+                imgRow[col] = row+I*col;
+            }
+        }
+
+        //  7. Call psImageClipComplexRegion with min > max; should error and return 0,
+        //     but not stop execution
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,10.0+I*1.0,-1.0,5.0+5.0*I,-2.0);
+        ok(retVal == 0, "Expected zero return for creal(min)>creal(max)");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,1.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+        ok(retVal == 0, "Expected zero return for cimag(min)>cimag(max)");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,10.0+I*10.0,-1.0,5.0+5.0*I,-2.0);
+        ok(retVal == 0, "Expected zero return for min>max");
+
+        //  8. Call psImageClipComplexRegion with the follow vmin/vmax values; each
+        //     should error and return 0, but not stop execution
+        //      a) vmin < datatype region's minimum
+        //      b) vmax < datatype region's minimum
+        //      c) vmin > datatype region's maximum
+        //      d) vmax > datatype region's maximum
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          -2.0*(double)FLT_MAX,
+                                          5.0+5.0*I,
+                                          0.0);
+        ok(retVal == 0, "Expected zero return for vmin not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          2.0*(double)FLT_MAX,
+                                          5.0+5.0*I,
+                                          0.0);
+        ok(retVal == 0, "Expected zero return for vmin not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          FLT_EPSILON-2.0*(double)FLT_MAX*I,
+                                          5.0+5.0*I,
+                                          0.0);
+        ok(retVal == 0, "Expected zero return for vmin not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          FLT_EPSILON+2.0*(double)FLT_MAX*I,
+                                          5.0+5.0*I,
+                                          0.0);
+        ok(retVal == 0, "Expected zero return for vmin not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          0.0,
+                                          5.0+5.0*I,
+                                          -2.0*(double)FLT_MAX);
+        ok(retVal == 0, "Expected zero return for vmax not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          0.0,
+                                          5.0+5.0*I,
+                                          2.0*(double)FLT_MAX);
+        ok(retVal == 0, "Expected zero return for vmax not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          0.0,
+                                          5.0+5.0*I,
+                                          FLT_EPSILON-2.0*(double)FLT_MAX*I);
+        ok(retVal == 0, "Expected zero return for vmax not in datatype range");
+
+        // Following should be an error
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          0.0,
+                                          5.0+5.0*I,
+                                          FLT_EPSILON+2.0*(double)FLT_MAX*I);
+        ok(retVal == 0, "Expected zero return for vmax not in datatype range");
+
+        // now check if vmin > vmax is OK
+        for (unsigned row=0;row<r;row++)
+        {
+            psC32* imgRow = img->data.C32[row];
+            for (unsigned col=0;col<c;col++) {
+                imgRow[col] = row+I*col;
+            }
+        }
+        retVal = psImageClipComplexRegion(img,
+                                          1.0+I*1.0,
+                                          10.0,
+                                          5.0+5.0*I,
+                                          0.0);
+        ok(retVal != 0, "Didn't expect zero return for vmin > vmax");
+        psFree(img);
+        img = NULL;
+
+        //  9. Call psImageClipComplexRegion with the max value out of datatype's
+        //     range; should clip as expected (see step 1-5). Repeat with min value
+        //     out of datatype's range.
+
+        testImageClipComplexByType(C32,-(double)FLT_MAX*2.0-I*(double)FLT_MAX*2.0,10.0+I*10.0);
+        testImageClipComplexByType(C32,10.0+I*10.0,(double)FLT_MAX*2.0+I*(double)FLT_MAX*2.0);
+
+        // Verify program execution doesn't stop if the input image type is something
+        // other than C32, C64.
+        img = psImageAlloc(c,r,PS_TYPE_S32);
+        // Following should be an error (incorrect type)
+        // XXX: Verify error
+        retVal = psImageClipComplexRegion(img,2.0,10.0,5.0,0.0);
+        ok(retVal == 0, "Expected zero return for clip of incorrect image type");
+        psFree(img);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testImageOverlay()
+    {
+        psMemId id = psMemGetId();
+        psImage* img = NULL;
+        psImage* img2 = NULL;
+        psImage* img3 = NULL;
+        psImage* img4 = NULL;
+        psU32 c = 128;
+        psU32 r = 256;
+        psS32 retVal;
+
+        // psImageSectionOverlay shall modified pixel values in a psImage structure to
+        // be equal to the value of the originaldata and an overlay image with a
+        // specified operation. Valid operations include =, +, -, *, /.
+        //
+        // Verify the returned integer is zero
+        // and the input parameter psImage structure is modified at the specified
+        // location and range with the given overlay image and the specified
+        // function. Cases should include all the valid operations. Comparison of
+        // expected values should include a delta to allow for testing on
+        // different platforms.
+        #define testOverlayTypeOP(DATATYPE,OP,OPSTRING) \
+        { \
+            psMemId id = psMemGetId(); \
+            img = psImageAlloc(c,r,PS_TYPE_##DATATYPE); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    imgRow[col] = 6.0; \
+                } \
+            } \
+            img2 = psImageAlloc(c/2,r/2,PS_TYPE_##DATATYPE); \
+            for (unsigned row=0;row<r/2;row++) { \
+                ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c/2;col++) { \
+                    img2Row[col] = 2.0; \
+                } \
+            } \
+            retVal = psImageOverlaySection(img,img2,c/4,r/4,OPSTRING); \
+            if (retVal == 0) { \
+                psError(PS_ERR_UNKNOWN, true,"psImageOverlaySection returned zero with %s op", \
+                        OPSTRING); \
+                return 1; \
+            } \
+            bool errorFlag = false; \
+            for (unsigned row=0;row<r;row++) { \
+                ps##DATATYPE* imgRow = img->data.DATATYPE[row]; \
+                ps##DATATYPE* img2Row = img2->data.DATATYPE[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    ps##DATATYPE val = 6.0; \
+                    if ( ! (row < r/4 || row >= r/2+r/4 || col < c/4 || col >= c/2+c/4)) { \
+                        val OP 2.0; \
+                    } \
+                    if (fabsf(imgRow[col] - val) > FLT_EPSILON) { \
+                        diag("Value incorrect at %d,%d (%.2f vs %.2f for %s)", \
+                             col,row,imgRow[col],val,OPSTRING); \
+                        errorFlag = true; \
+                    } \
+                    if (row < r/2 && col < c/2 && fabsf(img2Row[col] - 2.0) > FLT_EPSILON) { \
+                        diag("Overlay modified at %d,%d (%.2f for %s)", \
+                             col,row,img2Row[col],OPSTRING); \
+                        errorFlag = true; \
+                    } \
+                } \
+            } \
+            ok(!errorFlag, "psImageOverlaySection() produced the correct data values"); \
+            psFree(img); \
+            psFree(img2); \
+            ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); \
+        }
+
+        #define testOverlayType(DATATYPE) \
+        testOverlayTypeOP(DATATYPE,+=,"+"); \
+        testOverlayTypeOP(DATATYPE,-=,"-"); \
+        testOverlayTypeOP(DATATYPE,*=,"*");\
+        testOverlayTypeOP(DATATYPE,/=,"/");\
+        testOverlayTypeOP(DATATYPE,=,"=");
+
+
+        //      testOverlayType(C64);
+        //        testOverlayType(C32);
+        //        testOverlayType(F64);
+        //        testOverlayType(F32);
+        //        testOverlayType(S16);
+        //        testOverlayType(S8);
+        //        testOverlayType(U16);
+        //        testOverlayType(U8);
+
+        // Verify the returned integer is equal to non-zero and the input psImage structure
+        // is unmodified, if the overlay specified is not within the data range of the
+        // input psImage structure.
+        img = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                imgRow[col] = 6.0f;
+            }
+        }
+        img2 = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                img2Row[col] = 2.0f;
+            }
+        }
+        img3 = psImageAlloc(c,r,PS_TYPE_S64);
+        for (unsigned row=0;row<r;row++)
+        {
+            psS64* img3Row = img3->data.S64[row];
+            for (unsigned col=0;col<c;col++) {
+                img3Row[col] = 6.0f;
+            }
+        }
+        img4 = psImageAlloc(c,r,PS_TYPE_S64);
+        for (unsigned row=0;row<r;row++)
+        {
+            psS64* img4Row = img4->data.S64[row];
+            for (unsigned col=0;col<c;col++) {
+                img4Row[col] = 2.0f;
+            }
+        }
+
+        // Following should error as overlay isn't within image boundaries
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection did return zero when overlay too big");
+
+        bool errorFlag = false;
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if (imgRow[col] != 6.0f) {
+                    diag("Input image modified when overlay size too big");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageOverlaySection() produced the correct data values");
+
+
+        // Verify the returned integer is equal to non-zero, the input psImage
+        // structure is unmodified and program execution doesn't stop, if the
+        // overlay specified is null.
+        // Following should error as overlay is NULL
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,NULL,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection did return zero when overlay too big");
+        errorFlag = false;
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if (imgRow[col] != 6.0f) {
+                    diag("Input image modified when overlay NULL");
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageOverlaySection() produced the correct data values");
+
+
+        // Verify the returned integer is equal to non-zero and program execution
+        // doesn't stop, if the input parameter image is null.
+        // Following should error as image input is NULL
+        // XXX: Verify error
+        retVal = psImageOverlaySection(NULL,img2,c/4,r/4,"+");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay too big");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if the specified operator is not =,+,-,*,/
+        // Following should error as operator is incorrect
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,0,0,"$");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay too big");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if the specified operator is NULL
+        // Following should error as operator is incorrect
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img2,0,0,NULL);
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay operator is NULL");
+
+
+        // Verify the return integer is equal to non-zero and program execution
+        // doesn't stop, if overlay image is a different type than the input image
+        // Following should error as overlay is a different type
+        // XXX: Verify error
+        retVal = psImageOverlaySection(img,img3,0,0,"+");
+        ok(retVal == 0, "psImageOverlaySection returned zero when overlay image type is different than input image");
+
+
+        // Verify program execution doen't stop, if the overly image contains
+        // zero values with division operation is specified.
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                img2Row[col] = 0.0f;
+            }
+        }
+        retVal = psImageOverlaySection(img,img2,0,0,"/");
+        ok(retVal == 0, "psImageOverlaySection returned zero when checking divide-by-zero");
+
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        psFree(img4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /trunk/psLib/test/imageops/tap_psImageStructManip.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psImageStructManip.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psImageStructManip.c	(revision 11398)
@@ -0,0 +1,496 @@
+/** @file  tst_psImageExtraction.c
+*
+*  @brief Contains the tests for psImageExtraction.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-30 00:13:01 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(185);
+
+
+    // psImageSubset shall create child image of a specified size from a
+    // parent psImage structure
+
+    // psImageSubset()
+    {
+        psMemId id = psMemGetId();
+        psImage preSubsetStruct;
+        psS32 c = 128;
+        psS32 r = 256;
+        psRegion region1 = psRegionSet(0,c/2,0,r/2);
+        psRegion region2 = psRegionSet(c/4,c/4+c/2,r/4,r/4+r/2);
+
+        psImage* original = psImageAlloc(c,r,PS_TYPE_U32);
+        for (psS32 row=0;row<r;row++)
+        {
+            for (psS32 col=0;col<c;col++) {
+                original->data.F32[row][col] = row*1000+col;
+            }
+        }
+
+        memcpy(&preSubsetStruct,original,sizeof(psImage));
+        psImage* subset2 = psImageSubset(original,region2);
+        ok(subset2, "psImageSubset() returned non-NULL (subset2)");
+        skip_start(subset2 == NULL, 25, "Skipping tests because psImageSubset() returned NULL");
+        psImage* subset3 = psImageSubset(original,region1);
+        ok(subset3, "psImageSubset() returned non-NULL (subset3)");
+        skip_start(subset3 == NULL, 24, "Skipping tests because psImageSubset() returned NULL");
+
+        // Verify the returned psImage structure members nrow and ncol are equal to
+        // the input parameter nrow and ncol respectively
+        ok(subset2->numCols == c/2 && subset2->numRows == r/2,
+           "psImageSubset output size set properly");
+        ok(subset3->numCols == c/2 && subset3->numRows == r/2,
+           "psImageSubset output size set properly");
+
+        // Verify the returned psImage structure contains expected values in the
+        // row member, if the input psImage structure image contains known values
+
+        bool errorFlag;
+        for (psS32 row=0;row<r/2;row++)
+        {
+            for (psS32 col=0;col<c/2;col++) {
+                if (subset2->data.U32[row][col] != original->data.U32[row+r/4][col+c/4]) {
+                    diag("psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                         row,col,subset2->data.U32[row][col], original->data.U32[row+r/4][col+c/4]);
+                    errorFlag = true;
+                }
+                if (subset3->data.U32[row][col] != original->data.U32[row][col]) {
+                    diag("psImageSubset output #1 was wrong at %dx%d (%d vs %d).",
+                         row,col,subset2->data.U32[row][col], original->data.U32[row][col]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageSubset() produced the expected values");
+
+        // Verify the returned psImage structure member type is equal to the input
+        // psImage structure member type
+        ok(subset2->type.type == PS_TYPE_U32, "psImageSubset() type was correct (subset2)");
+        ok(subset3->type.type == PS_TYPE_U32, "psImageSubset() type was correct (subset3)");
+
+        // Verify the returned psImage structure members row0 and col0 are equal to
+        // the input parameters row0 and col0 respectively
+        ok(subset2->col0 == c/4 && subset2->row0 == r/4,
+           "psImageSubset() set col0/row0 correctly (subset2)");
+        ok(subset3->col0 == 0 && subset3->row0 == 0,
+           "psImageSubset() set col0/row0 correctly (subset3)");
+
+        // Verify the returned psImage structure member parent is equal to the
+        // input psImage structure pointer image
+        ok(subset2->parent == original && subset3->parent == original, "psImageSubset() set ->parent correctly");
+
+        // Verify the returned psImage structure member children is null
+        ok(subset2->children == NULL && subset3->children == NULL, "psImageSubset() set ->children correctly");
+
+
+        // Verify the input psImage structure image only has the following members
+        // changed: 1) Nchildren is increased by one. 2) parent contains pointer psImage structure
+        // out at parent[Nchildren-1]
+        ok(original->children != NULL && original->children->n == 2, "psImageSubset did increment number of children by one per subset.");
+        ok(original->children->data[0] == subset2 && original->children->data[1] == subset3,
+           "psImageSubset did properly store the children pointers.");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameter image is null.
+        // Also verified the input psImage structure is not modified
+        // An error should follow...
+        // XXX: Verify error
+        psImage* subset1 = psImageSubset(NULL,region1);
+        ok(subset1 == NULL, "psImageSubset returned NULL when input image was NULL.");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameters nrow and/or ncol are zero.
+        // Also verify input psImage structure is not modified
+        // An error should follow...
+        // XXX: Verify error
+        memcpy(&preSubsetStruct,original,sizeof(psImage));
+        subset1 = psImageSubset(original, psRegionSet(0,c/2,r/2,r/2));
+        ok(subset1 == NULL, "psImageSubset returned NULL when numRows=0.");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original,psRegionSet(c/2,c/2,0,r/2));
+        ok(subset1 == NULL, "psImageSubset returned NULL when numCols=0.");
+        ok(memcmp(original,&preSubsetStruct,sizeof(psImage)) == 0,
+           "psImageSubset didn't change the original struct though it failed to subset.");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameters row0 and col0 are not within
+        // the range of values of psImage structure image
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original, psRegionSet(0,c/2, 0,r*2));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset origin was outside of image (via cols)");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original,psRegionSet(0,c*2,0,r/2));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset origin was outside of image (via rows)");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original, psRegionSet(-1,c/2,0,r/2));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset origin was outside of image (col0=-1)");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original, psRegionSet(0,c/2,-1,r/2));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset origin was outside of image (row0=-1)");
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop if the input parameters nrow, ncol, row0 and col0
+        // specify a range of data not within the input psImage structure image.  Also
+        // verify the input psImage structure is not modified
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original,psRegionSet(0,c/2,0,r+1));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset was outside of image (via rows)");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original, psRegionSet(0,c+1,0,r/2));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset was outside of image (via cols)");
+        // An error should follow...
+        // XXX: Verify error
+        subset1 = psImageSubset(original,psRegionSet(0,c+1,0,r+1));
+        ok(subset1 == NULL,
+           "psImageSubset returned NULL when subset was outside of image (via row+cols)");
+
+
+        // psImageFreeChildren shall deallocate any children images of a
+        // psImage structure
+        memcpy(&preSubsetStruct,original,sizeof(psImage));
+        psImageFreeChildren(original);
+
+        // Verify the returned psImage structure member Nchildren is set to zero.
+        // XXX: This doesn't make sense.
+        ok(original->children == NULL || original->children->n == 0,
+           "psImageFreeChildren didn't set children to NULL");
+
+        //Verify the returned psImage structure members type, nrow, ncol, row0, col0, rows
+        // and parent are not modified.
+        ok(preSubsetStruct.numRows == original->numRows &&
+           preSubsetStruct.numCols == original->numCols &&
+           preSubsetStruct.row0 == original->row0 &&
+           preSubsetStruct.col0 == original->col0,
+           "psImageFreeChildren modified parent's non-children elements");
+
+        skip_end();
+        skip_end();
+        psFree(original);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psImageCopy()
+    {
+        psMemId id = psMemGetId();
+        psU32 c = 128;
+        psU32 r = 256;
+
+        psImage* img = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* imgRow = img->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                imgRow[col] = (psF32)(row+col);
+            }
+        }
+        psImage* img2 = psImageAlloc(c,r,PS_TYPE_F32);
+        for (unsigned row=0;row<r;row++)
+        {
+            psF32* img2Row = img2->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                img2Row[col] = 0.0f;
+            }
+        }
+
+        psImage* img3 = psImageCopy(img2,img,PS_TYPE_F32);
+        // Verify the returned psImage structure pointer is equal to the input parameter output.
+        ok(img2 == img3, "psImageCopy(): recycled input image");
+
+        // Verify the returned psImage structure is the same type as the input image structure
+        // if the specified output argument is NULL.
+        psImage* img4 = psImageCopy(NULL,img,PS_TYPE_F32);
+        ok(img4 != NULL, "psImageCopy() returned non-NULL with NULL output argument");
+        ok(img4->type.type == img->type.type, "psImageCopy() set the correct image type");
+        bool errorFlag = false;
+        for (psU32 row=0;row<r;row++)
+        {
+            psF32* imgInRow = img->data.F32[row];
+            psF32* imgOutRow = img4->data.F32[row];
+            for (unsigned col=0;col<c;col++) {
+                if(imgInRow[col] != imgOutRow[col]) {
+                    diag("Input image not equal to output image at %d,%d", col, row);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageCopy() set data correctly");
+
+
+        // Verify the returned psImage structure member are equal to the values in
+        // the input psImage structure input.
+        #define testImageCopyType(IN,OUT) \
+        { \
+            bool errorFlag = false; \
+            img = psImageRecycle(img,c,r,PS_TYPE_##IN); \
+            for (unsigned row=0;row<r;row++) { \
+                ps##IN* imgRow = img->data.IN[row]; \
+                for (unsigned col=0;col<c;col++) { \
+                    imgRow[col] = (ps##IN)(row+col); \
+                } \
+            } \
+            img2 = psImageCopy(img2,img,PS_TYPE_##OUT); \
+            if(img2 != NULL) { \
+                ok(img2, "psImageCopy() returned non-NULL"); \
+                for (psU32 row=0;row<r;row++) { \
+                    ps##IN* imgRow = img->data.IN[row]; \
+                    ps##OUT* img2Row = img2->data.OUT[row]; \
+                    for (psU32 col=0;col<c;col++) { \
+                        if (abs(imgRow[col] - (ps##IN)(row+col)) > 0.5) { \
+                            diag("Input image was changed at %d,%d", col,row); \
+                            errorFlag = true; \
+                        } \
+                        if (abs(img2Row[col] - (ps##OUT)(imgRow[col])) > 0.5) { \
+                            diag("returned psImage values after copy don't match at %d,%d " \
+                                 "(%d vs %d)",\
+                                 col,row,img2Row[col], (ps##OUT)(imgRow[col])); \
+                            errorFlag = true; \
+                        } \
+                    } \
+                } \
+                ok(!errorFlag, "psImageCopy() set image data correctly"); \
+            } else {\
+                ok(img2, "psImageCopy() returned non-NULL"); \
+            } \
+        }
+
+        #define testImageCopyTypes(IN) \
+        testImageCopyType(IN,F32);\
+        testImageCopyType(IN,F64); \
+        testImageCopyType(IN,U8); \
+        testImageCopyType(IN,U16); \
+        testImageCopyType(IN,U32); \
+        testImageCopyType(IN,S8);\
+        testImageCopyType(IN,S16);\
+        testImageCopyType(IN,S32);
+
+        testImageCopyTypes(U8);
+        testImageCopyTypes(U16);
+        testImageCopyTypes(U32);
+        testImageCopyTypes(S8);
+        testImageCopyTypes(S16);
+        testImageCopyTypes(S32);
+        testImageCopyTypes(F32);
+        testImageCopyTypes(F64);
+
+        // Verify the returned psImage structure pointer is null and program
+        // execution doesn't stop, if the input parameter input is null.
+        // An error should follow...
+        // XXX: Verify error
+        img3 = psImageCopy(NULL,NULL,PS_TYPE_F32);
+        ok(img3 == NULL, "psImageCopy() returned NULL when input image was NULL");
+
+        psFree(img);
+        psFree(img2);
+        psFree(img3);
+        psFree(img4);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    // psImageTrim()
+    // XXX: This should probably be broken into separate blocks
+    {
+        psMemId id = psMemGetId();
+        psS32 r = 200;
+        psS32 c = 300;
+        psS32 qtrR = r/4;
+        psS32 qtrC = c/4;
+        psS32 halfR = r/2;
+        psS32 halfC = c/2;
+        psRegion centerHalf = {qtrC,qtrC+halfC,qtrR,qtrR+halfR};
+
+        psImage* image = psImageAlloc(c,r,PS_TYPE_F32);
+        for (psS32 row = 0; row < image->numRows; row++)
+        {
+            for (psS32 col = 0; col < image->numCols; col++) {
+                image->data.F32[row][col] = (psF32)col + (psF32)row/1000.0f;
+            }
+        }
+
+        // invoke psImageTrim with non-NULL image, and a valid region
+        // x0,y0->x1,y1 (using only positive values). Verify that:
+        // a. the return psImage is the same as the input psImage.
+        // b. the size of the psImage is x1-x0 by y1-y0.
+        // c. the pixel values coorespond to the region [x0:x1-1,y0:y1-1].
+        psImage* image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        psImage* image2 = psImageTrim(image1,centerHalf);
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == halfC && image2->numRows == halfR,
+           "The resulting image size was %dx%d, should be %dx%d.",
+           image2->numCols, image2->numRows,
+           halfC, halfR);
+
+        bool errorFlag = false;
+        for (psS32 row = 0; row < image2->numRows; row++)
+        {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] - image->data.F32[row+qtrR][col+qtrC])
+                        > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+
+
+        // 2. invoke psImageTrim with non-NULL image and valid region where x1=0,
+        //    y1=0. Verify that:
+        //    a. the return psImage size is numCols-x0 by numRows-y0
+        //    b. the pixel values coorespond to the region
+        //       [x0:numCols-1,y0:numRows-1].
+        image1 = psImageCopy(image1,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1,psRegionSet(qtrC,0,qtrR,0));
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == image->numCols-qtrC && image2->numRows == image->numRows-qtrR,
+           "The resulting image size was %dx%d, it should be %dx%d.",
+           image2->numCols, image2->numRows,
+           image->numCols-qtrC, image->numRows-qtrR);
+
+        for (psS32 row = 0; row < image2->numRows; row++)
+        {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] -
+                          image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+
+        //  4. invoke psImageTrim with x1<0, y1<0. Verify:
+        //      a. the psImage size is (numCols+x1)-x0 by (numRows+y1)-y0.
+        //      b. the pixel values coorespond to the region
+        //         [x0:numCols+x1-1,y0:numRows+y1-1].
+        image1 = psImageCopy(image1,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1,psRegionSet(qtrC,-qtrC, qtrR,-qtrR));
+        ok(image1 == image2, "psImageTrim() Return value same as input value");
+        ok(image2->numCols == image->numCols-qtrC-qtrC && image2->numRows == image->numRows-qtrR-qtrR,
+           "The resulting image size was %dx%d, but should be %dx%d.",
+           image2->numCols, image2->numRows,
+           image->numCols-qtrC, image->numRows-qtrR);
+
+        for (psS32 row = 0; row < image2->numRows; row++)
+        {
+            for (psS32 col = 0; col < image2->numCols; col++) {
+                if (fabsf(image2->data.F32[row][col] -
+                          image->data.F32[row+qtrR][col+qtrC]) > FLT_EPSILON) {
+                    diag("The value at (%d,%d) was %g, but should be %g.",
+                         col,row,
+                         image2->data.F32[row][col],
+                         image->data.F32[row+qtrR][col+qtrC]);
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psImageTrim() set image data correctly");
+        psFree(image1);
+
+        //  6. invoke psImageTrim with image=NULL Verify:
+        //      a. execution does not cease.
+        //      b. return value is NULL
+        //      c. appropriate error is generated.
+        // An error should follow...
+        // XXX: Verify errors
+
+
+        image2 = psImageTrim(NULL, psRegionSet(qtrC,0,qtrR,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given a NULL input image");
+        psErr* err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_NULL,
+           "psImageTrim did generate an appropriate error for NULL input image.");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(-1,0,0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x0=-1.");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x0=-1.");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,-1,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given y0=-1.");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y0=-1");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,image->numCols+1,0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x1=numCols+1");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x1=numCols+1");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,0,image->numRows+1));
+        ok(image2 == NULL, "psImageTrim returned NULL given y1=numRows+1");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y1=numRows+1");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,0,0,(((psF32)image->numRows)*-1.0)));
+        ok(image2 == NULL, "psImageTrim returned NULL given y1=-numRows");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for y1=-numRows");
+        psFree(err);
+
+
+        image1 = psImageCopy(NULL,image,PS_TYPE_F32);
+        image2 = psImageTrim(image1, psRegionSet(0,(((psF32)image->numCols)*-1.0),0,0));
+        ok(image2 == NULL, "psImageTrim returned NULL given x1=-numCols");
+        err = psErrorLast();
+        ok(err != NULL && err->code == PS_ERR_BAD_PARAMETER_VALUE,
+           "psImageTrim did generate an appropriate error for x1=-numCols");
+
+
+        psFree(image);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /trunk/psLib/test/imageops/tap_psVectorFFT.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psVectorFFT.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psVectorFFT.c	(revision 11398)
@@ -0,0 +1,502 @@
+/** @file  tst_psVectorFFT.c
+*
+*  @brief Contains the tests for psFFT.[ch]
+*
+*
+*  @author Robert DeSonia, MHPCC
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2007-01-30 00:13:01 $
+*
+* XXX: Must add skip_start() macros
+*
+*
+*
+*
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+#define GENIMAGE(img,c,r,TYP, valueFcn) \
+img = psImageAlloc(c,r,PS_TYPE_##TYP); \
+for (psU32 row=0;row<r;row++) { \
+    ps##TYP* imgRow = img->data.TYP[row]; \
+    for (psU32 col=0;col<c;col++) { \
+        imgRow[col] = (ps##TYP)(valueFcn); \
+    } \
+}
+
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(58);
+
+    // testVectorFFT()
+    // 1. assign a vector to a sinisoid
+    // 2. perform forward transform
+    //  3. verify that the only significant component cooresponds to the freqency of the input in step 1.
+    //  4. perform reverse transform
+    //  5. compare to original (should be equal to within a reasonable error)
+    {
+        psMemId id = psMemGetId();
+        psVector *vec = NULL;
+        psVector* vec2 = NULL;
+        psVector* vec3 = NULL;
+        psVector* vec4 = NULL;
+
+        vec = psVectorAlloc(100, PS_TYPE_F32);
+        vec->n = vec->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.F32[ n ] = sinf( ( psF32 ) n / 50.0f * M_PI );
+        }
+
+        vec2 = psVectorFFT(NULL, vec, PS_FFT_FORWARD);
+        ok(vec2 != NULL, "psVectorFFT() returned non-NULL");
+        ok(vec2->type.type == PS_TYPE_C32, "psVectorFFT() returned the correct type");
+        ok(vec2->n == vec->n, "psVectorFFT() returned the correct size vector");
+
+        bool errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            if ( n == 1 || n == 99 ) {
+                if ( fabsf( cabsf( vec2->data.C32[ n ] ) - 50.0f ) > 0.1f ) {
+                    diag("FFT didn't work for vector (n=%d)", n );
+                    errorFlag = true;
+                }
+            } else {
+                if ( fabsf( cabsf( vec2->data.C32[ n ] ) ) > 0.1f ) {
+                    diag("FFT didn't work for vector (n=%d)", n );
+                    errorFlag = true;
+                }
+            }
+        }
+        ok(!errorFlag, "psVectorFFT() returned the correct data values");
+
+        vec3 = psVectorFFT( NULL, vec2, PS_FFT_REVERSE );
+        ok(vec3 != NULL, "psVectorFFT() returned non-NULL");
+        ok(vec3->type.type == PS_TYPE_C32, "psVectorFFT() returned the correct type");
+        ok(vec3->n != vec2->n, "psVectorFFT() returned the correct size vectors");
+
+        errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            psF32 val = sinf( ( psF32 ) n / 50.0f * M_PI );
+            psF32 vecVal = crealf( vec3->data.C32[ n ] ) / 100;
+            if ( fabsf( vecVal - val ) > 0.1f ) {
+                diag("Reverse FFT didn't give me the original vector back (n=%d) (%.2f vs %.2f)",
+                     n, vecVal, val );
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorFFT() returned the correct data values");
+
+        // Perform reverse transform with real flag set
+        vec4 = psVectorFFT(NULL,vec2, (PS_FFT_REVERSE | PS_FFT_REAL_RESULT));
+        ok(vec4->type.type == PS_TYPE_F32, "FFT with real result did produce real values");
+
+        // Perform vector FFT with incorrect direction flags
+        // Following should generate an error message
+        // XXX: Verify error
+        ok(psVectorFFT(NULL,vec2,(psFFTFlags)0) == NULL, "psVectorFFT() returned NULL with incorrect direction");
+        psFree(vec);
+        psFree(vec2);
+        psFree(vec3);
+        psFree(vec4);
+
+        // Perform vector FFT with null input
+        ok(psVectorFFT(NULL,NULL,PS_FFT_FORWARD) == NULL, "psVectorFFT() returned NULL with null input vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testVectorRealImaginary()
+    // 1. create a C32 complex vector with distinctly different real and imaginary parts.
+    // 2. call psVectorReal and psVectorImaginary
+    // 3. compare results to the real/imaginary components of input
+    {
+        psMemId id = psMemGetId();
+        psVector * vec = NULL;
+        psVector* vec2 = NULL;
+        psVector* vec3 = NULL;
+        psVector* vec4 = NULL;
+        psVector* vec5 = NULL;
+        psVector* vec6 = NULL;
+        psVector* vec7 = NULL;
+        psVector* vec8 = NULL;
+        psVector* vec9 = NULL;
+        psVector* vec10 = NULL;
+        psVector* vec11 = NULL;
+
+        vec = psVectorAlloc( 100, PS_TYPE_C32 );
+        vec8 = psVectorAlloc( 100, PS_TYPE_C64 );
+        vec10 = psVectorAlloc( 100, PS_TYPE_C64 );
+        vec->n = vec->nalloc;
+        vec8->n = vec8->nalloc;
+        vec10->n = vec10->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.C32[ n ] = n + I * ( n * 2 );
+            vec8->data.C64[n] = n + I * ( n * 2 );
+            vec10->data.C64[n] = n + I * ( n * 2 );
+        }
+        vec4 = psVectorAlloc( 100, PS_TYPE_F32);
+        vec4->n = vec4->nalloc;
+        vec6 = psVectorAlloc( 100, PS_TYPE_F32);
+        vec6->n = vec6->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec4->data.F32[n] = n;
+            vec6->data.F32[n] = n;
+        }
+
+        vec2 = psVectorReal( vec2, vec );
+        ok(vec2 != NULL, "psVectorReal() returned non-NULL");
+        ok(vec2->type.type == PS_TYPE_F32, "psVectorReal() returned the correct type");
+
+        // Following should generate a warning
+        // XXX: Verify warning
+        vec5 = psVectorReal(vec5, vec4);
+        ok(vec5 != NULL, "psVectorReal() returned non-NULL");
+        ok(vec5->type.type == PS_TYPE_F32, "psVectorReal() returned the correct type");
+
+        vec9 = psVectorReal(vec9,vec8);
+        ok(vec9 != NULL, "psVectorReal() returned non-NULL");
+        ok(vec9->type.type == PS_TYPE_F64, "psVectorReal() returned the correct type");
+
+        // Following should generate a warning
+        // XXX: Verify warning
+        vec3 = psVectorImaginary( vec3, vec );
+        ok(vec3 != NULL, "psVectorImaginary() returned non-NULL");
+        ok(vec3->type.type == PS_TYPE_F32, "psVectorImaginary() returned the correct type");
+
+        vec7 = psVectorImaginary(vec7, vec6);
+        ok(vec7 != NULL, "psVectorImaginary() returned non-NULL");
+        ok(vec7->type.type == PS_TYPE_F32, "psVectorImaginary() returned the correct type");
+
+        vec11 = psVectorImaginary(vec11, vec10);
+        ok(vec11 != NULL, "psVectorImaginary() returned non-NULL");
+        ok(vec11->type.type == PS_TYPE_F64, "psVectorImaginary() returned the correct type");
+
+
+        // 3. compare results to the real/imaginary components of input
+        bool errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            psF32 r = n;
+            psF32 i = ( n * 2 );
+            psF64 rr = n;
+            psF64 ii = ( n * 2 );
+            if ( fabsf( vec2->data.F32[ n ] - r ) > FLT_EPSILON ) {
+                diag("psVectorReal didn't return the real portion at n=%d", n);
+                errorFlag = true;
+            }
+            if ( fabsf( vec3->data.F32[ n ] - i ) > FLT_EPSILON ) {
+                diag("psVectorImaginary didn't return the real portion at n=%d", n);
+                errorFlag = true;
+            }
+            if ( fabsf( vec5->data.F32[n] - r) > FLT_EPSILON) {
+                diag("psVectorReal didn't return the real portion at n=%d",n);
+                errorFlag = true;
+            }
+            if ( fabsf( vec7->data.F32[n] - 0) > FLT_EPSILON) {
+                diag("psVectorImaginary did not return the imaginary portion at n=%d",n);
+                errorFlag = true;
+            }
+            if ( fabsf(vec9->data.F64[n] - rr) > FLT_EPSILON ) {
+                diag("psVectorReal did not return the real portion at n=%d",n);
+                errorFlag = true;
+            }
+            if ( fabsf(vec11->data.F64[n] - ii) > FLT_EPSILON) {
+                diag("psVectorImaginary did not return the imaginary portion at n=%d",n);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorImaginary() returned the correct data values");
+
+        psFree( vec );
+        psFree( vec2 );
+        psFree( vec3 );
+        psFree( vec4 );
+        psFree( vec5 );
+        psFree( vec6 );
+        psFree( vec7 );
+        psFree( vec8 );
+        psFree( vec9 );
+        psFree( vec10 );
+        psFree( vec11 );
+
+        // Perform vector Real with null input
+        ok(psVectorReal(NULL,NULL) == NULL, "psVectorReal returned NULL with NULL input");
+        ok(psVectorImaginary(NULL,NULL) == NULL, "psVectorImaginary returned NULL with NULL input");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testVectorComplex()
+    // 1. create two unique psF32 vectors of the same size
+    // 2. call psVectorComplex
+    // 3. verify that the result is a psC32
+    // 4. call psVectorReal and psVectorImaginary on step 2 results
+    // 5. compare step 4 results to input.
+    // 6. create a psF32 and a psF64 vector of the same size
+    // 7. call psVectorComplex
+    // 8. verify that an appropriate error occurred.
+    // 9. create two psf32 vectors of different sizes
+    // 10. call psVectorComplex
+    // 11. verify thet an appropriate error occurred.
+    {
+        psMemId id = psMemGetId();
+        psVector * vec = NULL;
+        psVector* vec2 = NULL;
+        psVector* vec3 = NULL;
+        psVector* vec4 = NULL;
+        psVector* vec5 = NULL;
+        psVector* vec6 = NULL;
+
+        // 1. create two unique psF32 vectors of the same size
+        vec = psVectorAlloc( 100, PS_TYPE_F32 );
+        vec2 = psVectorAlloc( 100, PS_TYPE_F32 );
+        vec4 = psVectorAlloc( 100, PS_TYPE_F64 );
+        vec5 = psVectorAlloc( 100, PS_TYPE_F64 );
+        vec->n = vec->nalloc;
+        vec2->n = vec2->nalloc;
+        vec4->n = vec4->nalloc;
+        vec5->n = vec5->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.F32[ n ] = n;
+            vec2->data.F32[ n ] = ( n * 2 );
+            vec4->data.F64[ n ] = n;
+            vec5->data.F64[ n ] = ( n * 2 );
+        }
+
+        vec3 = psVectorComplex( vec3, vec, vec2 );
+        ok(vec3 != NULL, "psVectorComplex() returned non-NULL");
+        ok(vec3->type.type == PS_TYPE_C32, "psVectorComplex() returned the correct type");
+        bool errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            if ( fabsf( crealf( vec3->data.C32[ n ] ) - n ) > FLT_EPSILON ||
+                    fabsf( cimagf( vec3->data.C32[ n ] ) - ( n * 2 ) ) > FLT_EPSILON ) {
+                diag("psVectorComplex result is incorrect (n=%d, %.2f+%.2fi)",
+                     n, crealf( vec3->data.C32[ n ] ), cimagf( vec3->data.C32[ n ] ) );
+                errorFlag = true;
+            };
+        }
+        ok(!errorFlag, "psVectorComplex() returned the correct data values");
+
+
+        vec2 = psVectorRecycle( vec2, 100, PS_TYPE_F64 );
+        // Following should be an error (type mismatch)
+        // Verify error
+        vec3 = psVectorComplex( vec3, vec, vec2 );
+        ok(vec3 == NULL, "psVectorComplex() returned NULL when input types mismatched." );
+
+        vec2 = psVectorRecycle( vec2, 200, PS_TYPE_F32 );
+        vec3 = psVectorComplex( vec3, vec, vec2 );
+        ok(vec3->n == 100, "psVectorComplex() returned the correct size vector");
+
+        // Verify the function works with psF64 type
+        vec6 = psVectorComplex(vec6, vec4, vec5);
+        ok(vec6->type.type == PS_TYPE_C64, "psVectorComplex() returned the correct type (C64)");
+
+        // Verify error message generated with input of incorrect type
+        // Following should generate an error message
+        vec4->type.type = PS_TYPE_S8;
+        vec5->type.type = PS_TYPE_S8;
+        vec6 = psVectorComplex(vec6, vec4, vec5);
+        ok(vec6 == NULL, "psVectorComplex() returned NULL for incorrect type");
+        vec4->type.type = PS_TYPE_F64;
+        vec5->type.type = PS_TYPE_F64;
+        psFree(vec);
+        psFree(vec2);
+        psFree(vec3);
+        psFree(vec4);
+        psFree(vec5);
+
+        // Perform vector complex with null input
+        ok(psVectorComplex(NULL,NULL,NULL) == NULL, "psVectorComplex() returned NULL with null input vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testVectorConjugate()
+    // 1. create a psC32 with unique real and imaginary values.
+    // 2. call psVectorConjugate
+    // 3. verify result is psC32
+    // 4. verify each value is conjugate of input (a+bi -> a-bi)
+    {
+        psMemId id = psMemGetId();
+        psVector * vec = NULL;
+        psVector* vec2 = NULL;
+
+        vec = psVectorAlloc( 100, PS_TYPE_C32 );
+        vec->n = vec->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.C32[ n ] = n + I * ( n * 2 );
+        }
+
+        vec2 = psVectorConjugate(vec2, vec);
+        ok(vec2 != NULL, "psVectorConjugate() returned non-NULL");
+        ok(vec2->type.type == PS_TYPE_C32, "psVectorConjugate() returned the correct type");
+
+        bool errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            if ( fabsf( crealf( vec->data.C32[ n ] ) - crealf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ||
+                    fabsf( cimagf( vec->data.C32[ n ] ) + cimagf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ) {
+                diag("psVectorConjugate result is incorrect (n=%d, %.2f+%.2fi)",
+                     n, crealf( vec2->data.C32[ n ] ), cimagf( vec2->data.C32[ n ] ) );
+                errorFlag = true;
+            };
+        }
+        ok(!errorFlag, "psVectorConjugate() returned the correct data values");
+        psFree(vec);
+
+        // Perform conjugate for non-complex number
+        vec = psVectorAlloc( 100, PS_TYPE_F32 );
+        vec->n = vec->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.F32[ n ] = n;
+        }
+        // Following should generate a warning message
+        // XXX: verify warning
+        vec2 = psVectorConjugate(vec2,vec);
+        ok(vec2->type.type == PS_TYPE_F32, "psVectorConjugate did return a F32 vector");
+
+        errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            if( vec->data.F32[n] != vec2->data.F32[n] ) {
+                diag("psVectorConjugate result is incorrect (n=%d)",n);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorConjugate() returned the correct data values");
+        psFree(vec);
+
+        // Perform vector conjugate with C64 type
+        vec = psVectorAlloc( 100, PS_TYPE_C64 );
+        vec->n = vec->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.C64[n] = n + I * ( n * 2 );
+        }
+        vec2 = psVectorConjugate(vec2,vec);
+        ok(vec2 != NULL, "psVectorConjugate() returned non-NULL");
+        ok(vec2->type.type == PS_TYPE_C64, "psVectorConjugate() returned the correct type");
+        errorFlag = false;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            if ( fabsf( crealf(vec->data.C64[n]) - crealf(vec2->data.C64[n])) > FLT_EPSILON ||
+                    fabsf( cimagf(vec->data.C64[n]) + cimagf(vec2->data.C64[n])) > FLT_EPSILON ) {
+                diag("psVectorConjugate result is incorrect (n=%d)",n);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorConjugate() returned the correct data values");
+        psFree(vec);
+
+        // Perform vector conjugate with null input (vec2 should be freed too)
+        ok(psVectorConjugate(vec2,NULL) == NULL, "psVectorConjugate() returned NULL with null input vector");
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testVectorPowerSpectrum()
+    // 1. create a psC32 vector with unique real and imaginary components
+    // 2. call psVectorPowerSpectrum
+    // 3. verify result is psF32
+    // 4. verify the values are the square of the absolute values of the original
+    {
+        psMemId id = psMemGetId();
+        psVector * vec = NULL;
+        psVector* vec2 = NULL;
+        psVector* vec3 = NULL;
+        psVector* vec4 = NULL;
+        psF32 val;
+        psF64 val1;
+
+        vec = psVectorAlloc( 100, PS_TYPE_C32 );
+        vec->n = vec->nalloc;
+        vec3 = psVectorAlloc(100,PS_TYPE_C64);
+        vec3->n = vec3->nalloc;
+        for ( psU32 n = 0; n < 100; n++ )
+        {
+            vec->data.C32[ n ] = n + I * sinf( ( ( psF32 ) n ) / 50.f * M_PI );
+            vec3->data.C64[ n ] = n + I * sinf( ( ( psF64 ) n ) / 50.f * M_PI );
+        }
+
+        vec2 = psVectorPowerSpectrum(vec2, vec);
+        ok(vec2 != NULL, "psVectorPowerSpectrum() returned non-NULL");
+        vec4 = psVectorPowerSpectrum(vec4, vec3);
+        ok(vec4 != NULL, "psVectorPowerSpectrum() returned non-NULL");
+        // XXX: These next two tests fail
+        ok(vec2->type.type != PS_TYPE_F32, "psVectorPowerSpectrum() returned the correct type");
+        ok(vec4->type.type != PS_TYPE_F64, "psVectorPowerSpectrum() returned the correct type");
+
+        val = cabsf( vec->data.C32[ 0 ] ) * cabsf( vec->data.C32[ 0 ] ) / 100 / 100;
+        val1= cabsf( vec3->data.C64[0] ) * cabsf(vec3->data.C64[0])/100/100;
+        ok(fabsf(vec2->data.F32[ 0 ] - val ) <= FLT_EPSILON,
+           "psVectorPowerSpectrum result is correct (n=0, %.2f %.2f)",
+           vec2->data.F32[ 0 ], val );
+        ok(fabsf( vec4->data.C64[0] - val1 ) <= FLT_EPSILON,
+           "psVectorPowerSpectrum result is correct (n=0)");
+
+        bool errorFlag = false;
+        for ( psU32 n = 1; n < 50; n++ )
+        {
+            val = ( cabsf( vec->data.C32[ n ] ) * cabsf( vec->data.C32[ n ] ) +
+                    cabsf( vec->data.C32[ 100 - n ] ) * cabsf( vec->data.C32[ 100 - n ] ) ) / 100 / 100;
+            val1 = (cabsf(vec3->data.C64[n]) * cabsf(vec3->data.C64[n]) +
+                    cabsf(vec3->data.C64[100-n]) * cabsf(vec3->data.C64[100-n]))/100/100;
+            if ( fabsf( val - vec2->data.F32[ n ] ) > 10*FLT_EPSILON ) {
+                diag("psVectorPowerSpectrum result is incorrect (n=%d, %.2f %.2f)",
+                     n, vec2->data.F32[ n ], val );
+                errorFlag = true;
+            }
+            if (fabsf(val1 - vec4->data.F64[n]) > 10*FLT_EPSILON) {
+                diag("psVectorPowerSpectrum result is incorrect (n=%d, %.2f %.2f)",n,vec4->data.F64[n],val1);
+                errorFlag = true;
+            }
+        }
+        ok(!errorFlag, "psVectorPowerSpectrum() returned the correct data values");
+
+        val = cabsf( vec->data.C32[ 50 ] ) * cabsf( vec->data.C32[ 50 ] ) / 100 / 100;
+        ok(fabsf( vec2->data.F32[ 50 ] - val ) <= 10*FLT_EPSILON,
+           "psVectorPowerSpectrum result is correct (n=50, %.2f %.2f)",
+           vec2->data.F32[ 0 ], val );
+        psFree( vec );
+        psFree( vec2 );
+        psFree( vec3 );
+        psFree( vec4 );
+
+        // Perform vector power spectrum with non-complex number
+        vec = psVectorAlloc(100,PS_TYPE_F32);
+        vec->n = vec->nalloc;
+        for( psU32 n=0; n<100; n++)
+        {
+            vec->data.F32[n] = n;
+        }
+
+        // Following should generate an error message
+        // XXX: Verify error
+        ok(psVectorPowerSpectrum(NULL,vec) == NULL,
+           "psVectorPowerSpectrum() did return a NULL vector.");
+        // Perform vector power spectrum with null input
+        ok(psVectorPowerSpectrum(NULL,NULL) == NULL,
+           "psVectorPowerSpectrum() did return NULL with null input vector");
+
+        psFree(vec);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+}
Index: /trunk/psLib/test/imageops/tap_psXML.c
===================================================================
--- /trunk/psLib/test/imageops/tap_psXML.c	(revision 11398)
+++ /trunk/psLib/test/imageops/tap_psXML.c	(revision 11398)
@@ -0,0 +1,317 @@
+/** @file  tst_psXML.c
+*
+*  @brief Test driver for psXML functions
+*
+*  This test driver contains the following tests for psXML:
+*     Test 1 - Parse an XML file
+*     Test 2 - Parse an XML memory block
+*     Test 3 - Parse an XML file descriptor
+*     Test 4 - Convert an XML doc to Metadata
+*     Test 5 - Convert Metadata to an XML doc
+*     Test 6 - Write an XML doc to file
+*     Test 7 - Write an XML doc to memory block
+*     Test 8 - Write an XML doc to file descriptor
+*
+*  @author  Dave Robbins, MHPCC
+*
+* XXXX: This doesn't even compile
+* XXXX: There are no data tests, he simple prints data to STDOUT
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2007-01-30 00:13:01 $
+*
+*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include "tap.h"
+#include "pstap.h"
+
+//static void writeMetadata(psMetadata* metadata, char* indentStr);
+
+// XXX: What should SRCDIR be?
+#define SRCDIR
+const char testFile1[] = SRCDIR "/psTime.xml";
+const char testFile2[] = SRCDIR "/psTime2.xml";
+const char testFile3[] = SRCDIR "/psTime3.xml";
+const char testFile4[] = SRCDIR "/psTime4.xml";
+//static void printMetadata(psMetadata *in);
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces);
+static void printMetadata(psMetadata *metadata);
+static void printMetadataList(psList *metadataItemList, char* spaces);
+static void printMetadataTable(psHash *mdTable);
+
+static void printMetadata(psMetadata *metadata)
+{
+    printf("Contents of metadata list:\n");
+    printMetadataList(metadata->list, " ");
+    printf("\nContents of metadata table:\n");
+    printMetadataTable(metadata->hash);
+}
+
+static void printMetadataList(psList *metadataItemList, char* spaces)
+{
+    psMetadataItem *entryChild = NULL;
+
+    psListIterator* iter = psListIteratorAlloc(metadataItemList, PS_LIST_HEAD, true);
+
+    while ( (entryChild=psListGetAndIncrement(iter)) != NULL) {
+        printMetadataItem(entryChild, spaces);
+    }
+
+    psFree(iter);
+}
+
+static void printMetadataTable(psHash *mdTable)
+{
+    psS32 i;
+    psHashBucket* ptr = NULL;
+    for(i=0; i<mdTable->n; i++) {
+        ptr = mdTable->buckets[i];
+        while (ptr != NULL) {
+            printMetadataItem(ptr->data, " ");
+            ptr = ptr->next;
+        }
+    }
+}
+
+static void printMetadataItem(psMetadataItem *metadataItem, char *spaces)
+{
+    int i = 0;
+    printf("%sKey Name: %25s  ", spaces, metadataItem->name);
+    //    printf("Key mdType: %d  ", (int)metadataItem->type);
+    //    printf("Key mdType: 0x%08x  ", metadataItem->type);
+    //    if ( metadataItem->type == PS_DATA_S32 )
+    //        printf("Key mdType: S32  " );
+
+    switch (metadataItem->type) {
+    case PS_DATA_BOOL:
+        printf("Key Type:  BOOL     Key Value: %15d  ", metadataItem->data.B);
+        break;
+    case PS_DATA_S32:
+        printf("Key Type:  S32      Key Value: %15d  ", metadataItem->data.S32);
+        break;
+    case PS_DATA_F32:
+        printf("Key Type:  F32      Key Value: %15.3f  ", metadataItem->data.F32);
+        break;
+    case PS_DATA_F64:
+        printf("Key Type:  F64      Key Value: %15.3f  ", metadataItem->data.F64);
+        break;
+    case PS_DATA_METADATA:
+        printf("Key Type:  METADATA    ");
+        break;
+    default:
+        printf("Key type:  psPtr    ");
+    }
+    if ( !strncmp(metadataItem->name, "psLib.time.Vector.S32", 256) ) {
+        printf("Key Values:   ");
+        while ( (int)((psVector*)(metadataItem->data.V))->data.S32[i] != 0 ) {
+            printf("%d  ", (int)((psVector*)(metadataItem->data.V))->data.S32[i] );
+            i++;
+        }
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.time.tables.dir", 256) ) {
+        printf("Key Value:   ");
+        printf("%s", (char*)metadataItem->data.V );
+        printf("\n");
+    } else if ( !strncmp(metadataItem->name, "psLib.TIME.Magazine", 256) ) {
+        printf("Key Value:   ");
+        printf("%ld, ", (long)((psTime*)(metadataItem->data.V))->sec );
+        printf("%u, ", ((psTime*)(metadataItem->data.V))->nsec );
+        if( ((psTime*)(metadataItem->data.V))->leapsecond )
+            printf("TRUE  ");
+        else
+            printf("FALSE  ");
+        if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UTC )
+            printf("PS_TIME_UTC ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TAI )
+            printf("PS_TIME_TAI ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_UT1 )
+            printf("PS_TIME_UT1 ");
+        else if( ((psTime*)(metadataItem->data.V))->type == PS_TIME_TT )
+            printf("PS_TIME_TT ");
+        printf("\n");
+    } else
+        printf("Key Comment: %s\n", metadataItem->comment);
+
+    //    if(metadataItem->data.V && metadataItem->type==PS_META_MULTI) {
+    //    if(metadataItem->data.V) {
+    //        printMetadataList(metadataItem->data.V, "    ");
+    //    }
+}
+
+typedef xmlDocPtr psXMLDoc;
+psS32 main( psS32 argc, char* argv[] )
+{
+    psLogSetFormat("HLNM");
+    psLogSetLevel(PS_LOG_INFO);
+    plan_tests(24);
+
+    //Parses an XML file into memory.  Stores as a psXMLDoc//
+    // testXMLInput00
+    {
+        psMemId id = psMemGetId();
+        //psXMLParseFile should return a psXMLDoc* of testFile1//
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(newXML != NULL, "psXMLParseFile() returned non-NULL");
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+    //Parses an XML file from memory.  Stores as a psXMLDoc//
+    // testXMLInput01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        char buffer[2048];
+        ok(psXMLDocToMem(newXML, buffer), "psXMLDocToMem() returned non-NULL");
+        psXMLDoc *newDoc = NULL;
+        newDoc = psXMLParseMem(buffer, strlen(buffer) );
+        ok(newDoc != NULL, "psXMLParseMem() returned non-NULL");
+        psFree(newDoc);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Parses an XML file from a file descriptor.  Stores as a psXMLDoc//
+    // testXMLInput02
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(newXML != NULL, "psXMLParseFile () returned non-NULL");
+        int fd = creat("psTest5.xml", 0644);
+        ok(psXMLDocToFD(newXML, fd), "psXMLDocToFD() returned TRUE");
+
+        psXMLDoc *newDoc = NULL;
+        fd = open("psTest5.xml", O_RDWR, 0);
+        newDoc = psXMLParseFD(fd);
+        ok(newDoc != NULL, "psXMLParseFD () returned non-NULL");
+        close(fd);
+        psFree(newXML);
+        psFree(newDoc);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Converts an existing psXMLDoc into psMetadata//
+    // testXMLConvert00
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        if (metaData == NULL)
+        {
+            ok(false, "psXMLDocToMetadata() returned non-NULL");
+        } else
+        {
+            ok(true, "psXMLDocToMetadata() returned non-NULL");
+            printMetadata(metaData);
+        }
+        psFree(newXML);
+        psFree(metaData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // Converts existing psMetadata into a psXMLDoc//
+    // testXMLConvert01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        ok(metaData != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psXMLDoc *XML2 = NULL;
+        XML2 = psMetadataToXMLDoc(metaData);
+        ok(psXMLDocToFile(XML2, "psTest2.xml"), "psMetadataToXMLDoc() returned TRUE");
+        psFree(newXML);
+        psFree(XML2);
+        psFree(metaData);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to File//
+    // testXMLOutput00
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        ok(psXMLDocToFile(newXML, "psTest.xml"), "psXMLParseFile() returned TRUE");
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to Memory//
+    // testXMLOutput01
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        char buffer[2048];
+        FILE *file;
+        file = fopen("psTest3.xml", "w");
+        ok(psXMLDocToMem(newXML, buffer), "fopen() successful");
+        fprintf(file, "%s", buffer);
+        fclose(file);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    //Writes a psXMLDoc to a file descriptor//
+    // testXMLOutput02
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile1);
+        int fd = creat("psTest4.xml", 0666);
+        ok(!psXMLDocToFD(newXML, fd), "psXMLDocToFD() returned TRUE");
+        close(fd);
+        psFree(newXML);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+
+
+    // testXMLWrongInput
+    {
+        psMemId id = psMemGetId();
+        psXMLDoc *newXML = NULL;
+        newXML = psXMLParseFile(testFile2);
+        ok(newXML != NULL, "psXMLParseFile() returned non-NULL");
+        psMetadata *metaData = NULL;
+        metaData = psXMLDocToMetadata(newXML);
+        ok(metaData != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML);
+        psFree(metaData);
+        psXMLDoc *newXML2 = NULL;
+        psMetadata *metaData2 = NULL;
+        newXML2 = psXMLParseFile(testFile3);
+        ok(newXML2 != NULL, "psXMLParseFile() returned non-NULL");
+        metaData2 = psXMLDocToMetadata(newXML2);
+        ok(metaData2 != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML2);
+        psFree(metaData2);
+        psXMLDoc *newXML3 = NULL;
+        psMetadata *metaData3 = NULL;
+        newXML3 = psXMLParseFile(testFile4);
+        ok(newXML3 != NULL, "psXMLParseFile() returned non-NULL");
+        metaData3 = psXMLDocToMetadata(newXML3);
+        ok(metaData3 != NULL, "psXMLDocToMetadata() returned non-NULL");
+        psFree(newXML3);
+        psFree(metaData3);
+        ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
+    }
+    /* HERE
+    */
+}
