lines 24-230 of file: test_more/compare_c/det_by_minor.c {xrst_begin det_of_minor_c app} {xrst_spell factorial } Determinant of a Minor ###################### Syntax ****** *d* = ``det_of_minor`` ( *a* , *m* , *n* , *r* , *c* ) Purpose ******* returns the determinant of a minor of the matrix :math:`A` using expansion by minors. The elements of the :math:`n \times n` minor :math:`M` of the matrix :math:`A` are defined, for :math:`i = 0 , \ldots , n-1` and :math:`j = 0 , \ldots , n-1`, by .. math:: M_{i,j} = A_{R(i), C(j)} where the functions :math:`R(i)` is defined by the :ref:`argument r` and :math:`C(j)` is defined by the :ref:`argument c` . This function is for example and testing purposes only. Expansion by minors is chosen as an example because it uses a lot of floating point operations yet does not require much source code (on the order of *m* factorial floating point operations and about 70 lines of source code including comments). This is not an efficient method for computing a determinant; for example, using an LU factorization would be better. Determinant of A **************** If the following conditions hold, the minor is the entire matrix :math:`A` and hence ``det_of_minor`` will return the determinant of :math:`A`: #. :math:`n = m`. #. for :math:`i = 0 , \ldots , m-1`, :math:`r[i] = i+1`, and :math:`r[m] = 0`. #. for :math:`j = 0 , \ldots , m-1`, :math:`c[j] = j+1`, and :math:`c[m] = 0`. a * The argument *a* has prototype ``const double`` * *a* and is a vector with size :math:`m * m`. The elements of the :math:`m \times m` matrix :math:`A` are defined, for :math:`i = 0 , \ldots , m-1` and :math:`j = 0 , \ldots , m-1`, by .. math:: A_{i,j} = a[ i * m + j] m * The argument *m* has prototype ``size_t`` *m* and is the size of the square matrix :math:`A`. n * The argument *n* has prototype ``size_t`` *n* and is the size of the square minor :math:`M`. r * The argument *r* has prototype ``size_t`` * *r* and is a vector with :math:`m + 1` elements. This vector defines the function :math:`R(i)` which specifies the rows of the minor :math:`M`. To be specific, the function :math:`R(i)` for :math:`i = 0, \ldots , n-1` is defined by .. math:: :nowrap: \begin{eqnarray} R(0) & = & r[m] \\ R(i+1) & = & r[ R(i) ] \end{eqnarray} All the elements of *r* must have value less than or equal *m* . The elements of vector *r* are modified during the computation, and restored to their original value before the return from ``det_of_minor`` . c * The argument *c* has prototype ``size_t`` * *c* and is a vector with :math:`m + 1` elements This vector defines the function :math:`C(i)` which specifies the rows of the minor :math:`M`. To be specific, the function :math:`C(i)` for :math:`j = 0, \ldots , n-1` is defined by .. math:: :nowrap: \begin{eqnarray} C(0) & = & c[m] \\ C(j+1) & = & c[ C(j) ] \end{eqnarray} All the elements of *c* must have value less than or equal *m* . The elements of vector *c* are modified during the computation, and restored to their original value before the return from ``det_of_minor`` . d * The result *d* has prototype ``double`` *d* and is equal to the determinant of the minor :math:`M`. Source Code *********** {xrst_spell_off} {xrst_code cpp} */ double det_of_minor( const double* a , size_t m , size_t n , size_t* r , size_t* c ) { size_t R0, Cj, Cj1, j; double detM, M0j, detS; int s; R0 = r[m]; /* R(0) */ Cj = c[m]; /* C(j) (case j = 0) */ Cj1 = m; /* C(j-1) (case j = 0) */ /* check for 1 by 1 case */ if( n == 1 ) return a[ R0 * m + Cj ]; /* initialize determinant of the minor M */ detM = 0.; /* initialize sign of factor for neat sub-minor */ s = 1; /* remove row with index 0 in M from all the sub-minors of M */ r[m] = r[R0]; /* for each column of M */ for(j = 0; j < n; j++) { /* element with index (0,j) in the minor M */ M0j = a[ R0 * m + Cj ]; /* remove column with index j in M to form next sub-minor S of M */ c[Cj1] = c[Cj]; /* compute determinant of the current sub-minor S */ detS = det_of_minor(a, m, n - 1, r, c); /* restore column Cj to representation of M as a minor of A */ c[Cj1] = Cj; /* include this sub-minor term in the summation */ if( s > 0 ) detM = detM + M0j * detS; else detM = detM - M0j * detS; /* advance to neat column of M */ Cj1 = Cj; Cj = c[Cj]; s = - s; } /* restore row zero to the minor representation for M */ r[m] = R0; /* return the determinant of the minor M */ return detM; } /* {xrst_code} {xrst_spell_on} {xrst_end det_of_minor_c}