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
FindRoot.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Jolien Creighton, Kipp Cannon
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/* ---------- see FindRoot.h for doxygen documentation ---------- */
21
22#include <math.h>
23#include <lal/LALStdlib.h>
24#include <lal/LALConstants.h>
25#include <lal/FindRoot.h>
26
27/** \see See \ref FindRoot_h for documentation */
28void
31 SFindRootIn *inout,
32 void *params
33 )
34{
35 const REAL4 fac = LAL_SQRT2;
36
37 INT4 i = 0;
38 REAL4 y_1;
39 REAL4 y_2;
40
43
44 /* check that arguments are reasonable */
45 ASSERT (inout, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
46 ASSERT (inout->function, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
47 /* params can be NULL ... */
48
49 ASSERT (inout->xmax != inout->xmin, status,
50 FINDROOTH_EIDOM, FINDROOTH_MSGEIDOM);
51
52 /* evaluate function at endpoints */
53
54 inout->function (status->statusPtr, &y_1, inout->xmin, params);
56
57 inout->function (status->statusPtr, &y_2, inout->xmax, params);
59
60 while (1)
61 {
62 /* break out if root has been bracketed */
63 if (y_1*y_2 < 0)
64 {
65 break;
66 }
67
68 /* increment iteration count */
69 const INT4 imax = 64;
70 ASSERT (i < imax, status, FINDROOTH_EMXIT, FINDROOTH_MSGEMXIT);
71 ++i;
72
73 if (fabs(y_1) < fabs(y_2))
74 {
75 /* expand lower limit */
76 inout->xmin += fac*(inout->xmin - inout->xmax);
77 inout->function (status->statusPtr, &y_1, inout->xmin, params);
79 }
80 else
81 {
82 /* expand upper limit */
83 inout->xmax += fac*(inout->xmax - inout->xmin);
84 inout->function (status->statusPtr, &y_2, inout->xmax, params);
86 }
87
88 }
89
91 RETURN (status);
92}
93
94
95/** \see See \ref FindRoot_h for documentation */
96int
98 REAL8 (*y)(REAL8, void *),
99 REAL8 *xmin,
100 REAL8 *xmax,
101 void *params
102)
103{
104 const INT4 imax = 64;
105 INT4 i;
106 REAL8 y_1;
107 REAL8 y_2;
108
109 /* put xmin and xmax in the correct order (use y_1 as temporary storage) */
110 if(*xmin > *xmax)
111 {
112 y_1 = *xmin;
113 *xmin = *xmax;
114 *xmax = y_1;
115 }
116
117 /* evaluate function at endpoints */
118 y_1 = y(*xmin, params);
119 y_2 = y(*xmax, params);
120
121 /* loop until iteration limit exceeded or root bracketed */
122 for(i = 0; y_1 * y_2 >= 0.0; i++)
123 {
126 if(i >= imax)
128 if(fabs(y_1) < fabs(y_2))
129 {
130 /* expand lower limit */
131 *xmin -= LAL_SQRT2 * (*xmax - *xmin);
132 y_1 = y(*xmin, params);
133 }
134 else
135 {
136 /* expand upper limit */
137 *xmax += LAL_SQRT2 * (*xmax - *xmin);
138 y_2 = y(*xmax, params);
139 }
140 }
141
142 return(0);
143}
144
145/** \see See \ref FindRoot_h for documentation */
146void
149 DFindRootIn *inout,
150 void *params
151 )
152{
153 const REAL8 fac = LAL_SQRT2;
154
155 INT4 i = 0;
156 REAL8 y_1;
157 REAL8 y_2;
158
161
162 /* check that arguments are reasonable */
163 ASSERT (inout, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
164 ASSERT (inout->function, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
165 /* params can be NULL ... */
166
167 ASSERT (inout->xmax != inout->xmin, status,
168 FINDROOTH_EIDOM, FINDROOTH_MSGEIDOM);
169
170 /* evaluate function at endpoints */
171
172 inout->function (status->statusPtr, &y_1, inout->xmin, params);
174
175 inout->function (status->statusPtr, &y_2, inout->xmax, params);
177
178 while (1)
179 {
180 /* break out if root has been bracketed */
181 if (y_1*y_2 < 0)
182 {
183 break;
184 }
185
186 /* increment iteration count */
187 const INT4 imax = 64;
188 ASSERT (i < imax, status, FINDROOTH_EMXIT, FINDROOTH_MSGEMXIT);
189 ++i;
190
191 if (fabs(y_1) < fabs(y_2))
192 {
193 /* expand lower limit */
194 inout->xmin += fac*(inout->xmin - inout->xmax);
195 inout->function (status->statusPtr, &y_1, inout->xmin, params);
197 }
198 else
199 {
200 /* expand upper limit */
201 inout->xmax += fac*(inout->xmax - inout->xmin);
202 inout->function (status->statusPtr, &y_2, inout->xmax, params);
204 }
205
206 }
207
209 RETURN (status);
210}
211
212
213/** \see See \ref FindRoot_h for documentation */
214void
217 REAL4 *root,
218 SFindRootIn *input,
219 void *params
220 )
221{
222
223 INT4 i = 0;
224 REAL4 y_1;
225 REAL4 y_2;
226 REAL4 x;
227 REAL4 dx;
228
231
232 /* check that arguments are reasonable */
233 ASSERT (root, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
234 ASSERT (input, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
235 ASSERT (input->function, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
236 /* params can be NULL ... */
237
238 /* evaluate function at endpoints */
239
240 input->function (status->statusPtr, &y_1, input->xmin, params);
242
243 input->function (status->statusPtr, &y_2, input->xmax, params);
245
246 ASSERT (y_1*y_2 < 0, status, FINDROOTH_EBRKT, FINDROOTH_MSGEBRKT);
247
248 if (y_1 < 0)
249 {
250 /* start search at xmin and increase */
251 x = input->xmin;
252 dx = input->xmax - input->xmin;
253 }
254 else
255 {
256 /* start search at xmax and decrease */
257 x = input->xmax;
258 dx = input->xmin - input->xmax;
259 }
260
261 /* infinite loop to locate root */
262 while (1)
263 {
264 REAL4 xmid;
265 REAL4 ymid;
266
267 /* increment iteration count */
268 const INT4 imax = 40;
269 ASSERT (i < imax, status, FINDROOTH_EMXIT, FINDROOTH_MSGEMXIT);
270 ++i;
271
272 /* locate midpoint of domain */
273 dx /= 2;
274 xmid = x + dx;
275
276 /* evaluate function at midpoint */
277 input->function (status->statusPtr, &ymid, xmid, params);
279
280 if (ymid < 0)
281 {
282 /* function is in second half of domain */
283 x = xmid;
284 }
285 else if (ymid == 0)
286 {
287 /* root has been found */
288 *root = xmid;
289 break;
290 }
291
292 if (fabs(dx) < input->xacc)
293 {
294 /* domain has shrunk to acceptably small size */
295 *root = xmid;
296 break;
297 }
298
299 }
300
302 RETURN (status);
303}
304
305
306/** \see See \ref FindRoot_h for documentation */
307REAL8
309 REAL8 (*y)(REAL8, void *),
310 REAL8 xmin,
311 REAL8 xmax,
312 REAL8 xacc,
313 void *params
314)
315{
316 const INT4 imax = 80;
317 INT4 i;
318 REAL8 y_1;
319 REAL8 y_2;
320 REAL8 xmid;
321 REAL8 ymid;
322
323 /* check arguments */
324 if(xacc < 0.0)
326
327 /* put xmin and xmax in the correct order, using y_1 as temporary storage */
328 if(xmin > xmax) {
329 y_1 = xmin;
330 xmin = xmax;
331 xmax = y_1;
332 }
333
334 /* evaluate function at endpoints */
335 y_1 = y(xmin, params);
336 y_2 = y(xmax, params);
339
340 /* loop until root found within requested accuracy or iteration limit
341 * exceeded */
342 for(i = 0; (xmax - xmin) > xacc; i++)
343 {
344 if(i >= imax)
346
347 /* evaluate function at midpoint */
348 xmid = (xmin + xmax) / 2.0;
349 ymid = y(xmid, params);
350 if(XLALIsREAL8FailNaN(ymid))
352
353 /* did we get lucky? */
354 if(ymid == 0.0)
355 break;
356
357 if(y_1 * ymid < 0.0)
358 {
359 /* root is in first half of domain */
360 xmax = xmid;
361 y_2 = ymid;
362 }
363 else if(y_2 * ymid < 0.0)
364 {
365 /* root is in second half of domain */
366 xmin = xmid;
367 y_1 = ymid;
368 }
369 else
370 {
371 /* something's gone wrong */
373 }
374 }
375
376 return((xmin + xmax) / 2.0);
377}
378
379/** \see See \ref FindRoot_h for documentation */
380void
383 REAL8 *root,
384 DFindRootIn *input,
385 void *params
386 )
387{
388
389 INT4 i = 0;
390 REAL8 y_1;
391 REAL8 y_2;
392 REAL8 x;
393 REAL8 dx;
394
397
398 /* check that arguments are reasonable */
399 ASSERT (root, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
400 ASSERT (input, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
401 ASSERT (input->function, status, FINDROOTH_ENULL, FINDROOTH_MSGENULL);
402 /* params can be NULL ... */
403
404 /* evaluate function at endpoints */
405
406 input->function (status->statusPtr, &y_1, input->xmin, params);
408
409 input->function (status->statusPtr, &y_2, input->xmax, params);
411
412 ASSERT (y_1*y_2 < 0, status, FINDROOTH_EBRKT, FINDROOTH_MSGEBRKT);
413
414 if (y_1 < 0)
415 {
416 /* start search at xmin and increase */
417 x = input->xmin;
418 dx = input->xmax - input->xmin;
419 }
420 else
421 {
422 /* start search at xmax and decrease */
423 x = input->xmax;
424 dx = input->xmin - input->xmax;
425 }
426
427 /* infinite loop to locate root */
428 while (1)
429 {
430 REAL8 xmid;
431 REAL8 ymid;
432
433 /* increment iteration count */
434 const INT4 imax = 80;
435 ASSERT (i < imax, status, FINDROOTH_EMXIT, FINDROOTH_MSGEMXIT);
436 ++i;
437
438 /* locate midpoint of domain */
439 dx /= 2;
440 xmid = x + dx;
441
442 /* evaluate function at midpoint */
443 input->function (status->statusPtr, &ymid, xmid, params);
445
446 if (ymid < 0)
447 {
448 /* function is in second half of domain */
449 x = xmid;
450 }
451 else if (ymid == 0)
452 {
453 /* root has been found */
454 *root = xmid;
455 break;
456 }
457
458 if (fabs(dx) < input->xacc)
459 {
460 /* domain has shrunk to acceptably small size */
461 *root = xmid;
462 break;
463 }
464
465 }
466
468 RETURN (status);
469}
#define CHECKSTATUSPTR(statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
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
REAL8 XLALDBisectionFindRoot(REAL8(*y)(REAL8, void *), REAL8 xmin, REAL8 xmax, REAL8 xacc, void *params)
Definition: FindRoot.c:308
int XLALDBracketRoot(REAL8(*y)(REAL8, void *), REAL8 *xmin, REAL8 *xmax, void *params)
Definition: FindRoot.c:97
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
#define LAL_SQRT2
Pythagoras's constant, sqrt(2)
Definition: LALConstants.h:174
double REAL8
Double precision real floating-point number (8 bytes).
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
#define XLAL_ERROR_REAL8(...)
Macro to invoke a failure from a XLAL routine returning a REAL8.
Definition: XLALError.h:752
#define XLAL_ERROR(...)
Macro to invoke a failure from a XLAL routine returning an integer.
Definition: XLALError.h:700
static _LAL_INLINE_ int XLALIsREAL8FailNaN(REAL8 val)
Tests if a value is an XLAL REAL8 failure NaN.
Definition: XLALError.h:368
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EMAXITER
Exceeded maximum number of iterations.
Definition: XLALError.h:455
@ XLAL_EDOM
Input domain error.
Definition: XLALError.h:410
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
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