SDDSlib
Loading...
Searching...
No Matches
zeroIH.c
Go to the documentation of this file.
1/**
2 * @file zeroIH.c
3 * @brief Implements the zeroIntHalve function for finding zeros of a function using interval halving.
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
19#define sign(x) ((x) > 0 ? 1 : ((x) == 0 ? 0 : -1))
20
21/**
22 * @brief Finds the zero of a function within a specified interval using interval halving.
23 *
24 * This function attempts to find a value `x` such that `fn(x)` is approximately equal to the given `value`.
25 * It employs the bisection method to iteratively narrow down the interval where the zero lies within `[x_i, x_f]`.
26 *
27 * @param fn Pointer to the function for which the zero is to be found.
28 * @param value The target value to solve for, i.e., find `x` such that `fn(x) = value`.
29 * @param x_i Initial value of the independent variable (start of the interval).
30 * @param x_f Final value of the independent variable (end of the interval).
31 * @param dx Step size to use when searching the interval.
32 * @param _zero Acceptable tolerance for the zero, determining when to stop the halving process.
33 *
34 * @return The `x` value where `fn(x)` is approximately equal to `value`, or `x_f + dx` if no zero is found within the interval.
35 */
37 double (*fn)(), /* pointer to function to be zeroed */
38 double value, /* solve for fn=value */
39 double x_i, /* initial, final values for independent variable */
40 double x_f,
41 double dx, /* size of steps in independent variable */
42 double _zero) /* value acceptably close to true zero */
43{
44 double xa, xb, xm, x_b;
45 double fa, fb, fm;
46 double f_abs, f_bdd;
47 long s_fa, s_fb, s_fm;
48 /* double zeroIH();*/
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 halve the interval, etc... */
75 f_bdd = 1000 * fabs(fa);
76 fm = (*fn)(xm = (xa + xb) / 2) - value;
77 s_fm = sign(fm);
78 x_b = xb;
79 do {
80 if (s_fm == 0)
81 return (xm);
82 else if (s_fm != s_fa) {
83 xb = xm;
84 fb = fm;
85 s_fb = s_fm;
86 } else {
87 xa = xm;
88 fa = fm;
89 s_fa = s_fm;
90 }
91 fm = (*fn)(xm = (xa + xb) / 2) - value;
92 s_fm = sign(fm);
93 f_abs = fabs(fm);
94 } while (f_abs > _zero && f_abs < f_bdd);
95 if (f_abs < _zero)
96 return (xm);
97 /* Function had a tan(x)-like singularity, which
98 * looked like a zero. So step beyond singularity
99 * and continue search.
100 */
101 /*return(zeroIH(fn, x_b, x_f, dx, _zero));*/
102 return (zeroIntHalve(fn, value, x_b, x_f, dx, _zero));
103 }
104 }
105 return (x_f + dx);
106}
double zeroIntHalve(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 interval halving.
Definition zeroIH.c:36