Mercurial > octave
diff liboctave/numeric/svd.cc @ 22329:7f3c7a8bd131
maint: Indent namespaces in liboctave/numeric files.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 17 Aug 2016 10:55:38 -0400 |
parents | bac0d6f07a3e |
children | 4caa7b28d183 |
line wrap: on
line diff
--- a/liboctave/numeric/svd.cc Wed Aug 17 10:37:57 2016 -0400 +++ b/liboctave/numeric/svd.cc Wed Aug 17 10:55:38 2016 -0400 @@ -42,376 +42,374 @@ namespace octave { -namespace math -{ - -template <typename T> -T -svd<T>::left_singular_matrix (void) const -{ - if (m_type == svd::Type::sigma_only) - (*current_liboctave_error_handler) - ("svd: U not computed because type == svd::sigma_only"); + namespace math + { + template <typename T> + T + svd<T>::left_singular_matrix (void) const + { + if (m_type == svd::Type::sigma_only) + (*current_liboctave_error_handler) + ("svd: U not computed because type == svd::sigma_only"); - return left_sm; -} + return left_sm; + } -template <typename T> -T -svd<T>::right_singular_matrix (void) const -{ - if (m_type == svd::Type::sigma_only) - (*current_liboctave_error_handler) - ("svd: V not computed because type == svd::sigma_only"); + template <typename T> + T + svd<T>::right_singular_matrix (void) const + { + if (m_type == svd::Type::sigma_only) + (*current_liboctave_error_handler) + ("svd: V not computed because type == svd::sigma_only"); - return right_sm; -} + return right_sm; + } -// GESVD specializations + // GESVD specializations -#define GESVD_REAL_STEP(f, F) \ - F77_XFCN (f, F, (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.data (), lwork, info \ - F77_CHAR_ARG_LEN (1) \ - F77_CHAR_ARG_LEN (1))) +#define GESVD_REAL_STEP(f, F) \ + F77_XFCN (f, F, (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.data (), lwork, info \ + F77_CHAR_ARG_LEN (1) \ + F77_CHAR_ARG_LEN (1))) -#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG) \ - F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \ - F77_CONST_CHAR_ARG2 (&jobv, 1), \ - m, n, CMPLX_ARG (tmp_data), \ - m1, s_vec, CMPLX_ARG (u), m1, \ - CMPLX_ARG (vt), nrow_vt1, \ - CMPLX_ARG (work.data ()), \ - lwork, rwork.data (), info \ - F77_CHAR_ARG_LEN (1) \ - F77_CHAR_ARG_LEN (1))) +#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG) \ + F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \ + F77_CONST_CHAR_ARG2 (&jobv, 1), \ + m, n, CMPLX_ARG (tmp_data), \ + m1, s_vec, CMPLX_ARG (u), m1, \ + CMPLX_ARG (vt), nrow_vt1, \ + CMPLX_ARG (work.data ()), \ + lwork, rwork.data (), info \ + F77_CHAR_ARG_LEN (1) \ + F77_CHAR_ARG_LEN (1))) -// DGESVD -template<> -void -svd<Matrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, - octave_idx_type n, double* tmp_data, octave_idx_type m1, - double* s_vec, double* u, double* vt, - octave_idx_type nrow_vt1, std::vector<double>& work, - octave_idx_type& lwork, octave_idx_type& info) -{ - GESVD_REAL_STEP (dgesvd, DGESVD); + // DGESVD + template<> + void + svd<Matrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, + octave_idx_type n, double* tmp_data, octave_idx_type m1, + double* s_vec, double* u, double* vt, + octave_idx_type nrow_vt1, std::vector<double>& work, + octave_idx_type& lwork, octave_idx_type& info) + { + GESVD_REAL_STEP (dgesvd, DGESVD); - lwork = work[0]; - work.reserve (lwork); + lwork = work[0]; + work.reserve (lwork); - GESVD_REAL_STEP (dgesvd, DGESVD); -} + GESVD_REAL_STEP (dgesvd, DGESVD); + } -// SGESVD -template<> -void -svd<FloatMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, - octave_idx_type n, float* tmp_data, - octave_idx_type m1, float* s_vec, float* u, float* vt, - octave_idx_type nrow_vt1, std::vector<float>& work, - octave_idx_type& lwork, octave_idx_type& info) -{ - GESVD_REAL_STEP (sgesvd, SGESVD); + // SGESVD + template<> + void + svd<FloatMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, + octave_idx_type n, float* tmp_data, + octave_idx_type m1, float* s_vec, float* u, float* vt, + octave_idx_type nrow_vt1, std::vector<float>& work, + octave_idx_type& lwork, octave_idx_type& info) + { + GESVD_REAL_STEP (sgesvd, SGESVD); - lwork = work[0]; - work.reserve (lwork); + lwork = work[0]; + work.reserve (lwork); - GESVD_REAL_STEP (sgesvd, SGESVD); -} + GESVD_REAL_STEP (sgesvd, SGESVD); + } -// ZGESVD -template<> -void -svd<ComplexMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, - octave_idx_type n, Complex* tmp_data, - octave_idx_type m1, double* s_vec, Complex* u, - Complex* vt, octave_idx_type nrow_vt1, - std::vector<Complex>& work, - octave_idx_type& lwork, octave_idx_type& info) -{ - std::vector<double> rwork (5 * std::max (m, n)); + // ZGESVD + template<> + void + svd<ComplexMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m, + octave_idx_type n, Complex* tmp_data, + octave_idx_type m1, double* s_vec, Complex* u, + Complex* vt, octave_idx_type nrow_vt1, + std::vector<Complex>& work, + octave_idx_type& lwork, octave_idx_type& info) + { + std::vector<double> rwork (5 * std::max (m, n)); - GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); + GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); - lwork = work[0].real (); - work.reserve (lwork); + lwork = work[0].real (); + work.reserve (lwork); - GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); -} + GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); + } -// CGESVD -template<> -void -svd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv, - octave_idx_type m, octave_idx_type n, - FloatComplex* tmp_data, octave_idx_type m1, - float* s_vec, FloatComplex* u, - FloatComplex* vt, octave_idx_type nrow_vt1, - std::vector<FloatComplex>& work, - octave_idx_type& lwork, octave_idx_type& info) -{ - std::vector<float> rwork (5 * std::max (m, n)); + // CGESVD + template<> + void + svd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv, + octave_idx_type m, octave_idx_type n, + FloatComplex* tmp_data, octave_idx_type m1, + float* s_vec, FloatComplex* u, + FloatComplex* vt, octave_idx_type nrow_vt1, + std::vector<FloatComplex>& work, + octave_idx_type& lwork, octave_idx_type& info) + { + std::vector<float> rwork (5 * std::max (m, n)); - GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); + GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); - lwork = work[0].real (); - work.reserve (lwork); + lwork = work[0].real (); + work.reserve (lwork); - GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); -} + GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); + } #undef GESVD_REAL_STEP #undef GESVD_COMPLEX_STEP -// GESDD specializations + // GESDD specializations -#define GESDD_REAL_STEP(f, F) \ - F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \ - m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \ - work.data (), lwork, iwork, info \ - F77_CHAR_ARG_LEN (1))) +#define GESDD_REAL_STEP(f, F) \ + F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \ + m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \ + work.data (), lwork, iwork, info \ + F77_CHAR_ARG_LEN (1))) -#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG) \ - F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n, \ - CMPLX_ARG (tmp_data), m1, \ - s_vec, CMPLX_ARG (u), m1, \ - CMPLX_ARG (vt), nrow_vt1, \ - CMPLX_ARG (work.data ()), lwork, \ - rwork.data (), iwork, info \ - F77_CHAR_ARG_LEN (1))) +#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG) \ + F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n, \ + CMPLX_ARG (tmp_data), m1, \ + s_vec, CMPLX_ARG (u), m1, \ + CMPLX_ARG (vt), nrow_vt1, \ + CMPLX_ARG (work.data ()), lwork, \ + rwork.data (), iwork, info \ + F77_CHAR_ARG_LEN (1))) -// DGESDD -template<> -void -svd<Matrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, - double* tmp_data, octave_idx_type m1, - double* s_vec, double* u, - double* vt, octave_idx_type nrow_vt1, - std::vector<double>& work, octave_idx_type& lwork, - octave_idx_type* iwork, octave_idx_type& info) -{ - GESDD_REAL_STEP (dgesdd, DGESDD); + // DGESDD + template<> + void + svd<Matrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, + double* tmp_data, octave_idx_type m1, + double* s_vec, double* u, + double* vt, octave_idx_type nrow_vt1, + std::vector<double>& work, octave_idx_type& lwork, + octave_idx_type* iwork, octave_idx_type& info) + { + GESDD_REAL_STEP (dgesdd, DGESDD); - lwork = work[0]; - work.reserve (lwork); + lwork = work[0]; + work.reserve (lwork); - GESDD_REAL_STEP (dgesdd, DGESDD); -} + GESDD_REAL_STEP (dgesdd, DGESDD); + } -// SGESDD -template<> -void -svd<FloatMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, - float* tmp_data, octave_idx_type m1, - float* s_vec, float* u, - float* vt, octave_idx_type nrow_vt1, - std::vector<float>& work, octave_idx_type& lwork, - octave_idx_type* iwork, octave_idx_type& info) -{ - GESDD_REAL_STEP (sgesdd, SGESDD); + // SGESDD + template<> + void + svd<FloatMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, + float* tmp_data, octave_idx_type m1, + float* s_vec, float* u, + float* vt, octave_idx_type nrow_vt1, + std::vector<float>& work, octave_idx_type& lwork, + octave_idx_type* iwork, octave_idx_type& info) + { + GESDD_REAL_STEP (sgesdd, SGESDD); - lwork = work[0]; - work.reserve (lwork); + lwork = work[0]; + work.reserve (lwork); - GESDD_REAL_STEP (sgesdd, SGESDD); -} + GESDD_REAL_STEP (sgesdd, SGESDD); + } -// ZGESDD -template<> -void -svd<ComplexMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, - Complex* tmp_data, octave_idx_type m1, - double* s_vec, Complex* u, - Complex* vt, octave_idx_type nrow_vt1, - std::vector<Complex>& work, octave_idx_type& lwork, - octave_idx_type* iwork, octave_idx_type& info) -{ + // ZGESDD + template<> + void + svd<ComplexMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n, + Complex* tmp_data, octave_idx_type m1, + double* s_vec, Complex* u, + Complex* vt, octave_idx_type nrow_vt1, + std::vector<Complex>& work, octave_idx_type& lwork, + octave_idx_type* iwork, octave_idx_type& info) + { - octave_idx_type min_mn = std::min (m, n); + octave_idx_type min_mn = std::min (m, n); - octave_idx_type lrwork; - if (jobz == 'N') - lrwork = 7*min_mn; - else - lrwork = 5*min_mn*min_mn + 5*min_mn; + octave_idx_type lrwork; + if (jobz == 'N') + lrwork = 7*min_mn; + else + lrwork = 5*min_mn*min_mn + 5*min_mn; - std::vector<double> rwork (lrwork); + std::vector<double> rwork (lrwork); - GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); + GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); - lwork = work[0].real (); - work.reserve (lwork); + lwork = work[0].real (); + work.reserve (lwork); - GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); -} + GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); + } -// CGESDD -template<> -void -svd<FloatComplexMatrix>::gesdd (char& jobz, octave_idx_type m, - octave_idx_type n, - FloatComplex* tmp_data, octave_idx_type m1, - float* s_vec, FloatComplex* u, - FloatComplex* vt, octave_idx_type nrow_vt1, - std::vector<FloatComplex>& work, - octave_idx_type& lwork, octave_idx_type* iwork, - octave_idx_type& info) -{ - octave_idx_type min_mn = std::min (m, n); - octave_idx_type max_mn = std::max (m, n); + // CGESDD + template<> + void + svd<FloatComplexMatrix>::gesdd (char& jobz, octave_idx_type m, + octave_idx_type n, + FloatComplex* tmp_data, octave_idx_type m1, + float* s_vec, FloatComplex* u, + FloatComplex* vt, octave_idx_type nrow_vt1, + std::vector<FloatComplex>& work, + octave_idx_type& lwork, octave_idx_type* iwork, + octave_idx_type& info) + { + octave_idx_type min_mn = std::min (m, n); + octave_idx_type max_mn = std::max (m, n); - octave_idx_type lrwork; - if (jobz == 'N') - lrwork = 5*min_mn; - else - lrwork = min_mn * std::max (5*min_mn+7, 2*max_mn+2*min_mn+1); - std::vector<float> rwork (lrwork); + octave_idx_type lrwork; + if (jobz == 'N') + lrwork = 5*min_mn; + else + lrwork = min_mn * std::max (5*min_mn+7, 2*max_mn+2*min_mn+1); + std::vector<float> rwork (lrwork); - GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); + GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); - lwork = work[0].real (); - work.reserve (lwork); + lwork = work[0].real (); + work.reserve (lwork); - GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); -} + GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); + } #undef GESDD_REAL_STEP #undef GESDD_COMPLEX_STEP -template<typename T> -svd<T>::svd (const T& a, svd::Type type, - svd::Driver driver) - : m_type (type), m_driver (driver), left_sm (), sigma (), right_sm () -{ - octave_idx_type info; + template<typename T> + svd<T>::svd (const T& a, svd::Type type, + svd::Driver driver) + : m_type (type), m_driver (driver), left_sm (), sigma (), right_sm () + { + octave_idx_type info; + + octave_idx_type m = a.rows (); + octave_idx_type n = a.cols (); + + if (m == 0 || n == 0) + { + switch (m_type) + { + case svd::Type::std: + left_sm = T (m, m, 0); + for (octave_idx_type i = 0; i < m; i++) + left_sm.xelem (i, i) = 1; + sigma = DM_T (m, n); + right_sm = T (n, n, 0); + for (octave_idx_type i = 0; i < n; i++) + right_sm.xelem (i, i) = 1; + break; - octave_idx_type m = a.rows (); - octave_idx_type n = a.cols (); + case svd::Type::economy: + left_sm = T (m, 0, 0); + sigma = DM_T (0, 0); + right_sm = T (0, n, 0); + break; + + case svd::Type::sigma_only: + default: + sigma = DM_T (0, 1); + break; + } + return; + } - if (m == 0 || n == 0) - { + T atmp = a; + P* tmp_data = atmp.fortran_vec (); + + octave_idx_type min_mn = m < n ? m : n; + + char jobu = 'A'; + char jobv = 'A'; + + octave_idx_type ncol_u = m; + octave_idx_type nrow_vt = n; + octave_idx_type nrow_s = m; + octave_idx_type ncol_s = n; + switch (m_type) { - case svd::Type::std: - left_sm = T (m, m, 0); - for (octave_idx_type i = 0; i < m; i++) - left_sm.xelem (i, i) = 1; - sigma = DM_T (m, n); - right_sm = T (n, n, 0); - for (octave_idx_type i = 0; i < n; i++) - right_sm.xelem (i, i) = 1; - break; - case svd::Type::economy: - left_sm = T (m, 0, 0); - sigma = DM_T (0, 0); - right_sm = T (0, n, 0); + jobu = jobv = 'S'; + ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; break; case svd::Type::sigma_only: + + // Note: for this case, both jobu and jobv should be 'N', but + // there seems to be a bug in dgesvd from Lapack V2.0. To + // demonstrate the bug, set both jobu and jobv to 'N' and find + // the singular values of [eye(3), eye(3)]. The result is + // [-sqrt(2), -sqrt(2), -sqrt(2)]. + // + // For Lapack 3.0, this problem seems to be fixed. + + jobu = jobv = 'N'; + ncol_u = nrow_vt = 1; + break; + default: - sigma = DM_T (0, 1); break; } - return; - } + + if (! (jobu == 'N' || jobu == 'O')) + left_sm.resize (m, ncol_u); - T atmp = a; - P* tmp_data = atmp.fortran_vec (); + P* u = left_sm.fortran_vec (); - octave_idx_type min_mn = m < n ? m : n; + sigma.resize (nrow_s, ncol_s); + DM_P* s_vec = sigma.fortran_vec (); - char jobu = 'A'; - char jobv = 'A'; + if (! (jobv == 'N' || jobv == 'O')) + right_sm.resize (nrow_vt, n); + + P* vt = right_sm.fortran_vec (); - octave_idx_type ncol_u = m; - octave_idx_type nrow_vt = n; - octave_idx_type nrow_s = m; - octave_idx_type ncol_s = n; + // Query _GESVD for the correct dimension of WORK. + + octave_idx_type lwork = -1; + + std::vector<P> work (1); - switch (m_type) - { - case svd::Type::economy: - jobu = jobv = 'S'; - ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; - break; - - case svd::Type::sigma_only: + octave_idx_type m1 = std::max (m, static_cast<octave_idx_type> (1)); + octave_idx_type nrow_vt1 = std::max (nrow_vt, + static_cast<octave_idx_type> (1)); - // Note: for this case, both jobu and jobv should be 'N', but - // there seems to be a bug in dgesvd from Lapack V2.0. To - // demonstrate the bug, set both jobu and jobv to 'N' and find - // the singular values of [eye(3), eye(3)]. The result is - // [-sqrt(2), -sqrt(2), -sqrt(2)]. - // - // For Lapack 3.0, this problem seems to be fixed. + if (m_driver == svd::Driver::GESVD) + gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, + work, lwork, info); + else if (m_driver == svd::Driver::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; - jobu = jobv = 'N'; - ncol_u = nrow_vt = 1; - break; + std::vector<octave_idx_type> iwork (8 * std::min (m, n)); - default: - break; + gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, + work, lwork, iwork.data (), info); + } + else + abort (); + + if (! (jobv == 'N' || jobv == 'O')) + right_sm = right_sm.transpose (); } - if (! (jobu == 'N' || jobu == 'O')) - left_sm.resize (m, ncol_u); - - P* u = left_sm.fortran_vec (); - - sigma.resize (nrow_s, ncol_s); - DM_P* s_vec = sigma.fortran_vec (); - - if (! (jobv == 'N' || jobv == 'O')) - right_sm.resize (nrow_vt, n); + // Instantiations we need. - P* vt = right_sm.fortran_vec (); - - // Query _GESVD for the correct dimension of WORK. - - octave_idx_type lwork = -1; + template class svd<Matrix>; - std::vector<P> work (1); - - octave_idx_type m1 = std::max (m, static_cast<octave_idx_type> (1)); - octave_idx_type nrow_vt1 = std::max (nrow_vt, - static_cast<octave_idx_type> (1)); + template class svd<FloatMatrix>; - if (m_driver == svd::Driver::GESVD) - gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, - work, lwork, info); - else if (m_driver == svd::Driver::GESDD) - { - assert (jobu == jobv); - char jobz = jobu; - - std::vector<octave_idx_type> iwork (8 * std::min (m, n)); - - gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, - work, lwork, iwork.data (), info); - } - else - abort (); + template class svd<ComplexMatrix>; - if (! (jobv == 'N' || jobv == 'O')) - right_sm = right_sm.transpose (); + template class svd<FloatComplexMatrix>; + } } - -// Instantiations we need. - -template class svd<Matrix>; - -template class svd<FloatMatrix>; - -template class svd<ComplexMatrix>; - -template class svd<FloatComplexMatrix>; - -} -}