icedb  version 0.5.1
Snow particle scattering database API
zeros.cpp
Go to the documentation of this file.
1 #include "../icedb/zeros.hpp"
2 #include <cmath>
3 
4 namespace icedb {
5 
6  namespace zeros {
7  double findzero(double a, double b, const std::function<double(double) > &f )
8  {
9  using namespace std;
10  /* Define the basic testing variables.
11  eval func is the function's evaluator.
12  It typically links to the polynomial eval func.
13  The rest of the vars are used in Brent's method.
14  */
15  //evalfunction *f = evaltarget;
16  //double (*f)(double) = (double (*)(double)) evalfunc;
17  double convint = 1E-7;
18  double fcint = 1E-13;
19  double fa, fb, fc, fd, fs = 1.0;
20  unsigned int i=0;
21  fa = f(a);
22  fb = f(b);
23 
24  // Bad starting points if fa*fb > 0
25  if (fa*fb > 0)
27  .add<std::string>("Reason",
28  "Bad selection of a,b. f(a) and f(b) need to have opposite signs.")
29  .add<double>("a",a).add<double>("b",b)
30  .add<double>("fa",fa).add<double>("fb",fb);
31 
32  if ( abs(fa) < abs(fb) )
33  {
34  // Swap the two here. Junk only declared in block.
35  double junk = b;
36  b = a;
37  a = junk;
38  fa = f(a);
39  fb = f(b);
40  }
41 
42  double c = a; // A testing point
43  double s = 0, d = 0; // Initialize these to stop VS whining
44  fc = f(c);
45  bool mflag = true; // Flag for method stuff
46  while (fb != 0 || fs != 0 || abs(b-a) > convint)
47  {
48  if (fa != fc && fb != fc)
49  {
50  // Perform inverse quadratic interpolation
51  double i,j,k;
52  i = a * fb * fc / ( (fa - fb)*(fa - fc));
53  j = b * fa * fc / ( (fb - fa)*(fb - fc));
54  k = c * fa * fb / ( (fc - fa)*(fc - fb));
55  s = i + j + k;
56  } else {
57  // Use Secant Rule
58  s = b - fb * (b - a) / ( fb - fa );
59  }
60 
61  if (
62  ( (3.0*a+b)/4.0 < s && s < b) == false ||
63  (mflag && abs(s-b) >= (abs(b-c)/2.0) ) ||
64  (!mflag && abs(s-b) >= (abs(c-d)/2.0) ) ||
65  (mflag && abs(b-c) < convint) ||
66  (!mflag && abs(c-d) < convint)
67  )
68  {
69  // Bisection Method
70  mflag = true;
71  s = 0.5 * (a + b);
72  } else {
73  mflag = false;
74  }
75 
76  fs = f(s);
77 
78  d = c;
79  c = b;
80 
81  fd = f(d);
82  fc = f(c);
83 
84  if (fa * fs < 0)
85  {
86  b = s;
87  fb = f(b);
88  } else {
89  a = s;
90  fa = f(a);
91  }
92 
93 
94  if ( abs(fa) < abs(fb) )
95  {
96  // Do a swap again
97  double junk = b;
98  b = a;
99  a = junk;
100  fa = f(a);
101  fb = f(b);
102  }
103  i++;
104  //if (i > 100) break;
105  if ( abs(b-a) < convint && abs(fb) < fcint && abs(fs) < fcint ) break;
106  }
107  return s;
108  }
109 
110 
111  }
112 }
113 
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88
double findzero(double a, double b, const std::function< double(double) > &f)
Zero-finding implementation - Brent&#39;s method.
Definition: zeros.cpp:7