Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
DetInverse.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Teviet Creighton
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20#include <math.h>
21#include <lal/LALStdlib.h>
22#include <lal/AVFactories.h>
23#include <lal/MatrixUtils.h>
24
25
26/*
27 * author Creighton, T. D.
28 *
29 * Internal routines used to compute matrix determinants and inverses.
30 *
31 * ### Description ###
32 *
33 * These functions are called by the routines in \ref DetInverse_c to
34 * compute the determinant and inverse of a nondegenerate square matrix
35 * <tt>*matrix</tt>. They are useful routines in their own right, though,
36 * so they are made publically available.
37 *
38 * <tt>LALSLUDecomp()</tt> and <tt>LALDLUDecomp()</tt> replace <tt>*matrix</tt>
39 * with an LU decomposition of a <em>row-wise permutation</em> of itself.
40 * The output parameter <tt>*indx</tt> stores the permutation, and the
41 * output <tt>*sgn</tt> records the sign of the permutation.
42 *
43 * <tt>LALSLUBackSub()</tt> and <tt>LALDLUBackSub()</tt> take the permuted
44 * LU-decomposed matrix returned by the above routine, and
45 * back-substitute the vector <tt>*vector</tt> representing \f$\mathsf{v}^a\f$
46 * in \eqref{eq_linear_system}, to compute the vector \f$\mathsf{x}^b\f$.
47 * This is returned in-place in <tt>*vector</tt>. The input parameter
48 * <tt>*indx</tt> is the list of row permutations returned by the above
49 * routines.
50 *
51 * ### Algorithm ###
52 *
53 * LU decomposition is performed by Crout's algorithm, described in
54 * Sec. 2.3 of \cite ptvf1992; the routines in this module are
55 * essentially re-implementations of the Numerical Recipes routines
56 * <tt>ludcmp()</tt> and <tt>lubksub()</tt>. For large \f$N\f$, their operation
57 * counts are approximately \f$N^3/3\f$ and \f$N^2\f$, respectively.
58 *
59 * One difference between <tt>ludcmp()</tt> in \cite ptvf1992 and the
60 * routines <tt>LALSLUDecomp()</tt> and <tt>LALDLUDecomp()</tt> in this
61 * module is the way in which singular matrices are handled.
62 * In \cite ptvf1992 , there is a distinction between between a
63 * manifestly singular matrix (where an entire row of the matrix is zero)
64 * and a numerically singular matrix (if a diagonal element in the
65 * decomposed matrix turns out to be zero). In the former case, they
66 * raise an error signal; in the latter, they replace the offending
67 * element with a tiny but nonzero number and continue. This
68 * treatment does not strike the present author as satisfactory.
69 *
70 * Instead, the routines <tt>LALSLUDecomp()</tt> and <tt>LALDLUDecomp()</tt>
71 * will \e always return successfully, even with a singular matrix,
72 * but will \e not adjust away a numerical singularity. Instead,
73 * they will signal the presence of the singularity in two ways: First,
74 * they will set the permutation sign <tt>*sgn</tt> to zero; second, they
75 * will set \e all elements of the <tt>*indx</tt> vector yo zero. This
76 * ensures that routines computing the determinant (whose sign depends on
77 * <tt>*sgn</tt>) will correctly give a zero determinant, while the
78 * meaningless <tt>*indx</tt> provides a simple sanity check for routines
79 * such as <tt>LALSLUBackSub()</tt> and <tt>LALDLUBackSub()</tt> that attempt
80 * to invert the linear system. Note that the returned value of
81 * <tt>*matrix</tt> will be meaningless garbage.
82 *
83 */
84
85
86static void
88 INT2 *sgn,
89 REAL4Array *matrix,
90 UINT4Vector *indx )
91{
92 UINT4 n, imax = 0; /* matrix dimension and pivot index */
93 UINT4 i, j, k; /* dimension indecies */
94 UINT4 ij, ik, kj, jk; /* matrix array indecies */
95 UINT4 *d; /* pointer to indx->data */
96 REAL4 *s, *m; /* pointers to data arrays */
97 REAL4 tmp, max, sum; /* temporary computation variables */
98
99 INITSTATUS(stat);
100
101 /* Check input fields. */
108 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
110 ASSERT( matrix->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
112 n = indx->length;
114 ASSERT( n == matrix->dimLength->data[0], stat, MATRIXUTILSH_EDIM,
116 ASSERT( n == matrix->dimLength->data[1], stat, MATRIXUTILSH_EDIM,
118
119 /* Set up pointers. */
120 if ( !( s = (REAL4 *)LALMalloc( n*sizeof(REAL4) ) ) ) {
122 }
123 m = matrix->data;
124 d = indx->data;
125 *sgn = 1;
126
127 /* Get row scaling information. */
128 for ( i = 0; i < n; i++ ) {
129 max = 0.0;
130 for ( j = 0, ij = i*n; j < n; j++, ij++ )
131 if ( ( tmp = fabs( m[ij] ) ) > max )
132 max = tmp;
133 /* Check for singular matrix. */
134 if ( max == 0.0 ) {
135 *sgn = 0;
136 memset( d, 0, n*sizeof(UINT4) );
137 LALFree( s );
138 RETURN( stat );
139 }
140 s[i] = 1.0/max;
141 }
142
143 /* Loop over columns of matrix. */
144 for ( j = 0; j < n; j++ ) {
145
146 /* Compute Uij for i not equal to j. */
147 for ( i = 0, ij = j; i < j; i++, ij += n ) {
148 sum = m[ij];
149 for ( k = 0, ik = i*n, kj = j; k < i; k++, ik++, kj += n )
150 sum -= m[ik]*m[kj];
151 m[ij] = sum;
152 }
153
154 /* Compute Uii and Lij while searching for pivot point. */
155 max = 0.0;
156 for ( i = j, ij = j*(n+1); i < n; i++, ij += n ) {
157 sum = m[ij];
158 for ( k = 0, ik = i*n, kj = j; k < j; k++, ik++, kj += n )
159 sum -= m[ik]*m[kj];
160 m[ij] = sum;
161 if ( ( tmp = s[i]*fabs( sum ) ) >= max ) {
162 max = tmp;
163 imax = i;
164 }
165 }
166
167 /* Permute rows if necessary. */
168 if ( j != imax ) {
169 for ( k = 0, ik = imax*n, jk = j*n; k < n; k++, ik++, jk++ ) {
170 tmp = m[ik];
171 m[ik] = m[jk];
172 m[jk] = tmp;
173 }
174 s[imax] = s[j];
175 *sgn *= -1;
176 }
177 d[j] = imax;
178
179 /* Divide by pivot element, checking for singularity. */
180 if ( ( tmp = m[j*(n+1)] ) == 0.0 ) {
181 *sgn = 0;
182 memset( d, 0, n*sizeof(UINT4) );
183 LALFree( s );
184 RETURN( stat );
185 }
186 tmp = 1.0/tmp;
187 if ( j != n )
188 for ( i = j + 1, ij = j*(n+1) + n; i < n; i++, ij += n )
189 m[ij] *= tmp;
190 }
191
192 /* Finished! */
193 LALFree( s );
194 RETURN( stat );
195}
196
197
198static void
200 REAL4Vector *vector,
201 REAL4Array *matrix,
202 UINT4Vector *indx )
203{
204 INT4 n; /* matrix dimension */
205 INT4 i, j; /* dimension indecies */
206 INT4 ii, ij; /* matrix array indecies */
207 INT4 id, jmin = -1; /* permuted and first nonzero vector indecies */
208 UINT4 *d; /* pointer to indx->data */
209 REAL4 *v, *m; /* pointers to data arrays */
210 REAL4 sum; /* temporary computation variable */
211
212 INITSTATUS(stat);
213
214 /* Check input fields. */
222 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
224 ASSERT( matrix->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
226 n = (INT4)( indx->length );
228 ASSERT( n == (INT4)( vector->length ), stat, MATRIXUTILSH_EDIM,
230 ASSERT( n == (INT4)( matrix->dimLength->data[0] ), stat,
232 ASSERT( n == (INT4)( matrix->dimLength->data[1] ), stat,
234
235 /* Set up pointers. */
236 v = vector->data;
237 m = matrix->data;
238 d = indx->data;
239
240 /* Check for singular matrix. */
241 if ( n > 1 && d[0] == 0 && d[1] == 0 ) {
243 }
244
245 /* Compute intermediate vector y, reversing the permutation as we
246 go, and skipping quickly to the first nonzero element of v. */
247 for ( i = 0; i < n; i++ ) {
248 id = d[i];
249 sum = v[id];
250 v[id] = v[i];
251 if ( jmin >= 0 )
252 for ( j = jmin, ij = i*n + jmin; j < i; j++, ij++ )
253 sum -= m[ij]*v[j];
254 else if ( sum != 0.0 )
255 jmin = i;
256 v[i] = sum;
257 }
258
259 /* Now compute the final vector x. */
260 for ( i = n - 1, ii = n*n - 1; i >= 0; i--, ii -= n + 1 ) {
261 sum = v[i];
262 for ( j = i + 1, ij = ii + 1; j < n; j++, ij++ )
263 sum -= m[ij]*v[j];
264 v[i] = sum/m[ii];
265 }
266 RETURN( stat );
267}
268
269
270static void
272 INT2 *sgn,
273 REAL8Array *matrix,
274 UINT4Vector *indx )
275{
276 UINT4 n, imax = 0; /* matrix dimension and pivot index */
277 UINT4 i, j, k; /* dimension indecies */
278 UINT4 ij, ik, kj, jk; /* matrix array indecies */
279 UINT4 *d; /* pointer to indx->data */
280 REAL8 *s, *m; /* pointers to data arrays */
281 REAL8 tmp, max, sum; /* temporary computation variables */
282
283 INITSTATUS(stat);
284
285 /* Check input fields. */
292 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
294 ASSERT( matrix->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
296 n = indx->length;
298 ASSERT( n == matrix->dimLength->data[0], stat, MATRIXUTILSH_EDIM,
300 ASSERT( n == matrix->dimLength->data[1], stat, MATRIXUTILSH_EDIM,
302
303 /* Set up pointers. */
304 if ( !( s = (REAL8 *)LALMalloc( n*sizeof(REAL8) ) ) ) {
306 }
307 m = matrix->data;
308 d = indx->data;
309 *sgn = 1;
310
311 /* Get row scaling information. */
312 for ( i = 0; i < n; i++ ) {
313 max = 0.0;
314 for ( j = 0, ij = i*n; j < n; j++, ij++ )
315 if ( ( tmp = fabs( m[ij] ) ) > max )
316 max = tmp;
317 /* Check for singular matrix. */
318 if ( max == 0.0 ) {
319 *sgn = 0;
320 memset( d, 0, n*sizeof(UINT4) );
321 LALFree( s );
322 RETURN( stat );
323 }
324 s[i] = 1.0/max;
325 }
326
327 /* Loop over columns of matrix. */
328 for ( j = 0; j < n; j++ ) {
329
330 /* Compute Uij for i not equal to j. */
331 for ( i = 0, ij = j; i < j; i++, ij += n ) {
332 sum = m[ij];
333 for ( k = 0, ik = i*n, kj = j; k < i; k++, ik++, kj += n )
334 sum -= m[ik]*m[kj];
335 m[ij] = sum;
336 }
337
338 /* Compute Uii and Lij while searching for pivot point. */
339 max = 0.0;
340 for ( i = j, ij = j*(n+1); i < n; i++, ij += n ) {
341 sum = m[ij];
342 for ( k = 0, ik = i*n, kj = j; k < j; k++, ik++, kj += n )
343 sum -= m[ik]*m[kj];
344 m[ij] = sum;
345 if ( ( tmp = s[i]*fabs( sum ) ) >= max ) {
346 max = tmp;
347 imax = i;
348 }
349 }
350
351 /* Permute rows if necessary. */
352 if ( j != imax ) {
353 for ( k = 0, ik = imax*n, jk = j*n; k < n; k++, ik++, jk++ ) {
354 tmp = m[ik];
355 m[ik] = m[jk];
356 m[jk] = tmp;
357 }
358 s[imax] = s[j];
359 *sgn *= -1;
360 }
361 d[j] = imax;
362
363 /* Divide by pivot element, checking for singularity. */
364 if ( ( tmp = m[j*(n+1)] ) == 0.0 ) {
365 *sgn = 0;
366 memset( d, 0, n*sizeof(UINT4) );
367 LALFree( s );
368 RETURN( stat );
369 }
370 tmp = 1.0/tmp;
371 if ( j != n )
372 for ( i = j + 1, ij = j*(n+1) + n; i < n; i++, ij += n )
373 m[ij] *= tmp;
374 }
375
376 /* Finished! */
377 LALFree( s );
378 RETURN( stat );
379}
380
381
382static void
384 REAL8Vector *vector,
385 REAL8Array *matrix,
386 UINT4Vector *indx )
387{
388 INT4 n; /* matrix dimension */
389 INT4 i, j; /* dimension indecies */
390 INT4 ii, ij; /* matrix array indecies */
391 INT4 id, jmin = -1; /* permuted and first nonzero vector indecies */
392 UINT4 *d; /* pointer to indx->data */
393 REAL8 *v, *m; /* pointers to data arrays */
394 REAL8 sum; /* temporary computation variable */
395
396 INITSTATUS(stat);
397
398 /* Check input fields. */
406 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
408 ASSERT( matrix->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
410 n = (INT4)( indx->length );
412 ASSERT( n == (INT4)( vector->length ), stat, MATRIXUTILSH_EDIM,
414 ASSERT( n == (INT4)( matrix->dimLength->data[0] ), stat,
416 ASSERT( n == (INT4)( matrix->dimLength->data[1] ), stat,
418
419 /* Set up pointers. */
420 v = vector->data;
421 m = matrix->data;
422 d = indx->data;
423
424 /* Check for singular matrix. */
425 if ( n > 1 && d[0] == 0 && d[1] == 0 ) {
427 }
428
429 /* Compute intermediate vector y, reversing the permutation as we
430 go, and skipping quickly to the first nonzero element of v. */
431 for ( i = 0; i < n; i++ ) {
432 id = d[i];
433 sum = v[id];
434 v[id] = v[i];
435 if ( jmin >= 0 )
436 for ( j = jmin, ij = i*n + jmin; j < i; j++, ij++ )
437 sum -= m[ij]*v[j];
438 else if ( sum != 0.0 )
439 jmin = i;
440 v[i] = sum;
441 }
442
443 /* Now compute the final vector x. */
444 for ( i = n - 1, ii = n*n - 1; i >= 0; i--, ii -= n + 1 ) {
445 sum = v[i];
446 for ( j = i + 1, ij = ii + 1; j < n; j++, ij++ )
447 sum -= m[ij]*v[j];
448 v[i] = sum/m[ii];
449 }
450 RETURN( stat );
451}
452
453
454/**
455 * \defgroup DetInverse_c Module DetInverse.c
456 * \ingroup MatrixUtils_h
457 * \author Creighton, T. D.
458 *
459 * \brief Routines to compute matrix determinants and inverses.
460 *
461 * ### Description ###
462 *
463 * <tt>LALDMatrixDeterminant()</tt>
464 * computes the determinant <tt>*det</tt> of the square matrix
465 * <tt>*matrix</tt>. The internal computations will corrupt
466 * <tt>*matrix</tt>; if you don't want the input matrix to be changed, make
467 * a copy of it first.
468 *
469 * <tt>LALSMatrixInverse()</tt> and <tt>LALDMatrixInverse()</tt> compute the
470 * inverse <tt>*inverse</tt> of the square matrix <tt>*matrix</tt>. If the
471 * pointer \c det is non-\c NULL, then the determinant is also
472 * computed and returned in <tt>*det</tt>. The array <tt>*inverse</tt> must
473 * already be allocated to the correct size. The internal computations
474 * will corrupt <tt>*matrix</tt>; if you don't want the input matrix to be
475 * changed, make a copy of it first.
476 *
477 * <tt>LALDMatrixDeterminantErr()</tt> computes the determinant
478 * <tt>det[0]</tt> of the square matrix <tt>*matrix</tt>. If
479 * <tt>*matrixErr</tt> is non-\c NULL, it stores uncertainties in the
480 * corresponding components of <tt>*matrix</tt>, and the resulting
481 * uncertainty in the determinant (computed by linear error propagation)
482 * is returned in <tt>det[1]</tt>. This routine is not highly optimized,
483 * and uses an internal matrix in its computations, so the contents of
484 * <tt>*matrix</tt> and <tt>*matrixErr</tt> will not be changed.
485 *
486 * ### Algorithm ###
487 *
488 * A linear system of equations is written in matrix terms as:
489 * \f{equation}{
490 * \label{eq_linear_system}
491 * \mathsf{M}^a{}_b \mathsf{x}^b = \mathsf{v}^a \;,
492 * \f}
493 * where \f$\mathsf{M}^a{}_b\f$ is a known matrix, \f$\mathsf{v}^a\f$ a known
494 * vector, and \f$\mathsf{x}^b\f$ an unknown vector that we wish to solve
495 * for. A standard method for solving this is the method of LU
496 * decomposition, based on the fact that any non-singular square matrix
497 * \f$\mathsf{M}^a{}_b\f$ can be \e decomposed into the product of a
498 * lower-triangular matrix \f$\mathsf{L}^a{}_b\f$ and an upper-triangular
499 * matrix \f$\mathsf{U}^a{}_b\f$:
500 * \f{equation}{
501 * \mathsf{M}^a{}_b = \mathsf{L}^a{}_c \mathsf{U}^c{}_b =
502 * \left[\begin{array}{cccc}
503 * 1 & 0 & \cdots & 0 \\
504 * L^2{}_1 & 1 & \cdots & 0 \\
505 * \vdots & \vdots & \ddots & \vdots \\
506 * L^N{}_1 & L^N{}_2 & \cdots & 1
507 * \end{array}\right] \cdot \left[\begin{array}{cccc}
508 * U^1{}_1 & U^1{}_2 & \cdots & U^1{}_N \\
509 * 0 & U^2{}_2 & \cdots & U^2{}_N \\
510 * \vdots & \vdots & \ddots & \vdots \\
511 * 0 & 0 & \cdots & U^N{}_N
512 * \end{array}\right] \;.
513 * \f}
514 * The linear system can then be broken up as \f$\mathsf{L}^a{}_b
515 * \mathsf{y}^b = \mathsf{v}^a\f$ and \f$\mathsf{U}^b{}_c \mathsf{x}^c =
516 * \mathsf{y}^b\f$, where these two equations are trivially invertible:
517 * \f{eqnarray}{
518 * y^i & = & v^i - \sum_{j=1}^i-1 L^i{}_j y^j \;,\qquad i=1,2,\ldots,N \;, \\
519 * x^i & = & \frac{1}{U^i{}_i}\left( y^i - \sum_{j=i+1}^N U^i{}_j x_j \right)
520 * \;,\qquad i=N,N-1,\ldots,1 \;,
521 * \f}
522 * where the calculations are arranged so that the computation of a given
523 * \f$y^i\f$ or \f$x^i\f$ requires only those values that have been computed
524 * already. This process of solving the linear system is called
525 * \e backsubstitution.
526 *
527 * The determinant of \f$\mathsf{M}^a{}_b\f$ is simply the product of the
528 * diagonal elements of the decomposed matrix:
529 * \f$|\mathsf{M}^a{}_b|=\prod_{i=1}^N U^i{}_i\f$. The inverse matrix
530 * \f$(\mathsf{M}^{-1}){}^a{}_b\f$ can be computed by performing a
531 * column-by-column backsubstitution of the identity matrix.
532 *
533 * The routines in \ref DetInverse_c first use <tt>LALSLUDecomp()</tt> or
534 * <tt>LALDLUDecomp()</tt> to perform an LU decomposition of the matrix,
535 * then either compute the determinant from the diagonal elements, or
536 * use <tt>LALSLUBackSub()</tt> or <tt>LALDLUBackSub()</tt> to determine
537 * the inverse by back-substitution of basis vectors. The routines that
538 * compute the determinant will also handle any singular matrix error
539 * code returned by the LU decomposition routines, returning zero as the
540 * determinant.
541 *
542 * Since the diagonal components \f$L^i{}_i\f$ are conventionally assigned to
543 * 1, they do not need to be explicitly stored. Therefore we can store
544 * \e both matrices \f$\mathsf{L}^a{}_b\f$ and \f$\mathsf{U}^a{}_b\f$
545 * in-place, in the same memory block used for the input matrix
546 * \f$\mathsf{M}^a{}_b\f$. This the procedure taken by <tt>LALSLUDecomp()</tt>
547 * and <tt>LALDLUDecomp()</tt>; hence on return the routines in this module
548 * will leave the input <tt>*matrix</tt> in this decomposed state.
549 * However, these routines also <em>permute the rows</em> of the input
550 * matrix, and the information on this permutation is \e not returned
551 * by the routines in \ref DetInverse_c, so the information in
552 * <tt>*matrix</tt> will be irretrievably mangled.
553 *
554 * Computing the determinant is dominated by the cost of doing the LU
555 * decomposition, or of order \f$N^3/3\f$ operations. Computing the inverse
556 * requires an additional \f$N\f$ back-substitutions, but since most of the
557 * vector elements are zero, this reduces the average cost of each
558 * back-substitution from \f$N^2\f$ to \f$2N^2/3\f$, for a total operation count
559 * of \f$N^3\f$.
560 *
561 * \par Computing determinant uncertainties:
562 * To determine the
563 * dependence of the determinant on any one element of the matrix, we
564 * take advantage of the fact that the determinant \f$|\mathsf{M}^a{}_b|\f$
565 * can be written as:
566 * \f{eqnarray}{
567 * |\mathsf{M}^a{}_b| & = & \sum_{j=1}^N (-1)^{i+j} M^i{}_j
568 * |(\mathsf{C}^i{}_j){}^a{}_b| \quad\mbox{for any }i\in[1,N]
569 * \;,\\
570 * & = & \sum_{i=1}^N (-1)^{i+j} M^i{}_j
571 * |(\mathsf{C}^i{}_j){}^a{}_b| \quad\mbox{for any }j\in[1,N] \;,
572 * \f}
573 * where
574 * \f{equation}{
575 * (\mathsf{C}^i{}_j){}^a{}_b = \left[\begin{array}{ccccccc}
576 * M^1{}_1 & \cdots & M^1{}_{j-1} & 0 & M^1{}_{j+1}
577 * & \cdots & M^1{}_N \\
578 * \vdots & \ddots & \vdots & \vdots & \vdots
579 * & & \vdots \\
580 * M^{i-1}{}_1 & \cdots & M^{i-1}{}_{j-1} & 0 & M^{i-1}{}_{j+1}
581 * & \cdots & M^{i-1}{}_N \\
582 * 0 & \cdots & 0 & 1 & 0
583 * & \cdots & 0 \\
584 * \vdots & & \vdots & \vdots & \vdots
585 * & \ddots & \vdots \\
586 * M^N{}_1 & \cdots & M^N{}_{j-1} & 0 & M^N{}_{j+1}
587 * & \cdots & M^N{}_N \end{array}\right]
588 * \f}
589 * is called the co-matrix of the element \f$M^i{}_j\f$.
590 *
591 * Assuming all matrix elements are statistically independent, linear
592 * error propagation can give us the uncertainty in the determinant:
593 * \f{eqnarray}{
594 * E\left(|\mathsf{M}^a{}_b|\right) & = & \sqrt{\sum_{i,j=1}^N
595 * \left[ \frac{\partial|\mathsf{M}^a{}_b|}{\partial M^i{}_j}
596 * E\left(M^i{}_j\right)\right]^2 }\\
597 * & = & \sqrt{\sum_{i,j=1}^N \left[ |(\mathsf{C}^i{}_j){}^a{}_b|
598 * E\left(M^i{}_j\right)\right]^2 } \;.\\
599 * \f}
600 * The routines <tt>LALSMatrixDeterminantErr()</tt> and
601 * <tt>LALDMatrixDeterminantErr()</tt> thus simply compute the determinant
602 * multiple times, successively zeroing out rows and columns of
603 * <tt>*matrix</tt> and replacing the element at their intersection with
604 * the corresponding element of <tt>*matrixErr</tt>, and take the square
605 * root of the sum of the squares of these determinants. As mentioned
606 * earlier, they use an internal matrix for all computations, so the
607 * input parameters are unchanged. The uncertainty requires evaluating
608 * \f$N^2\f$ determinants, so the operation count scales as \f$N^5\f$: this
609 * routine should \e not be used for large matrices!
610 *
611 */
612/** @{ */
613
614/** \see See \ref DetInverse_c for documentation */
615void
616LALSMatrixInverse( LALStatus *stat, REAL4 *det, REAL4Array *matrix, REAL4Array *inverse )
617{
618 INT2 sgn; /* sign of permutation. */
619 UINT4 n, i, j, ij; /* array dimension and indecies */
620 UINT4Vector *indx = NULL; /* permutation storage vector */
621 REAL4Vector *col = NULL; /* columns of inverse matrix */
622
623 INITSTATUS(stat);
624 ATTATCHSTATUSPTR( stat );
625
626 /* Check dimension length. Other argument testing is done by the
627 subroutines. */
629 ASSERT( matrix->dimLength, stat, MATRIXUTILSH_ENUL,
631 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
634 ASSERT( inverse->dimLength, stat, MATRIXUTILSH_ENUL,
636 ASSERT( inverse->dimLength->data, stat, MATRIXUTILSH_ENUL,
638 ASSERT( inverse->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
640 n = inverse->dimLength->data[0];
642 ASSERT( n == inverse->dimLength->data[1], stat, MATRIXUTILSH_EDIM,
644
645 /* Allocate vectors to store the matrix permutation and column
646 vectors. */
647 TRY( LALU4CreateVector( stat->statusPtr, &indx, n ), stat );
648 LALSCreateVector( stat->statusPtr, &col, n );
649 BEGINFAIL( stat ) {
650 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
651 } ENDFAIL( stat );
652
653 /* Decompose the matrix. */
654 sgn = 0; /* silence -Werror=maybe-uninitialized. note: there is no check here that LALSLUDecomp() is successful and the compiler knows this. *that's* the real problem, but I'm not fixing (Kipp) */
655 LALSLUDecomp( stat->statusPtr, &sgn, matrix, indx );
656 BEGINFAIL( stat ) {
657 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
658 TRY( LALSDestroyVector( stat->statusPtr, &col ), stat );
659 } ENDFAIL( stat );
660
661 /* Compute the determinant, if available. */
662 if ( det ) {
663 *det = sgn;
664 for ( i = 0; i < n; i++ )
665 *det *= matrix->data[i*(n+1)];
666 }
667
668 /* Compute each column of inverse matrix. */
669 for ( j = 0; j < n; j++ ) {
670 memset( col->data, 0, n*sizeof(REAL4) );
671 col->data[j] = 1.0;
672 LALSLUBackSub( stat->statusPtr, col, matrix, indx );
673 BEGINFAIL( stat ) {
674 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
675 TRY( LALSDestroyVector( stat->statusPtr, &col ), stat );
676 } ENDFAIL( stat );
677 for ( i = 0, ij = j; i < n; i++, ij += n )
678 inverse->data[ij] = col->data[i];
679 }
680
681 /* Clean up. */
682 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
683 TRY( LALSDestroyVector( stat->statusPtr, &col ), stat );
684 DETATCHSTATUSPTR( stat );
685 RETURN( stat );
686}
687
688
689/** \see See \ref DetInverse_c for documentation */
690void
692{
693 INT2 sgn; /* sign of permutation. */
694 UINT4 n, i; /* array dimension and index */
695 UINT4Vector *indx = NULL; /* permutation storage vector */
696
697 INITSTATUS(stat);
698 ATTATCHSTATUSPTR( stat );
699
700 /* Check dimension length. All other argument testing is done by
701 the subroutines. */
704 ASSERT( matrix->dimLength, stat, MATRIXUTILSH_ENUL,
706 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
708 n = matrix->dimLength->data[0];
710
711 /* Allocate a vector to store the matrix permutation. */
712 TRY( LALU4CreateVector( stat->statusPtr, &indx, n ), stat );
713
714 /* Decompose the matrix. */
715 LALDLUDecomp( stat->statusPtr, &sgn, matrix, indx );
716 BEGINFAIL( stat ) {
717 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
718 } ENDFAIL( stat );
719
720 /* Compute determinant. */
721 *det = sgn;
722 for ( i = 0; i < n; i++ )
723 *det *= matrix->data[i*(n+1)];
724
725 /* Clean up. */
726 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
727 DETATCHSTATUSPTR( stat );
728 RETURN( stat );
729}
730
731
732/** \see See \ref DetInverse_c for documentation */
733void
734LALDMatrixInverse( LALStatus *stat, REAL8 *det, REAL8Array *matrix, REAL8Array *inverse )
735{
736 INT2 sgn; /* sign of permutation. */
737 UINT4 n, i, j, ij; /* array dimension and indecies */
738 UINT4Vector *indx = NULL; /* permutation storage vector */
739 REAL8Vector *col = NULL; /* columns of inverse matrix */
740
741 INITSTATUS(stat);
742 ATTATCHSTATUSPTR( stat );
743
744 /* Check dimension length. Other argument testing is done by the
745 subroutines. */
747 ASSERT( matrix->dimLength, stat, MATRIXUTILSH_ENUL,
749 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
752 ASSERT( inverse->dimLength, stat, MATRIXUTILSH_ENUL,
754 ASSERT( inverse->dimLength->data, stat, MATRIXUTILSH_ENUL,
756 ASSERT( inverse->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
758 n = inverse->dimLength->data[0];
760 ASSERT( n == inverse->dimLength->data[1], stat, MATRIXUTILSH_EDIM,
762
763 /* Allocate vectors to store the matrix permutation and column
764 vectors. */
765 TRY( LALU4CreateVector( stat->statusPtr, &indx, n ), stat );
766 LALDCreateVector( stat->statusPtr, &col, n );
767 BEGINFAIL( stat ) {
768 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
769 } ENDFAIL( stat );
770
771 /* Decompose the matrix. */
772 LALDLUDecomp( stat->statusPtr, &sgn, matrix, indx );
773 BEGINFAIL( stat ) {
774 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
775 TRY( LALDDestroyVector( stat->statusPtr, &col ), stat );
776 } ENDFAIL( stat );
777
778 /* Compute the determinant, if available. */
779 if ( det ) {
780 *det = sgn;
781 for ( i = 0; i < n; i++ )
782 *det *= matrix->data[i*(n+1)];
783 }
784
785 /* Compute each column of inverse matrix. */
786 for ( j = 0; j < n; j++ ) {
787 memset( col->data, 0, n*sizeof(REAL8) );
788 col->data[j] = 1.0;
789 LALDLUBackSub( stat->statusPtr, col, matrix, indx );
790 BEGINFAIL( stat ) {
791 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
792 TRY( LALDDestroyVector( stat->statusPtr, &col ), stat );
793 } ENDFAIL( stat );
794 for ( i = 0, ij = j; i < n; i++, ij += n )
795 inverse->data[ij] = col->data[i];
796 }
797
798 /* Clean up. */
799 TRY( LALU4DestroyVector( stat->statusPtr, &indx ), stat );
800 TRY( LALDDestroyVector( stat->statusPtr, &col ), stat );
801 DETATCHSTATUSPTR( stat );
802 RETURN( stat );
803}
804
805
806/** \see See \ref DetInverse_c for documentation */
807void
808LALDMatrixDeterminantErr( LALStatus *stat, REAL8 det[2], REAL8Array *matrix, REAL8Array *matrixErr )
809{
810 UINT4 n, i, j, k; /* matrix dimension and indecies */
811 UINT4 ij, ik, kj; /* array data indecies */
812 REAL8 var; /* partial derivative of determinant */
813 REAL8Array *temp = NULL; /* internal copy of *matrix */
814
815 INITSTATUS(stat);
816 ATTATCHSTATUSPTR( stat );
817
818 /* Check input arguments. */
820 ASSERT( matrix, stat, MATRIXUTILSH_ENUL,
822 ASSERT( matrix->data, stat, MATRIXUTILSH_ENUL,
824 ASSERT( matrix->dimLength, stat, MATRIXUTILSH_ENUL,
826 ASSERT( matrix->dimLength->data, stat, MATRIXUTILSH_ENUL,
828 ASSERT( matrix->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
830 n = matrix->dimLength->data[0];
831 ASSERT( matrix->dimLength->data[1] == n, stat, MATRIXUTILSH_EDIM,
833 if ( matrixErr ) {
834 ASSERT( matrixErr->data, stat, MATRIXUTILSH_ENUL,
836 ASSERT( matrixErr->dimLength, stat, MATRIXUTILSH_ENUL,
838 ASSERT( matrixErr->dimLength->data, stat, MATRIXUTILSH_ENUL,
840 ASSERT( matrixErr->dimLength->length == 2, stat, MATRIXUTILSH_EDIM,
842 ASSERT( matrixErr->dimLength->data[0] == n, stat, MATRIXUTILSH_EDIM,
844 ASSERT( matrixErr->dimLength->data[1] == n, stat, MATRIXUTILSH_EDIM,
846 }
847
848 /* Allocate internal copy, and compute determinant. */
849 TRY( LALDCreateArray( stat->statusPtr, &temp, matrix->dimLength ),
850 stat );
851 memcpy( temp->data, matrix->data, n*n*sizeof(REAL8) );
852 LALDMatrixDeterminant( stat->statusPtr, det, temp );
853 BEGINFAIL( stat ) {
854 TRY( LALDDestroyArray( stat->statusPtr, &temp ), stat );
855 } ENDFAIL( stat );
856 det[1] = 0.0;
857
858 /* Compute derivatives of determinant. */
859 if ( matrixErr ) {
860 for ( i = 0; i < n; i++ ) {
861 for ( j = 0, ij = i*n; j < n; j++, ij++ ) {
862 memcpy( temp->data, matrix->data, n*n*sizeof(REAL8) );
863 for ( k = 0, ik = i*n, kj = j; k < n; k++, ik++, kj += n )
864 temp->data[ik] = temp->data[kj] = 0.0;
865 temp->data[ij] = matrixErr->data[ij];
866 LALDMatrixDeterminant( stat->statusPtr, &var, temp );
867 BEGINFAIL( stat ) {
868 TRY( LALDDestroyArray( stat->statusPtr, &temp ), stat );
869 } ENDFAIL( stat );
870 det[1] += var*var;
871 }
872 }
873 det[1] = sqrt( det[1] );
874 }
875
876 /* Done. */
877 TRY( LALDDestroyArray( stat->statusPtr, &temp ), stat );
878 DETATCHSTATUSPTR( stat );
879 RETURN( stat );
880}
881/** @} */
static void LALSLUBackSub(LALStatus *stat, REAL4Vector *vector, REAL4Array *matrix, UINT4Vector *indx)
Definition: DetInverse.c:199
static void LALSLUDecomp(LALStatus *stat, INT2 *sgn, REAL4Array *matrix, UINT4Vector *indx)
Definition: DetInverse.c:87
static void LALDLUBackSub(LALStatus *stat, REAL8Vector *vector, REAL8Array *matrix, UINT4Vector *indx)
Definition: DetInverse.c:383
static void LALDLUDecomp(LALStatus *stat, INT2 *sgn, REAL8Array *matrix, UINT4Vector *indx)
Definition: DetInverse.c:271
#define LALMalloc(n)
Definition: LALMalloc.h:93
#define LALFree(p)
Definition: LALMalloc.h:96
#define ABORT(statusptr, code, mesg)
#define ENDFAIL(statusptr)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define BEGINFAIL(statusptr)
#define MATRIXUTILSH_MSGESING
Definition: MatrixUtils.h:140
#define MATRIXUTILSH_MSGEMEM
Definition: MatrixUtils.h:141
#define MATRIXUTILSH_MSGEDIM
Definition: MatrixUtils.h:138
#define MATRIXUTILSH_MSGENUL
Definition: MatrixUtils.h:137
void LALDCreateArray(LALStatus *, REAL8Array **, UINT4Vector *)
void LALDDestroyArray(LALStatus *, REAL8Array **)
void LALDMatrixInverse(LALStatus *stat, REAL8 *det, REAL8Array *matrix, REAL8Array *inverse)
Definition: DetInverse.c:734
void LALDMatrixDeterminant(LALStatus *stat, REAL8 *det, REAL8Array *matrix)
Definition: DetInverse.c:691
void LALSMatrixInverse(LALStatus *stat, REAL4 *det, REAL4Array *matrix, REAL4Array *inverse)
Definition: DetInverse.c:616
void LALDMatrixDeterminantErr(LALStatus *stat, REAL8 det[2], REAL8Array *matrix, REAL8Array *matrixErr)
Definition: DetInverse.c:808
double REAL8
Double precision real floating-point number (8 bytes).
int16_t INT2
Two-byte signed integer.
uint32_t UINT4
Four-byte unsigned integer.
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
#define MATRIXUTILSH_ENUL
Unexpected null pointer in arguments.
Definition: MatrixUtils.h:128
#define MATRIXUTILSH_ESING
Singular matrix.
Definition: MatrixUtils.h:131
#define MATRIXUTILSH_EDIM
Bad matrix dimensions.
Definition: MatrixUtils.h:129
#define MATRIXUTILSH_EMEM
Memory allocation error.
Definition: MatrixUtils.h:132
static const INT4 m
Definition: Random.c:80
void LALU4CreateVector(LALStatus *, UINT4Vector **, UINT4)
void LALDCreateVector(LALStatus *, REAL8Vector **, UINT4)
void LALDDestroyVector(LALStatus *, REAL8Vector **)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALU4DestroyVector(LALStatus *, UINT4Vector **)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
struct tagLALStatus * statusPtr
Pointer to the next node in the list; NULL if this function is not reporting a subroutine error.
Definition: LALDatatypes.h:954
Multidimentional array of REAL4, see DATATYPE-Array types for more details.
Definition: LALDatatypes.h:220
UINT4Vector * dimLength
Vector of array dimensions.
Definition: LALDatatypes.h:221
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:222
Vector of type REAL4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:145
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:150
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:149
Multidimentional array of REAL8, see DATATYPE-Array types for more details.
Definition: LALDatatypes.h:226
UINT4Vector * dimLength
Vector of array dimensions.
Definition: LALDatatypes.h:227
REAL8 * data
Pointer to the data array.
Definition: LALDatatypes.h:228
Vector of type REAL8, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:154
REAL8 * data
Pointer to the data array.
Definition: LALDatatypes.h:159
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:158
Vector of type UINT4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:118
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:122
UINT4 * data
Pointer to the data array.
Definition: LALDatatypes.h:123