00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #include <stdio.h>
00067 #include <stdlib.h>
00068 #include <math.h>
00069 #include <lal/LALConfig.h>
00070
00071 #ifdef HAVE_UNISTD_H
00072 #include <unistd.h>
00073 #endif
00074
00075 #ifdef HAVE_GETOPT_H
00076 #include <getopt.h>
00077 #endif
00078
00079 #include <lal/LALStdlib.h>
00080 #include <lal/LALConstants.h>
00081 #include <lal/SeqFactories.h>
00082 #include <lal/RealFFT.h>
00083 #include <lal/VectorOps.h>
00084
00085 #define CODES_(x) #x
00086 #define CODES(x) CODES_(x)
00087
00088 NRCSID( MAIN, "$Id: RealFFTTest.c,v 1.12 2007/06/08 14:41:44 bema Exp $" );
00089
00090 extern char *optarg;
00091 extern int optind;
00092
00093 int lalDebugLevel = 0;
00094 int verbose = 0;
00095 UINT4 m_ = 1;
00096 UINT4 n_ = 0;
00097
00098 static void
00099 Usage( const char *program, int exitflag );
00100
00101 static void
00102 ParseOptions( int argc, char *argv[] );
00103
00104 static void
00105 TestStatus( LALStatus *status, const char *expectedCodes, int exitCode );
00106
00107 static void
00108 ClearStatus( LALStatus *status );
00109
00110 void LALForwardRealDFT(
00111 LALStatus *status,
00112 COMPLEX8Vector *output,
00113 REAL4Vector *input
00114 );
00115
00116 int main( int argc, char *argv[] )
00117 {
00118 static LALStatus status;
00119
00120 RealFFTPlan *fwd = NULL;
00121 RealFFTPlan *rev = NULL;
00122 REAL4Vector *dat = NULL;
00123 REAL4Vector *rfft = NULL;
00124 REAL4Vector *ans = NULL;
00125 COMPLEX8Vector *dft = NULL;
00126 COMPLEX8Vector *fft = NULL;
00127 REAL8 eps = 1e-6;
00128 REAL8 lbn;
00129 REAL8 ssq;
00130 REAL8 var;
00131 REAL8 tol;
00132
00133 UINT4 nmax;
00134 UINT4 m;
00135 UINT4 n;
00136 UINT4 i;
00137 UINT4 j;
00138 UINT4 k;
00139 UINT4 s = 0;
00140
00141 FILE *fp;
00142
00143 ParseOptions( argc, argv );
00144 m = m_;
00145 n = n_;
00146
00147 fp = verbose ? stdout : NULL ;
00148
00149 if ( n == 0 )
00150 {
00151 nmax = 65536;
00152 }
00153 else
00154 {
00155 nmax = n--;
00156 }
00157
00158 while ( n < nmax )
00159 {
00160 if ( n < 128 )
00161 {
00162 ++n;
00163 }
00164 else
00165 {
00166 n *= 2;
00167 }
00168
00169 LALSCreateVector( &status, &dat, n );
00170 TestStatus( &status, CODES( 0 ), 1 );
00171 LALSCreateVector( &status, &rfft, n );
00172 TestStatus( &status, CODES( 0 ), 1 );
00173 LALSCreateVector( &status, &ans, n );
00174 TestStatus( &status, CODES( 0 ), 1 );
00175 LALCCreateVector( &status, &dft, n / 2 + 1 );
00176 TestStatus( &status, CODES( 0 ), 1 );
00177 LALCCreateVector( &status, &fft, n / 2 + 1 );
00178 TestStatus( &status, CODES( 0 ), 1 );
00179 LALCreateForwardRealFFTPlan( &status, &fwd, n, 0 );
00180 TestStatus( &status, CODES( 0 ), 1 );
00181 LALCreateReverseRealFFTPlan( &status, &rev, n, 0 );
00182 TestStatus( &status, CODES( 0 ), 1 );
00183
00184
00185
00186
00187
00188
00189 for ( i = 0; i < m; ++i )
00190 {
00191 srand( s++ );
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 srand( i );
00203 ssq = 0;
00204 for ( j = 0; j < n; ++j )
00205 {
00206 dat->data[j] = 20.0 * rand() / (REAL4)( RAND_MAX + 1.0 ) - 10.0;
00207 ssq += dat->data[j] * dat->data[j];
00208 fp ? fprintf( fp, "%e\n", dat->data[j] ) : 0;
00209 }
00210 lbn = log( n ) / log( 2 );
00211 var = 2.5 * lbn * eps * eps * ssq / n;
00212 tol = 5 * sqrt( var );
00213 fp ? fprintf( fp, "\neps = %e \ntol = %e\n", eps, tol ) : 0;
00214
00215
00216
00217
00218
00219
00220 LALForwardRealFFT( &status, fft, dat, fwd );
00221 TestStatus( &status, CODES( 0 ), 1 );
00222 LALREAL4VectorFFT( &status, rfft, dat, fwd );
00223 TestStatus( &status, CODES( 0 ), 1 );
00224 LALREAL4VectorFFT( &status, ans, rfft, rev );
00225 TestStatus( &status, CODES( 0 ), 1 );
00226 fp ? fprintf( fp, "rfft()\t\trfft(rfft())\trfft(rfft())\n\n" ) : 0;
00227 for ( j = 0; j < n; ++j )
00228 {
00229 fp ? fprintf( fp, "%e\t%e\t%e\n",
00230 rfft->data[j], ans->data[j], ans->data[j] / n ) : 0;
00231 }
00232 if ( n < 128 )
00233 {
00234 LALForwardRealDFT( &status, dft, dat );
00235 TestStatus( &status, CODES( 0 ), 1 );
00236
00237
00238
00239
00240
00241
00242 fp ? fprintf( fp, "\nfftre\t\tfftim\t\t" ) : 0;
00243 fp ? fprintf( fp, "dtfre\t\tdftim\n" ) : 0;
00244 for ( k = 0; k <= n / 2; ++k )
00245 {
00246 REAL8 fftre = fft->data[k].re;
00247 REAL8 fftim = fft->data[k].im;
00248 REAL8 dftre = dft->data[k].re;
00249 REAL8 dftim = dft->data[k].im;
00250 REAL8 errre = fabs( dftre - fftre );
00251 REAL8 errim = fabs( dftim - fftim );
00252 REAL8 avere = fabs( dftre + fftre ) / 2 + eps;
00253 REAL8 aveim = fabs( dftim + fftim ) / 2 + eps;
00254 REAL8 ferre = errre / avere;
00255 REAL8 ferim = errim / aveim;
00256 fp ? fprintf( fp, "%e\t%e\t", fftre, fftim ) : 0;
00257 fp ? fprintf( fp, "%e\t%e\n", dftre, dftim ) : 0;
00258
00259
00260 if ( ferre > eps && errre > tol )
00261 {
00262 fputs( "FAIL: Incorrect result from forward transform\n", stderr );
00263 fprintf( stderr, "\tdifference = %e\n", errre );
00264 fprintf( stderr, "\ttolerance = %e\n", tol );
00265 fprintf( stderr, "\tfrac error = %e\n", ferre );
00266 fprintf( stderr, "\tprecision = %e\n", eps );
00267 return 1;
00268 }
00269 if ( ferim > eps && errim > tol )
00270 {
00271 fputs( "FAIL: Incorrect result from forward transform\n", stderr );
00272 fprintf( stderr, "\tdifference = %e\n", errim );
00273 fprintf( stderr, "\ttolerance = %e\n", tol );
00274 fprintf( stderr, "\tfrac error = %e\n", ferim );
00275 fprintf( stderr, "\tprecision = %e\n", eps );
00276 return 1;
00277 }
00278 }
00279 }
00280
00281
00282
00283
00284
00285
00286 LALReverseRealFFT( &status, ans, fft, rev );
00287 TestStatus( &status, CODES( 0 ), 1 );
00288 fp ? fprintf( fp, "\ndat->data[j]\tans->data[j] / n\n" ) : 0;
00289 for ( j = 0; j < n; ++j )
00290 {
00291 REAL8 err = fabs( dat->data[j] - ans->data[j] / n );
00292 REAL8 ave = fabs( dat->data[j] + ans->data[j] / n ) / 2 + eps;
00293 REAL8 fer = err / ave;
00294 fp ? fprintf( fp, "%e\t%e\n", dat->data[j], ans->data[j] / n ) : 0;
00295
00296 if ( fer > eps && err > tol )
00297 {
00298 fputs( "FAIL: Incorrect result after reverse transform\n", stderr );
00299 fprintf( stderr, "\tdifference = %e\n", err );
00300 fprintf( stderr, "\ttolerance = %e\n", tol );
00301 fprintf( stderr, "\tfrac error = %e\n", fer );
00302 fprintf( stderr, "\tprecision = %e\n", eps );
00303 return 1;
00304 }
00305 }
00306 }
00307
00308 LALSDestroyVector( &status, &dat );
00309 TestStatus( &status, CODES( 0 ), 1 );
00310 LALSDestroyVector( &status, &rfft );
00311 TestStatus( &status, CODES( 0 ), 1 );
00312 LALSDestroyVector( &status, &ans );
00313 TestStatus( &status, CODES( 0 ), 1 );
00314 LALCDestroyVector( &status, &dft );
00315 TestStatus( &status, CODES( 0 ), 1 );
00316 LALCDestroyVector( &status, &fft );
00317 TestStatus( &status, CODES( 0 ), 1 );
00318 LALDestroyRealFFTPlan( &status, &fwd );
00319 TestStatus( &status, CODES( 0 ), 1 );
00320 LALDestroyRealFFTPlan( &status, &rev );
00321 TestStatus( &status, CODES( 0 ), 1 );
00322 }
00323
00324 LALCheckMemoryLeaks();
00325 return 0;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 static void
00337 TestStatus( LALStatus *status, const char *ignored, int exitcode )
00338 {
00339 char str[64];
00340 char *tok;
00341
00342 if ( verbose )
00343 {
00344 REPORTSTATUS( status );
00345 }
00346
00347 if ( strncpy( str, ignored, sizeof( str ) ) )
00348 {
00349 if ( (tok = strtok( str, " " ) ) )
00350 {
00351 do
00352 {
00353 if ( status->statusCode == atoi( tok ) )
00354 {
00355 return;
00356 }
00357 }
00358 while ( ( tok = strtok( NULL, " " ) ) );
00359 }
00360 else
00361 {
00362 if ( status->statusCode == atoi( tok ) )
00363 {
00364 return;
00365 }
00366 }
00367 }
00368
00369 fprintf( stderr, "\nExiting to system with code %d\n", exitcode );
00370 exit( exitcode );
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 void
00383 ClearStatus( LALStatus *status )
00384 {
00385 if ( status->statusPtr )
00386 {
00387 ClearStatus( status->statusPtr );
00388 DETATCHSTATUSPTR( status );
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 static void
00401 Usage( const char *program, int exitcode )
00402 {
00403 fprintf( stderr, "Usage: %s [options]\n", program );
00404 fprintf( stderr, "Options:\n" );
00405 fprintf( stderr, " -h print this message\n" );
00406 fprintf( stderr, " -q quiet: run silently\n" );
00407 fprintf( stderr, " -v verbose: print extra information\n" );
00408 fprintf( stderr, " -d level set lalDebugLevel to level\n" );
00409 fprintf( stderr, " -m trials set number of random trials\n" );
00410 fprintf( stderr, " -n size set size of FFTs\n" );
00411 exit( exitcode );
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421 static void
00422 ParseOptions( int argc, char *argv[] )
00423 {
00424 while ( 1 )
00425 {
00426 int c = -1;
00427
00428 c = getopt( argc, argv, "hqvd:m:n:" );
00429 if ( c == -1 )
00430 {
00431 break;
00432 }
00433
00434 switch ( c )
00435 {
00436 case 'n':
00437 n_ = atoi( optarg );
00438 break;
00439
00440 case 'm':
00441 m_ = atoi( optarg );
00442 break;
00443
00444 case 'd':
00445 lalDebugLevel = atoi( optarg );
00446 break;
00447
00448 case 'v':
00449 ++verbose;
00450 break;
00451
00452 case 'q':
00453 freopen( "/dev/null", "w", stderr );
00454 freopen( "/dev/null", "w", stdout );
00455 break;
00456
00457 case 'h':
00458 Usage( argv[0], 0 );
00459 break;
00460
00461 default:
00462 Usage( argv[0], 1 );
00463 }
00464
00465 }
00466
00467 if ( optind < argc )
00468 {
00469 Usage( argv[0], 1 );
00470 }
00471
00472 return;
00473 }
00474
00475
00476 static void
00477 LALDFT(
00478 LALStatus *status,
00479 COMPLEX8Vector *output,
00480 COMPLEX8Vector *input,
00481 INT4 sign
00482 )
00483 {
00484 UINT4 n;
00485 UINT4 j;
00486 UINT4 k;
00487
00488 INITSTATUS( status, "DFT", MAIN );
00489
00490 n = output->length;
00491
00492 for ( k = 0; k < n; ++k )
00493 {
00494 REAL8 sre = 0;
00495 REAL8 sim = 0;
00496 for ( j = 0; j < n; ++j )
00497 {
00498 REAL8 phi = sign * LAL_TWOPI * (REAL8)(j) * (REAL8)(k) / (REAL8)(n);
00499 REAL8 c = cos( phi );
00500 REAL8 s = sin( phi );
00501 REAL8 re = input->data[j].re;
00502 REAL8 im = input->data[j].im;
00503 sre += c * re - s * im;
00504 sim += c * im + s * re;
00505 }
00506 output->data[k].re = sre;
00507 output->data[k].im = sim;
00508 }
00509
00510 RETURN( status );
00511 }
00512
00513 void LALForwardRealDFT(
00514 LALStatus *status,
00515 COMPLEX8Vector *output,
00516 REAL4Vector *input
00517 )
00518 {
00519 COMPLEX8Vector *a = NULL;
00520 COMPLEX8Vector *b = NULL;
00521 UINT4 n;
00522 UINT4 j;
00523 UINT4 k;
00524
00525 INITSTATUS( status, "LALForwardRealDFT", MAIN );
00526 ATTATCHSTATUSPTR( status );
00527
00528 n = input->length;
00529
00530 TRY( LALCCreateVector( status->statusPtr, &a, n ), status );
00531 TRY( LALCCreateVector( status->statusPtr, &b, n ), status );
00532
00533 for ( j = 0; j < n; ++j )
00534 {
00535 a->data[j].re = input->data[j];
00536 a->data[j].im = 0;
00537 }
00538
00539 TRY( LALDFT( status->statusPtr, b, a, -1 ), status );
00540
00541 for ( k = 0; k <= n / 2; ++k )
00542 {
00543 output->data[k].re = b->data[k].re;
00544 output->data[k].im = b->data[k].im;
00545 }
00546
00547 TRY( LALCDestroyVector( status->statusPtr, &a ), status );
00548 TRY( LALCDestroyVector( status->statusPtr, &b ), status );
00549
00550 DETATCHSTATUSPTR( status );
00551 RETURN( status );
00552 }
00553