LAL  7.5.0.1-ec27e42
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 
86 static 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 
198 static 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 
270 static 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 
382 static 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 */
615 void
616 LALSMatrixInverse( 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,
633  ASSERT( inverse, stat, MATRIXUTILSH_ENUL, MATRIXUTILSH_MSGENUL );
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 */
690 void
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 */
733 void
734 LALDMatrixInverse( 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,
751  ASSERT( inverse, stat, MATRIXUTILSH_ENUL, MATRIXUTILSH_MSGENUL );
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 */
807 void
808 LALDMatrixDeterminantErr( 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