Beispiel #1
0
QVector<Quadric2D> processa(const QMatrix4x4& vInverse)
{
    gsl_matrix * A = gsl_matrix_calloc (n, 3*5);
    real bary[3];

    for (int i = 0; i < n; ++i)
    {
        QVector4D b(points[0][i], points[1][i], 1.0, 1.0);
        b = vInverse * b;
        bary[0] = b.x();
        bary[1] = b.y();
        bary[2] = b.z();
        for (int j = 0; j < 3; ++j)
        {
            gsl_matrix_set (A, i, j*5    ,     points[0][i]*points[0][i]*bary[j]); //x^2
            gsl_matrix_set (A, i, j*5 + 1, 2.0*points[0][i]*points[1][i]*bary[j]); //2xy
            gsl_matrix_set (A, i, j*5 + 2, 2.0*points[0][i]             *bary[j]); //2x
            gsl_matrix_set (A, i, j*5 + 3,     points[1][i]*points[1][i]*bary[j]); //y^2
            gsl_matrix_set (A, i, j*5 + 4, 2.0*points[1][i]             *bary[j]); //2y
        }
    }

    gsl_matrix *cov = gsl_matrix_alloc (15, 15);
    gsl_vector * B = gsl_vector_alloc(n);
    gsl_vector * x = gsl_vector_alloc(15);
    gsl_vector_set_all(B, 1.0);

    gsl_multifit_linear_workspace * work = gsl_multifit_linear_alloc (n,15);
    real chisq = 0.0;
//    gsl_multifit_linear (A, B, x, cov, &chisq, work);
    real tol = 0.0001 ;
    size_t rank = 0 ;
    gsl_multifit_linear_svd( A,B, tol, &rank, x, cov, &chisq, work);
    gsl_multifit_linear_free (work);

    //qDebug() << chisq;
    //qDebug() << rank ;

    QVector<Quadric2D> resp;
    for(int i = 0; i < 3; ++i)
    {
        float x1 = gsl_vector_get(x, i*5);
        float x2 = gsl_vector_get(x, i*5 + 1);
        float x3 = gsl_vector_get(x, i*5 + 2);
        float x4 = gsl_vector_get(x, i*5 + 3);
        float x5 = gsl_vector_get(x, i*5 + 4);

        resp.push_back(Quadric2D(x1,x2,x3,x4,x5,-1.0));
    }

    gsl_matrix_free (A);
    gsl_vector_free (B);
    gsl_vector_free (x);
    gsl_matrix_free (cov);

    return resp;
}
int
gsl_multifit_linear (const gsl_matrix * X,
                     const gsl_vector * y,
                     gsl_vector * c,
                     gsl_matrix * cov,
                     double *chisq, gsl_multifit_linear_workspace * work)
{
  size_t rank;
  int status  = gsl_multifit_linear_svd (X, y, GSL_DBL_EPSILON, &rank, c,
                                         cov, chisq, work);
  return status;
}
Beispiel #3
0
 gsl_vector* simpleFitting(gsl_matrix * A, gsl_vector * B)
{
    gsl_matrix *cov = gsl_matrix_alloc (A->size2, A->size2);
    gsl_vector * x = gsl_vector_alloc(A->size2);

    gsl_multifit_linear_workspace * work = gsl_multifit_linear_alloc (A->size1,A->size2);
    real chisq = 0.0;
    real tol = 0.000001 ;
    size_t rank = 0 ;
    gsl_multifit_linear_svd( A,B, tol, &rank, x, cov, &chisq, work);
    qDebug() << "rank: " << rank << ", chisq: " << chisq;
    //gsl_multifit_linear(A,B, x, cov, &chisq, work);
    gsl_multifit_linear_free (work);

    return x;
}
Beispiel #4
0
int
main()
{
  const size_t n = 1000; /* number of observations */
  const size_t p = 2;    /* number of model parameters */
  size_t i;
  gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
  gsl_matrix *X = gsl_matrix_alloc(n, p);
  gsl_vector *y = gsl_vector_alloc(n);

  for (i = 0; i < n; ++i)
    {
      /* generate first random variable u */
      double ui = 5.0 * gsl_ran_gaussian(r, 1.0);

      /* set v = u + noise */
      double vi = ui + gsl_ran_gaussian(r, 0.001);

      /* set y = u + v + noise */
      double yi = ui + vi + gsl_ran_gaussian(r, 1.0);

      /* since u =~ v, the matrix X is ill-conditioned */
      gsl_matrix_set(X, i, 0, ui);
      gsl_matrix_set(X, i, 1, vi);

      /* rhs vector */
      gsl_vector_set(y, i, yi);
    }

  {
    const size_t nL = 200;                   /* number of points on L-curve */
    gsl_multifit_linear_workspace *w =
      gsl_multifit_linear_alloc(n, p);
    gsl_vector *c = gsl_vector_alloc(p);     /* OLS solution */
    gsl_vector *c_reg = gsl_vector_alloc(p); /* regularized solution */
    gsl_vector *reg_param = gsl_vector_alloc(nL);
    gsl_vector *rho = gsl_vector_alloc(nL);  /* residual norms */
    gsl_vector *eta = gsl_vector_alloc(nL);  /* solution norms */
    double lambda;                           /* optimal regularization parameter */
    size_t reg_idx;                          /* index of optimal lambda */
    double chisq, rnorm, snorm;

    /* compute SVD of X */
    gsl_multifit_linear_svd(X, w);

    /* unregularized (standard) least squares fit, lambda = 0 */
    gsl_multifit_linear_solve(0.0, X, y, c, &rnorm, &snorm, w);
    chisq = pow(rnorm, 2.0);

    fprintf(stderr, "=== Unregularized fit ===\n");
    fprintf(stderr, "best fit: y = %g u + %g v\n",
      gsl_vector_get(c, 0), gsl_vector_get(c, 1));
    fprintf(stderr, "chisq/dof = %g\n", chisq / (n - p));

    /* calculate L-curve and find its corner */
    gsl_multifit_linear_lcurve(y, reg_param, rho, eta, w);
    gsl_multifit_linear_lcorner(rho, eta, &reg_idx);

    /* store optimal regularization parameter */
    lambda = gsl_vector_get(reg_param, reg_idx);

    /* output L-curve */
    for (i = 0; i < nL; ++i)
      printf("%f %f\n", gsl_vector_get(rho, i), gsl_vector_get(eta, i));

    /* output L-curve corner point */
    printf("\n\n%f %f\n",
           gsl_vector_get(rho, reg_idx),
           gsl_vector_get(eta, reg_idx));

    /* regularize with lambda */
    gsl_multifit_linear_solve(lambda, X, y, c_reg, &rnorm, &snorm, w);
    chisq = pow(rnorm, 2.0) + pow(lambda * snorm, 2.0);

    fprintf(stderr, "=== Regularized fit ===\n");
    fprintf(stderr, "optimal lambda: %g\n", lambda);
    fprintf(stderr, "best fit: y = %g u + %g v\n",
            gsl_vector_get(c_reg, 0), gsl_vector_get(c_reg, 1));
    fprintf(stderr, "chisq/dof = %g\n", chisq / (n - p));

    gsl_multifit_linear_free(w);
    gsl_vector_free(c);
    gsl_vector_free(c_reg);
    gsl_vector_free(reg_param);
    gsl_vector_free(rho);
    gsl_vector_free(eta);
  }

  gsl_rng_free(r);
  gsl_matrix_free(X);
  gsl_vector_free(y);

  return 0;
}
Beispiel #5
0
/* solve system with given lambda and L and test against
 * normal equations solution */
static void
test_reg4(const double lambda, const gsl_matrix * L, const gsl_matrix * X,
          const gsl_vector * y, const gsl_vector * wts, const double tol,
          gsl_multifit_linear_workspace * w, const char *desc)
{
  const size_t m = L->size1;
  const size_t n = X->size1;
  const size_t p = X->size2;
  double rnorm0, snorm0;
  double rnorm1, snorm1;
  gsl_vector *c0 = gsl_vector_alloc(p);
  gsl_vector *c1 = gsl_vector_alloc(p);
  gsl_matrix *LTL = gsl_matrix_alloc(p, p); /* L^T L */
  gsl_matrix *XTX = gsl_matrix_alloc(p, p); /* X^T W X + lambda^2 L^T L */
  gsl_vector *XTy = gsl_vector_alloc(p);    /* X^T W y */
  gsl_permutation *perm = gsl_permutation_alloc(p);
  gsl_matrix *Xs = (m < p) ? gsl_matrix_alloc(n - (p - m), m) : gsl_matrix_alloc(n, p);
  gsl_vector *ys = (m < p) ? gsl_vector_alloc(n - (p - m)) : gsl_vector_alloc(n);
  gsl_matrix *M = (m < p) ? gsl_matrix_alloc(n, p) : gsl_matrix_alloc(m, p);
  gsl_vector *cs = (m < p) ? gsl_vector_alloc(m) : gsl_vector_alloc(p);
  gsl_matrix *WX = gsl_matrix_alloc(n, p);
  gsl_vector *Wy = gsl_vector_alloc(n);
  gsl_vector *Lc = gsl_vector_alloc(m);
  gsl_vector *r = gsl_vector_alloc(n);
  gsl_matrix *LQR = gsl_matrix_alloc(m, p);
  gsl_vector *Ltau = gsl_vector_alloc(GSL_MIN(m, p));
  int signum;
  size_t j;

  /* compute WX = sqrt(W) X, Wy = sqrt(W) y */
  gsl_multifit_linear_wstdform1(NULL, X, wts, y, WX, Wy, w);

  /* construct XTy = X^T W y */
  gsl_blas_dgemv(CblasTrans, 1.0, WX, Wy, 0.0, XTy);

  /* construct XTX = X^T W X + lambda^2 L^T L */
  gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, L, L, 0.0, LTL);
  gsl_matrix_scale(LTL, lambda * lambda);

  gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, WX, WX, 0.0, XTX);
  gsl_matrix_add(XTX, LTL);

  /* solve XTX c = XTy with LU decomp */
  gsl_linalg_LU_decomp(XTX, perm, &signum);
  gsl_linalg_LU_solve(XTX, perm, XTy, c0);

  /* solve with reg routine */
  gsl_matrix_memcpy(LQR, L);
  gsl_multifit_linear_L_decomp(LQR, Ltau);
  gsl_multifit_linear_wstdform2(LQR, Ltau, X, wts, y, Xs, ys, M, w);
  gsl_multifit_linear_svd(Xs, w);
  gsl_multifit_linear_solve(lambda, Xs, ys, cs, &rnorm0, &snorm0, w);
  gsl_multifit_linear_wgenform2(LQR, Ltau, X, wts, y, cs, M, c1, w);

  /* test snorm = ||L c1|| */
  gsl_blas_dgemv(CblasNoTrans, 1.0, L, c1, 0.0, Lc);
  snorm1 = gsl_blas_dnrm2(Lc);
  gsl_test_rel(snorm0, snorm1, tol, "test_reg4: %s snorm lambda=%g", desc, lambda);

  /* test rnorm = ||y - X c1||_W */
  gsl_vector_memcpy(r, Wy);
  gsl_blas_dgemv(CblasNoTrans, -1.0, WX, c1, 1.0, r);
  rnorm1 = gsl_blas_dnrm2(r);
  gsl_test_rel(rnorm0, rnorm1, tol, "test_reg4: %s rnorm lambda=%g", desc, lambda);

  /* test c0 = c1 */
  for (j = 0; j < p; ++j)
    {
      double c0j = gsl_vector_get(c0, j);
      double c1j = gsl_vector_get(c1, j);

      gsl_test_rel(c1j, c0j, tol, "test_reg4: %s lambda=%g n=%zu p=%zu j=%zu",
                   desc, lambda, n, p, j);
    }

  gsl_matrix_free(LTL);
  gsl_matrix_free(XTX);
  gsl_vector_free(XTy);
  gsl_vector_free(c0);
  gsl_vector_free(c1);
  gsl_permutation_free(perm);
  gsl_matrix_free(Xs);
  gsl_vector_free(ys);
  gsl_vector_free(cs);
  gsl_matrix_free(M);
  gsl_vector_free(Lc);
  gsl_matrix_free(WX);
  gsl_vector_free(Wy);
  gsl_vector_free(r);
  gsl_matrix_free(LQR);
  gsl_vector_free(Ltau);
}
Beispiel #6
0
/* solve system with given lambda and L = diag(L) and test against
 * normal equations solution */
static void
test_reg3(const double lambda, const gsl_vector * L, const gsl_matrix * X,
          const gsl_vector * y, const gsl_vector * wts, const double tol,
          gsl_multifit_linear_workspace * w, const char * desc)
{
  const size_t n = X->size1;
  const size_t p = X->size2;
  double rnorm0, snorm0;
  double rnorm1, snorm1;
  gsl_vector *c0 = gsl_vector_alloc(p);
  gsl_vector *c1 = gsl_vector_alloc(p);
  gsl_matrix *XTX = gsl_matrix_alloc(p, p); /* X^T W X + lambda^2 L^T L */
  gsl_vector *XTy = gsl_vector_alloc(p);    /* X^T W y */
  gsl_matrix *Xs = gsl_matrix_alloc(n, p);  /* standard form X~ */
  gsl_vector *ys = gsl_vector_alloc(n);     /* standard form y~ */
  gsl_vector *Lc = gsl_vector_alloc(p);
  gsl_vector *r = gsl_vector_alloc(n);
  gsl_permutation *perm = gsl_permutation_alloc(p);
  int signum;
  size_t j;

  /* compute Xs = sqrt(W) X, ys = sqrt(W) y */
  gsl_multifit_linear_wstdform1(NULL, X, wts, y, Xs, ys, w);

  /* construct XTy = X^T W y */
  gsl_blas_dgemv(CblasTrans, 1.0, Xs, ys, 0.0, XTy);

  /* construct XTX = X^T W X + lambda^2 L^T L */
  gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, Xs, Xs, 0.0, XTX);

  for (j = 0; j < p; ++j)
    {
      double lj = gsl_vector_get(L, j);
      *gsl_matrix_ptr(XTX, j, j) += pow(lambda * lj, 2.0);
    }

  /* solve XTX c = XTy with LU decomp */
  gsl_linalg_LU_decomp(XTX, perm, &signum);
  gsl_linalg_LU_solve(XTX, perm, XTy, c0);

  /* solve with reg routine */
  gsl_multifit_linear_wstdform1(L, X, wts, y, Xs, ys, w);
  gsl_multifit_linear_svd(Xs, w);
  gsl_multifit_linear_solve(lambda, Xs, ys, c1, &rnorm0, &snorm0, w);
  gsl_multifit_linear_genform1(L, c1, c1, w);

  /* test snorm = ||L c1|| */
  gsl_vector_memcpy(Lc, c1);
  gsl_vector_mul(Lc, L);
  snorm1 = gsl_blas_dnrm2(Lc);
  gsl_test_rel(snorm0, snorm1, tol, "test_reg3: %s, snorm lambda=%g n=%zu p=%zu",
               desc, lambda, n, p);

  /* test rnorm = ||y - X c1||, compute again Xs = sqrt(W) X and ys = sqrt(W) y */
  gsl_multifit_linear_wstdform1(NULL, X, wts, y, Xs, ys, w);
  gsl_vector_memcpy(r, ys);
  gsl_blas_dgemv(CblasNoTrans, -1.0, Xs, c1, 1.0, r);
  rnorm1 = gsl_blas_dnrm2(r);
  gsl_test_rel(rnorm0, rnorm1, tol, "test_reg3: %s, rnorm lambda=%g n=%zu p=%zu",
               desc, lambda, n, p);

  /* test c0 = c1 */
  for (j = 0; j < p; ++j)
    {
      double c0j = gsl_vector_get(c0, j);
      double c1j = gsl_vector_get(c1, j);

      gsl_test_rel(c1j, c0j, tol, "test_reg3: %s, c0/c1 j=%zu lambda=%g n=%zu p=%zu",
                   desc, j, lambda, n, p);
    }

  gsl_matrix_free(Xs);
  gsl_matrix_free(XTX);
  gsl_vector_free(XTy);
  gsl_vector_free(c0);
  gsl_vector_free(c1);
  gsl_vector_free(Lc);
  gsl_vector_free(ys);
  gsl_vector_free(r);
  gsl_permutation_free(perm);
}
Beispiel #7
0
/* solve standard form system with given lambda and test against
 * normal equations solution, L = I */
