ComplexFFTTest.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Duncan Brown, Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /**** <lalVerbatim file="ComplexFFTTestCV">
00021  * $Id: ComplexFFTTest.c,v 1.14 2007/06/08 14:41:44 bema Exp $
00022  **** </lalVerbatim> */
00023 
00024 /**** <lalLaTeX>
00025  * 
00026  * \subsection{Program \texttt{ComplexFFTTest.c}}
00027  * \label{ss:ComplexFFTTest.c}
00028  * 
00029  * Tests the routines in \verb+ComplexFFT.h+.
00030  * 
00031  * \subsection*{Usage}
00032  * \begin{verbatim}
00033  * ComplexFFTTest [options]
00034  * Options:
00035  *   -h         print this message
00036  *   -q         quiet: run silently
00037  *   -v         verbose: print extra information
00038  *   -d level   set lalDebugLevel to level
00039  * \end{verbatim}
00040  * 
00041  * \subsubsection*{Description}
00042  * \subsubsection*{Exit codes}
00043  * \begin{tabular}{|c|l|}
00044  * \hline
00045  * Code & Explanation                   \\
00046  * \hline
00047  * \tt 0 & Success, normal exit.         \\
00048  * \tt 1 & Subroutine failed.            \\
00049  * \hline
00050  * \end{tabular}
00051  * 
00052  * \subsubsection*{Uses}
00053  * \subsubsection*{Notes}
00054  * 
00055  * \vfill{\footnotesize\input{ComplexFFTTestCV}}
00056  * 
00057  **** </lalLaTeX> */
00058 
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <string.h>
00062 #include <math.h>
00063 #include <lal/LALConfig.h>
00064 
00065 #ifdef HAVE_UNISTD_H
00066 #include <unistd.h>
00067 #endif
00068 
00069 #ifdef HAVE_GETOPT_H
00070 #include <getopt.h>
00071 #endif
00072 
00073 #include <lal/LALStdlib.h>
00074 #include <lal/AVFactories.h>
00075 #include <lal/ComplexFFT.h>
00076 
00077 #define CODES_(x) #x
00078 #define CODES(x) CODES_(x)
00079 
00080 NRCSID( MAIN, "$Id: ComplexFFTTest.c,v 1.14 2007/06/08 14:41:44 bema Exp $" );
00081 
00082 extern char *optarg;
00083 extern int   optind;
00084 
00085 int lalDebugLevel = 0;
00086 int verbose       = 0;
00087 
00088 static void
00089 Usage( const char *program, int exitflag );
00090 
00091 static void
00092 ParseOptions( int argc, char *argv[] );
00093 
00094 static void
00095 TestStatus( LALStatus *status, const char *expectedCodes, int exitCode );
00096 
00097 static void
00098 ClearStatus( LALStatus *status );
00099 
00100 static void
00101 CheckErrorCodes( void );
00102 
00103 int
00104 main( int argc, char *argv[] )
00105 {
00106   const UINT4 n   = 17;
00107   const REAL4 eps = 1e-6;
00108 
00109   static LALStatus  status;
00110   ComplexFFTPlan   *pfwd = NULL;
00111   ComplexFFTPlan   *prev = NULL;
00112   COMPLEX8Vector   *avec = NULL;
00113   COMPLEX8Vector   *bvec = NULL;
00114   COMPLEX8Vector   *cvec = NULL;
00115 
00116   FILE *fp;
00117   UINT4 i;
00118 
00119   ParseOptions( argc, argv );
00120 
00121   fp = verbose ? stdout : NULL ;
00122 
00123   LALCCreateVector( &status, &avec, n );
00124   TestStatus( &status, CODES( 0 ), 1 );
00125 
00126   LALCCreateVector( &status, &bvec, n );
00127   TestStatus( &status, CODES( 0 ), 1 );
00128 
00129   LALCCreateVector( &status, &cvec, n );
00130   TestStatus( &status, CODES( 0 ), 1 );
00131 
00132   LALCreateForwardComplexFFTPlan( &status, &pfwd, n, 0 );
00133   TestStatus( &status, CODES( 0 ), 1 );
00134 
00135   LALCreateReverseComplexFFTPlan( &status, &prev, n, 0 );
00136   TestStatus( &status, CODES( 0 ), 1 );
00137 
00138 
00139   for ( i = 0; i < n; ++i )
00140   {
00141     avec->data[i].im = rand() % 5 - 2;
00142     avec->data[i].re = rand() % 3 - 1;
00143     fp ? fprintf( fp, "%+.0f\t%+.0f\n", avec->data[i].re, avec->data[i].im )
00144        : 0;
00145   }
00146   fp ? fprintf( fp, "\n" ) : 0;
00147   fflush( stdout );
00148 
00149   LALCOMPLEX8VectorFFT( &status, bvec, avec, pfwd );
00150   TestStatus( &status, CODES( 0 ), 1 );
00151 
00152   for ( i = 0; i < n; ++i )
00153   {
00154     fp ? fprintf( fp, "%+f\t%+f\n", bvec->data[i].re, bvec->data[i].im ) : 0;
00155   }
00156   fp ? fprintf( fp, "\n" ) : 0;
00157   fflush( stdout );
00158 
00159   LALCOMPLEX8VectorFFT( &status, cvec, bvec, prev );
00160   TestStatus( &status, CODES( 0 ), 1 );
00161 
00162   for ( i = 0; i < n; ++i )
00163   {
00164     cvec->data[i].re /= n;
00165     cvec->data[i].im /= n;
00166     fp ? fprintf( fp, "%+.0f\t%+.0f\n", cvec->data[i].re, cvec->data[i].im )
00167        : 0;
00168     fflush( stdout );
00169     if ( fabs( avec->data[i].re - cvec->data[i].re ) > eps )
00170     {
00171       fprintf( stderr, "FAIL: IFFT( FFT( a[] ) ) not equal to a[].\n" );
00172       fprintf( stderr, "avec->data[%d].re = %e\n", i, avec->data[i].re );
00173       fprintf( stderr, "cvec->data[%d].re = %e\n", i, cvec->data[i].re );
00174       return 1;
00175     }
00176     if ( fabs( avec->data[i].im - cvec->data[i].im ) > eps )
00177     {
00178       fprintf( stderr, "FAIL: IFFT( FFT( a[] ) ) not equal to a[].\n" );
00179       fprintf( stderr, "avec->data[%d].im = %e\n", i, avec->data[i].im );
00180       fprintf( stderr, "cvec->data[%d].im = %e\n", i, cvec->data[i].im );
00181       return 1;
00182     }
00183   }
00184 
00185   LALDestroyComplexFFTPlan( &status, &prev );
00186   TestStatus( &status, CODES( 0 ), 1 );
00187 
00188   LALDestroyComplexFFTPlan( &status, &pfwd );
00189   TestStatus( &status, CODES( 0 ), 1 );
00190 
00191   LALCDestroyVector( &status, &cvec );
00192   TestStatus( &status, CODES( 0 ), 1 );
00193 
00194   LALCDestroyVector( &status, &bvec );
00195   TestStatus( &status, CODES( 0 ), 1 );
00196 
00197   LALCDestroyVector( &status, &avec );
00198   TestStatus( &status, CODES( 0 ), 1 );
00199 
00200   fp ? fprintf( fp, "\nChecking error codes:\n\n" ) : 0;
00201   CheckErrorCodes();
00202 
00203   LALCheckMemoryLeaks();
00204   return 0;
00205 }
00206 
00207 /* need to have definition of tagComplexFFTPlan to corrupt it */
00208 struct
00209 tagComplexFFTPlan
00210 {
00211   INT4   sign;
00212   UINT4  size;
00213   void  *plan;
00214 };
00215 
00216 static void
00217 CheckErrorCodes( void )
00218 {
00219 #ifndef LAL_NDEBUG
00220   enum { Size = 19 };
00221   const UINT4 size = Size;
00222   static LALStatus status;
00223   ComplexFFTPlan *plan;
00224   ComplexFFTPlan  aplan;
00225   COMPLEX8Vector  avec;
00226   COMPLEX8Vector  bvec;
00227   COMPLEX8        adat[Size];
00228   COMPLEX8        bdat[Size];
00229 
00230   if ( ! lalNoDebug )
00231   {
00232     aplan.size = size;
00233 
00234     LALCreateForwardComplexFFTPlan( &status, NULL, size, 0 );
00235     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00236     LALCreateReverseComplexFFTPlan( &status, NULL, size, 0 );
00237     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00238 
00239     plan = &aplan;
00240     LALCreateForwardComplexFFTPlan( &status, &plan, size, 0 );
00241     TestStatus( &status, CODES( COMPLEXFFTH_ENNUL ), 1 );
00242     LALCreateReverseComplexFFTPlan( &status, &plan, size, 0 );
00243     TestStatus( &status, CODES( COMPLEXFFTH_ENNUL ), 1 );
00244 
00245     plan = NULL;
00246     LALCreateForwardComplexFFTPlan( &status, &plan, 0, 0 );
00247     TestStatus( &status, CODES( COMPLEXFFTH_ESIZE ), 1 );
00248     LALCreateReverseComplexFFTPlan( &status, &plan, 0, 0 );
00249     TestStatus( &status, CODES( COMPLEXFFTH_ESIZE ), 1 );
00250 
00251     LALDestroyComplexFFTPlan( &status, &plan );
00252     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00253     LALDestroyComplexFFTPlan( &status, NULL );
00254     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00255 
00256     plan        = &aplan;
00257     avec.length = size;
00258     bvec.length = size;
00259     avec.data   = adat;
00260     bvec.data   = bdat;
00261     LALCOMPLEX8VectorFFT( &status, NULL, &avec, plan );
00262     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00263     LALCOMPLEX8VectorFFT( &status, &bvec, NULL, plan );
00264     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00265     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, NULL );
00266     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00267 
00268     avec.data = NULL;
00269     bvec.data = bdat;
00270     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00271     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00272 
00273     avec.data = adat;
00274     bvec.data = NULL;
00275     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00276     TestStatus( &status, CODES( COMPLEXFFTH_ENULL ), 1 );
00277 
00278     avec.data = adat;
00279     bvec.data = adat;
00280     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00281     TestStatus( &status, CODES( COMPLEXFFTH_ESAME ), 1 );
00282 
00283     aplan.size = 0;
00284     avec.data  = adat;
00285     avec.data  = bdat;
00286     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00287     TestStatus( &status, CODES( COMPLEXFFTH_ESIZE ), 1 );
00288 
00289     aplan.size  = size;
00290     avec.length = 0;
00291     bvec.length = size;
00292     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00293     TestStatus( &status, CODES( COMPLEXFFTH_ESZMM ), 1 );
00294 
00295     aplan.size  = size;
00296     avec.length = size;
00297     bvec.length = 0;
00298     LALCOMPLEX8VectorFFT( &status, &bvec, &avec, plan );
00299     TestStatus( &status, CODES( COMPLEXFFTH_ESZMM ), 1 );
00300   }
00301 #endif
00302 
00303   return;
00304 }
00305 
00306 
00307 /*
00308  * TestStatus()
00309  *
00310  * Routine to check that the status code status->statusCode agrees with one of
00311  * the codes specified in the space-delimited string ignored; if not,
00312  * exit to the system with code exitcode.
00313  *
00314  */
00315 static void
00316 TestStatus( LALStatus *status, const char *ignored, int exitcode )
00317 {
00318   char  str[64];
00319   char *tok;
00320 
00321   if ( verbose )
00322   {
00323     REPORTSTATUS( status );
00324   }
00325 
00326   if ( strncpy( str, ignored, sizeof( str ) ) )
00327   {
00328     if ( (tok = strtok( str, " " ) ) )
00329     {
00330       do
00331       {
00332         if ( status->statusCode == atoi( tok ) )
00333         {
00334           return;
00335         }
00336       }
00337       while ( ( tok = strtok( NULL, " " ) ) );
00338     }
00339     else
00340     {
00341       if ( status->statusCode == atoi( tok ) )
00342       {
00343         return;
00344       }
00345     }
00346   }
00347 
00348   fprintf( stderr, "\nExiting to system with code %d\n", exitcode );
00349   exit( exitcode );
00350 }
00351 
00352 
00353 /*
00354  *
00355  * ClearStatus()
00356  *
00357  * Recursively applies DETATCHSTATUSPTR() to status structure to destroy
00358  * linked list of statuses.
00359  *
00360  */
00361 void
00362 ClearStatus( LALStatus *status )
00363 {
00364   if ( status->statusPtr )
00365   {
00366     ClearStatus( status->statusPtr );
00367     DETATCHSTATUSPTR( status );
00368   }
00369 }
00370 
00371 
00372 /*
00373  *
00374  * Usage()
00375  *
00376  * Prints a usage message for program program and exits with code exitcode.
00377  *
00378  */
00379 static void
00380 Usage( const char *program, int exitcode )
00381 {
00382   fprintf( stderr, "Usage: %s [options]\n", program );
00383   fprintf( stderr, "Options:\n" );
00384   fprintf( stderr, "  -h         print this message\n" );
00385   fprintf( stderr, "  -q         quiet: run silently\n" );
00386   fprintf( stderr, "  -v         verbose: print extra information\n" );
00387   fprintf( stderr, "  -d level   set lalDebugLevel to level\n" );
00388   exit( exitcode );
00389 }
00390 
00391 
00392 /*
00393  * ParseOptions()
00394  *
00395  * Parses the argc - 1 option strings in argv[].
00396  *
00397  */
00398 static void
00399 ParseOptions( int argc, char *argv[] )
00400 {
00401   while ( 1 )
00402   {
00403     int c = -1;
00404 
00405     c = getopt( argc, argv, "hqvd:" );
00406     if ( c == -1 )
00407     {
00408       break;
00409     }
00410 
00411     switch ( c )
00412     {
00413       case 'd': /* set debug level */
00414         lalDebugLevel = atoi( optarg );
00415         break;
00416 
00417       case 'v': /* verbose */
00418         ++verbose;
00419         break;
00420 
00421       case 'q': /* quiet: run silently (ignore error messages) */
00422         freopen( "/dev/null", "w", stderr );
00423         freopen( "/dev/null", "w", stdout );
00424         break;
00425 
00426       case 'h':
00427         Usage( argv[0], 0 );
00428         break;
00429 
00430       default:
00431         Usage( argv[0], 1 );
00432     }
00433 
00434   }
00435 
00436   if ( optind < argc )
00437   {
00438     Usage( argv[0], 1 );
00439   }
00440 
00441   return;
00442 }
00443 

Generated on Sat Sep 6 03:06:43 2008 for LAL by  doxygen 1.5.2