3 * Copyright (C) 2000, 2007 Brian Gough
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.
21 #include <gsl/gsl_errno.h>
22 #include <gsl/gsl_fit.h>
24 /* Fit the data (x_i, y_i) to the linear relationship
30 c0, c1 -- coefficients
31 cov00, cov01, cov11 -- variance-covariance matrix of c0 and c1,
32 sumsq -- sum of squares of residuals
34 This fit can be used in the case where the errors for the data are
35 uknown, but assumed equal for all points. The resulting
36 variance-covariance matrix estimates the error in the coefficients
37 from the observed variance of the points around the best fit line.
41 gsl_fit_linear (const double *x, const size_t xstride,
42 const double *y, const size_t ystride,
44 double *c0, double *c1,
45 double *cov_00, double *cov_01, double *cov_11, double *sumsq)
47 double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
51 for (i = 0; i < n; i++)
53 m_x += (x[i * xstride] - m_x) / (i + 1.0);
54 m_y += (y[i * ystride] - m_y) / (i + 1.0);
57 for (i = 0; i < n; i++)
59 const double dx = x[i * xstride] - m_x;
60 const double dy = y[i * ystride] - m_y;
62 m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
63 m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
66 /* In terms of y = a + b x */
69 double s2 = 0, d2 = 0;
70 double b = m_dxdy / m_dx2;
71 double a = m_y - m_x * b;
76 /* Compute chi^2 = \sum (y_i - (a + b * x_i))^2 */
78 for (i = 0; i < n; i++)
80 const double dx = x[i * xstride] - m_x;
81 const double dy = y[i * ystride] - m_y;
82 const double d = dy - b * dx;
86 s2 = d2 / (n - 2.0); /* chisq per degree of freedom */
88 *cov_00 = s2 * (1.0 / n) * (1 + m_x * m_x / m_dx2);
89 *cov_11 = s2 * 1.0 / (n * m_dx2);
91 *cov_01 = s2 * (-m_x) / (n * m_dx2);
100 /* Fit the weighted data (x_i, w_i, y_i) to the linear relationship
106 c0, c1 -- coefficients
107 s0, s1 -- the standard deviations of c0 and c1,
108 r -- the correlation coefficient between c0 and c1,
109 chisq -- weighted sum of squares of residuals */
112 gsl_fit_wlinear (const double *x, const size_t xstride,
113 const double *w, const size_t wstride,
114 const double *y, const size_t ystride,
116 double *c0, double *c1,
117 double *cov_00, double *cov_01, double *cov_11,
121 /* compute the weighted means and weighted deviations from the means */
123 /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
125 double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
129 for (i = 0; i < n; i++)
131 const double wi = w[i * wstride];
136 wm_x += (x[i * xstride] - wm_x) * (wi / W);
137 wm_y += (y[i * ystride] - wm_y) * (wi / W);
141 W = 0; /* reset the total weight */
143 for (i = 0; i < n; i++)
145 const double wi = w[i * wstride];
149 const double dx = x[i * xstride] - wm_x;
150 const double dy = y[i * ystride] - wm_y;
153 wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
154 wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
158 /* In terms of y = a + b x */
162 double b = wm_dxdy / wm_dx2;
163 double a = wm_y - wm_x * b;
168 *cov_00 = (1 / W) * (1 + wm_x * wm_x / wm_dx2);
169 *cov_11 = 1 / (W * wm_dx2);
171 *cov_01 = -wm_x / (W * wm_dx2);
173 /* Compute chi^2 = \sum w_i (y_i - (a + b * x_i))^2 */
175 for (i = 0; i < n; i++)
177 const double wi = w[i * wstride];
181 const double dx = x[i * xstride] - wm_x;
182 const double dy = y[i * ystride] - wm_y;
183 const double d = dy - b * dx;
197 gsl_fit_linear_est (const double x,
198 const double c0, const double c1,
199 const double cov00, const double cov01, const double cov11,
200 double *y, double *y_err)
203 *y_err = sqrt (cov00 + x * (2 * cov01 + cov11 * x));
209 gsl_fit_mul (const double *x, const size_t xstride,
210 const double *y, const size_t ystride,
212 double *c1, double *cov_11, double *sumsq)
214 double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
218 for (i = 0; i < n; i++)
220 m_x += (x[i * xstride] - m_x) / (i + 1.0);
221 m_y += (y[i * ystride] - m_y) / (i + 1.0);
224 for (i = 0; i < n; i++)
226 const double dx = x[i * xstride] - m_x;
227 const double dy = y[i * ystride] - m_y;
229 m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
230 m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
233 /* In terms of y = b x */
236 double s2 = 0, d2 = 0;
237 double b = (m_x * m_y + m_dxdy) / (m_x * m_x + m_dx2);
241 /* Compute chi^2 = \sum (y_i - b * x_i)^2 */
243 for (i = 0; i < n; i++)
245 const double dx = x[i * xstride] - m_x;
246 const double dy = y[i * ystride] - m_y;
247 const double d = (m_y - b * m_x) + dy - b * dx;
251 s2 = d2 / (n - 1.0); /* chisq per degree of freedom */
253 *cov_11 = s2 * 1.0 / (n * (m_x * m_x + m_dx2));
263 gsl_fit_wmul (const double *x, const size_t xstride,
264 const double *w, const size_t wstride,
265 const double *y, const size_t ystride,
267 double *c1, double *cov_11, double *chisq)
270 /* compute the weighted means and weighted deviations from the means */
272 /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
274 double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
278 for (i = 0; i < n; i++)
280 const double wi = w[i * wstride];
285 wm_x += (x[i * xstride] - wm_x) * (wi / W);
286 wm_y += (y[i * ystride] - wm_y) * (wi / W);
290 W = 0; /* reset the total weight */
292 for (i = 0; i < n; i++)
294 const double wi = w[i * wstride];
298 const double dx = x[i * xstride] - wm_x;
299 const double dy = y[i * ystride] - wm_y;
302 wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
303 wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
307 /* In terms of y = b x */
311 double b = (wm_x * wm_y + wm_dxdy) / (wm_x * wm_x + wm_dx2);
315 *cov_11 = 1 / (W * (wm_x * wm_x + wm_dx2));
317 /* Compute chi^2 = \sum w_i (y_i - b * x_i)^2 */
319 for (i = 0; i < n; i++)
321 const double wi = w[i * wstride];
325 const double dx = x[i * xstride] - wm_x;
326 const double dy = y[i * ystride] - wm_y;
327 const double d = (wm_y - b * wm_x) + (dy - b * dx);
339 gsl_fit_mul_est (const double x,
340 const double c1, const double cov11,
341 double *y, double *y_err)
344 *y_err = sqrt (cov11) * fabs (x);