Canoe
Comprehensive Atmosphere N' Ocean Engine
root.c
Go to the documentation of this file.
1 #define MAX_IT 100
2 #define UNLIKELY_VAL -1.11111e+30
3 
4 #include "root.h"
5 
6 #include <math.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 int root(double x1, double x2, double xacc, double *x_root, RootFunction_t func,
11  void *aux) {
12  int iter, compare;
13  double fh, fl, fm, fnew, s, xh, xl, xm, xnew;
14  static char name[] = "_root";
15 
16  fl = func(x1, aux);
17  fh = func(x2, aux);
18  if ((fl > 0. && fh < 0.) || (fl < 0. && fh > 0.)) {
19  xl = x1;
20  xh = x2;
21  /* Set *x_root to an unlikely value: */
22  *x_root = UNLIKELY_VAL;
23 
24  for (iter = 0; iter < MAX_IT; iter++) {
25  xm = 0.5 * (xl + xh);
26  fm = func(xm, aux);
27  s = sqrt(fm * fm - fl * fh);
28  if (s == 0.) {
29  return 0;
30  }
31  xnew = xm + (xm - xl) * ((fl > fh ? 1. : -1.) * fm / s);
32 
33  if (fabs(xnew - *x_root) <= xacc) {
34  return 0;
35  }
36  *x_root = xnew;
37 
38  fnew = func(*x_root, aux);
39  if (fnew == 0.) {
40  return 0;
41  }
42 
43  if ((fnew > 0. ? fabs(fm) : -fabs(fm)) != fm) {
44  xl = xm;
45  fl = fm;
46  xh = *x_root;
47  fh = fnew;
48  } else if ((fnew > 0. ? fabs(fl) : -fabs(fl)) != fl) {
49  xh = *x_root;
50  fh = fnew;
51  } else if ((fnew > 0. ? fabs(fh) : -fabs(fh)) != fh) {
52  xl = *x_root;
53  fl = fnew;
54  } else {
55  fprintf(stderr,
56  "### FATAL ERROR in _root function: should never get here\n");
57  exit(1);
58  }
59  if (fabs(xh - xl) <= xacc) {
60  return 0;
61  }
62  }
63  fprintf(stderr, "### FATAL ERROR in _root function: exceeded MAX_IT = ");
64  fprintf(stderr, "%d\n", MAX_IT);
65  fprintf(stderr, "current root calc = ");
66  fprintf(stderr, "%12.4g\n", *x_root);
67  exit(1);
68  } else {
69  if (fl == 0.) {
70  *x_root = x1;
71  return 0;
72  }
73  if (fh == 0.) {
74  *x_root = x2;
75  return 0;
76  }
77 
78  compare = fabs(fl) >= fabs(fh) ? 1 : -1;
79  if (compare < 0) {
80  return -1;
81  } else {
82  return 1;
83  }
84  }
85 
86  /* Should never get here. */
87  fprintf(stderr, "### FATAL ERROR in _root function: should never get here\n");
88  exit(1);
89 }
90 
91 #undef MAX_IT
92 #undef UNLIKELY_VAL
Real fl[8]
#define UNLIKELY_VAL
Definition: root.c:2
#define MAX_IT
Definition: root.c:1
int root(double x1, double x2, double xacc, double *x_root, RootFunction_t func, void *aux)
Definition: root.c:10
double(* RootFunction_t)(double, void *)
Definition: root.h:8