Blame fit/linear.c

Packit 67cb25
/* fit/linear.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2000, 2007 Brian Gough
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_fit.h>
Packit 67cb25
Packit 67cb25
/* Fit the data (x_i, y_i) to the linear relationship 
Packit 67cb25
Packit 67cb25
   Y = c0 + c1 x
Packit 67cb25
Packit 67cb25
   returning, 
Packit 67cb25
Packit 67cb25
   c0, c1  --  coefficients
Packit 67cb25
   cov00, cov01, cov11  --  variance-covariance matrix of c0 and c1,
Packit 67cb25
   sumsq   --   sum of squares of residuals 
Packit 67cb25
Packit 67cb25
   This fit can be used in the case where the errors for the data are
Packit 67cb25
   uknown, but assumed equal for all points. The resulting
Packit 67cb25
   variance-covariance matrix estimates the error in the coefficients
Packit 67cb25
   from the observed variance of the points around the best fit line.
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_linear (const double *x, const size_t xstride,
Packit 67cb25
                const double *y, const size_t ystride,
Packit 67cb25
                const size_t n,
Packit 67cb25
                double *c0, double *c1,
Packit 67cb25
                double *cov_00, double *cov_01, double *cov_11, double *sumsq)
Packit 67cb25
{
Packit 67cb25
  double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
Packit 67cb25
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      m_x += (x[i * xstride] - m_x) / (i + 1.0);
Packit 67cb25
      m_y += (y[i * ystride] - m_y) / (i + 1.0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double dx = x[i * xstride] - m_x;
Packit 67cb25
      const double dy = y[i * ystride] - m_y;
Packit 67cb25
Packit 67cb25
      m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
Packit 67cb25
      m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* In terms of y = a + b x */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    double s2 = 0, d2 = 0;
Packit 67cb25
    double b = m_dxdy / m_dx2;
Packit 67cb25
    double a = m_y - m_x * b;
Packit 67cb25
Packit 67cb25
    *c0 = a;
Packit 67cb25
    *c1 = b;
Packit 67cb25
Packit 67cb25
    /* Compute chi^2 = \sum (y_i - (a + b * x_i))^2 */
Packit 67cb25
Packit 67cb25
    for (i = 0; i < n; i++)
