Mercurial > hg > octave-terminal
changeset 10601:3ce0c530a9c9
implement svd_driver
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Mon, 03 May 2010 13:21:35 +0200 |
parents | 036bdc2d0af0 |
children | 38eae0c3a003 |
files | liboctave/ChangeLog liboctave/CmplxSVD.cc liboctave/CmplxSVD.h liboctave/dbleSVD.cc liboctave/dbleSVD.h liboctave/fCmplxSVD.cc liboctave/fCmplxSVD.h liboctave/floatSVD.cc liboctave/floatSVD.h src/ChangeLog src/DLD-FUNCTIONS/svd.cc |
diffstat | 11 files changed, 307 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,15 @@ +2010-05-03 Jaroslav Hajek <highegg@gmail.com> + + * dbleSVD.h (SVD::driver): New enum. + (SVD::SVD, SVD::init): Add driver option. + * floatSVD.h (FloatSVD::FloatSVD, FloatSVD::init): Add driver option. + * CmplxSVD.h (ComplexSVD::ComplexSVD, ComplexSVD::init): Add driver option. + * fCmplxSVD.h (FloatComplexSVD::FloatComplexSVD, FloatComplexSVD::init): Add driver option. + * dbleSVD.cc (SVD::init): Optionally use xGESDD driver. + * floatSVD.cc (FloatSVD::init): Ditto. + * CmplxSVD.cc (ComplexSVD::init): Ditto. + * fCmplxSVD.cc (FloatComplexSVD::init): Ditto. + 2010-04-28 John W. Eaton <jwe@octave.org> * dim-vector.h (dim_vector (const octave_idx_type *, size_t)): Delete.
--- a/liboctave/CmplxSVD.cc +++ b/liboctave/CmplxSVD.cc @@ -28,6 +28,7 @@ #include "CmplxSVD.h" #include "f77-fcn.h" #include "lo-error.h" +#include "oct-locbuf.h" extern "C" { @@ -40,6 +41,14 @@ double*, octave_idx_type& F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zgesdd, ZGESDD) (F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, const octave_idx_type&, Complex*, + const octave_idx_type&, double*, Complex*, const octave_idx_type&, + Complex*, const octave_idx_type&, Complex*, const octave_idx_type&, + double*, octave_idx_type *, octave_idx_type& + F77_CHAR_ARG_LEN_DECL); } ComplexMatrix @@ -69,7 +78,7 @@ } octave_idx_type -ComplexSVD::init (const ComplexMatrix& a, SVD::type svd_type) +ComplexSVD::init (const ComplexMatrix& a, SVD::type svd_type, SVD::driver svd_driver) { octave_idx_type info; @@ -144,24 +153,50 @@ octave_idx_type one = 1; octave_idx_type m1 = std::max (m, one), nrow_vt1 = std::max (nrow_vt, one); - F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, - rwork.fortran_vec (), info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (svd_driver == SVD::GESVD) + { + F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0).real ()); + work.resize (lwork, 1); - lwork = static_cast<octave_idx_type> (work(0).real ()); - work.resize (lwork, 1); + F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + else if (svd_driver == SVD::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; + OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn); - F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, - rwork.fortran_vec (), info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (zgesdd, ZGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0).real ()); + work.resize (lwork, 1); + + F77_XFCN (zgesdd, ZGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1))); + } + else + assert (0); // impossible if (! (jobv == 'N' || jobv == 'O')) right_sm = right_sm.hermitian ();
--- a/liboctave/CmplxSVD.h +++ b/liboctave/CmplxSVD.h @@ -38,15 +38,16 @@ ComplexSVD (void) { } - ComplexSVD (const ComplexMatrix& a, SVD::type svd_type = SVD::std) + ComplexSVD (const ComplexMatrix& a, + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) { - init (a, svd_type); + { init (a, svd_type, svd_driver); } } ComplexSVD (const ComplexMatrix& a, octave_idx_type& info, - SVD::type svd_type = SVD::std) + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) { - info = init (a, svd_type); + info = init (a, svd_type, svd_driver); } ComplexSVD (const ComplexSVD& a) @@ -83,7 +84,9 @@ ComplexMatrix left_sm; ComplexMatrix right_sm; - octave_idx_type init (const ComplexMatrix& a, SVD::type svd_type = SVD::std); + octave_idx_type init (const ComplexMatrix& a, + SVD::type svd_type = SVD::std, + SVD::driver svd_driver = SVD::GESVD); }; #endif
--- a/liboctave/dbleSVD.cc +++ b/liboctave/dbleSVD.cc @@ -29,6 +29,7 @@ #include "dbleSVD.h" #include "f77-fcn.h" +#include "oct-locbuf.h" extern "C" { @@ -41,6 +42,14 @@ double*, const octave_idx_type&, octave_idx_type& F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (dgesdd, DGESDD) (F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, const octave_idx_type&, double*, + const octave_idx_type&, double*, double*, + const octave_idx_type&, double*, const octave_idx_type&, + double*, const octave_idx_type&, octave_idx_type *, octave_idx_type& + F77_CHAR_ARG_LEN_DECL); } Matrix @@ -70,7 +79,7 @@ } octave_idx_type -SVD::init (const Matrix& a, SVD::type svd_type) +SVD::init (const Matrix& a, SVD::type svd_type, SVD::driver svd_driver) { octave_idx_type info; @@ -140,22 +149,48 @@ octave_idx_type one = 1; octave_idx_type m1 = std::max (m, one), nrow_vt1 = std::max (nrow_vt, one); - F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (svd_driver == SVD::GESVD) + { + F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0)); + work.resize (lwork, 1); + + F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - lwork = static_cast<octave_idx_type> (work(0)); - work.resize (lwork, 1); + } + else if (svd_driver == SVD::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; + OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn); + + F77_XFCN (dgesdd, DGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, iwork, info + F77_CHAR_ARG_LEN (1))); - F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + lwork = static_cast<octave_idx_type> (work(0)); + work.resize (lwork, 1); + + F77_XFCN (dgesdd, DGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, iwork, info + F77_CHAR_ARG_LEN (1))); + + } + else + assert (0); // impossible if (! (jobv == 'N' || jobv == 'O')) right_sm = right_sm.transpose ();
--- a/liboctave/dbleSVD.h +++ b/liboctave/dbleSVD.h @@ -42,13 +42,22 @@ sigma_only }; + enum driver + { + GESVD, + GESDD + }; + SVD (void) : sigma (), left_sm (), right_sm () { } - SVD (const Matrix& a, type svd_type = SVD::std) { init (a, svd_type); } + SVD (const Matrix& a, + type svd_type = SVD::std, driver svd_driver = SVD::GESVD) + { init (a, svd_type, svd_driver); } - SVD (const Matrix& a, octave_idx_type& info, type svd_type = SVD::std) + SVD (const Matrix& a, octave_idx_type& info, + type svd_type = SVD::std, driver svd_driver = SVD::GESVD) { - info = init (a, svd_type); + info = init (a, svd_type, svd_driver); } SVD (const SVD& a) @@ -86,7 +95,8 @@ Matrix left_sm; Matrix right_sm; - octave_idx_type init (const Matrix& a, type svd_type = std); + octave_idx_type init (const Matrix& a, + type svd_type = std, driver svd_driver = GESVD); }; #endif
--- a/liboctave/fCmplxSVD.cc +++ b/liboctave/fCmplxSVD.cc @@ -28,6 +28,7 @@ #include "fCmplxSVD.h" #include "f77-fcn.h" #include "lo-error.h" +#include "oct-locbuf.h" extern "C" { @@ -40,6 +41,14 @@ float*, octave_idx_type& F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (cgesdd, CGESDD) (F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, const octave_idx_type&, FloatComplex*, + const octave_idx_type&, float*, FloatComplex*, const octave_idx_type&, + FloatComplex*, const octave_idx_type&, FloatComplex*, const octave_idx_type&, + float*, octave_idx_type *, octave_idx_type& + F77_CHAR_ARG_LEN_DECL); } FloatComplexMatrix @@ -69,7 +78,7 @@ } octave_idx_type -FloatComplexSVD::init (const FloatComplexMatrix& a, SVD::type svd_type) +FloatComplexSVD::init (const FloatComplexMatrix& a, SVD::type svd_type, SVD::driver svd_driver) { octave_idx_type info; @@ -144,24 +153,50 @@ octave_idx_type one = 1; octave_idx_type m1 = std::max (m, one), nrow_vt1 = std::max (nrow_vt, one); - F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, - rwork.fortran_vec (), info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (svd_driver == SVD::GESVD) + { + F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0).real ()); + work.resize (lwork, 1); - lwork = static_cast<octave_idx_type> (work(0).real ()); - work.resize (lwork, 1); + F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + else if (svd_driver == SVD::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; + OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn); - F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, - rwork.fortran_vec (), info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (cgesdd, CGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0).real ()); + work.resize (lwork, 1); + + F77_XFCN (cgesdd, CGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1))); + } + else + assert (0); // impossible if (! (jobv == 'N' || jobv == 'O')) right_sm = right_sm.hermitian ();
--- a/liboctave/fCmplxSVD.h +++ b/liboctave/fCmplxSVD.h @@ -38,15 +38,16 @@ FloatComplexSVD (void) { } - FloatComplexSVD (const FloatComplexMatrix& a, SVD::type svd_type = SVD::std) + FloatComplexSVD (const FloatComplexMatrix& a, + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) { - init (a, svd_type); + init (a, svd_type, svd_driver); } FloatComplexSVD (const FloatComplexMatrix& a, octave_idx_type& info, - SVD::type svd_type = SVD::std) + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) { - info = init (a, svd_type); + info = init (a, svd_type, svd_driver); } FloatComplexSVD (const FloatComplexSVD& a) @@ -83,7 +84,9 @@ FloatComplexMatrix left_sm; FloatComplexMatrix right_sm; - octave_idx_type init (const FloatComplexMatrix& a, SVD::type svd_type = SVD::std); + octave_idx_type init (const FloatComplexMatrix& a, + SVD::type svd_type = SVD::std, + SVD::driver svd_driver = SVD::GESVD); }; #endif
--- a/liboctave/floatSVD.cc +++ b/liboctave/floatSVD.cc @@ -29,6 +29,7 @@ #include "floatSVD.h" #include "f77-fcn.h" +#include "oct-locbuf.h" extern "C" { @@ -41,6 +42,14 @@ float*, const octave_idx_type&, octave_idx_type& F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (sgesdd, SGESDD) (F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, const octave_idx_type&, float*, + const octave_idx_type&, float*, float*, + const octave_idx_type&, float*, const octave_idx_type&, + float*, const octave_idx_type&, octave_idx_type *, octave_idx_type& + F77_CHAR_ARG_LEN_DECL); } FloatMatrix @@ -70,7 +79,7 @@ } octave_idx_type -FloatSVD::init (const FloatMatrix& a, SVD::type svd_type) +FloatSVD::init (const FloatMatrix& a, SVD::type svd_type, SVD::driver svd_driver) { octave_idx_type info; @@ -140,22 +149,48 @@ octave_idx_type one = 1; octave_idx_type m1 = std::max (m, one), nrow_vt1 = std::max (nrow_vt, one); - F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (svd_driver == SVD::GESVD) + { + F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + lwork = static_cast<octave_idx_type> (work(0)); + work.resize (lwork, 1); + + F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - lwork = static_cast<octave_idx_type> (work(0)); - work.resize (lwork, 1); + } + else if (svd_driver == SVD::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; + OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn); + + F77_XFCN (sgesdd, SGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, iwork, info + F77_CHAR_ARG_LEN (1))); - F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - m, n, tmp_data, m1, s_vec, u, m1, vt, - nrow_vt1, work.fortran_vec (), lwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + lwork = static_cast<octave_idx_type> (work(0)); + work.resize (lwork, 1); + + F77_XFCN (sgesdd, SGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1), + m, n, tmp_data, m1, s_vec, u, m1, vt, + nrow_vt1, work.fortran_vec (), lwork, iwork, info + F77_CHAR_ARG_LEN (1))); + + } + else + assert (0); // impossible if (! (jobv == 'N' || jobv == 'O')) right_sm = right_sm.transpose ();
--- a/liboctave/floatSVD.h +++ b/liboctave/floatSVD.h @@ -38,11 +38,14 @@ FloatSVD (void) : sigma (), left_sm (), right_sm () { } - FloatSVD (const FloatMatrix& a, SVD::type svd_type = SVD::std) { init (a, svd_type); } + FloatSVD (const FloatMatrix& a, + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) + { init (a, svd_type, svd_driver); } - FloatSVD (const FloatMatrix& a, octave_idx_type& info, SVD::type svd_type = SVD::std) + FloatSVD (const FloatMatrix& a, octave_idx_type& info, + SVD::type svd_type = SVD::std, SVD::driver svd_driver = SVD::GESVD) { - info = init (a, svd_type); + info = init (a, svd_type, svd_driver); } FloatSVD (const FloatSVD& a) @@ -80,7 +83,9 @@ FloatMatrix left_sm; FloatMatrix right_sm; - octave_idx_type init (const FloatMatrix& a, SVD::type svd_type = SVD::std); + octave_idx_type init (const FloatMatrix& a, + SVD::type svd_type = SVD::std, + SVD::driver svd_driver = SVD::GESVD); }; #endif
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2010-05-03 Jaroslav Hajek <highegg@gmail.com> + + * DLD-FUNCTIONS/svd.cc (driver): New static var. + (Fsvd): Use it to select a driver. + (Fsvd_driver): New DEFUN. + 2010-05-02 Rik <octave@nomad.inbox5.com> * ov-cell.cc: Wrap documentation line to prevent overfull hbox
--- a/src/DLD-FUNCTIONS/svd.cc +++ b/src/DLD-FUNCTIONS/svd.cc @@ -37,6 +37,8 @@ #include "pr-output.h" #include "utils.h" +static SVD::driver driver = SVD::GESVD; + DEFUN_DLD (svd, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{s} =} svd (@var{a})\n\ @@ -203,7 +205,7 @@ return retval; } - FloatSVD result (tmp, type); + FloatSVD result (tmp, type, driver); FloatDiagMatrix sigma = result.singular_values (); @@ -231,7 +233,7 @@ return retval; } - FloatComplexSVD result (ctmp, type); + FloatComplexSVD result (ctmp, type, driver); FloatDiagMatrix sigma = result.singular_values (); @@ -262,7 +264,7 @@ return retval; } - SVD result (tmp, type); + SVD result (tmp, type, driver); DiagMatrix sigma = result.singular_values (); @@ -290,7 +292,7 @@ return retval; } - ComplexSVD result (ctmp, type); + ComplexSVD result (ctmp, type, driver); DiagMatrix sigma = result.singular_values (); @@ -396,3 +398,43 @@ %!error <Invalid call to svd.*> [u, v] = svd ([1, 2; 3, 4]); */ + +DEFUN_DLD (svd_driver, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{old} =} svd_driver (@var{new})\n\ +Sets or queries the underlying LAPACK driver used by svd.\n\ +Currently recognized are \"gesvd\" and \"gesdd\". Default is \"gesvd\".\n\ +@seealso{svd}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin == 0 || (nargin == 1 && args(0).is_string ())) + { + if (driver == SVD::GESVD) + retval = "gesvd"; + else if (driver == SVD::GESDD) + retval = "gesdd"; + else + panic_impossible (); + + + if (nargin == 1) + { + std::string opt = args(0).xtolower ().string_value (); + if (opt == "gesvd") + driver = SVD::GESVD; + else if (opt == "gesdd") + driver = SVD::GESDD; + else + error ("svd_driver: invalid driver spec: %s", opt.c_str ()); + } + } + else + print_usage (); + + return retval; +} + +