3 * Copyright (C) 1996, 1997, 1998, 1999, 2000 David Morrison
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <gsl/gsl_math.h>
23 #include <gsl/gsl_errno.h>
24 #include <gsl/gsl_diff.h>
27 gsl_diff_backward (const gsl_function * f,
28 double x, double *result, double *abserr)
30 /* Construct a divided difference table with a fairly large step
31 size to get a very rough estimate of f''. Use this to estimate
32 the step size which will minimize the error in calculating f'. */
35 double h = GSL_SQRT_DBL_EPSILON;
36 double a[3], d[3], a2;
38 /* Algorithm based on description on pg. 204 of Conte and de Boor
39 (CdB) - coefficients of Newton form of polynomial of degree 2. */
41 for (i = 0; i < 3; i++)
43 a[i] = x + (i - 2.0) * h;
44 d[i] = GSL_FN_EVAL (f, a[i]);
47 for (k = 1; k < 4; k++)
49 for (i = 0; i < 3 - k; i++)
51 d[i] = (d[i + 1] - d[i]) / (a[i + k] - a[i]);
55 /* Adapt procedure described on pg. 282 of CdB to find best value of
58 a2 = fabs (d[0] + d[1] + d[2]);
60 if (a2 < 100.0 * GSL_SQRT_DBL_EPSILON)
62 a2 = 100.0 * GSL_SQRT_DBL_EPSILON;
65 h = sqrt (GSL_SQRT_DBL_EPSILON / (2.0 * a2));
67 if (h > 100.0 * GSL_SQRT_DBL_EPSILON)
69 h = 100.0 * GSL_SQRT_DBL_EPSILON;
72 *result = (GSL_FN_EVAL (f, x) - GSL_FN_EVAL (f, x - h)) / h;
73 *abserr = fabs (10.0 * a2 * h);
79 gsl_diff_forward (const gsl_function * f,
80 double x, double *result, double *abserr)
82 /* Construct a divided difference table with a fairly large step
83 size to get a very rough estimate of f''. Use this to estimate
84 the step size which will minimize the error in calculating f'. */
87 double h = GSL_SQRT_DBL_EPSILON;
88 double a[3], d[3], a2;
90 /* Algorithm based on description on pg. 204 of Conte and de Boor
91 (CdB) - coefficients of Newton form of polynomial of degree 2. */
93 for (i = 0; i < 3; i++)
96 d[i] = GSL_FN_EVAL (f, a[i]);
99 for (k = 1; k < 4; k++)
101 for (i = 0; i < 3 - k; i++)
103 d[i] = (d[i + 1] - d[i]) / (a[i + k] - a[i]);
107 /* Adapt procedure described on pg. 282 of CdB to find best value of
110 a2 = fabs (d[0] + d[1] + d[2]);
112 if (a2 < 100.0 * GSL_SQRT_DBL_EPSILON)
114 a2 = 100.0 * GSL_SQRT_DBL_EPSILON;
117 h = sqrt (GSL_SQRT_DBL_EPSILON / (2.0 * a2));
119 if (h > 100.0 * GSL_SQRT_DBL_EPSILON)
121 h = 100.0 * GSL_SQRT_DBL_EPSILON;
124 *result = (GSL_FN_EVAL (f, x + h) - GSL_FN_EVAL (f, x)) / h;
125 *abserr = fabs (10.0 * a2 * h);
131 gsl_diff_central (const gsl_function * f,
132 double x, double *result, double *abserr)
134 /* Construct a divided difference table with a fairly large step
135 size to get a very rough estimate of f'''. Use this to estimate
136 the step size which will minimize the error in calculating f'. */
139 double h = GSL_SQRT_DBL_EPSILON;
140 double a[4], d[4], a3;
142 /* Algorithm based on description on pg. 204 of Conte and de Boor
143 (CdB) - coefficients of Newton form of polynomial of degree 3. */
145 for (i = 0; i < 4; i++)
147 a[i] = x + (i - 2.0) * h;
148 d[i] = GSL_FN_EVAL (f, a[i]);
151 for (k = 1; k < 5; k++)
153 for (i = 0; i < 4 - k; i++)
155 d[i] = (d[i + 1] - d[i]) / (a[i + k] - a[i]);
159 /* Adapt procedure described on pg. 282 of CdB to find best
160 value of step size. */
162 a3 = fabs (d[0] + d[1] + d[2] + d[3]);
164 if (a3 < 100.0 * GSL_SQRT_DBL_EPSILON)
166 a3 = 100.0 * GSL_SQRT_DBL_EPSILON;
169 h = pow (GSL_SQRT_DBL_EPSILON / (2.0 * a3), 1.0 / 3.0);
171 if (h > 100.0 * GSL_SQRT_DBL_EPSILON)
173 h = 100.0 * GSL_SQRT_DBL_EPSILON;
176 *result = (GSL_FN_EVAL (f, x + h) - GSL_FN_EVAL (f, x - h)) / (2.0 * h);
177 *abserr = fabs (100.0 * a3 * h * h);