Packit 67cb25
      {
Packit 67cb25
        const double dx = x[i * xstride] - m_x;
Packit 67cb25
        const double dy = y[i * ystride] - m_y;
Packit 67cb25
        const double d = dy - b * dx;
Packit 67cb25
        d2 += d * d;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    s2 = d2 / (n - 2.0);        /* chisq per degree of freedom */
Packit 67cb25
Packit 67cb25
    *cov_00 = s2 * (1.0 / n) * (1 + m_x * m_x / m_dx2);
Packit 67cb25
    *cov_11 = s2 * 1.0 / (n * m_dx2);
Packit 67cb25
Packit 67cb25
    *cov_01 = s2 * (-m_x) / (n * m_dx2);
Packit 67cb25
Packit 67cb25
    *sumsq = d2;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* Fit the weighted data (x_i, w_i, y_i) to the linear relationship 
Packit 67cb25
Packit 67cb25
   Y = c0 + c1 x
Packit 67cb25
Packit 67cb25
   returning, 
Packit 67cb25
Packit 67cb25
   c0, c1  --  coefficients
Packit 67cb25
   s0, s1  --  the standard deviations of c0 and c1,
Packit 67cb25
   r       --  the correlation coefficient between c0 and c1,
Packit 67cb25
   chisq   --  weighted sum of squares of residuals */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_wlinear (const double *x, const size_t xstride,
Packit 67cb25
                 const double *w, const size_t wstride,
Packit 67cb25
                 const double *y, const size_t ystride,
Packit 67cb25
                 const size_t n,
Packit 67cb25
                 double *c0, double *c1,
Packit 67cb25
                 double *cov_00, double *cov_01, double *cov_11,
Packit 67cb25
                 double *chisq)
Packit 67cb25
{
Packit 67cb25
Packit 67cb25
  /* compute the weighted means and weighted deviations from the means */
Packit 67cb25
Packit 67cb25
  /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
Packit 67cb25
Packit 67cb25
  double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
Packit 67cb25
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
      if (wi > 0)
Packit 67cb25
        {
Packit 67cb25
          W += wi;
Packit 67cb25
          wm_x += (x[i * xstride] - wm_x) * (wi / W);
Packit 67cb25
          wm_y += (y[i * ystride] - wm_y) * (wi / W);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  W = 0;                        /* reset the total weight */
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
      if (wi > 0)
Packit 67cb25
        {
Packit 67cb25
          const double dx = x[i * xstride] - wm_x;
Packit 67cb25
          const double dy = y[i * ystride] - wm_y;
Packit 67cb25
Packit 67cb25
          W += wi;
Packit 67cb25
          wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
Packit 67cb25
          wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* In terms of y = a + b x */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    double d2 = 0;
Packit 67cb25
    double b = wm_dxdy / wm_dx2;
Packit 67cb25
    double a = wm_y - wm_x * b;
Packit 67cb25
Packit 67cb25
    *c0 = a;
Packit 67cb25
    *c1 = b;
Packit 67cb25
Packit 67cb25
    *cov_00 = (1 / W) * (1 + wm_x * wm_x / wm_dx2);
Packit 67cb25
    *cov_11 = 1 / (W * wm_dx2);
Packit 67cb25
Packit 67cb25
    *cov_01 = -wm_x / (W * wm_dx2);
Packit 67cb25
Packit 67cb25
    /* Compute chi^2 = \sum w_i (y_i - (a + b * x_i))^2 */
Packit 67cb25
Packit 67cb25
    for (i = 0; i < n; i++)
Packit 67cb25
      {
Packit 67cb25
        const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
        if (wi > 0)
Packit 67cb25
          {
Packit 67cb25
            const double dx = x[i * xstride] - wm_x;
Packit 67cb25
            const double dy = y[i * ystride] - wm_y;
Packit 67cb25
            const double d = dy - b * dx;
Packit 67cb25
            d2 += wi * d * d;
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    *chisq = d2;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_linear_est (const double x,
Packit 67cb25
                    const double c0, const double c1,
Packit 67cb25
                    const double cov00, const double cov01, const double cov11,
Packit 67cb25
                    double *y, double *y_err)
Packit 67cb25
{
Packit 67cb25
  *y = c0 + c1 * x;
Packit 67cb25
  *y_err = sqrt (cov00 + x * (2 * cov01 + cov11 * x));
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_mul (const double *x, const size_t xstride,
Packit 67cb25
             const double *y, const size_t ystride,
Packit 67cb25
             const size_t n, 
Packit 67cb25
             double *c1, double *cov_11, double *sumsq)
Packit 67cb25
{
Packit 67cb25
  double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
Packit 67cb25
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      m_x += (x[i * xstride] - m_x) / (i + 1.0);
Packit 67cb25
      m_y += (y[i * ystride] - m_y) / (i + 1.0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double dx = x[i * xstride] - m_x;
Packit 67cb25
      const double dy = y[i * ystride] - m_y;
Packit 67cb25
Packit 67cb25
      m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
Packit 67cb25
      m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* In terms of y =  b x */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    double s2 = 0, d2 = 0;
Packit 67cb25
    double b = (m_x * m_y + m_dxdy) / (m_x * m_x + m_dx2);
Packit 67cb25
Packit 67cb25
    *c1 = b;
Packit 67cb25
Packit 67cb25
    /* Compute chi^2 = \sum (y_i -  b * x_i)^2 */
Packit 67cb25
Packit 67cb25
    for (i = 0; i < n; i++)
Packit 67cb25
      {
Packit 67cb25
        const double dx = x[i * xstride] - m_x;
Packit 67cb25
        const double dy = y[i * ystride] - m_y;
Packit 67cb25
        const double d = (m_y - b * m_x) + dy - b * dx;
Packit 67cb25
        d2 += d * d;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    s2 = d2 / (n - 1.0);        /* chisq per degree of freedom */
Packit 67cb25
Packit 67cb25
    *cov_11 = s2 * 1.0 / (n * (m_x * m_x + m_dx2));
Packit 67cb25
Packit 67cb25
    *sumsq = d2;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_wmul (const double *x, const size_t xstride,
Packit 67cb25
              const double *w, const size_t wstride,
Packit 67cb25
              const double *y, const size_t ystride,
Packit 67cb25
              const size_t n, 
Packit 67cb25
              double *c1, double *cov_11, double *chisq)
Packit 67cb25
{
Packit 67cb25
Packit 67cb25
  /* compute the weighted means and weighted deviations from the means */
Packit 67cb25
Packit 67cb25
  /* wm denotes a "weighted mean", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */
Packit 67cb25
Packit 67cb25
  double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;
Packit 67cb25
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
      if (wi > 0)
Packit 67cb25
        {
Packit 67cb25
          W += wi;
Packit 67cb25
          wm_x += (x[i * xstride] - wm_x) * (wi / W);
Packit 67cb25
          wm_y += (y[i * ystride] - wm_y) * (wi / W);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  W = 0;                        /* reset the total weight */
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
      if (wi > 0)
Packit 67cb25
        {
Packit 67cb25
          const double dx = x[i * xstride] - wm_x;
Packit 67cb25
          const double dy = y[i * ystride] - wm_y;
Packit 67cb25
Packit 67cb25
          W += wi;
Packit 67cb25
          wm_dx2 += (dx * dx - wm_dx2) * (wi / W);
Packit 67cb25
          wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* In terms of y = b x */
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    double d2 = 0;
Packit 67cb25
    double b = (wm_x * wm_y + wm_dxdy) / (wm_x * wm_x + wm_dx2);
Packit 67cb25
Packit 67cb25
    *c1 = b;
Packit 67cb25
Packit 67cb25
    *cov_11 = 1 / (W * (wm_x * wm_x + wm_dx2));
Packit 67cb25
Packit 67cb25
    /* Compute chi^2 = \sum w_i (y_i - b * x_i)^2 */
Packit 67cb25
Packit 67cb25
    for (i = 0; i < n; i++)
Packit 67cb25
      {
Packit 67cb25
        const double wi = w[i * wstride];
Packit 67cb25
Packit 67cb25
        if (wi > 0)
Packit 67cb25
          {
Packit 67cb25
            const double dx = x[i * xstride] - wm_x;
Packit 67cb25
            const double dy = y[i * ystride] - wm_y;
Packit 67cb25
            const double d = (wm_y - b * wm_x) + (dy - b * dx);
Packit 67cb25
            d2 += wi * d * d;
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    *chisq = d2;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_fit_mul_est (const double x, 
Packit 67cb25
                 const double c1, const double cov11, 
Packit 67cb25
                 double *y, double *y_err)
Packit 67cb25
{
Packit 67cb25
  *y = c1 * x;
Packit 67cb25
  *y_err = sqrt (cov11) * fabs (x);
Packit 67cb25
  return GSL_SUCCESS;
Packit 67cb25
}