Mercurial > hg > octave-max
changeset 2815:33486d9e2d00
[project @ 1997-03-14 08:24:46 by jwe]
author | jwe |
---|---|
date | Fri, 14 Mar 1997 08:25:58 +0000 |
parents | ffa60dc8e49b |
children | ad4bf2a82b4f |
files | NEWS kpathsea/ChangeLog kpathsea/configure.in libcruft/ChangeLog liboctave/Array2.cc liboctave/Array2.h liboctave/CMatrix.cc liboctave/CMatrix.h liboctave/ChangeLog liboctave/EIG.cc liboctave/EIG.h readline/ChangeLog readline/configure.in |
diffstat | 13 files changed, 250 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ function y = f (x) y = sqrt (x); endfunction quad ("f", 0, 1) + * If the argument to eig() is symmetric, Octave uses the specialized + Lapack subroutine for symmetric matrices for a significant + increase in performance. + Summary of changes for version 2.0.5: ------------------------------------
--- a/kpathsea/ChangeLog +++ b/kpathsea/ChangeLog @@ -1,3 +1,8 @@ +Thu Mar 13 13:08:05 1997 John W. Eaton <jwe@bevo.che.wisc.edu> + + * configure.in: Don't set special PIC options on SGI systems, + since PIC is apparently the default. + Wed Mar 12 17:00:16 1997 John W. Eaton <jwe@bevo.che.wisc.edu> * Makefile.in (install-strip): New target.
--- a/kpathsea/configure.in +++ b/kpathsea/configure.in @@ -37,6 +37,9 @@ SHLEXT=sl SH_LDFLAGS="-shared -fPIC" ;; + *-sgi-*) + CPICFLAG= + ;; esac AC_MSG_RESULT([defining CPICFLAG to be $CPICFLAG]) AC_MSG_RESULT([defining SHLEXT to be $SHLEXT])
--- a/libcruft/ChangeLog +++ b/libcruft/ChangeLog @@ -1,3 +1,8 @@ +Thu Mar 13 22:31:35 1997 John W. Eaton <jwe@bevo.che.wisc.edu> + + * blas, lapack: Add new files for symmetric eigenvalue + computation. + Wed Mar 12 16:59:59 1997 John W. Eaton <jwe@bevo.che.wisc.edu> * misc/Makefile.in (install-strip): New target.
--- a/liboctave/Array2.cc +++ b/liboctave/Array2.cc @@ -171,6 +171,23 @@ return *this; } +template <class T> +bool +Array2<T>::is_symmetric (void) const +{ + if (is_square () && d1 > 0) + { + for (int i = 0; i < d1; i++) + for (int j = i+1; j < d2; j++) + if (elem (i, j) != elem (j, i)) + return false; + + return true; + } + + return false; +} + /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/liboctave/Array2.h +++ b/liboctave/Array2.h @@ -173,6 +173,10 @@ Array2<T>& insert (const Array2<T>& a, int r, int c); + bool is_square (void) const { return (d1 == d2); } + + bool is_symmetric (void) const; + #ifdef HEAVYWEIGHT_INDEXING void maybe_delete_elements (idx_vector& i, idx_vector& j);
--- a/liboctave/CMatrix.cc +++ b/liboctave/CMatrix.cc @@ -181,6 +181,25 @@ return !(*this == a); } +bool +ComplexMatrix::is_hermitian (void) const +{ + int nr = rows (); + int nc = cols (); + + if (is_square () && nr > 0) + { + for (int i = 0; i < nr; i++) + for (int j = i; j < nc; j++) + if (elem (i, j) != conj (elem (j, i))) + return false; + + return true; + } + + return false; +} + // destructive insert/delete/reorder operations ComplexMatrix&
--- a/liboctave/CMatrix.h +++ b/liboctave/CMatrix.h @@ -72,6 +72,8 @@ bool operator == (const ComplexMatrix& a) const; bool operator != (const ComplexMatrix& a) const; + bool is_hermitian (void) const; + // destructive insert/delete/reorder operations ComplexMatrix& insert (const Matrix& a, int r, int c);
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,17 @@ +Fri Mar 14 00:29:46 1997 John W. Eaton <jwe@bevo.che.wisc.edu> + + * EIG.cc (EIG::hermitian_init (const ComplexMatrix&)): New function. + (EIG::init (const ComplexMatrix&)): Call it if arg is hermitian. + (EIG::symmetric_init (const Matrix&)): New function. + (EIG::init (const Matrix&)): Call it if arg is symmetric. + + * CMatrix.cc (ComplexMatrix::is_hermitian): New function. + +Thu Mar 13 17:04:26 1997 John W. Eaton <jwe@bevo.che.wisc.edu> + + * Array2.cc (is_symmetric): New function. + * Array2.h (is_square): New function. + Wed Mar 12 16:59:49 1997 John W. Eaton <jwe@bevo.che.wisc.edu> * Makefile.in (install-strip): New target.
--- a/liboctave/EIG.cc +++ b/liboctave/EIG.cc @@ -29,6 +29,7 @@ #endif #include "EIG.h" +#include "dColVector.h" #include "f77-fcn.h" #include "lo-error.h" @@ -45,11 +46,22 @@ Complex*, const int&, Complex*, const int&, Complex*, const int&, double*, int&, long, long); + + int F77_FCN (dsyev, DSYEV) (const char*, const char*, const int&, + double*, const int&, double*, double*, + const int&, int&, long, long); + + int F77_FCN (zheev, ZHEEV) (const char*, const char*, const int&, + Complex*, const int&, double*, Complex*, + const int&, double*, int&, long, long); } int EIG::init (const Matrix& a) { + if (a.is_symmetric ()) + return symmetric_init (a); + int n = a.rows (); if (n != a.cols ()) @@ -58,7 +70,7 @@ return -1; } - int info; + int info = 0; Matrix atmp = a; double *tmp_data = atmp.fortran_vec (); @@ -72,8 +84,10 @@ Matrix vr (n, n); double *pvr = vr.fortran_vec (); + // XXX FIXME XXX -- it might be possible to choose a better value of + // lwork that would result in more efficient computations. + int lwork = 8*n; - Array<double> work (lwork); double *pwork = work.fortran_vec (); @@ -83,40 +97,95 @@ F77_XFCN (dgeev, DGEEV, ("N", "V", n, tmp_data, n, pwr, pwi, dummy, idummy, pvr, n, pwork, lwork, info, 1L, 1L)); - if (f77_exception_encountered) + if (f77_exception_encountered || info < 0) (*current_liboctave_error_handler) ("unrecoverable error in dgeev"); else { - lambda.resize (n); - v.resize (n, n); + if (info > 0) + (*current_liboctave_error_handler) ("dgeev failed to converge"); + else + { + lambda.resize (n); + v.resize (n, n); - for (int j = 0; j < n; j++) - { - if (wi.elem (j) == 0.0) + for (int j = 0; j < n; j++) { - lambda.elem (j) = Complex (wr.elem (j)); - for (int i = 0; i < n; i++) - v.elem (i, j) = vr.elem (i, j); - } - else - { - if (j+1 >= n) + if (wi.elem (j) == 0.0) + { + lambda.elem (j) = Complex (wr.elem (j)); + for (int i = 0; i < n; i++) + v.elem (i, j) = vr.elem (i, j); + } + else { - (*current_liboctave_error_handler) ("EIG: internal error"); - return -1; + if (j+1 >= n) + { + (*current_liboctave_error_handler) + ("EIG: internal error"); + return -1; + } + + for (int i = 0; i < n; i++) + { + lambda.elem(j) = Complex (wr.elem(j), wi.elem(j)); + lambda.elem(j+1) = Complex (wr.elem(j+1), wi.elem(j+1)); + double real_part = vr.elem (i, j); + double imag_part = vr.elem (i, j+1); + v.elem (i, j) = Complex (real_part, imag_part); + v.elem (i, j+1) = Complex (real_part, -imag_part); + } + j++; } + } + } + } + + return info; +} + +int +EIG::symmetric_init (const Matrix& a) +{ + int n = a.rows (); - for (int i = 0; i < n; i++) - { - lambda.elem (j) = Complex (wr.elem (j), wi.elem (j)); - lambda.elem (j+1) = Complex (wr.elem (j+1), wi.elem (j+1)); - double real_part = vr.elem (i, j); - double imag_part = vr.elem (i, j+1); - v.elem (i, j) = Complex (real_part, imag_part); - v.elem (i, j+1) = Complex (real_part, -imag_part); - } - j++; - } + if (n != a.cols ()) + { + (*current_liboctave_error_handler) ("EIG requires square matrix"); + return -1; + } + + int info = 0; + + Matrix atmp = a; + double *tmp_data = atmp.fortran_vec (); + + Array<double> wr (n); + double *pwr = wr.fortran_vec (); + + // XXX FIXME XXX -- it might be possible to choose a better value of + // lwork that would result in more efficient computations. + + int lwork = 8*n; + Array<double> work (lwork); + double *pwork = work.fortran_vec (); + + F77_XFCN (dsyev, DSYEV, ("V", "U", n, tmp_data, n, pwr, pwork, + lwork, info, 1L, 1L)); + + if (f77_exception_encountered || info < 0) + (*current_liboctave_error_handler) ("unrecoverable error in dsyev"); + else + { + if (info > 0) + (*current_liboctave_error_handler) ("dsyev failed to converge"); + else + { + lambda.resize (n); + + for (int j = 0; j < n; j++) + lambda.elem (j) = Complex (wr.elem (j)); + + v = atmp; } } @@ -126,6 +195,9 @@ int EIG::init (const ComplexMatrix& a) { + if (a.is_hermitian ()) + return hermitian_init (a); + int n = a.rows (); if (n != a.cols ()) @@ -134,33 +206,89 @@ return -1; } - int info; - - lambda.resize (n); - v.resize (n, n); - - Complex *pw = lambda.fortran_vec (); - Complex *pvr = v.fortran_vec (); + int info = 0; ComplexMatrix atmp = a; Complex *tmp_data = atmp.fortran_vec (); + ComplexColumnVector w (n); + Complex *pw = w.fortran_vec (); + + ComplexMatrix vtmp (n, n); + Complex *pv = vtmp.fortran_vec (); + + // XXX FIXME XXX -- it might be possible to choose a better value of + // lwork that would result in more efficient computations. + int lwork = 8*n; - Array<Complex> work (lwork); Complex *pwork = work.fortran_vec (); - Array<double> rwork (4*n); + int lrwork = 2*n; + Array<double> rwork (lrwork); double *prwork = rwork.fortran_vec (); Complex *dummy = 0; int idummy = 1; F77_XFCN (zgeev, ZGEEV, ("N", "V", n, tmp_data, n, pw, dummy, idummy, - pvr, n, pwork, lwork, prwork, info, 1L, 1L)); + pv, n, pwork, lwork, prwork, info, 1L, 1L)); + + if (f77_exception_encountered || info < 0) + (*current_liboctave_error_handler) ("unrecoverable error in zgeev"); + else if (info > 0) + (*current_liboctave_error_handler) ("zgeev failed to converge"); + else + { + lambda = w; + v = vtmp; + } + + return info; +} + +int +EIG::hermitian_init (const ComplexMatrix& a) +{ + int n = a.rows (); + + if (n != a.cols ()) + { + (*current_liboctave_error_handler) ("EIG requires square matrix"); + return -1; + } + + int info = 0; - if (f77_exception_encountered) - (*current_liboctave_error_handler) ("unrecoverable error in zgeev"); + ComplexMatrix atmp = a; + Complex *tmp_data = atmp.fortran_vec (); + + ColumnVector w (n); + double *pw = w.fortran_vec (); + + // XXX FIXME XXX -- it might be possible to choose a better value of + // lwork that would result in more efficient computations. + + int lwork = 8*n; + Array<Complex> work (lwork); + Complex *pwork = work.fortran_vec (); + + int lrwork = 3*n; + Array<double> rwork (lrwork); + double *prwork = rwork.fortran_vec (); + + F77_XFCN (zheev, ZHEEV, ("V", "U", n, tmp_data, n, pw, pwork, + lwork, prwork, info, 1L, 1L)); + + if (f77_exception_encountered || info < 0) + (*current_liboctave_error_handler) ("unrecoverable error in zheev"); + else if (info > 0) + (*current_liboctave_error_handler) ("zheev failed to converge"); + else + { + lambda = w; + v = atmp; + } return info; }
--- a/liboctave/EIG.h +++ b/liboctave/EIG.h @@ -80,6 +80,9 @@ int init (const Matrix& a); int init (const ComplexMatrix& a); + + int symmetric_init (const Matrix& a); + int hermitian_init (const ComplexMatrix& a); }; #endif
--- a/readline/ChangeLog +++ b/readline/ChangeLog @@ -1,5 +1,8 @@ Thu Mar 13 11:43:35 1997 John W. Eaton <jwe@bevo.che.wisc.edu> + * configure.in: Don't set special PIC options on SGI systems, + since PIC is apparently the default. + * Makefile.in (realclean, distclean): Don't remove configure or config.h.in.