Changeset 12154
- Timestamp:
- Mar 1, 2007, 1:35:33 PM (19 years ago)
- Location:
- trunk/psLib/test/fft
- Files:
-
- 2 edited
-
tap_psImageFFT.c (modified) (1 diff)
-
tap_psVectorFFT.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/test/fft/tap_psImageFFT.c
r11685 r12154 1 /** @file tst_psImageFFT.c2 *3 * @brief Contains the tests for psFFT.[ch]4 *5 *6 * @author Robert DeSonia, MHPCC7 *8 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $9 * @date $Date: 2007-02-07 22:50:18 $10 *11 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii12 */13 1 #include <stdio.h> 14 #include < string.h>2 #include <math.h> 15 3 #include <pslib.h> 4 16 5 #include "tap.h" 17 6 #include "pstap.h" 18 7 19 #define GENIMAGE(img,c,r,TYP, valueFcn) \ 20 img = psImageAlloc(c,r,PS_TYPE_##TYP); \ 21 for (psU32 row=0;row<r;row++) { \ 22 ps##TYP* imgRow = img->data.TYP[row]; \ 23 for (psU32 col=0;col<c;col++) { \ 24 imgRow[col] = (ps##TYP)(valueFcn); \ 25 } \ 8 #define TOL 2.0e-6 // Tolerance for comparison 9 10 11 // Generate image with single high pixel 12 static psImage *generateImage(int numCols, int numRows) 13 { 14 psImage *image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 15 for (int y = 0; y < numRows; y++) { 16 for (int x = 0; x < numCols; x++) { 17 image->data.F32[y][x] = 1.2 * cos(2.0 * M_PI * x / numCols + M_PI / 4.0) + 18 3.4 * sin(2.0 * M_PI * y / numRows + M_PI); 19 } 20 } 21 return image; 26 22 } 27 23 28 psS32 main(psS32 argc, char* argv[]) 24 // FFT forward, then back --- do I get what I started with? 25 // A total of 6 tests here. 26 static void testFFT(int numCols, int numRows) 29 27 { 30 psLogSetFormat("HLNM"); 31 psLogSetLevel(PS_LOG_INFO); 32 plan_tests(68); 28 psMemId id = psMemGetId(); 33 29 34 // psImageFFT(void) 30 diag("Testing %dx%d", numCols, numRows); 31 psImage *old = generateImage(numCols, numRows); 32 psImage *fftReal = NULL, *fftImag = NULL; 33 bool result = psImageForwardFFT(&fftReal, &fftImag, old); 34 ok(result, "forward fft result"); 35 skip_start(!result || !fftReal || !fftImag, 3, "forward fft failed"); 36 ok(fftReal->type.type == PS_TYPE_F32 && fftImag->type.type == PS_TYPE_F32, "forward fft types"); 37 psImage *new = NULL; 38 result = psImageBackwardFFT(&new, fftReal, fftImag, old->numCols); 39 ok(result, "backward fft result"); 40 skip_start(!result || !new, 2, "backward fft failed"); 41 ok(new->type.type == PS_TYPE_F32, "backward fft type"); 42 float maxDev = 0.0; // Maximum deviation from expected 43 for (int y = 0; y < old->numRows; y++) { 44 for (int x = 0; x < old->numCols; x++) { 45 float dev = fabs(new->data.F32[y][x] / numCols / numRows - old->data.F32[y][x]); 46 if (dev > maxDev) { 47 maxDev = dev; 48 } 49 } 50 } 51 ok(maxDev < TOL, "maximum deviation: %f", maxDev); 52 psFree(new); 53 skip_end(); 54 skip_end(); 55 56 psFree(fftReal); 57 psFree(fftImag); 58 psFree(old); 59 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 60 61 return; 62 } 63 64 65 int main(int argc, char *argv[]) 66 { 67 plan_tests(8 + 6 * 5); 68 69 // Test with NULL real arg 35 70 { 36 71 psMemId id = psMemGetId(); 37 psImage* img = NULL; 38 psImage* img2 = NULL; 39 psImage* img3 = NULL; 40 psU32 m = 128; 41 psU32 n = 64; 42 psImage* img4 = NULL; 43 psImage* img5 = NULL; 44 45 // 1. assign a image to a radial sinisoid 46 // 2. perform forward transform 47 // 3. verify that the only significant component cooresponds to the freqency of the input in step 1. 48 // 4. perform reverse transform 49 // 5. compare to original (should be equal to within a reasonable error) 50 51 // 1. assign a image to a radial sinisoid 52 GENIMAGE(img,m,n,F32, sinf((32.0f-row)/32.0f*M_PI)+sinf((64.0f-col)/64.0f*M_PI)); 53 54 // 2. perform forward transform 55 img2 = psImageFFT(img2,img,PS_FFT_FORWARD); 56 ok(img2 != NULL, "psImageFFT() returned non-NULL"); 57 skip_start(img2 == NULL, 1, "Skipping tests because psImageFFT() returned NULL"); 58 ok(img2->type.type == PS_TYPE_C32, "FFT produced complex values"); 59 ok(img2->numCols == m && img2->numRows == n, "FFT produced proper size result (%dx%d vs. expected %dx%d).", 60 img2->numCols,img2->numRows,m,n); 61 62 // 3. verify that the only significant component cooresponds to the freqency of the input in step 1. 63 bool errorFlag = false; 64 for (psU32 row=0;row<n;row++) 65 { 66 psC32* img2Row = img2->data.C32[row]; 67 for (psU32 col=0;col<m;col++) { 68 psF32 mag = cabsf(img2Row[col])/m/n; 69 if (mag > 0.1f) { 70 // must be (0,1) or (0,n-1) or (1,0) or (m-1,0) 71 if (! (col == 0 && (row == 1 || row == n-1)) 72 && ! (row == 0 && (col==1 || col == m-1)) ) { 73 diag("Result incorrect at %d,%d (%.2f)",col,row,mag); 74 errorFlag = true; 75 } 76 } else { 77 if ( (col == 0 && (row == 1 || row == n-1)) 78 || (row == 0 && (col==1 || col == m-1)) ) { 79 diag("Result incorrect at %d,%d (%.2f)",col,row,mag); 80 errorFlag = true; 81 } 82 } 83 } 84 } 85 ok(!errorFlag, "FFT produced correct data values"); 86 87 88 89 // 4. perform reverse transform 90 img3 = psImageFFT(img3,img2,PS_FFT_REVERSE); 91 ok(img3 != NULL, "psImageFFT() returned non-NULL"); 92 skip_start(img3 == NULL, 1, "Skipping tests because psImageFFT() returned NULL"); 93 ok(img3->type.type == PS_TYPE_C32, "FFT produced complex values"); 94 95 ok(img3->numCols == m && img3->numRows == n, "FFT didt produce proper size result (%dx%d vs. expected %dx%d).", 96 img3->numCols,img3->numRows,m,n); 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 errorFlag = false; 114 for (psU32 row=0;row<n;row++) 115 { 116 psC32* img3Row = img3->data.C32[row]; 117 psF32* imgRow = img->data.F32[row]; 118 for (psU32 col=0;col<m;col++) { 119 psF32 pixel = creal(img3Row[col])/m/n; 120 if (fabsf(pixel-imgRow[col]) > 0.1) { 121 diag("Reverse FFT gave original image back (%d,%d %.2f vs %.2f)", 122 col,row,pixel,imgRow[col]); 123 errorFlag = true; 124 } 125 } 126 } 127 ok(!errorFlag, "FFT produced correct data values"); 128 ok(!errorFlag, "FFT produced correct data values"); 129 130 131 132 // 4. perform reverse transform to real result 133 img3 = psImageFFT(img3,img2,PS_FFT_REVERSE|PS_FFT_REAL_RESULT); 134 ok(img3 != NULL, "psImageFFT() returned non-NULL"); 135 skip_start(img3 == NULL, 1, "Skipping tests because psImageFFT() returned NULL"); 136 ok(img3->type.type == PS_TYPE_F32, "FFT asked to make real result"); 137 ok(img3->numCols == m && img3->numRows == n, "FFT produced proper size result (%dx%d vs. expected %dx%d).", 138 img3->numCols,img3->numRows,m,n); 139 140 errorFlag = false; 141 for (psU32 row=0;row<n;row++) 142 { 143 psF32* img3Row = img3->data.F32[row]; 144 psF32* imgRow = img->data.F32[row]; 145 for (psU32 col=0;col<m;col++) { 146 psF32 pixel = img3Row[col]/m/n; 147 if (fabsf(pixel-imgRow[col]) > 0.1) { 148 diag("Reverse FFT gave original image back (%d,%d %.2f vs %.2f)", 149 col,row,pixel,imgRow[col]); 150 errorFlag = true; 151 } 152 } 153 } 154 ok(!errorFlag, "FFT produced correct data values"); 155 ok(!errorFlag, "FFT produced correct data values"); 156 157 158 159 // check if error occurs if FORWARD and REVERSE are both given. 160 // Following should be an error 161 // XXX: werify error 162 ok(psImageFFT(NULL,img2,PS_FFT_REVERSE|PS_FFT_FORWARD) == NULL, 163 "PS_FFT_REVERSE|PS_FFT_FORWARD returned NULL"); 164 165 // Following should be an error 166 // XXX: werify error 167 ok(psImageFFT(NULL,img2,PS_FFT_FORWARD|PS_FFT_REAL_RESULT) == NULL, 168 "PS_FFT_FORWARD|PS_FFT_REAL_RESULT returned NULL"); 169 170 // Verify return null and program execution doesn't stop if input image is null 171 img4 = psImageFFT(NULL,NULL,PS_FFT_FORWARD); 172 ok(img4 == NULL, "psImageFFT should return null for a null input image"); 173 174 // Verify return null and program execution doesn't stop if input image is incorrect direction 175 // Following should generate error for incorrect direction 176 // XXX: werify error 177 GENIMAGE(img4,8,8,S8,row+col); 178 img5 = psImageFFT(NULL,img4,PS_FFT_REAL_RESULT); 179 ok(img5 == NULL, "psImageFFT should return null for an incorrect FFT direction"); 180 181 psFree(img4); 182 psFree(img); 183 psFree(img2); 184 psFree(img3); 185 skip_end(); 186 skip_end(); 187 skip_end(); 188 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 72 psImage *real = psImageAlloc(512, 512, PS_TYPE_F32); 73 psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32); 74 psImage *in = psImageAlloc(512, 512, PS_TYPE_F32); 75 bool rc = psImageForwardFFT(NULL, &imag, in); 76 ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL real image input"); 77 psFree(real); 78 psFree(imag); 79 psFree(in); 80 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 189 81 } 190 82 191 // 1. create a C64 complex vector with distinctly different real and imaginary parts. 192 // 2. call psImageReal and psImageImaginary 193 // 3. compare results to the real/imaginary components of input 83 // Test with NULL imag arg 194 84 { 195 85 psMemId id = psMemGetId(); 196 psImage* c64Img = NULL; 197 psImage* c64Img2 = NULL; 198 psImage* c64Img3 = NULL; 199 psU32 m = 128; 200 psU32 n = 64; 201 202 // XXX: What is I? 203 GENIMAGE(c64Img,m,n,C64, row + I * col); 204 c64Img2 = psImageReal(c64Img2,c64Img); 205 ok(c64Img2 != NULL, "psImageReal() returned non-NULL"); 206 ok(c64Img2->type.type == PS_TYPE_F64, "psImageReal() returned the correct type"); 207 c64Img3 = psImageImaginary(c64Img3,c64Img); 208 ok(c64Img3 != NULL, "psImageImaginary() returned non-NULL"); 209 ok(c64Img3->type.type == PS_TYPE_F64, "psImageImaginary() returned the correct type"); 210 211 bool errorFlag = false; 212 for (psU32 row=0;row<n;row++) 213 { 214 psF64* img2Row = c64Img2->data.F64[row]; 215 psF64* img3Row = c64Img3->data.F64[row]; 216 for (psU32 col=0;col<m;col++) { 217 if (fabsf(img2Row[col] - row) > FLT_EPSILON) { 218 diag("psImageReal didn't return the real portion at n=%d", n); 219 errorFlag = true; 220 } 221 if (fabsf(img3Row[col] - col) > FLT_EPSILON) { 222 diag("psImageImaginary didn't return the imag portion at n=%d", n); 223 errorFlag = true; 224 } 225 } 226 } 227 ok(!errorFlag, "psImageReal() and psImageImaginary() returned the correct data"); 228 psFree(c64Img); 229 psFree(c64Img2); 230 psFree(c64Img3); 231 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 86 psImage *real = psImageAlloc(512, 512, PS_TYPE_F32); 87 psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32); 88 psImage *in = psImageAlloc(512, 512, PS_TYPE_F32); 89 bool rc = psImageForwardFFT(&real, NULL, in); 90 ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL imaginary image input"); 91 psFree(real); 92 psFree(imag); 93 psFree(in); 94 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 232 95 } 233 96 234 235 97 // Test with NULL input arg 236 98 { 237 99 psMemId id = psMemGetId(); 238 psImage* ncImg = NULL; 239 psImage* ncImg2 = NULL; 240 psImage* ncImg3 = NULL; 241 psU32 m = 128; 242 psU32 n = 64; 243 244 GENIMAGE(ncImg,m,n,F32,row+col); 245 ncImg2 = psImageReal(ncImg2,ncImg); 246 ncImg3 = psImageImaginary(ncImg3,ncImg); 247 ok(ncImg2 != NULL, "psImageReal() returned non-NULL"); 248 ok(ncImg2->type.type == PS_TYPE_F32, "psImageReal() returned the correct type"); 249 ok(ncImg3 != NULL, "psImageImaginary() returned non-NULL"); 250 ok(ncImg3->type.type == PS_TYPE_F32, "psImageImaginary() returned the correct type"); 251 252 bool errorFlag = false; 253 for(psU32 row=0; row<n; row++) 254 { 255 psF32* ncImg2Row = ncImg2->data.F32[row]; 256 psF32* ncImg3Row = ncImg3->data.F32[row]; 257 for(psU32 col=0; col<m; col++) { 258 if(fabsf(ncImg2Row[col] - (row+col)) > FLT_EPSILON) { 259 diag("psImageReal didn't return the real portion"); 260 errorFlag = true; 261 } 262 if(fabsf(ncImg3Row[col] - 0) > FLT_EPSILON) { 263 diag("psImageImaginary didn't return the imaginary portion"); 264 errorFlag = true; 265 } 266 } 267 } 268 ok(!errorFlag, "psImageReal() and psImageImaginary() returned the correct data"); 269 psFree(ncImg); 270 psFree(ncImg2); 271 psFree(ncImg3); 272 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 100 psImage *real = psImageAlloc(512, 512, PS_TYPE_F32); 101 psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32); 102 psImage *in = psImageAlloc(512, 512, PS_TYPE_F32); 103 bool rc = psImageForwardFFT(&real, &imag, NULL); 104 ok(rc == false, "psImageForwardFFT() returned FALSE with a NULL real image input"); 105 psFree(real); 106 psFree(imag); 107 psFree(in); 108 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 273 109 } 274 110 275 276 277 // Perform psImageReal with null input 111 // Test with incorrect input image type 278 112 { 279 113 psMemId id = psMemGetId(); 280 ok(psImageReal(NULL,NULL) == NULL, "psImageReal() returned NULL with NULL inputs"); 281 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 114 psImage *real = psImageAlloc(512, 512, PS_TYPE_F32); 115 psImage *imag = psImageAlloc(512, 512, PS_TYPE_F32); 116 psImage *in = psImageAlloc(512, 512, PS_TYPE_F64); 117 bool rc = psImageForwardFFT(NULL, &imag, in); 118 ok(rc == false, "psImageForwardFFT() returned FALSE with incorrect input image type"); 119 psFree(real); 120 psFree(imag); 121 psFree(in); 122 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 282 123 } 283 124 284 285 // Perform psImageImaginary with null input 286 { 287 psMemId id = psMemGetId(); 288 ok(psImageImaginary(NULL,NULL) == NULL, "psImageImaginary() returned NULL with NULL inputs"); 289 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 290 } 291 292 293 // testImageComplex() 294 // 1. create two unique psF32 vectors of the same size 295 // 2. call psImageComplex 296 // 3. verify that the result is a psC32 297 // 4. use crealf and cimagf on step 2 results 298 // 5. compare step 4 results to input. 299 // 6. create a psF32 and a psF64 vector of the same size 300 // 7. call psImageComplex 301 // 8. verify that an appropriate error occurred. 302 // 9. create two psf32 vectors of different sizes 303 // 10. call psImageComplex 304 // 11. verify thet an appropriate error occurred. 305 { 306 psMemId id = psMemGetId(); 307 psImage* img = NULL; 308 psImage* img2 = NULL; 309 psImage* img3 = NULL; 310 psImage* c64Img = NULL; 311 psImage* c64Img2 = NULL; 312 psImage* c64Img3 = NULL; 313 psImage* pImg = NULL; 314 psImage* pImg2 = NULL; 315 psImage* pImg3 = NULL; 316 psU32 m = 128; 317 psU32 n = 64; 318 GENIMAGE(img,m,n,F32,row); 319 GENIMAGE(img2,m,n,F32,col); 320 GENIMAGE(c64Img,m,n,F64,row); 321 GENIMAGE(c64Img2,m,n,F64,col); 322 GENIMAGE(pImg,m,n,S16,row); 323 GENIMAGE(pImg2,m,n,S16,col); 324 img3 = psImageComplex(img3,img,img2); 325 ok(img3 != NULL, "psImageComplex() returned non-NULL"); 326 ok(img3->type.type == PS_TYPE_C32, "psImageComplex() returned the correct type"); 327 c64Img3 = psImageComplex(c64Img3,c64Img,c64Img2); 328 ok(c64Img3 != NULL, "psImageComplex() returned non-NULL"); 329 ok(c64Img3->type.type == PS_TYPE_C64, "psImageComplex() returned the correct type"); 330 bool errorFlag = false; 331 for (psU32 row=0;row<n;row++) 332 { 333 psC32* img3Row = img3->data.C32[row]; 334 psC64* c64Img3Row = c64Img3->data.C64[row]; 335 for (psU32 col=0;col<m;col++) { 336 if (fabsf(crealf(img3Row[col]) - row) > FLT_EPSILON || 337 fabsf(cimagf(img3Row[col]) - col) > FLT_EPSILON) { 338 diag("psImageComplex result is incorrect (%d,%d, %.2f+%.2fi)", 339 col,row,crealf(img3Row[col]),cimagf(img3Row[col])); 340 errorFlag = true; 341 } 342 if (fabsf(crealf(c64Img3Row[col]) - row) > FLT_EPSILON || 343 fabsf(cimagf(c64Img3Row[col]) - col) > FLT_EPSILON) { 344 diag("psImageComplex result is incorrect"); 345 errorFlag = true; 346 347 } 348 } 349 } 350 ok(!errorFlag, "psImageComplex() returned correct results"); 351 352 img2 = psImageRecycle(img2,m,n,PS_TYPE_F64); 353 354 // Following should be an error (type mismatch) 355 // Verify that an appropriate error occurred 356 img3 = psImageComplex(img3,img,img2); 357 ok(img3 == NULL, "psImageComplex() returned NULL when input types mismatched."); 358 359 // Following should be an error (size mismatch) 360 img2 = psImageRecycle(img2,m/2,n,PS_TYPE_F32); 361 img3 = psImageComplex(img3,img,img2); 362 ok(img3 == NULL, "psImageComplex() returned a NULL when input sizes mismatched"); 363 364 // Perform psImageComplex with incorrect type 365 // Following should generate an error message."); 366 pImg3 = psImageComplex(pImg3,pImg,pImg2); 367 ok(pImg3 == NULL, "psImageComplex returned NULL with incorrect type input"); 368 369 psFree(img); 370 psFree(img2); 371 psFree(img3); 372 psFree(c64Img); 373 psFree(c64Img2); 374 psFree(c64Img3); 375 psFree(pImg); 376 psFree(pImg2); 377 378 // Perform psImageComplex with null input 379 ok(psImageComplex(NULL,NULL,NULL) == NULL, "psImageComplex() returned NULL with null input"); 380 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 381 } 382 383 // 1. create a psC32 with unique real and imaginary values. 384 // 2. call psImageConjugate 385 // 3. verify result is psC32 386 // 4. verify each value is conjugate of input (a+bi -> a-bi) 387 // testImageConjugate() 388 { 389 psMemId id = psMemGetId(); 390 psImage* img = NULL; 391 psImage* img2 = NULL; 392 psImage* c64Img = NULL; 393 psImage* c64Img2 = NULL; 394 psImage* pImg = NULL; 395 psImage* pImg2 = NULL; 396 psU32 m = 128; 397 psU32 n = 64; 398 GENIMAGE(img,m,n,C32, row + I * col); 399 GENIMAGE(c64Img,m,n,C64,row + I*col); 400 GENIMAGE(pImg,m,n,F32,row+col); 401 402 403 img2 = psImageConjugate(img2,img); 404 ok(img2 != NULL, "psImageConjugate() returned non-NULL"); 405 c64Img2 = psImageConjugate(c64Img2,c64Img); 406 ok(c64Img2 != NULL, "psImageConjugate() returned non-NULL"); 407 pImg2 = psImageConjugate(pImg2,pImg); 408 ok(pImg2 != NULL, "psImageConjugate() returned non-NULL"); 409 410 ok(img2->type.type == PS_TYPE_C32, "psImageConjugate() returned the correct type"); 411 ok(c64Img2->type.type == PS_TYPE_C64, "psImageConjugate() returned the correct type"); 412 ok(pImg2->type.type == PS_TYPE_F32, "psImageConjugate() returned the correct type"); 413 414 bool errorFlag = false; 415 for (psU32 row=0;row<n;row++) 416 { 417 psC32* img2Row = img2->data.C32[row]; 418 psC64* c64Img2Row = c64Img2->data.C64[row]; 419 psF32* pImg2Row = pImg2->data.F32[row]; 420 for (psU32 col=0;col<m;col++) { 421 if (fabsf(crealf(img2Row[col]) - row) > FLT_EPSILON || 422 fabsf(cimagf(img2Row[col]) + col) > FLT_EPSILON) { 423 diag("psImageComplex result is incorrect (%d,%d, %.2f+%.2fi)", 424 col,row,crealf(img2Row[col]),cimagf(img2Row[col])); 425 errorFlag = true; 426 } 427 if (fabsf(crealf(c64Img2Row[col]) - row) > FLT_EPSILON || 428 fabsf(cimagf(c64Img2Row[col]) + col) > FLT_EPSILON) { 429 diag("psImageComplex result is incorrect"); 430 errorFlag = true; 431 } 432 if (fabsf(pImg2Row[col] - (row+col)) > FLT_EPSILON) { 433 diag("psImageComplex result is incorrect"); 434 errorFlag = true; 435 } 436 } 437 } 438 ok(!errorFlag, "psImageConjugate() generated the correct data values"); 439 psFree(img); 440 psFree(img2); 441 psFree(c64Img); 442 psFree(c64Img2); 443 psFree(pImg); 444 psFree(pImg2); 445 446 // Perform psImageConjugate with null input 447 ok(psImageConjugate(NULL,NULL) == NULL, "psImageConjugate() returned NULL with NULL input"); 448 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 449 } 450 451 // testImagePowerSpectrum() 452 // 1. create a psC32 vector with unique real and imaginary components 453 // 2. call psImagePowerSpectrum 454 // 3. verify result is psF32 455 // 4. verify the values are the square of the absolute values of the original 456 { 457 psMemId id = psMemGetId(); 458 psImage* img = NULL; 459 psImage* img2 = NULL; 460 psImage* c64Img = NULL; 461 psImage* c64Img2 = NULL; 462 psImage* pImg = NULL; 463 psU32 m = 128; 464 psU32 n = 64; 465 466 GENIMAGE(img,m,n,C32, row + I * col); 467 GENIMAGE(c64Img,m,n,C64,row+I*col); 468 GENIMAGE(pImg,m,n,F32,row+col); 469 470 img2 = psImagePowerSpectrum(img2,img); 471 c64Img2 = psImagePowerSpectrum(c64Img2, c64Img); 472 ok(img2 != NULL, "psImagePowerSpectrum() returned non-NULL"); 473 ok(c64Img2 != NULL, "psImagePowerSpectrum() returned non-NULL"); 474 ok(img2->type.type == PS_TYPE_F32, "psImagePowerSpectrum() returned the correct type"); 475 ok(c64Img2->type.type == PS_TYPE_F64, "psImagePowerSpectrum() returned the correct type"); 476 477 bool errorFlag = false; 478 for (psU32 row=0;row<n;row++) 479 { 480 psC32* imgRow = img->data.C32[row]; 481 psF32* img2Row = img2->data.F32[row]; 482 psC64* c64ImgRow = c64Img->data.C64[row]; 483 psF64* c64Img2Row = c64Img2->data.F64[row]; 484 for (psU32 col=0;col<m;col++) { 485 psF32 power = cabs(imgRow[col]); 486 psF64 power64 = cabs(c64ImgRow[col]); 487 power *= power/n/n/m/m; 488 power64 *= power64/n/n/m/m; 489 490 if (fabsf(img2Row[col] - power) > 2.0f*FLT_EPSILON) { 491 diag("psImagePowerSpectrum result is incorrect (%d,%d, %.2f vs %.2f)", 492 col,row,img2Row[col],power); 493 errorFlag = true; 494 } 495 if (fabsf(c64Img2Row[col] - power64) > 2.0f*FLT_EPSILON) { 496 diag("psImagePowerSpectrum result is incorrect"); 497 errorFlag = true; 498 } 499 } 500 } 501 ok(!errorFlag, "psImagePowerSPectrum() generated the correct data values"); 502 psFree(img); 503 psFree(img2); 504 psFree(c64Img); 505 psFree(c64Img2); 506 507 // Perform psImagePowerSpectrum with incorrect input 508 // Following should generate error message 509 // XXX: Verify error 510 ok(psImagePowerSpectrum(NULL,pImg) == NULL, "psImagePowerSpectrum() returned NULL with incorrect type"); 511 psFree(pImg); 512 513 // Perform psImagePowerSpectrum with NULL input 514 ok(psImagePowerSpectrum(NULL,NULL) == NULL, "psImagePowerSpectrum() returned NULL with NULL input"); 515 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 516 } 517 518 519 // testImageRealImaginary() 520 // 1. create a C32 complex image with distinctly different real and imaginary parts 521 // 2. call psImageReal and psImageImaginary 522 // 3. compare results to the real/imaginary components of input 523 // XXX: If we put this block above the previous 2 blocks, then we get memory errors 524 { 525 psMemId id = psMemGetId(); 526 psImage* img = NULL; 527 psImage* img3 = NULL; 528 psU32 m = 128; 529 psU32 n = 64; 530 GENIMAGE(img,m,n,C32, row + I * col); 531 psImage* img2 = psImageReal(NULL,img); 532 ok(img2 != NULL, "psImageReal returned non-NULL"); 533 skip_start(img2 == NULL, 4, "Skipping tests because psImageReal() returned NULL"); 534 ok(img2->type.type == PS_TYPE_F32, "psImageReal returned the correct type"); 535 img3 = psImageImaginary(img3,img); 536 ok(img3 != NULL, "psImageImaginary() returned non-NULL"); 537 skip_start(img3 == NULL, 2, "Skipping tests because psImageImaginary() returned NULL"); 538 ok(img3->type.type == PS_TYPE_F32, "psImageImaginary() returned the correct type"); 539 540 bool errorFlag = false; 541 for (psU32 row=0;row<n;row++) 542 { 543 psF32* img2Row = img2->data.F32[row]; 544 psF32* img3Row = img3->data.F32[row]; 545 for (psU32 col=0;col<m;col++) { 546 if (fabsf(img2Row[col] - row) > FLT_EPSILON) { 547 diag("psImageReal didn't return the real portion at n=%d", n); 548 errorFlag = true; 549 } 550 if (fabsf(img3Row[col] - col) > FLT_EPSILON) { 551 diag("psImageImaginary didn't return the imag portion at n=%d", n); 552 errorFlag = true; 553 } 554 } 555 } 556 ok(!errorFlag, "psImageReal(), psImageImaginary() returned the correct data"); 557 skip_end(); 558 skip_end(); 559 psFree(img); 560 psFree(img2); 561 psFree(img3); 562 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 563 } 564 565 125 testFFT(10, 10); // Real quick test 126 testFFT(10, 20); // Testing differing numCols, numRows 127 testFFT(20, 10); // Testing differing numCols, numRows 128 testFFT(611, 610); // Test something like an OTA cell 129 testFFT(2048, 4096); // Test something like a megacam chip 566 130 } -
trunk/psLib/test/fft/tap_psVectorFFT.c
r11692 r12154 1 /** @file tst_psVectorFFT.c2 *3 * @brief Contains the tests for psFFT.[ch]4 *5 *6 * @author Robert DeSonia, MHPCC7 *8 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $9 * @date $Date: 2007-02-08 01:37:33 $10 *11 * XXX: Must add skip_start() macros12 *13 *14 *15 *16 *17 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii18 */19 1 #include <stdio.h> 20 #include < string.h>2 #include <math.h> 21 3 #include <pslib.h> 4 22 5 #include "tap.h" 23 6 #include "pstap.h" 24 7 25 #define GENIMAGE(img,c,r,TYP, valueFcn) \ 26 img = psImageAlloc(c,r,PS_TYPE_##TYP); \ 27 for (psU32 row=0;row<r;row++) { \ 28 ps##TYP* imgRow = img->data.TYP[row]; \ 29 for (psU32 col=0;col<c;col++) { \ 30 imgRow[col] = (ps##TYP)(valueFcn); \ 31 } \ 8 #define TOL 2.5e-5 // Tolerance for comparison 9 10 11 // Generate image with single high pixel 12 static psVector *generateVector(long num) 13 { 14 psVector *vector = psVectorAlloc(num, PS_TYPE_F32); 15 for (long i = 0; i < num; i++) { 16 vector->data.F32[i] = 1.2 * cos(2.0 * M_PI * i / num + M_PI / 4.0) + 17 3.4 * sin(0.5 * 2.0 * M_PI * i / num + M_PI); 18 } 19 return vector; 32 20 } 33 21 34 psS32 main( psS32 argc, char* argv[] ) 22 // FFT forward, then back --- do I get what I started with? 23 // A total of 6 tests here. 24 static void testFFT(long num) 35 25 { 36 psLogSetFormat("HLNM"); 37 psLogSetLevel(PS_LOG_INFO); 38 plan_tests(58); 26 psMemId id = psMemGetId(); 39 27 40 // testVectorFFT() 41 // 1. assign a vector to a sinisoid 42 // 2. perform forward transform 43 // 3. verify that the only significant component cooresponds to the freqency of the input in step 1. 44 // 4. perform reverse transform 45 // 5. compare to original (should be equal to within a reasonable error) 28 diag("Testing %d", num); 29 psVector *old = generateVector(num); 30 psVector *fftReal = NULL, *fftImag = NULL; 31 bool result = psVectorForwardFFT(&fftReal, &fftImag, old); 32 ok(result, "forward fft result"); 33 skip_start(!result || !fftReal || !fftImag, 3, "forward fft failed"); 34 ok(fftReal->type.type == PS_TYPE_F32 && fftImag->type.type == PS_TYPE_F32, "forward fft types"); 35 psVector *new = NULL; 36 result = psVectorBackwardFFT(&new, fftReal, fftImag, old->n); 37 ok(result, "backward fft result"); 38 skip_start(!result || !new, 2, "backward fft failed"); 39 ok(new->type.type == PS_TYPE_F32, "backward fft type"); 40 float maxDev = 0.0; // Maximum deviation from expected 41 for (long i = 0; i < old->n; i++) { 42 float dev = fabs(new->data.F32[i] / num - old->data.F32[i]); 43 if (dev > maxDev) { 44 maxDev = dev; 45 } 46 } 47 ok(maxDev < TOL, "maximum deviation: %f", maxDev); 48 psFree(new); 49 skip_end(); 50 skip_end(); 51 52 psFree(fftReal); 53 psFree(fftImag); 54 psFree(old); 55 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 56 57 return; 58 } 59 60 61 int main(int argc, char *argv[]) 62 { 63 plan_tests(8 + 6 * 3); 64 65 // Test with NULL real arg 46 66 { 47 67 psMemId id = psMemGetId(); 48 psVector *vec = NULL; 49 psVector* vec2 = NULL; 50 psVector* vec3 = NULL; 51 psVector* vec4 = NULL; 52 53 vec = psVectorAlloc(100, PS_TYPE_F32); 54 vec->n = vec->nalloc; 55 for ( psU32 n = 0; n < 100; n++ ) 56 { 57 vec->data.F32[ n ] = sinf( ( psF32 ) n / 50.0f * M_PI ); 58 } 59 60 vec2 = psVectorFFT(NULL, vec, PS_FFT_FORWARD); 61 ok(vec2 != NULL, "psVectorFFT() returned non-NULL"); 62 ok(vec2->type.type == PS_TYPE_C32, "psVectorFFT() returned the correct type"); 63 ok(vec2->n == vec->n, "psVectorFFT() returned the correct size vector"); 64 65 bool errorFlag = false; 66 for ( psU32 n = 0; n < 100; n++ ) 67 { 68 if ( n == 1 || n == 99 ) { 69 if ( fabsf( cabsf( vec2->data.C32[ n ] ) - 50.0f ) > 0.1f ) { 70 diag("FFT didn't work for vector (n=%d)", n ); 71 errorFlag = true; 72 } 73 } else { 74 if ( fabsf( cabsf( vec2->data.C32[ n ] ) ) > 0.1f ) { 75 diag("FFT didn't work for vector (n=%d)", n ); 76 errorFlag = true; 77 } 78 } 79 } 80 ok(!errorFlag, "psVectorFFT() returned the correct data values"); 81 82 vec3 = psVectorFFT( NULL, vec2, PS_FFT_REVERSE ); 83 ok(vec3 != NULL, "psVectorFFT() returned non-NULL"); 84 ok(vec3->type.type == PS_TYPE_C32, "psVectorFFT() returned the correct type"); 85 ok(vec3->n == vec2->n, "psVectorFFT() returned the correct size vectors"); 86 87 errorFlag = false; 88 for ( psU32 n = 0; n < 100; n++ ) 89 { 90 psF32 val = sinf( ( psF32 ) n / 50.0f * M_PI ); 91 psF32 vecVal = crealf( vec3->data.C32[ n ] ) / 100; 92 if ( fabsf( vecVal - val ) > 0.1f ) { 93 diag("Reverse FFT didn't give me the original vector back (n=%d) (%.2f vs %.2f)", 94 n, vecVal, val ); 95 errorFlag = true; 96 } 97 } 98 ok(!errorFlag, "psVectorFFT() returned the correct data values"); 99 100 // Perform reverse transform with real flag set 101 vec4 = psVectorFFT(NULL,vec2, (PS_FFT_REVERSE | PS_FFT_REAL_RESULT)); 102 ok(vec4->type.type == PS_TYPE_F32, "FFT with real result did produce real values"); 103 104 // Perform vector FFT with incorrect direction flags 105 // Following should generate an error message 106 // XXX: Verify error 107 ok(psVectorFFT(NULL,vec2,(psFFTFlags)0) == NULL, "psVectorFFT() returned NULL with incorrect direction"); 108 psFree(vec); 109 psFree(vec2); 110 psFree(vec3); 111 psFree(vec4); 112 113 // Perform vector FFT with null input 114 ok(psVectorFFT(NULL,NULL,PS_FFT_FORWARD) == NULL, "psVectorFFT() returned NULL with null input vector"); 115 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 68 psVector *real = psVectorAlloc(512, PS_TYPE_F32);; 69 psVector *imag = psVectorAlloc(512, PS_TYPE_F32); 70 psVector *in = psVectorAlloc(512, PS_TYPE_F32); 71 bool rc = psVectorForwardFFT(NULL, &imag, in); 72 ok(rc == false, "psVectorForwardFFT() returned FALSE with a null real vector input"); 73 psFree(real); 74 psFree(imag); 75 psFree(in); 76 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 116 77 } 117 78 118 119 // testVectorRealImaginary() 120 // 1. create a C32 complex vector with distinctly different real and imaginary parts. 121 // 2. call psVectorReal and psVectorImaginary 122 // 3. compare results to the real/imaginary components of input 79 // Test with NULL imag arg 123 80 { 124 81 psMemId id = psMemGetId(); 125 psVector * vec = NULL; 126 psVector* vec2 = NULL; 127 psVector* vec3 = NULL; 128 psVector* vec4 = NULL; 129 psVector* vec5 = NULL; 130 psVector* vec6 = NULL; 131 psVector* vec7 = NULL; 132 psVector* vec8 = NULL; 133 psVector* vec9 = NULL; 134 psVector* vec10 = NULL; 135 psVector* vec11 = NULL; 136 137 vec = psVectorAlloc( 100, PS_TYPE_C32 ); 138 vec8 = psVectorAlloc( 100, PS_TYPE_C64 ); 139 vec10 = psVectorAlloc( 100, PS_TYPE_C64 ); 140 vec->n = vec->nalloc; 141 vec8->n = vec8->nalloc; 142 vec10->n = vec10->nalloc; 143 for ( psU32 n = 0; n < 100; n++ ) 144 { 145 vec->data.C32[ n ] = n + I * ( n * 2 ); 146 vec8->data.C64[n] = n + I * ( n * 2 ); 147 vec10->data.C64[n] = n + I * ( n * 2 ); 148 } 149 vec4 = psVectorAlloc( 100, PS_TYPE_F32); 150 vec4->n = vec4->nalloc; 151 vec6 = psVectorAlloc( 100, PS_TYPE_F32); 152 vec6->n = vec6->nalloc; 153 for ( psU32 n = 0; n < 100; n++ ) 154 { 155 vec4->data.F32[n] = n; 156 vec6->data.F32[n] = n; 157 } 158 159 vec2 = psVectorReal( vec2, vec ); 160 ok(vec2 != NULL, "psVectorReal() returned non-NULL"); 161 ok(vec2->type.type == PS_TYPE_F32, "psVectorReal() returned the correct type"); 162 163 // Following should generate a warning 164 // XXX: Verify warning 165 vec5 = psVectorReal(vec5, vec4); 166 ok(vec5 != NULL, "psVectorReal() returned non-NULL"); 167 ok(vec5->type.type == PS_TYPE_F32, "psVectorReal() returned the correct type"); 168 169 vec9 = psVectorReal(vec9,vec8); 170 ok(vec9 != NULL, "psVectorReal() returned non-NULL"); 171 ok(vec9->type.type == PS_TYPE_F64, "psVectorReal() returned the correct type"); 172 173 // Following should generate a warning 174 // XXX: Verify warning 175 vec3 = psVectorImaginary( vec3, vec ); 176 ok(vec3 != NULL, "psVectorImaginary() returned non-NULL"); 177 ok(vec3->type.type == PS_TYPE_F32, "psVectorImaginary() returned the correct type"); 178 179 vec7 = psVectorImaginary(vec7, vec6); 180 ok(vec7 != NULL, "psVectorImaginary() returned non-NULL"); 181 ok(vec7->type.type == PS_TYPE_F32, "psVectorImaginary() returned the correct type"); 182 183 vec11 = psVectorImaginary(vec11, vec10); 184 ok(vec11 != NULL, "psVectorImaginary() returned non-NULL"); 185 ok(vec11->type.type == PS_TYPE_F64, "psVectorImaginary() returned the correct type"); 186 187 188 // 3. compare results to the real/imaginary components of input 189 bool errorFlag = false; 190 for ( psU32 n = 0; n < 100; n++ ) 191 { 192 psF32 r = n; 193 psF32 i = ( n * 2 ); 194 psF64 rr = n; 195 psF64 ii = ( n * 2 ); 196 if ( fabsf( vec2->data.F32[ n ] - r ) > FLT_EPSILON ) { 197 diag("psVectorReal didn't return the real portion at n=%d", n); 198 errorFlag = true; 199 } 200 if ( fabsf( vec3->data.F32[ n ] - i ) > FLT_EPSILON ) { 201 diag("psVectorImaginary didn't return the real portion at n=%d", n); 202 errorFlag = true; 203 } 204 if ( fabsf( vec5->data.F32[n] - r) > FLT_EPSILON) { 205 diag("psVectorReal didn't return the real portion at n=%d",n); 206 errorFlag = true; 207 } 208 if ( fabsf( vec7->data.F32[n] - 0) > FLT_EPSILON) { 209 diag("psVectorImaginary did not return the imaginary portion at n=%d",n); 210 errorFlag = true; 211 } 212 if ( fabsf(vec9->data.F64[n] - rr) > FLT_EPSILON ) { 213 diag("psVectorReal did not return the real portion at n=%d",n); 214 errorFlag = true; 215 } 216 if ( fabsf(vec11->data.F64[n] - ii) > FLT_EPSILON) { 217 diag("psVectorImaginary did not return the imaginary portion at n=%d",n); 218 errorFlag = true; 219 } 220 } 221 ok(!errorFlag, "psVectorImaginary() returned the correct data values"); 222 223 psFree( vec ); 224 psFree( vec2 ); 225 psFree( vec3 ); 226 psFree( vec4 ); 227 psFree( vec5 ); 228 psFree( vec6 ); 229 psFree( vec7 ); 230 psFree( vec8 ); 231 psFree( vec9 ); 232 psFree( vec10 ); 233 psFree( vec11 ); 234 235 // Perform vector Real with null input 236 ok(psVectorReal(NULL,NULL) == NULL, "psVectorReal returned NULL with NULL input"); 237 ok(psVectorImaginary(NULL,NULL) == NULL, "psVectorImaginary returned NULL with NULL input"); 238 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 82 psVector *real = psVectorAlloc(512, PS_TYPE_F32);; 83 psVector *imag = psVectorAlloc(512, PS_TYPE_F32); 84 psVector *in = psVectorAlloc(512, PS_TYPE_F32); 85 bool rc = psVectorForwardFFT(&real, NULL, in); 86 ok(rc == false, "psVectorForwardFFT() returned FALSE with a null imag vector input"); 87 psFree(real); 88 psFree(imag); 89 psFree(in); 90 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 239 91 } 240 92 241 242 // testVectorComplex() 243 // 1. create two unique psF32 vectors of the same size 244 // 2. call psVectorComplex 245 // 3. verify that the result is a psC32 246 // 4. call psVectorReal and psVectorImaginary on step 2 results 247 // 5. compare step 4 results to input. 248 // 6. create a psF32 and a psF64 vector of the same size 249 // 7. call psVectorComplex 250 // 8. verify that an appropriate error occurred. 251 // 9. create two psf32 vectors of different sizes 252 // 10. call psVectorComplex 253 // 11. verify thet an appropriate error occurred. 93 // Test with NULL input arg 254 94 { 255 95 psMemId id = psMemGetId(); 256 psVector * vec = NULL; 257 psVector* vec2 = NULL; 258 psVector* vec3 = NULL; 259 psVector* vec4 = NULL; 260 psVector* vec5 = NULL; 261 psVector* vec6 = NULL; 262 263 // 1. create two unique psF32 vectors of the same size 264 vec = psVectorAlloc( 100, PS_TYPE_F32 ); 265 vec2 = psVectorAlloc( 100, PS_TYPE_F32 ); 266 vec4 = psVectorAlloc( 100, PS_TYPE_F64 ); 267 vec5 = psVectorAlloc( 100, PS_TYPE_F64 ); 268 vec->n = vec->nalloc; 269 vec2->n = vec2->nalloc; 270 vec4->n = vec4->nalloc; 271 vec5->n = vec5->nalloc; 272 for ( psU32 n = 0; n < 100; n++ ) 273 { 274 vec->data.F32[ n ] = n; 275 vec2->data.F32[ n ] = ( n * 2 ); 276 vec4->data.F64[ n ] = n; 277 vec5->data.F64[ n ] = ( n * 2 ); 278 } 279 280 vec3 = psVectorComplex( vec3, vec, vec2 ); 281 ok(vec3 != NULL, "psVectorComplex() returned non-NULL"); 282 ok(vec3->type.type == PS_TYPE_C32, "psVectorComplex() returned the correct type"); 283 bool errorFlag = false; 284 for ( psU32 n = 0; n < 100; n++ ) 285 { 286 if ( fabsf( crealf( vec3->data.C32[ n ] ) - n ) > FLT_EPSILON || 287 fabsf( cimagf( vec3->data.C32[ n ] ) - ( n * 2 ) ) > FLT_EPSILON ) { 288 diag("psVectorComplex result is incorrect (n=%d, %.2f+%.2fi)", 289 n, crealf( vec3->data.C32[ n ] ), cimagf( vec3->data.C32[ n ] ) ); 290 errorFlag = true; 291 }; 292 } 293 ok(!errorFlag, "psVectorComplex() returned the correct data values"); 294 295 296 vec2 = psVectorRecycle( vec2, 100, PS_TYPE_F64 ); 297 // Following should be an error (type mismatch) 298 // Verify error 299 vec3 = psVectorComplex( vec3, vec, vec2 ); 300 ok(vec3 == NULL, "psVectorComplex() returned NULL when input types mismatched." ); 301 302 vec2 = psVectorRecycle( vec2, 200, PS_TYPE_F32 ); 303 vec3 = psVectorComplex( vec3, vec, vec2 ); 304 ok(vec3->n == 100, "psVectorComplex() returned the correct size vector"); 305 306 // Verify the function works with psF64 type 307 vec6 = psVectorComplex(vec6, vec4, vec5); 308 ok(vec6->type.type == PS_TYPE_C64, "psVectorComplex() returned the correct type (C64)"); 309 310 // Verify error message generated with input of incorrect type 311 // Following should generate an error message 312 vec4->type.type = PS_TYPE_S8; 313 vec5->type.type = PS_TYPE_S8; 314 vec6 = psVectorComplex(vec6, vec4, vec5); 315 ok(vec6 == NULL, "psVectorComplex() returned NULL for incorrect type"); 316 vec4->type.type = PS_TYPE_F64; 317 vec5->type.type = PS_TYPE_F64; 318 psFree(vec); 319 psFree(vec2); 320 psFree(vec3); 321 psFree(vec4); 322 psFree(vec5); 323 324 // Perform vector complex with null input 325 ok(psVectorComplex(NULL,NULL,NULL) == NULL, "psVectorComplex() returned NULL with null input vector"); 326 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 96 psVector *real = psVectorAlloc(512, PS_TYPE_F32);; 97 psVector *imag = psVectorAlloc(512, PS_TYPE_F32); 98 psVector *in = psVectorAlloc(512, PS_TYPE_F32); 99 bool rc = psVectorForwardFFT(&real, &imag, NULL); 100 ok(rc == false, "psVectorForwardFFT() returned FALSE with a null input vector input"); 101 psFree(real); 102 psFree(imag); 103 psFree(in); 104 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 327 105 } 328 106 329 330 // testVectorConjugate() 331 // 1. create a psC32 with unique real and imaginary values. 332 // 2. call psVectorConjugate 333 // 3. verify result is psC32 334 // 4. verify each value is conjugate of input (a+bi -> a-bi) 107 // Test with incorrect type for input arg 335 108 { 336 109 psMemId id = psMemGetId(); 337 psVector * vec = NULL; 338 psVector* vec2 = NULL; 339 340 vec = psVectorAlloc( 100, PS_TYPE_C32 ); 341 vec->n = vec->nalloc; 342 for ( psU32 n = 0; n < 100; n++ ) 343 { 344 vec->data.C32[ n ] = n + I * ( n * 2 ); 345 } 346 347 vec2 = psVectorConjugate(vec2, vec); 348 ok(vec2 != NULL, "psVectorConjugate() returned non-NULL"); 349 ok(vec2->type.type == PS_TYPE_C32, "psVectorConjugate() returned the correct type"); 350 351 bool errorFlag = false; 352 for ( psU32 n = 0; n < 100; n++ ) 353 { 354 if ( fabsf( crealf( vec->data.C32[ n ] ) - crealf( vec2->data.C32[ n ] ) ) > FLT_EPSILON || 355 fabsf( cimagf( vec->data.C32[ n ] ) + cimagf( vec2->data.C32[ n ] ) ) > FLT_EPSILON ) { 356 diag("psVectorConjugate result is incorrect (n=%d, %.2f+%.2fi)", 357 n, crealf( vec2->data.C32[ n ] ), cimagf( vec2->data.C32[ n ] ) ); 358 errorFlag = true; 359 }; 360 } 361 ok(!errorFlag, "psVectorConjugate() returned the correct data values"); 362 psFree(vec); 363 364 // Perform conjugate for non-complex number 365 vec = psVectorAlloc( 100, PS_TYPE_F32 ); 366 vec->n = vec->nalloc; 367 for ( psU32 n = 0; n < 100; n++ ) 368 { 369 vec->data.F32[ n ] = n; 370 } 371 // Following should generate a warning message 372 // XXX: verify warning 373 vec2 = psVectorConjugate(vec2,vec); 374 ok(vec2->type.type == PS_TYPE_F32, "psVectorConjugate did return a F32 vector"); 375 376 errorFlag = false; 377 for ( psU32 n = 0; n < 100; n++ ) 378 { 379 if( vec->data.F32[n] != vec2->data.F32[n] ) { 380 diag("psVectorConjugate result is incorrect (n=%d)",n); 381 errorFlag = true; 382 } 383 } 384 ok(!errorFlag, "psVectorConjugate() returned the correct data values"); 385 psFree(vec); 386 387 // Perform vector conjugate with C64 type 388 vec = psVectorAlloc( 100, PS_TYPE_C64 ); 389 vec->n = vec->nalloc; 390 for ( psU32 n = 0; n < 100; n++ ) 391 { 392 vec->data.C64[n] = n + I * ( n * 2 ); 393 } 394 vec2 = psVectorConjugate(vec2,vec); 395 ok(vec2 != NULL, "psVectorConjugate() returned non-NULL"); 396 ok(vec2->type.type == PS_TYPE_C64, "psVectorConjugate() returned the correct type"); 397 errorFlag = false; 398 for ( psU32 n = 0; n < 100; n++ ) 399 { 400 if ( fabsf( crealf(vec->data.C64[n]) - crealf(vec2->data.C64[n])) > FLT_EPSILON || 401 fabsf( cimagf(vec->data.C64[n]) + cimagf(vec2->data.C64[n])) > FLT_EPSILON ) { 402 diag("psVectorConjugate result is incorrect (n=%d)",n); 403 errorFlag = true; 404 } 405 } 406 ok(!errorFlag, "psVectorConjugate() returned the correct data values"); 407 psFree(vec); 408 409 // Perform vector conjugate with null input (vec2 should be freed too) 410 ok(psVectorConjugate(vec2,NULL) == NULL, "psVectorConjugate() returned NULL with null input vector"); 411 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 110 psVector *real = psVectorAlloc(512, PS_TYPE_F32);; 111 psVector *imag = psVectorAlloc(512, PS_TYPE_F32); 112 psVector *in = psVectorAlloc(512, PS_TYPE_F64); 113 bool rc = psVectorForwardFFT(&real, &imag, in); 114 ok(rc == false, "psVectorForwardFFT() returned FALSE with a incorrect input vector type"); 115 psFree(real); 116 psFree(imag); 117 psFree(in); 118 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 412 119 } 413 120 414 415 // testVectorPowerSpectrum() 416 // 1. create a psC32 vector with unique real and imaginary components 417 // 2. call psVectorPowerSpectrum 418 // 3. verify result is psF32 419 // 4. verify the values are the square of the absolute values of the original 420 { 421 psMemId id = psMemGetId(); 422 psVector * vec = NULL; 423 psVector* vec2 = NULL; 424 psVector* vec3 = NULL; 425 psVector* vec4 = NULL; 426 psF32 val; 427 psF64 val1; 428 429 vec = psVectorAlloc( 100, PS_TYPE_C32 ); 430 vec->n = vec->nalloc; 431 vec3 = psVectorAlloc(100,PS_TYPE_C64); 432 vec3->n = vec3->nalloc; 433 for ( psU32 n = 0; n < 100; n++ ) 434 { 435 vec->data.C32[ n ] = n + I * sinf( ( ( psF32 ) n ) / 50.f * M_PI ); 436 vec3->data.C64[ n ] = n + I * sinf( ( ( psF64 ) n ) / 50.f * M_PI ); 437 } 438 439 vec2 = psVectorPowerSpectrum(vec2, vec); 440 ok(vec2 != NULL, "psVectorPowerSpectrum() returned non-NULL"); 441 vec4 = psVectorPowerSpectrum(vec4, vec3); 442 ok(vec4 != NULL, "psVectorPowerSpectrum() returned non-NULL"); 443 // XXX: These next two tests fail 444 ok(vec2->type.type == PS_TYPE_F32, "psVectorPowerSpectrum() returned the correct type"); 445 ok(vec4->type.type == PS_TYPE_F64, "psVectorPowerSpectrum() returned the correct type"); 446 447 val = cabsf( vec->data.C32[ 0 ] ) * cabsf( vec->data.C32[ 0 ] ) / 100 / 100; 448 val1= cabsf( vec3->data.C64[0] ) * cabsf(vec3->data.C64[0])/100/100; 449 ok(fabsf(vec2->data.F32[ 0 ] - val ) <= FLT_EPSILON, 450 "psVectorPowerSpectrum result is correct (n=0, %.2f %.2f)", 451 vec2->data.F32[ 0 ], val ); 452 ok(fabsf( vec4->data.C64[0] - val1 ) <= FLT_EPSILON, 453 "psVectorPowerSpectrum result is correct (n=0)"); 454 455 bool errorFlag = false; 456 for ( psU32 n = 1; n < 50; n++ ) 457 { 458 val = ( cabsf( vec->data.C32[ n ] ) * cabsf( vec->data.C32[ n ] ) + 459 cabsf( vec->data.C32[ 100 - n ] ) * cabsf( vec->data.C32[ 100 - n ] ) ) / 100 / 100; 460 val1 = (cabsf(vec3->data.C64[n]) * cabsf(vec3->data.C64[n]) + 461 cabsf(vec3->data.C64[100-n]) * cabsf(vec3->data.C64[100-n]))/100/100; 462 if ( fabsf( val - vec2->data.F32[ n ] ) > 10*FLT_EPSILON ) { 463 diag("psVectorPowerSpectrum result is incorrect (n=%d, %.2f %.2f)", 464 n, vec2->data.F32[ n ], val ); 465 errorFlag = true; 466 } 467 if (fabsf(val1 - vec4->data.F64[n]) > 10*FLT_EPSILON) { 468 diag("psVectorPowerSpectrum result is incorrect (n=%d, %.2f %.2f)",n,vec4->data.F64[n],val1); 469 errorFlag = true; 470 } 471 } 472 ok(!errorFlag, "psVectorPowerSpectrum() returned the correct data values"); 473 474 val = cabsf( vec->data.C32[ 50 ] ) * cabsf( vec->data.C32[ 50 ] ) / 100 / 100; 475 ok(fabsf( vec2->data.F32[ 50 ] - val ) <= 10*FLT_EPSILON, 476 "psVectorPowerSpectrum result is correct (n=50, %.2f %.2f)", 477 vec2->data.F32[ 0 ], val ); 478 psFree( vec ); 479 psFree( vec2 ); 480 psFree( vec3 ); 481 psFree( vec4 ); 482 483 // Perform vector power spectrum with non-complex number 484 vec = psVectorAlloc(100,PS_TYPE_F32); 485 vec->n = vec->nalloc; 486 for( psU32 n=0; n<100; n++) 487 { 488 vec->data.F32[n] = n; 489 } 490 491 // Following should generate an error message 492 // XXX: Verify error 493 ok(psVectorPowerSpectrum(NULL,vec) == NULL, 494 "psVectorPowerSpectrum() did return a NULL vector."); 495 // Perform vector power spectrum with null input 496 ok(psVectorPowerSpectrum(NULL,NULL) == NULL, 497 "psVectorPowerSpectrum() did return NULL with null input vector"); 498 499 psFree(vec); 500 ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks"); 501 } 121 testFFT(128); // Real quick test 122 testFFT(2048); // Test something big 123 testFFT(123456); // Test something really big 502 124 }
Note:
See TracChangeset
for help on using the changeset viewer.
