Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
FindRootTest.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 FindRoot_h
23 *
24 * \brief Tests the routines in \ref FindRoot.h.
25 *
26 * ### Usage ###
27 *
28 * \code
29 * FindRootTest [options]
30 * Options:
31 * -h print this message
32 * -q quiet: run silently
33 * -v verbose: print extra information
34 * -d level set lalDebugLevel to level
35 * \endcode
36 *
37 * ### Exit codes ###
38 *
39 * <table>
40 * <tr><th>Code</th><th>Explanation</th></tr>
41 * <tr><td>0</td><td>Success, normal exit.</td></tr>
42 * <tr><td>1</td><td>Subroutine failed.</td></tr>
43 * </table>
44 *
45 */
46/** \cond DONT_DOXYGEN */
47#include <config.h>
48
49#include <stdio.h>
50#include <string.h>
51#include <stdlib.h>
52#include <math.h>
53
54#include <lal/LALStdlib.h>
55#include <lal/LALgetopt.h>
56#include <lal/FindRoot.h>
57#include <lal/LALString.h>
58
59#define CODES_(x) #x
60#define CODES(x) CODES_(x)
61
62int verbose = 0;
63
64static void
65Usage (const char *program, int exitflag);
66
67static void
68ParseOptions (int argc, char *argv[]);
69
70static void
71TestStatus (LALStatus *status, const char *expectedCodes, int exitCode);
72
73static void
74ClearStatus (LALStatus *status);
75
76/*
77 *
78 * Function: y = F(x; p) = p + x*x
79 *
80 */
81static void
82F (LALStatus *s, REAL4 *y, REAL4 x, void *p)
83{
84 REAL4 y_0;
85 INITSTATUS(s);
86 ASSERT (y, s, 1, "Null pointer");
87 ASSERT (p, s, 1, "Null pointer");
88 y_0 = *(REAL4 *)p;
89 *y = y_0 + x*x;
90 RETURN (s);
91}
92
93static void
94FF (LALStatus *s, REAL8 *y, REAL8 x, void *p)
95{
96 REAL8 y_0;
97 INITSTATUS(s);
98 ASSERT (y, s, 1, "Null pointer");
99 ASSERT (p, s, 1, "Null pointer");
100 y_0 = *(REAL8 *)p;
101 *y = y_0 + x*x;
102 RETURN (s);
103}
104
105
106int
107main (int argc, char *argv[])
108{
109 static LALStatus status;
110 SFindRootIn sinput;
111 DFindRootIn dinput;
112 REAL4 y_0;
113 REAL4 sroot;
114 REAL8 yy0;
115 REAL8 droot;
116
117
118 /*
119 *
120 * Parse the command line options
121 *
122 */
123
124
125 ParseOptions (argc, argv);
126
127
128 /*
129 *
130 * Set up input structure and function parameter y_0.
131 *
132 */
133
134
135 y_0 = -1;
136 sinput.function = F;
137 sinput.xmin = 1e-3;
138 sinput.xmax = 2e-3;
139 sinput.xacc = 1e-6;
140 yy0 = -1;
141 dinput.function = FF;
142 dinput.xmin = 1e-3;
143 dinput.xmax = 2e-3;
144 dinput.xacc = 1e-15;
145
146
147 /*
148 *
149 * Check to see if bracketing and root finding work.
150 *
151 */
152
153
154 if (verbose)
155 {
156 printf ("\n===== Check Root Finding =====\n\n");
157 }
158
159 if (verbose)
160 {
161 printf ("Initial domain: [%e,%e]\n", dinput.xmin, dinput.xmax);
162 }
163
164 LALSBracketRoot (&status, &sinput, &y_0);
165 TestStatus (&status, CODES(0), 1);
166
167 if (verbose)
168 {
169 printf ("Bracket domain: [%e,%e]\n", sinput.xmin, sinput.xmax);
170 }
171
172 if (sinput.xmin > 1 || sinput.xmax < 1)
173 {
174 fprintf (stderr, "Root not bracketed correctly\n");
175 return 1;
176 }
177
178 LALDBracketRoot (&status, &dinput, &yy0);
179 TestStatus (&status, CODES(0), 1);
180
181 if (verbose)
182 {
183 printf ("Bracket domain: [%e,%e]\n", dinput.xmin, dinput.xmax);
184 }
185
186 if (dinput.xmin > 1 || dinput.xmax < 1)
187 {
188 fprintf (stderr, "Root not bracketed correctly\n");
189 return 1;
190 }
191
192
193 LALSBisectionFindRoot (&status, &sroot, &sinput, &y_0);
194 TestStatus (&status, CODES(0), 1);
195
196 if (verbose)
197 {
198 printf ("Root = %e (acc = %e)\n", sroot, sinput.xacc);
199 }
200
201 if (fabs(sroot - 1) > sinput.xacc)
202 {
203 fprintf (stderr, "Root not found to correct accuracy\n");
204 return 1;
205 }
206
207
208 LALDBisectionFindRoot (&status, &droot, &dinput, &yy0);
209 TestStatus (&status, CODES(0), 1);
210
211 if (verbose)
212 {
213 printf ("Root = %.15e (acc = %e)\n", droot, dinput.xacc);
214 }
215
216 if (fabs(droot - 1) > dinput.xacc)
217 {
218 fprintf (stderr, "Root not found to correct accuracy\n");
219 return 1;
220 }
221
222
223 /*
224 *
225 * Check to make sure that correct error codes are generated.
226 *
227 */
228
229
230 if (verbose || lalDebugLevel)
231 {
232 printf ("\n===== Check Errors =====\n");
233 }
234
235 /* recursive error from an error occurring in the function */
236
237 if (verbose)
238 {
239 printf ("\n----- Recursive Error: Code -1 (2 times)\n");
240 }
241
242 LALSBracketRoot (&status, &sinput, NULL);
243 TestStatus (&status, CODES(-1), 1);
244 ClearStatus (&status);
245 LALDBracketRoot (&status, &dinput, NULL);
246 TestStatus (&status, CODES(-1), 1);
247 ClearStatus (&status);
248
249 /* one of the arguments is a null pointer */
250
251 if (verbose)
252 {
253 printf ("\n----- Null Pointer Error: Code 1 (10 times)\n");
254 }
255
256 LALSBracketRoot (&status, NULL, &y_0);
257 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
258 LALDBracketRoot (&status, NULL, &yy0);
259 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
260
261 LALSBisectionFindRoot (&status, NULL, &sinput, &y_0);
262 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
263 LALDBisectionFindRoot (&status, NULL, &dinput, &yy0);
264 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
265
266 LALSBisectionFindRoot (&status, &sroot, NULL, &y_0);
267 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
268 LALDBisectionFindRoot (&status, &droot, NULL, &yy0);
269 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
270
271 sinput.function = NULL;
272 dinput.function = NULL;
273
274 LALSBracketRoot (&status, &sinput, &y_0);
275 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
276 LALDBracketRoot (&status, &dinput, &yy0);
277 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
278
279 LALSBisectionFindRoot (&status, &sroot, &sinput, &y_0);
280 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
281 LALDBisectionFindRoot (&status, &droot, &dinput, &yy0);
282 TestStatus (&status, CODES(FINDROOTH_ENULL), 1);
283
284 /* invalid initial domain error for BracketRoot() */
285
286 if (verbose)
287 {
288 printf ("\n----- Invalid Initial Domain: Code 2 (2 times)\n");
289 }
290
291 sinput.function = F;
292 sinput.xmin = 5;
293 sinput.xmax = 5;
294 dinput.function = FF;
295 dinput.xmin = 5;
296 dinput.xmax = 5;
297
298 LALSBracketRoot (&status, &sinput, &y_0);
299 TestStatus (&status, CODES(FINDROOTH_EIDOM), 1);
300 LALDBracketRoot (&status, &dinput, &yy0);
301 TestStatus (&status, CODES(FINDROOTH_EIDOM), 1);
302
303 /* maximum iterations exceeded error */
304
305 if (verbose)
306 {
307 printf ("\n----- Maximum Iteration Exceeded: Code 4 (4 times)\n");
308 }
309
310 y_0 = 1; /* there is no root when y_0 > 0 */
311 sinput.xmin = -1e-18;
312 sinput.xmax = 1e-18;
313 yy0 = 1; /* there is no root when y_0 > 0 */
314 dinput.xmin = -1e-18;
315 dinput.xmax = 1e-18;
316
317 LALSBracketRoot (&status, &sinput, &y_0);
318 TestStatus (&status, CODES(FINDROOTH_EMXIT), 1);
319 LALDBracketRoot (&status, &dinput, &yy0);
320 TestStatus (&status, CODES(FINDROOTH_EMXIT), 1);
321
322 y_0 = -1;
323 sinput.xmin = 0;
324 sinput.xmax = 1e19;
325 sinput.xacc = 2e-38;
326 yy0 = -1;
327 dinput.xmin = 0;
328 dinput.xmax = 1e19;
329 dinput.xacc = 2e-38;
330
331 LALSBisectionFindRoot (&status, &sroot, &sinput, &y_0);
332 TestStatus (&status, CODES(FINDROOTH_EMXIT), 1);
333 LALDBisectionFindRoot (&status, &droot, &dinput, &yy0);
334 TestStatus (&status, CODES(FINDROOTH_EMXIT), 1);
335
336 /* root not bracketed error in BisectionFindRoot() */
337
338 if (verbose)
339 {
340 printf ("\n----- Root Not Bracketed: Code 8 (2 times)\n");
341 }
342
343 sinput.xmin = -5;
344 sinput.xmax = -3;
345 sinput.xacc = 1e-6;
346 dinput.xmin = -5;
347 dinput.xmax = -3;
348 dinput.xacc = 1e-6;
349
350 LALSBisectionFindRoot (&status, &sroot, &sinput, &y_0);
351 TestStatus (&status, CODES(FINDROOTH_EBRKT), 1);
352 LALDBisectionFindRoot (&status, &droot, &dinput, &yy0);
353 TestStatus (&status, CODES(FINDROOTH_EBRKT), 1);
354
355
356 return 0;
357}
358
359
360/*
361 * TestStatus ()
362 *
363 * Routine to check that the status code status->statusCode agrees with one of
364 * the codes specified in the space-delimited string ignored; if not,
365 * exit to the system with code exitcode.
366 *
367 */
368static void
369TestStatus (LALStatus *status, const char *ignored, int exitcode)
370{
371 char str[64];
372 char *tok;
373
374 if (verbose)
375 {
377 }
378
379 if (XLALStringCopy(str, ignored, sizeof(str)))
380 {
381 if ((tok = strtok (str, " ")))
382 {
383 do
384 {
385 if (status->statusCode == atoi (tok))
386 {
387 return;
388 }
389 }
390 while ((tok = strtok (NULL, " ")));
391 }
392 else
393 {
394 if (status->statusCode == atoi (str))
395 {
396 return;
397 }
398 }
399 }
400
401 fprintf (stderr, "\nExiting to system with code %d\n", exitcode);
402 exit (exitcode);
403}
404
405
406/*
407 *
408 * ClearStatus ()
409 *
410 * Recursively applies DETATCHSTATUSPTR() to status structure to destroy
411 * linked list of statuses.
412 *
413 */
414static void
415ClearStatus (LALStatus *status)
416{
417 if (status->statusPtr)
418 {
419 ClearStatus (status->statusPtr);
421 }
422}
423
424/*
425 * Usage ()
426 *
427 * Prints a usage message for program program and exits with code exitcode.
428 *
429 */
430static void
431Usage (const char *program, int exitcode)
432{
433 fprintf (stderr, "Usage: %s [options]\n", program);
434 fprintf (stderr, "Options:\n");
435 fprintf (stderr, " -h print this message\n");
436 fprintf (stderr, " -q quiet: run silently\n");
437 fprintf (stderr, " -v verbose: print extra information\n");
438 fprintf (stderr, " -d level set lalDebugLevel to level\n");
439 exit (exitcode);
440}
441
442
443/*
444 * ParseOptions ()
445 *
446 * Parses the argc - 1 option strings in argv[].
447 *
448 */
449static void
450ParseOptions (int argc, char *argv[])
451{
452 FILE *fp;
453
454 while (1)
455 {
456 int c = -1;
457
458 c = LALgetopt (argc, argv, "hqvd:");
459 if (c == -1)
460 {
461 break;
462 }
463
464 switch (c)
465 {
466 case 'd': /* set debug level */
467 break;
468
469 case 'v': /* verbose */
470 ++verbose;
471 break;
472
473 case 'q': /* quiet: run silently (ignore error messages) */
474 fp = freopen ("/dev/null", "w", stderr);
475 if (fp == NULL)
476 {
477 fprintf(stderr, "Error: Unable to open /dev/null\n");
478 exit(1);
479 }
480 fp = freopen ("/dev/null", "w", stdout);
481 if (fp == NULL)
482 {
483 fprintf(stderr, "Error: Unable to open /dev/null\n");
484 exit(1);
485 }
486 break;
487
488 case 'h':
489 Usage (argv[0], 0);
490 break;
491
492 default:
493 Usage (argv[0], 1);
494 }
495
496 }
497
498 if (LALoptind < argc)
499 {
500 Usage (argv[0], 1);
501 }
502
503 return;
504}
505
506/** \endcond */
const char * program
void REPORTSTATUS(LALStatus *status)
Definition: LALError.c:322
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
int LALgetopt(int argc, char *const *argv, const char *optstring)
Definition: LALgetopt.c:172
int LALoptind
Definition: LALgetopt.c:79
#define fprintf
static void Usage(const char *program, int exitcode)
Definition: XLALChisqTest.c:70
static void ParseOptions(int argc, char *argv[])
Definition: XLALChisqTest.c:88
int main(int argc, char *argv[])
Definition: cache.c:25
void LALDBracketRoot(LALStatus *status, DFindRootIn *inout, void *params)
Definition: FindRoot.c:147
void LALSBracketRoot(LALStatus *status, SFindRootIn *inout, void *params)
Definition: FindRoot.c:29
#define FINDROOTH_ENULL
Null pointer.
Definition: FindRoot.h:99
#define FINDROOTH_EIDOM
Invalid initial domain.
Definition: FindRoot.h:100
#define FINDROOTH_EBRKT
Root not bracketed.
Definition: FindRoot.h:102
void LALDBisectionFindRoot(LALStatus *status, REAL8 *root, DFindRootIn *input, void *params)
Definition: FindRoot.c:381
#define FINDROOTH_EMXIT
Maximum iterations exceeded.
Definition: FindRoot.h:101
void LALSBisectionFindRoot(LALStatus *status, REAL4 *root, SFindRootIn *input, void *params)
Definition: FindRoot.c:215
double REAL8
Double precision real floating-point number (8 bytes).
float REAL4
Single precision real floating-point number (4 bytes).
#define lalDebugLevel
Definition: LALDebugLevel.h:58
size_t XLALStringCopy(char *dst, const char *src, size_t size)
Copy sources string src to destination string dst.
Definition: LALString.c:104
These are function pointers to functions that map REAL8 numbers to REAL8 numbers.
Definition: FindRoot.h:130
REAL8 xacc
The accuracy desired for the root.
Definition: FindRoot.h:134
REAL8 xmax
The maximum value of the domain interval to look for the root.
Definition: FindRoot.h:132
void(* function)(LALStatus *s, REAL8 *y, REAL8 x, void *p)
The function to find the root of.
Definition: FindRoot.h:131
REAL8 xmin
The minimum value of the domain interval to look for the root.
Definition: FindRoot.h:133
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
These are function pointers to functions that map REAL4 numbers to REAL4 numbers.
Definition: FindRoot.h:117
REAL4 xacc
The accuracy desired for the root.
Definition: FindRoot.h:121
REAL4 xmax
The maximum value of the domain interval to look for the root.
Definition: FindRoot.h:119
REAL4 xmin
The minimum value of the domain interval to look for the root.
Definition: FindRoot.h:120
void(* function)(LALStatus *s, REAL4 *y, REAL4 x, void *p)
The function to find the root of.
Definition: FindRoot.h:118
int verbose
Definition: tconvert.c:103
FILE * fp
Definition: tconvert.c:105