SDDSlib
Loading...
Searching...
No Matches
zeroInterp.c
Go to the documentation of this file.
1/**
2 * @file zeroInterp.c
3 * @brief Implements the zeroInterp function for finding zeros of a function using successive interpolation.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author M. Borland, C. Saunders, R. Soliday
14 */
15
16#include <math.h>
17#include <stdio.h>
18#include "mdb.h"
19
20#define sign(x) ((x) > 0 ? 1 : ((x) == 0 ? 0 : -1))
21
22/**
23 * @brief Finds the zero of a function within a specified interval using successive interpolation.
24 *
25 * This function attempts to find a value `x` such that `fn(x)` is approximately equal to the given `value`.
26 * It uses an iterative interpolation method to locate the zero within the interval `[x_i, x_f]`.
27 *
28 * @param fn Pointer to the function for which the zero is to be found.
29 * @param value The target value to solve for, i.e., find `x` such that `fn(x) = value`.
30 * @param x_i Initial value of the independent variable (start of the interval).
31 * @param x_f Final value of the independent variable (end of the interval).
32 * @param dx Step size to use when searching the interval.
33 * @param _zero Acceptable tolerance for the zero, determining when to stop the interpolation.
34 *
35 * @return The `x` value where `fn(x)` is approximately equal to `value`, or `x_f + dx` if no zero is found within the interval.
36 */
38 double (*fn)(), /* pointer to function to be zeroed */
39 double value, /* sovle for fn=value */
40 double x_i, /* initial, final values for independent variable */
41 double x_f,
42 double dx, /* size of steps in independent variable */
43 double _zero) /* value acceptably close to true zero */
44{
45 double xa, xb, xm, x_b;
46 double fa, fb, fm;
47 double f_abs, f_bdd;
48 long s_fa, s_fb, s_fm;
49
50 if (dx > (x_f - x_i))
51 dx = (x_f - x_i) / 2;
52
53 xa = x_i;
54 xb = xa + dx;
55
56 if (xb > x_f)
57 xb = x_f;
58 if (xa == xb)
59 xa = xb - dx;
60
61 fa = (*fn)(xa)-value;
62 s_fa = sign(fa);
63
64 while (xb <= x_f) {
65 fb = (*fn)(xb)-value;
66 s_fb = sign(fb);
67 if (s_fb == s_fa) {
68 fa = fb;
69 xa = xb;
70 s_fa = s_fb;
71 xb = xb + dx;
72 } else {
73 /* function has passed through zero */
74 /* so interpolate to find zero, repeat */
75 f_bdd = 1000 * fabs(fa);
76 xm = xa - fa * (xa - xb) / (fa - fb);
77 fm = (*fn)(xm)-value;
78 s_fm = sign(fm);
79 x_b = xb;
80 do {
81 if (s_fm == 0)
82 return (xm);
83 else if (s_fm != s_fa) {
84 xb = xm;
85 fb = fm;
86 s_fb = s_fm;
87 } else {
88 xa = xm;
89 fa = fm;
90 s_fa = s_fm;
91 }
92 xm = xa - fa * (xa - xb) / (fa - fb);
93 fm = (*fn)(xm)-value;
94 s_fm = sign(fm);
95 f_abs = fabs(fm);
96 } while (f_abs > _zero && f_abs < f_bdd);
97 if (f_abs < _zero)
98 return (xm);
99 /* Function had a tan(x)-like singularity, which
100 * looked like a zero. So step beyond singularity
101 * and continue search.
102 */
103 return (zeroInterp(fn, value, x_b, x_f, dx, _zero));
104 }
105 }
106 return (x_f + dx);
107}
double zeroInterp(double(*fn)(), double value, double x_i, double x_f, double dx, double _zero)
Finds the zero of a function within a specified interval using successive interpolation.
Definition zeroInterp.c:37