LAL  7.5.0.1-ec27e42
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 */
28 void
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 */
96 int
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  {
124  if(XLALIsREAL8FailNaN(y_1) || XLALIsREAL8FailNaN(y_2))
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 */
146 void
148  LALStatus *status,
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 */
214 void
216  LALStatus *status,
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 */
307 REAL8
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);
337  if(XLALIsREAL8FailNaN(y_1) || XLALIsREAL8FailNaN(y_2))
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 */
380 void
382  LALStatus *status,
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