LAL  7.5.0.1-b72065a
LALGSLTest.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Jolien Creighton
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 /**
21  * \file
22  * \ingroup LALGSL_h
23  * \author Creighton, J. D. E.
24  *
25  * This program tests the LAL macros for GSL function calls. It makes sure
26  * that a nominal status is returned if the GSL function succeeds, and that
27  * an error code is returned if the GSL function fails.
28  *
29  */
30 
31 /** \cond DONT_DOXYGEN */
32 
33 #include <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <lal/LALStdlib.h>
37 #include <lal/LALGSL.h>
38 #include <lal/LALConstants.h>
39 #include <gsl/gsl_sf.h>
40 #include <gsl/gsl_integration.h>
41 #include <gsl/gsl_errno.h>
42 
43 #ifdef __GNUC__
44 #define UNUSED __attribute__ ((unused))
45 #else
46 #define UNUSED
47 #endif
48 
49 /* macro for testing status */
50 #define TESTSTATUS( pstatus, code ) \
51  if ( (pstatus)->statusCode != code ) { REPORTSTATUS(pstatus); exit(1); } \
52  else ((void)(0))
53 
54 /* macro for testing handler */
55 extern gsl_error_handler_t *gsl_error_handler;
56 gsl_error_handler_t *original_handler;
57 #define TESTHANDLER \
58  if ( original_handler != gsl_error_handler ) \
59  { fprintf( stderr, "Error: handler was not restored!\n" ); exit(2); } \
60  else ((void)(0))
61 
62 /* function for clearing status pointer */
63 static void ClearStatus( LALStatus *status )
64 {
65  if ( status->statusPtr )
66  {
67  ClearStatus( status->statusPtr );
69  }
70  return;
71 }
72 
73 
74 /*
75  *
76  * Basic tests: call the logarithm with both positive and negative values.
77  *
78  */
79 
80 
81 /* call the GSL log routine to test the GSL macros */
82 static void Logarithm( LALStatus *status, REAL8 *output, REAL8 input )
83 {
86 
87  CALLGSL( *output = gsl_sf_log( input ), status );
89 
90  /* just for fun, use the TRYGSL macro to do the same thing too */
91  TRYGSL( *output = gsl_sf_log( input ), status );
92 
94  RETURN( status );
95 }
96 
97 
98 /*
99  *
100  * More complex tests: integrate the Heaviside function, but code the
101  * Heaviside function stupidly so that it can cause failures. This tests
102  * that the GSL-macros are reenterant-safe.
103  *
104  */
105 
106 
107 /* here is a really stupid Heaviside function: take the log of x;
108  * return 1 if no error otherwise return 0 */
109 static double Heaviside( double x, void UNUSED * params )
110 {
111  LALStatus newStatus;
112  double dummy;
113  double ans;
114 
115  /* blank the new status structure */
116  memset( &newStatus, 0, sizeof( newStatus ) );
117 
118  /* call the LAL function */
119  Logarithm( &newStatus, &dummy, x );
120  if ( newStatus.statusCode )
121  {
122  ClearStatus( &newStatus );
123  ans = 0;
124  }
125  else
126  ans = 1;
127 
128  return ans;
129 }
130 
131 static void Integral( LALStatus *status, REAL8 *y, REAL8 a, REAL8 b, REAL8 eps )
132 {
133  gsl_integration_workspace *work = NULL;
134  gsl_function F;
135  REAL8 err;
138 
139  F.function = &Heaviside;
140  F.params = NULL;
141 
142  TRYGSL( work = gsl_integration_workspace_alloc( 100 ), status );
143  CALLGSL( gsl_integration_qags( &F, a, b, eps, eps, 100, work, y, &err ),
144  status );
145  BEGINFAIL( status )
146  TRYGSL( gsl_integration_workspace_free( work ), status );
147  ENDFAIL( status );
148  TRYGSL( gsl_integration_workspace_free( work ), status );
149 
150  /* if eps is set too small the integration is supposed to fail, but on
151  * some systems it may happen that it doesn't... in this case, just make
152  * this routine fail with a recursive error */
153  if ( eps < LAL_REAL8_EPS )
154  {
155  TRY( Logarithm( status->statusPtr, y, 0 ), status );
156  }
157 
159  RETURN( status );
160 }
161 
162 
163 
164 int main( void )
165 {
166  static LALStatus status;
167  double x;
168  double y;
169 
170  original_handler = gsl_error_handler;
171 
172  /* these are simple tests of a LAL routine that calls a GSL function */
173 
174  /* this should succeed */
175  x = 10;
176  Logarithm( &status, &y, x );
177  TESTSTATUS( &status, 0 ); /* expect error code 0 */
178  TESTHANDLER;
179 
180  /* this should fail */
181  x = 0;
182  Logarithm( &status, &y, x );
183  TESTSTATUS( &status, -1 ); /* expect error code -1 */
184  TESTHANDLER;
185  ClearStatus( &status );
186 
187  /* this should succeed again */
188  x = 10;
189  Logarithm( &status, &y, x );
190  TESTSTATUS( &status, 0 ); /* expect error code 0 */
191  TESTHANDLER;
192 
193 
194  /* these are more complicated tests of a LAL routine that calls a GSL
195  * function that ultimately calls another LAL function, which in turn
196  * calls a GSL function... to make sure that everything is reenterant */
197 
198  /* this should pass */
199  Integral( &status, &y, -1, 1, 1e-7 );
200  TESTSTATUS( &status, 0 ); /* expect error code 0 */
201  TESTHANDLER;
202 
203  /* this should fail */
204  Integral( &status, &y, -1, 1, LAL_REAL8_MIN );
205  TESTSTATUS( &status, -1 ); /* expect error code -1 */
206  TESTHANDLER;
207  ClearStatus( &status );
208 
210 
211  return 0;
212 }
213 
214 /** \endcond */
#define TESTSTATUS(s)
#define TRYGSL(statement, statusptr)
Definition: LALGSL.h:135
#define CALLGSL(statement, statusptr)
Definition: LALGSL.h:115
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
#define CHECKSTATUSPTR(statusptr)
#define ENDFAIL(statusptr)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define BEGINFAIL(statusptr)
int main(int argc, char *argv[])
Definition: cache.c:25
#define LAL_REAL8_EPS
Difference between 1 and the next resolvable REAL8 2^-52.
Definition: LALConstants.h:61
#define LAL_REAL8_MIN
Smallest normalized REAL8 number 2^-1022.
Definition: LALConstants.h:60
double REAL8
Double precision real floating-point number (8 bytes).
static const REAL4 eps
Definition: Random.c:84
static const INT4 a
Definition: Random.c:79
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
INT4 statusCode
A numerical code identifying the type of error, or 0 for nominal status; Negative values are reserved...
Definition: LALDatatypes.h:948
void output(int gps_sec, int output_type)
Definition: tconvert.c:440