icedb  version 0.5.1
Snow particle scattering database API
Functions
icedb::zeros Namespace Reference

Functions

double findzero (double a, double b, const std::function< double(double) > &evaltarget)
 Zero-finding implementation - Brent's method. More...
 
template<class T , class U >
secantMethod (const T &f, U guess_a, U guess_b, double eps=0.000001, size_t maxIter=50)
 

Function Documentation

◆ findzero()

double icedb::zeros::findzero ( double  a,
double  b,
const std::function< double(double) > &  f 
)

Zero-finding implementation - Brent's method.

Definition at line 7 of file zeros.cpp.

References ICEDB_throw, and icedb::error::xBadInput.

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  }
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88

◆ secantMethod()

template<class T , class U >
U icedb::zeros::secantMethod ( const T &  f,
guess_a,
guess_b,
double  eps = 0.000001,
size_t  maxIter = 50 
)

Definition at line 17 of file zeros.hpp.

References ICEDB_throw, and icedb::error::xModelOutOfRange.

Referenced by icedb::refract::bruggeman(), icedb::refract::guessTemp(), and icedb::refract::sihvola().

20  {
21  // Secant method is defined by recurrance
22  // xn = x_(n-1) - f(x_(n-1)) * (x_(n-1) - x_(n-2)) / (f(x_(n-1)) - f(x_(n-2)))
23  using namespace std;
24  U zero;
25  U xn = guess_a, xn1 = guess_b, xn2;
26  U fxn1, fxn2;
27  size_t i=0;
28  do {
29  xn2 = xn1;
30  xn1 = xn;
31 
32  fxn1 = f(xn1);
33  fxn2 = f(xn2);
34 
35  xn = xn1 - fxn1 * (xn1 - xn2) / (fxn1 - fxn2);
36  } while ( (abs(xn-xn1) > eps) && (i++ < maxIter));
37 
39  .add<size_t>("maxIter", maxIter)
40  .add<double>("eps", eps)
41  .template add<U>("guess_a", guess_a)
42  .template add<U>("guess_b", guess_b)
43  .template add<U>("xn",xn)
44  .template add<U>("xn1",xn1)
45  .template add<U>("xn2",xn2)
46  .template add<U>("fxn1",fxn1)
47  .template add<U>("fxn2",fxn2);
48  zero = xn;
49  return zero;
50  }
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88
Here is the caller graph for this function: