3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004, 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_math.h>
22 #include <gsl/gsl_errno.h>
23 #include <gsl/gsl_permutation.h>
24 #include <gsl/gsl_linalg.h>
25 #include <gsl/gsl_multifit_nlin.h>
27 /* Compute the covariance matrix
31 by QRP^T decomposition of J
35 gsl_multifit_covar (const gsl_matrix * J, double epsrel, gsl_matrix * covar)
45 gsl_permutation * perm;
47 size_t m = J->size1, n = J->size2 ;
51 GSL_ERROR ("Jacobian be rectangular M x N with M >= N", GSL_EBADLEN);
54 if (covar->size1 != covar->size2 || covar->size1 != n)
56 GSL_ERROR ("covariance matrix must be square and match second dimension of jacobian", GSL_EBADLEN);
59 r = gsl_matrix_alloc (m, n);
60 tau = gsl_vector_alloc (n);
61 perm = gsl_permutation_alloc (n) ;
62 norm = gsl_vector_alloc (n) ;
66 gsl_matrix_memcpy (r, J);
67 gsl_linalg_QRPT_decomp (r, tau, perm, &signum, norm);
71 /* Form the inverse of R in the full upper triangle of R */
73 tolr = epsrel * fabs(gsl_matrix_get(r, 0, 0));
75 for (k = 0 ; k < n ; k++)
77 double rkk = gsl_matrix_get(r, k, k);
79 if (fabs(rkk) <= tolr)
84 gsl_matrix_set(r, k, k, 1.0/rkk);
86 for (j = 0; j < k ; j++)
88 double t = gsl_matrix_get(r, j, k) / rkk;
89 gsl_matrix_set (r, j, k, 0.0);
91 for (i = 0; i <= j; i++)
93 double rik = gsl_matrix_get (r, i, k);
94 double rij = gsl_matrix_get (r, i, j);
96 gsl_matrix_set (r, i, k, rik - t * rij);
102 /* Form the full upper triangle of the inverse of R^T R in the full
103 upper triangle of R */
105 for (k = 0; k <= kmax ; k++)
107 for (j = 0; j < k; j++)
109 double rjk = gsl_matrix_get (r, j, k);
111 for (i = 0; i <= j ; i++)
113 double rij = gsl_matrix_get (r, i, j);
114 double rik = gsl_matrix_get (r, i, k);
116 gsl_matrix_set (r, i, j, rij + rjk * rik);
121 double t = gsl_matrix_get (r, k, k);
123 for (i = 0; i <= k; i++)
125 double rik = gsl_matrix_get (r, i, k);
127 gsl_matrix_set (r, i, k, t * rik);
132 /* Form the full lower triangle of the covariance matrix in the
133 strict lower triangle of R and in w */
135 for (j = 0 ; j < n ; j++)
137 size_t pj = gsl_permutation_get (perm, j);
139 for (i = 0; i <= j; i++)
141 size_t pi = gsl_permutation_get (perm, i);
147 gsl_matrix_set (r, i, j, 0.0);
152 rij = gsl_matrix_get (r, i, j);
157 gsl_matrix_set (r, pi, pj, rij);
161 gsl_matrix_set (r, pj, pi, rij);
167 double rjj = gsl_matrix_get (r, j, j);
168 gsl_matrix_set (covar, pj, pj, rjj);
173 /* symmetrize the covariance matrix */
175 for (j = 0 ; j < n ; j++)
177 for (i = 0; i < j ; i++)
179 double rji = gsl_matrix_get (r, j, i);
181 gsl_matrix_set (covar, j, i, rji);
182 gsl_matrix_set (covar, i, j, rji);
187 gsl_permutation_free (perm);
188 gsl_vector_free (tau);
189 gsl_vector_free (norm);