gsl_fit__linear.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* fit/linear.c
  2. *
  3. * Copyright (C) 2000, 2007 Brian Gough
  4. *
  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.
  9. *
  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.
  14. *
  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.
  18. */
  19. #include "gsl__config.h"
  20. #include "gsl_errno.h"
  21. #include "gsl_fit.h"
  22. /* Fit the data (x_i, y_i) to the linear relationship
  23. Y = c0 + c1 x
  24. returning,
  25. c0, c1 -- coefficients
  26. cov00, cov01, cov11 -- variance-covariance matrix of c0 and c1,
  27. sumsq -- sum of squares of residuals
  28. This fit can be used in the case where the errors for the data are
  29. uknown, but assumed equal for all points. The resulting
  30. variance-covariance matrix estimates the error in the coefficients
  31. from the observed variance of the points around the best fit line.
  32. */
  33. int
  34. gsl_fit_linear (const double *x, const size_t xstride,
  35. const double *y, const size_t ystride,
  36. const size_t n,
  37. double *c0, double *c1,
  38. double *cov_00, double *cov_01, double *cov_11, double *sumsq)
  39. {
  40. double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
  41. size_t i;
  42. for (i = 0; i < n; i++)
  43. {
  44. m_x += (x[i * xstride] - m_x) / (i + 1.0);
  45. m_y += (y[i * ystride] - m_y) / (i + 1.0);
  46. }
  47. for (i = 0; i < n; i++)
  48. {
  49. const double dx = x[i * xstride] - m_x;
  50. const double dy = y[i * ystride] - m_y;
  51. m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
  52. m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
  53. }
  54. /* In terms of y = a + b x */
  55. {
  56. double s2 = 0, d2 = 0;
  57. double b = m_dxdy / m_dx2;
  58. double a = m_y - m_x * b;
  59. *c0 = a;
  60. *c1 = b;
  61. /* Compute chi^2 = \sum (y_i - (a + b * x_i))^2 */
  62. for (i = 0; i < n; i++)
  63. {
  64. const double dx = x[i * xstride] - m_x;
  65. const double dy = y[i * ystride] - m_y;
  66. const double d = dy - b * dx;
  67. d2 += d * d;
  68. }
  69. s2 = d2 / (n - 2.0); /* chisq per degree of freedom */
  70. *cov_00 = s2 * (1.0 / n) * (1 + m_x * m_x / m_dx2);
  71. *cov_11 = s2 * 1.0 / (n * m_dx2);
  72. *cov_01 = s2 * (-m_x) / (n * m_dx2);
  73. *sumsq = d2;
  74. }
  75. return GSL_SUCCESS;
  76. }
  77. /* Fit the weighted data (x_i, w_i, y_i) to the linear relationship
  78. Y = c0 + c1 x
  79. returning,
  80. c0, c1 -- coefficients
  81. s0, s1 -- the standard deviations of c0 and c1,
  82. r -- the correlation coefficient between c0 and c1,
  83. chisq -- weighted sum of squares of residuals */
  84. int
  85. gsl_fit_wlinear (const double *x, const size_t xstride,
  86. const double *w, const size_t wstride,
  87. const double *y, const size_t ystride,
  88. const size_t n,
  89. double *c0, double *c1,
  90. double *cov_00, double *cov_01, double *cov_11,
  91. double *chisq)
  92. {
  93. /* compute the weighted means and weighted deviations from the means */
  94. /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
  95. double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
  96. size_t i;
  97. for (i = 0; i < n; i++)
  98. {
  99. const double wi = w[i * wstride];
  100. if (wi > 0)
  101. {
  102. W += wi;
  103. wm_x += (x[i * xstride] - wm_x) * (wi / W);
  104. wm_y += (y[i * ystride] - wm_y) * (wi / W);
  105. }
  106. }
  107. W = 0; /* reset the total weight */
  108. for (i = 0; i < n; i++)
  109. {
  110. const double wi = w[i * wstride];
  111. if (wi > 0)
  112. {
  113. const double dx = x[i * xstride] - wm_x;
  114. const double dy = y[i * ystride] - wm_y;
  115. W += wi;
  116. wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
  117. wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
  118. }
  119. }
  120. /* In terms of y = a + b x */
  121. {
  122. double d2 = 0;
  123. double b = wm_dxdy / wm_dx2;
  124. double a = wm_y - wm_x * b;
  125. *c0 = a;
  126. *c1 = b;
  127. *cov_00 = (1 / W) * (1 + wm_x * wm_x / wm_dx2);
  128. *cov_11 = 1 / (W * wm_dx2);
  129. *cov_01 = -wm_x / (W * wm_dx2);
  130. /* Compute chi^2 = \sum w_i (y_i - (a + b * x_i))^2 */
  131. for (i = 0; i < n; i++)
  132. {
  133. const double wi = w[i * wstride];
  134. if (wi > 0)
  135. {
  136. const double dx = x[i * xstride] - wm_x;
  137. const double dy = y[i * ystride] - wm_y;
  138. const double d = dy - b * dx;
  139. d2 += wi * d * d;
  140. }
  141. }
  142. *chisq = d2;
  143. }
  144. return GSL_SUCCESS;
  145. }
  146. int
  147. gsl_fit_linear_est (const double x,
  148. const double c0, const double c1,
  149. const double cov00, const double cov01, const double cov11,
  150. double *y, double *y_err)
  151. {
  152. *y = c0 + c1 * x;
  153. *y_err = sqrt (cov00 + x * (2 * cov01 + cov11 * x));
  154. return GSL_SUCCESS;
  155. }
  156. int
  157. gsl_fit_mul (const double *x, const size_t xstride,
  158. const double *y, const size_t ystride,
  159. const size_t n,
  160. double *c1, double *cov_11, double *sumsq)
  161. {
  162. double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
  163. size_t i;
  164. for (i = 0; i < n; i++)
  165. {
  166. m_x += (x[i * xstride] - m_x) / (i + 1.0);
  167. m_y += (y[i * ystride] - m_y) / (i + 1.0);
  168. }
  169. for (i = 0; i < n; i++)
  170. {
  171. const double dx = x[i * xstride] - m_x;
  172. const double dy = y[i * ystride] - m_y;
  173. m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
  174. m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
  175. }
  176. /* In terms of y = b x */
  177. {
  178. double s2 = 0, d2 = 0;
  179. double b = (m_x * m_y + m_dxdy) / (m_x * m_x + m_dx2);
  180. *c1 = b;
  181. /* Compute chi^2 = \sum (y_i - b * x_i)^2 */
  182. for (i = 0; i < n; i++)
  183. {
  184. const double dx = x[i * xstride] - m_x;
  185. const double dy = y[i * ystride] - m_y;
  186. const double d = (m_y - b * m_x) + dy - b * dx;
  187. d2 += d * d;
  188. }
  189. s2 = d2 / (n - 1.0); /* chisq per degree of freedom */
  190. *cov_11 = s2 * 1.0 / (n * (m_x * m_x + m_dx2));
  191. *sumsq = d2;
  192. }
  193. return GSL_SUCCESS;
  194. }
  195. int
  196. gsl_fit_wmul (const double *x, const size_t xstride,
  197. const double *w, const size_t wstride,
  198. const double *y, const size_t ystride,
  199. const size_t n,
  200. double *c1, double *cov_11, double *chisq)
  201. {
  202. /* compute the weighted means and weighted deviations from the means */
  203. /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
  204. double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
  205. size_t i;
  206. for (i = 0; i < n; i++)
  207. {
  208. const double wi = w[i * wstride];
  209. if (wi > 0)
  210. {
  211. W += wi;
  212. wm_x += (x[i * xstride] - wm_x) * (wi / W);
  213. wm_y += (y[i * ystride] - wm_y) * (wi / W);
  214. }
  215. }
  216. W = 0; /* reset the total weight */
  217. for (i = 0; i < n; i++)
  218. {
  219. const double wi = w[i * wstride];
  220. if (wi > 0)
  221. {
  222. const double dx = x[i * xstride] - wm_x;
  223. const double dy = y[i * ystride] - wm_y;
  224. W += wi;
  225. wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
  226. wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
  227. }
  228. }
  229. /* In terms of y = b x */
  230. {
  231. double d2 = 0;
  232. double b = (wm_x * wm_y + wm_dxdy) / (wm_x * wm_x + wm_dx2);
  233. *c1 = b;
  234. *cov_11 = 1 / (W * (wm_x * wm_x + wm_dx2));
  235. /* Compute chi^2 = \sum w_i (y_i - b * x_i)^2 */
  236. for (i = 0; i < n; i++)
  237. {
  238. const double wi = w[i * wstride];
  239. if (wi > 0)
  240. {
  241. const double dx = x[i * xstride] - wm_x;
  242. const double dy = y[i * ystride] - wm_y;
  243. const double d = (wm_y - b * wm_x) + (dy - b * dx);
  244. d2 += wi * d * d;
  245. }
  246. }
  247. *chisq = d2;
  248. }
  249. return GSL_SUCCESS;
  250. }
  251. int
  252. gsl_fit_mul_est (const double x,
  253. const double c1, const double cov11,
  254. double *y, double *y_err)
  255. {
  256. *y = c1 * x;
  257. *y_err = sqrt (cov11) * fabs (x);
  258. return GSL_SUCCESS;
  259. }