Mercurial > hg > octave-nkf
diff liboctave/fCMatrix.cc @ 8336:9813c07ca946
make det take advantage of matrix type
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 19 Nov 2008 15:26:39 +0100 |
parents | 64cf956a109c |
children | e02242c54c49 |
line wrap: on
line diff
--- a/liboctave/fCMatrix.cc +++ b/liboctave/fCMatrix.cc @@ -3,6 +3,7 @@ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008 Jaroslav Hajek This file is part of Octave. @@ -54,6 +55,7 @@ #include "mx-fcm-fs.h" #include "mx-inlines.cc" #include "oct-cmplx.h" +#include "oct-norm.h" #if defined (HAVE_FFTW3) #include "oct-fftw.h" @@ -1567,74 +1569,132 @@ FloatComplexDET FloatComplexMatrix::determinant (octave_idx_type& info, float& rcon, int calc_cond) const { - FloatComplexDET retval; + MatrixType mattype (*this); + return determinant (mattype, info, rcon, calc_cond); +} + +FloatComplexDET +FloatComplexMatrix::determinant (MatrixType& mattype, + octave_idx_type& info, float& rcon, int calc_cond) const +{ + FloatComplexDET retval (1.0); octave_idx_type nr = rows (); octave_idx_type nc = cols (); - if (nr == 0 || nc == 0) - { - retval = FloatComplexDET (1.0, 0); - } + if (nr != nc) + (*current_liboctave_error_handler) ("matrix must be square"); else { - Array<octave_idx_type> ipvt (nr); - octave_idx_type *pipvt = ipvt.fortran_vec (); - - FloatComplexMatrix atmp = *this; - FloatComplex *tmp_data = atmp.fortran_vec (); - - info = 0; - - // Calculate the norm of the matrix, for later use. - float anorm = 0; - if (calc_cond) - anorm = atmp.abs().sum().row(static_cast<octave_idx_type>(0)).max(); - - F77_XFCN (cgetrf, CGETRF, (nr, nc, tmp_data, nr, pipvt, info)); - - // Throw-away extra info LAPACK gives so as to not change output. - rcon = 0.0; - if (info != 0) - { - info = -1; - retval = FloatComplexDET (); - } - else - { - if (calc_cond) - { - // Now calc the condition number for non-singular matrix. - char job = '1'; - Array<FloatComplex> z (2*nr); - FloatComplex *pz = z.fortran_vec (); - Array<float> rz (2*nr); - float *prz = rz.fortran_vec (); - - F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1), - nc, tmp_data, nr, anorm, - rcon, pz, prz, info - F77_CHAR_ARG_LEN (1))); - } - - if (info != 0) - { - info = -1; - retval = FloatComplexDET (); - } - else - { - retval = FloatComplexDET (1.0); - - for (octave_idx_type i = 0; i < nc; i++) - { - FloatComplex c = atmp(i,i); - retval *= (ipvt(i) != (i+1)) ? -c : c; + int typ = mattype.type (); + + if (typ == MatrixType::Lower || typ == MatrixType::Upper) + { + for (octave_idx_type i = 0; i < nc; i++) + retval *= elem (i,i); + } + else if (typ == MatrixType::Hermitian) + { + FloatComplexMatrix atmp = *this; + FloatComplex *tmp_data = atmp.fortran_vec (); + + info = 0; + float anorm = 0; + if (calc_cond) anorm = xnorm (*this, 1); + + + char job = 'L'; + F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr, + tmp_data, nr, info + F77_CHAR_ARG_LEN (1))); + + if (info != 0) + { + rcon = 0.0; + mattype.mark_as_unsymmetric (); + typ = MatrixType::Full; + } + else + { + Array<FloatComplex> z (2 * nc); + FloatComplex *pz = z.fortran_vec (); + Array<float> rz (nc); + float *prz = rz.fortran_vec (); + + F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1), + nr, tmp_data, nr, anorm, + rcon, pz, prz, info + F77_CHAR_ARG_LEN (1))); + + if (info != 0) + rcon = 0.0; + + for (octave_idx_type i = 0; i < nc; i++) + retval *= elem (i,i); + + retval = retval.square (); + } + } + else if (typ != MatrixType::Full) + (*current_liboctave_error_handler) ("det: invalid dense matrix type"); + + if (typ == MatrixType::Full) + { + Array<octave_idx_type> ipvt (nr); + octave_idx_type *pipvt = ipvt.fortran_vec (); + + FloatComplexMatrix atmp = *this; + FloatComplex *tmp_data = atmp.fortran_vec (); + + info = 0; + + // Calculate the norm of the matrix, for later use. + float anorm = 0; + if (calc_cond) anorm = xnorm (*this, 1); + + F77_XFCN (cgetrf, CGETRF, (nr, nr, tmp_data, nr, pipvt, info)); + + // Throw-away extra info LAPACK gives so as to not change output. + rcon = 0.0; + if (info != 0) + { + info = -1; + retval = FloatComplexDET (); + } + else + { + if (calc_cond) + { + // Now calc the condition number for non-singular matrix. + char job = '1'; + Array<FloatComplex> z (2 * nc); + FloatComplex *pz = z.fortran_vec (); + Array<float> rz (2 * nc); + float *prz = rz.fortran_vec (); + + F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1), + nc, tmp_data, nr, anorm, + rcon, pz, prz, info + F77_CHAR_ARG_LEN (1))); } - } - } + + if (info != 0) + { + info = -1; + retval = FloatComplexDET (); + } + else + { + for (octave_idx_type i = 0; i < nc; i++) + { + FloatComplex c = atmp(i,i); + retval *= (ipvt(i) != (i+1)) ? -c : c; + } + } + } + } } - + return retval; }