WARPXM v1.10.0
Loading...
Searching...
No Matches
root_finders.h
Go to the documentation of this file.
1#ifndef WXM_ROOT_FINDERS_H
2#define WXM_ROOT_FINDERS_H
3
4#include "warpxm/warpxm_config.h"
5#include <cassert>
6
7namespace wxm
8{
9namespace root_finders
10{
11
12// Finding root of function using bisection.
13// fun(a) and fun(b) must be of opposite sign
14// This is a modified version of:
15// //
16// https://stackoverflow.com/questions/28267910/function-as-parameter-of-a-function-using-bisection-method-c
17// instead of function pointer we have template
18// template <class T>
19// real bisection(const T &fun, real a, real b);
20
21// template <class T>
22// real bisection(const T &fun, real a, real b) {
23// static const real EPS = 1e-15; // 1×10^(-15)
24// real fa = fun(a), fb = fun(b);
25
26// std::cout << "initially a = " << a << " b = " << b << " f(a) = " << fa << " f(b) = "
27// << fb << std::endl;
28
29// // if either f(a) or f(b) are the root, return that
30// // nothing else to do
31// if (fa == 0) return a;
32// if (fb == 0) return b;
33
34// // this method only works if the signs of f(a) and f(b)
35// // are different. so just assert that
36// assert(fa * fb < 0); // 8.- macro assert from header cassert.
37
38// do {
39// // calculate fun at the midpoint of a,b
40// // if that's the root, we're done
41
42// // this line is awful, never write code like this...
43// //if ((f = fun((s = (a + b) / 2))) == 0) break;
44
45// // prefer:
46// real midpt = (a + b) / 2;
47// real fmid = fun(midpt);
48// std::cout << "(midpt,fmid) = (" << midpt << ", " << fmid << ")" << std::endl;
49
50// if (fmid == 0) return midpt;
51
52// // adjust our bounds to either [a,midpt] or [midpt,b]
53// // based on where fmid ends up being. I'm pretty
54// // sure the code in the question is wrong, so I fixed it
55// if (fa * fmid < 0) { // fmid, not f1
56// fb = fmid;
57// b = midpt;
58// }
59// else {
60// fa = fmid;
61// a = midpt;
62// }
63// } while (fabs(b-a) > EPS); // only loop while
64// // a and b are sufficiently far
65// // apart
66
67// std::cout << "a = " << a << " b = " << b << std::endl;
68// return (a + b) / 2; // approximation
69// }
70
71// This is a modified version of:
72// // https://www.geeksforgeeks.org/program-for-bisection-method/
73// instead of function pointer we have template
74// also there is a check that b >= a for the interval and if not they are swapped
75
76template<class T> real bisection(const T& fun, real a, real b)
77{
78 // make sure a < b
79
80 if (a > b)
81 {
82 int temp = b;
83 b = a;
84 a = temp;
85 }
86 // std::cout << "initially a = " << a << " b = " << b << " f(a) = " << fun(a) << "
87 // f(b) = " << fun(b) << std::endl;
88 static const real epsilon = 1e-15; // 1×10^(-15)
89 if (fun(a) * fun(b) >= 0)
90 {
91 // throw WxExcept("wxm::root_finders::bisection You have not assumed correct
92 // bounds a (=%f) and b\n",a);
93 WxExcept wxe("wxm::root_finders::bisection You have not assumed correct bounds");
94
95 throw wxe << " a = " << a << " b = " << b << std::endl;
96 // return;
97 }
98
99 // std::cout << "initially (b-a) = " << (b-a) << std::endl;
100 real c = a;
101 // while (fabs(b-a) >= epsilon)
102 while (b - a >= epsilon)
103 {
104 // std::cout << "(b-a) = " << (b-a) << std::endl;
105 // Find middle point
106 c = (a + b) / 2;
107
108 // Check if middle point is root
109 if (fun(c) == 0.0)
110 return c;
111
112 // Decide the side to repeat the steps
113 else if (fun(c) * fun(a) < 0)
114 b = c;
115 else
116 a = c;
117 }
118 // std::cout << "The value of root is : " << c << " and f(c) = " << fun(c) <<
119 // std::endl;
120
121 return c;
122}
123
124} // namespace root_finders
125} // namespace wxm
126
127#endif // WXM_ROOT_FINDERS_H
wxm::lib::Except is the class to use for creating and throwing exceptions.
Definition: wxexcept.h:31
real bisection(const T &fun, real a, real b)
Definition: root_finders.h:76
Base namespace for everything not included in the global namespace.
Definition: field_source.h:8
#define real
Definition: wmoclunstructuredreconstruction.h:11