static void
test_reg2(const double lambda, const gsl_matrix * X, const gsl_vector * y,
          const gsl_vector * wts, const double tol,
          gsl_multifit_linear_workspace * w, const char * desc)
{
  const size_t n = X->size1;
  const size_t p = X->size2;
  double rnorm0, snorm0;
  double rnorm1, snorm1;
  gsl_vector *c0 = gsl_vector_alloc(p);
  gsl_vector *c1 = gsl_vector_alloc(p);
  gsl_matrix *XTX = gsl_matrix_alloc(p, p); /* X^T W X + lambda^2 I */
  gsl_vector *XTy = gsl_vector_alloc(p);    /* X^T W y */
  gsl_matrix *Xs = gsl_matrix_alloc(n, p);
  gsl_vector *ys = gsl_vector_alloc(n);
  gsl_vector_view xtx_diag = gsl_matrix_diagonal(XTX);
  gsl_permutation *perm = gsl_permutation_alloc(p);
  gsl_vector *r = gsl_vector_alloc(n);
  int signum;
  size_t j;

  /* compute Xs = sqrt(W) X and ys = sqrt(W) y */
  gsl_multifit_linear_wstdform1(NULL, X, wts, y, Xs, ys, w);

  /* construct XTy = X^T W y */
  gsl_blas_dgemv(CblasTrans, 1.0, Xs, ys, 0.0, XTy);

  /* construct XTX = X^T W X + lambda^2 I */
  gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, Xs, Xs, 0.0, XTX);
  gsl_vector_add_constant(&xtx_diag.vector, lambda*lambda);

  /* solve XTX c = XTy with LU decomp */
  gsl_linalg_LU_decomp(XTX, perm, &signum);
  gsl_linalg_LU_solve(XTX, perm, XTy, c0);

  /* compute SVD of X */
  gsl_multifit_linear_svd(Xs, w);

  /* solve regularized standard form system with lambda */
  gsl_multifit_linear_solve(lambda, Xs, ys, c1, &rnorm0, &snorm0, w);

  /* test snorm = ||c1|| */
  snorm1 = gsl_blas_dnrm2(c1);
  gsl_test_rel(snorm0, snorm1, tol, "test_reg2: %s, snorm lambda=%g n=%zu p=%zu",
               desc, lambda, n, p);

  /* test rnorm = ||y - X c1|| */
  gsl_vector_memcpy(r, ys);
  gsl_blas_dgemv(CblasNoTrans, -1.0, Xs, c1, 1.0, r);
  rnorm1 = gsl_blas_dnrm2(r);
  gsl_test_rel(rnorm0, rnorm1, tol, "test_reg2: %s, rnorm lambda=%g n=%zu p=%zu",
               desc, lambda, n, p);

  /* test c0 = c1 */
  for (j = 0; j < p; ++j)
    {
      double c0j = gsl_vector_get(c0, j);
      double c1j = gsl_vector_get(c1, j);

      gsl_test_rel(c1j, c0j, tol, "test_reg2: %s, c0/c1 lambda=%g n=%zu p=%zu",
                   desc, lambda, n, p);
    }

  gsl_matrix_free(XTX);
  gsl_vector_free(XTy);
  gsl_matrix_free(Xs);
  gsl_vector_free(ys);
  gsl_vector_free(c0);
  gsl_vector_free(c1);
  gsl_vector_free(r);
  gsl_permutation_free(perm);
}
Beispiel #8
0
static int
test_shaw_system(gsl_rng *rng_p, const size_t n, const size_t p,
                 const double lambda_expected,
                 gsl_vector *rhs)
{
  const size_t npoints = 1000; /* number of points on L-curve */
  const double tol1 = 1.0e-12;
  const double tol2 = 1.0e-10;
  const double tol3 = 1.0e-5;
  gsl_vector * reg_param = gsl_vector_alloc(npoints);
  gsl_vector * rho = gsl_vector_alloc(npoints);
  gsl_vector * eta = gsl_vector_alloc(npoints);

  gsl_matrix * X = gsl_matrix_alloc(n, p);
  gsl_matrix * cov = gsl_matrix_alloc(p, p);
  gsl_vector * c = gsl_vector_alloc(p);
  gsl_vector * ytmp = gsl_vector_alloc(n);
  gsl_vector * y;
  gsl_vector * r = gsl_vector_alloc(n);
  gsl_multifit_linear_workspace * work = 
    gsl_multifit_linear_alloc (n, p);

  size_t reg_idx, i;
  double lambda, rnorm, snorm;

  /* build design matrix */
  shaw_system(X, ytmp);

  if (rhs)
    y = rhs;
  else
    {
      y = ytmp;

      /* add random noise to exact rhs vector */
      test_random_vector_noise(rng_p, y);
    }

  /* SVD decomposition */
  gsl_multifit_linear_svd(X, work);

  /* calculate L-curve */
  gsl_multifit_linear_lcurve(y, reg_param, rho, eta, work);

  /* test rho and eta vectors */
  for (i = 0; i < npoints; ++i)
    {
      double rhoi = gsl_vector_get(rho, i);
      double etai = gsl_vector_get(eta, i);
      double lami = gsl_vector_get(reg_param, i);

      /* solve regularized system and check for consistent rho/eta values */
      gsl_multifit_linear_solve(lami, X, y, c, &rnorm, &snorm, work);
      gsl_test_rel(rhoi, rnorm, tol3, "shaw rho n="F_ZU" p="F_ZU" lambda=%e",
                   n, p, lami);
      gsl_test_rel(etai, snorm, tol1, "shaw eta n="F_ZU" p="F_ZU" lambda=%e",
                   n, p, lami);
    }

  /* calculate corner of L-curve */
  gsl_multifit_linear_lcorner(rho, eta, &reg_idx);

  lambda = gsl_vector_get(reg_param, reg_idx);

  /* test against known lambda value if given */
  if (lambda_expected > 0.0)
    {
      gsl_test_rel(lambda, lambda_expected, tol1,
                   "shaw: n="F_ZU" p="F_ZU" L-curve corner lambda",
                   n, p);
    }

  /* compute regularized solution with optimal lambda */
  gsl_multifit_linear_solve(lambda, X, y, c, &rnorm, &snorm, work);

  /* compute residual norm ||y - X c|| */
  gsl_vector_memcpy(r, y);
  gsl_blas_dgemv(CblasNoTrans, 1.0, X, c, -1.0, r);

  /* test rnorm value */
  gsl_test_rel(rnorm, gsl_blas_dnrm2(r), tol2,
               "shaw: n="F_ZU" p="F_ZU" rnorm", n, p);

  /* test snorm value */
  gsl_test_rel(snorm, gsl_blas_dnrm2(c), tol2,
               "shaw: n="F_ZU" p="F_ZU" snorm", n, p);

  gsl_matrix_free(X);
  gsl_matrix_free(cov);
  gsl_vector_free(reg_param);
  gsl_vector_free(rho);
  gsl_vector_free(eta);
  gsl_vector_free(r);
  gsl_vector_free(c);
  gsl_vector_free(ytmp);
  gsl_multifit_linear_free(work);

  return 0;
} /* test_shaw_system() */
Beispiel #9
0
static int
secs2d_fit(void * vstate)
{
  secs2d_state_t *state = (secs2d_state_t *) vstate;
  const size_t npts = 200;
  /* Note: to get a reasonable current map, use tol = 3e-1 */
  const double tol = 1.0e-2;
  gsl_vector *reg_param = gsl_vector_alloc(npts);
  gsl_vector *rho = gsl_vector_alloc(npts);
  gsl_vector *eta = gsl_vector_alloc(npts);
  gsl_vector *G = gsl_vector_alloc(npts);
  gsl_matrix_view A = gsl_matrix_submatrix(state->X, 0, 0, state->n, state->p);
  gsl_vector_view b = gsl_vector_subvector(state->rhs, 0, state->n);
  gsl_vector_view wts = gsl_vector_subvector(state->wts, 0, state->n);
  double lambda_gcv, lambda_l, G_gcv;
  double rnorm, snorm;
  size_t i;
  const char *lambda_file = "lambda.dat";
  FILE *fp = fopen(lambda_file, "w");
  double s0; /* largest singular value */

  if (state->n < state->p)
    return -1;

  fprintf(stderr, "\n");
  fprintf(stderr, "\t n = %zu\n", state->n);
  fprintf(stderr, "\t p = %zu\n", state->p);

#if 1 /* TSVD */

  {
    double chisq;
    size_t rank;

    gsl_multifit_wlinear_tsvd(&A.matrix, &wts.vector, &b.vector, tol, state->c, state->cov,
                              &chisq, &rank, state->multifit_p);

    rnorm = sqrt(chisq);
    snorm = gsl_blas_dnrm2(state->c);

    fprintf(stderr, "secs2d_fit: rank = %zu/%zu\n", rank, state->p);
  }

#else /* Tikhonov / L-curve */

  /* convert to standard form */
  gsl_multifit_linear_applyW(&A.matrix, &wts.vector, &b.vector, &A.matrix, &b.vector);

  fprintf(stderr, "\t computing SVD...");

  /* compute SVD of A */
  gsl_multifit_linear_svd(&A.matrix, state->multifit_p);
  s0 = gsl_vector_get(state->multifit_p->S, 0);

  fprintf(stderr, "done\n");

  /* compute GCV curve */
  gsl_multifit_linear_gcv(&b.vector, reg_param, G, &lambda_gcv, &G_gcv, state->multifit_p);

  /* compute L-curve */
  gsl_multifit_linear_lcurve(&b.vector, reg_param, rho, eta, state->multifit_p);

  fprintf(stderr, "\t secs2d_fit: writing %s...", lambda_file);

  for (i = 0; i < npts; ++i)
    {
      fprintf(fp, "%e %e %e %e\n",
              gsl_vector_get(reg_param, i),
              gsl_vector_get(rho, i),
              gsl_vector_get(eta, i),
              gsl_vector_get(G, i));
    }

  fprintf(stderr, "done\n");

  gsl_multifit_linear_lcorner(rho, eta, &i);
  lambda_l = gsl_vector_get(reg_param, i);

  /* lower bound on lambda */
  lambda_l = GSL_MAX(lambda_l, tol * s0);

  /* solve regularized system with lambda_l */
  gsl_multifit_linear_solve(lambda_l, &A.matrix, &b.vector, state->c, &rnorm, &snorm, state->multifit_p);

  fprintf(stderr, "\t s0 = %.12e\n", s0);
  fprintf(stderr, "\t lambda_l = %.12e\n", lambda_l);
  fprintf(stderr, "\t lambda_gcv = %.12e\n", lambda_gcv);
  fprintf(stderr, "\t rnorm = %.12e\n", rnorm);
  fprintf(stderr, "\t snorm = %.12e\n", snorm);
  fprintf(stderr, "\t cond(X) = %.12e\n", 1.0 / gsl_multifit_linear_rcond(state->multifit_p));

#endif

  gsl_vector_free(reg_param);
  gsl_vector_free(rho);
  gsl_vector_free(eta);
  gsl_vector_free(G);

  fclose(fp);

  return 0;
}