Canoe
Comprehensive Atmosphere N' Ocean Engine
root.hpp
Go to the documentation of this file.
1 #ifndef SRC_CLIMATH_ROOT_HPP_
2 #define SRC_CLIMATH_ROOT_HPP_
3 
4 #include <cmath>
5 #include <cstdio>
6 #include <cstdlib>
7 
8 #undef MAX_IT
9 #define MAX_IT 100
10 
11 #undef UNLIKELY_VAL
12 #define UNLIKELY_VAL -1.11111e+30
13 
14 template <typename FLOAT, typename FUNC>
15 int root(FLOAT x1, FLOAT x2, FLOAT xacc, FLOAT *x_root, FUNC func) {
16  int iter, compare;
17  FLOAT
18  fh, fl, fm, fnew, s, xh, xl, xm, xnew;
19  /*
20  * The following are part of DEBUG_MILESTONE(.) statements:
21  int
22  idbms=0;
23  */
24  static char dbmsname[] = "_FindRoot";
25 
26  fl = func(x1);
27  fh = func(x2);
28  if ((fl > 0. && fh < 0.) || (fl < 0. && fh > 0.)) {
29  xl = x1;
30  xh = x2;
31  /* Set *x_root to an unlikely value: */
32  *x_root = UNLIKELY_VAL;
33 
34  for (iter = 0; iter < MAX_IT; iter++) {
35  xm = 0.5 * (xl + xh);
36  fm = func(xm);
37  s = sqrt(fm * fm - fl * fh);
38  if (s == 0.) {
39  return 0;
40  }
41  xnew = xm + (xm - xl) * ((fl > fh ? 1. : -1.) * fm / s);
42 
43  if (fabs(xnew - *x_root) <= xacc) {
44  return 0;
45  }
46  *x_root = xnew;
47 
48  fnew = func(*x_root);
49  if (fnew == 0.) {
50  return 0;
51  }
52 
53  if ((fnew > 0. ? fabs(fm) : -fabs(fm)) != fm) {
54  xl = xm;
55  fl = fm;
56  xh = *x_root;
57  fh = fnew;
58  } else if ((fnew > 0. ? fabs(fl) : -fabs(fl)) != fl) {
59  xh = *x_root;
60  fh = fnew;
61  } else if ((fnew > 0. ? fabs(fh) : -fabs(fh)) != fh) {
62  xl = *x_root;
63  fl = fnew;
64  } else {
65  fprintf(stderr, "**error:%s, should never get here\n", dbmsname);
66  exit(1);
67  }
68  if (fabs(xh - xl) <= xacc) {
69  return 0;
70  }
71  }
72  fprintf(stderr,
73  "**error:%s, exceeded MAX_IT = %d, current root calc = %e\n",
74  dbmsname, MAX_IT, *x_root);
75  exit(1);
76  } else {
77  if (fl == 0.) {
78  *x_root = x1;
79  return 0;
80  }
81  if (fh == 0.) {
82  *x_root = x2;
83  return 0;
84  }
85 
86  compare = fabs(fl) >= fabs(fh) ? 1 : -1;
87  if (compare < 0) {
88  return -1;
89  } else {
90  return 1;
91  }
92  }
93 
94  /* Should never get here. */
95  fprintf(stderr, "**error:%s, should never reach here\n", dbmsname);
96  exit(1);
97 }
98 
99 #undef MAX_IT
100 #undef UNLIKELY_VAL
101 
102 #endif // SRC_CLIMATH_ROOT_HPP_
Real fl[8]
#define UNLIKELY_VAL
Definition: root.hpp:12
#define MAX_IT
Definition: root.hpp:9
int root(FLOAT x1, FLOAT x2, FLOAT xacc, FLOAT *x_root, FUNC func)
Definition: root.hpp:15