Index: trunk/psLib/test/fft/Makefile.am
===================================================================
--- trunk/psLib/test/fft/Makefile.am	(revision 8958)
+++ trunk/psLib/test/fft/Makefile.am	(revision 11439)
@@ -1,9 +1,17 @@
-AM_CPPFLAGS = $(SRCINC) -I$(top_srcdir)/test/tap/src $(PSLIB_CFLAGS)
+AM_CPPFLAGS = \
+    $(SRCINC) \
+    -I$(top_srcdir)/test/tap/src \
+    -I$(top_srcdir)/test/pstap/src \
+    $(PSLIB_CFLAGS)
+
 AM_LDFLAGS = \
-	$(top_builddir)/src/libpslib.la  \
-	$(top_builddir)/test/tap/src/libtap.la \
-	$(PSLIB_LIBS)
+    $(top_builddir)/src/libpslib.la  \
+    $(top_builddir)/test/tap/src/libtap.la \
+    $(top_builddir)/test/pstap/src/libpstap.la \
+    $(PSLIB_LIBS)
 
-TEST_PROGS =
+TEST_PROGS = \
+	tap_psImageFFT \
+	tap_psVectorFFT
 
 if BUILD_TESTS
Index: trunk/psLib/test/fft/tap_psImageFFT.c
===================================================================
--- trunk/psLib/test/fft/tap_psImageFFT.c	(revision 11439)
+++ trunk/psLib/test/fft/tap_psImageFFT.c	(revision 11439)
@@ -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 21:32:56 $
+ *
+ *  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/fft/tap_psVectorFFT.c
===================================================================
--- trunk/psLib/test/fft/tap_psVectorFFT.c	(revision 11439)
+++ trunk/psLib/test/fft/tap_psVectorFFT.c	(revision 11439)
@@ -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 21:32:56 $
+*
+* 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");
+    }
+}
