gesvd.hpp

Go to the documentation of this file.
00001 /*
00002  * 
00003  * Copyright (c) Toon Knapen & Kresimir Fresl 2003
00004  *
00005  * Distributed under the Boost Software License, Version 1.0.
00006  * (See accompanying file LICENSE_1_0.txt or copy at
00007  * http://www.boost.org/LICENSE_1_0.txt)
00008  *
00009  * KF acknowledges the support of the Faculty of Civil Engineering, 
00010  * University of Zagreb, Croatia.
00011  *
00012  */
00013 
00014 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_GESVD_HPP
00015 #define BOOST_NUMERIC_BINDINGS_LAPACK_GESVD_HPP
00016 
00017 #include <boost/numeric/bindings/traits/type_traits.hpp>
00018 #include <boost/numeric/bindings/traits/traits.hpp>
00019 #include <boost/numeric/bindings/lapack/lapack.h>
00020 #include <boost/numeric/bindings/traits/detail/array.hpp>
00021 #include <boost/numeric/bindings/traits/detail/utils.hpp>
00022 
00023 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00024 #  include <boost/static_assert.hpp>
00025 #  include <boost/type_traits/is_same.hpp>
00026 #endif 
00027 
00028 #include <cassert>
00029 
00030 namespace boost { namespace numeric { namespace bindings { 
00031 
00032   namespace lapack {
00033 
00035     //
00036     // singular value decomposition 
00037     // 
00039 
00040     /* 
00041      * (simple driver) 
00042      * gesvd() computes the singular value decomposition (SVD) of 
00043      * M-by-N matrix A, optionally computing the left and/or right 
00044      * singular vectors. The SVD is written
00045      *
00046      *     A = U * S * V^T    or    A = U * S * V^H
00047      *
00048      * where S is an M-by-N matrix which is zero except for its min(m,n)
00049      * diagonal elements, U is an M-by-M orthogonal/unitary matrix, and V 
00050      * is an N-by-N orthogonal/unitary matrix. The diagonal elements of S
00051      * are the singular values of A; they are real and non-negative, and 
00052      * are returnede in descending  order. The first min(m,n) columns of 
00053      * U and V are the left and right singular vectors of A. (Note that 
00054      * the routine returns V^T or V^H, not V.
00055      */ 
00056 
00057     namespace detail {
00058 
00059       inline 
00060       void gesvd (char const jobu, char const jobvt, 
00061                   int const m, int const n, float* a, int const lda, 
00062                   float* s, float* u, int const ldu, 
00063                   float* vt, int const ldvt,
00064                   float* work, int const lwork, float* /* dummy */, 
00065                   int* info)
00066       {
00067         LAPACK_SGESVD (&jobu, &jobvt, &m, &n, a, &lda, 
00068                        s, u, &ldu, vt, &ldvt, work, &lwork, info); 
00069       }
00070 
00071       inline 
00072       void gesvd (char const jobu, char const jobvt, 
00073                   int const m, int const n, double* a, int const lda, 
00074                   double* s, double* u, int const ldu, 
00075                   double* vt, int const ldvt,
00076                   double* work, int const lwork, double* /* dummy */, 
00077                   int* info)
00078       {
00079         LAPACK_DGESVD (&jobu, &jobvt, &m, &n, a, &lda, 
00080                        s, u, &ldu, vt, &ldvt, work, &lwork, info); 
00081       }
00082 
00083       inline 
00084       void gesvd (char const jobu, char const jobvt, 
00085                   int const m, int const n, 
00086                   traits::complex_f* a, int const lda, 
00087                   float* s, traits::complex_f* u, int const ldu, 
00088                   traits::complex_f* vt, int const ldvt,
00089                   traits::complex_f* work, int const lwork, 
00090                   float* rwork, int* info)
00091       {
00092         LAPACK_CGESVD (&jobu, &jobvt, &m, &n, 
00093                        traits::complex_ptr (a), &lda, s, 
00094                        traits::complex_ptr (u), &ldu, 
00095                        traits::complex_ptr (vt), &ldvt, 
00096                        traits::complex_ptr (work), &lwork, rwork, info); 
00097       }
00098 
00099       inline 
00100       void gesvd (char const jobu, char const jobvt, 
00101                   int const m, int const n, 
00102                   traits::complex_d* a, int const lda, 
00103                   double* s, traits::complex_d* u, int const ldu, 
00104                   traits::complex_d* vt, int const ldvt,
00105                   traits::complex_d* work, int const lwork, 
00106                   double* rwork, int* info)
00107       {
00108         LAPACK_ZGESVD (&jobu, &jobvt, &m, &n, 
00109                        traits::complex_ptr (a), &lda, s, 
00110                        traits::complex_ptr (u), &ldu, 
00111                        traits::complex_ptr (vt), &ldvt, 
00112                        traits::complex_ptr (work), &lwork, rwork, info); 
00113       }
00114 
00115       inline 
00116       int gesvd_min_work (float, int m, int n) {
00117         int minmn = m < n ? m : n; 
00118         int maxmn = m < n ? n : m; 
00119         int m3x = 3 * minmn + maxmn; 
00120         int m5 = 5 * minmn; 
00121         return m3x < m5 ? m5 : m3x; 
00122       }
00123       inline 
00124       int gesvd_min_work (double, int m, int n) {
00125         int minmn = m < n ? m : n; 
00126         int maxmn = m < n ? n : m; 
00127         int m3x = 3 * minmn + maxmn; 
00128         int m5 = 5 * minmn; 
00129         return m3x < m5 ? m5 : m3x; 
00130       }
00131       inline 
00132       int gesvd_min_work (traits::complex_f, int m, int n) {
00133         int minmn = m < n ? m : n; 
00134         int maxmn = m < n ? n : m; 
00135         return 2 * minmn + maxmn; 
00136       }
00137       inline 
00138       int gesvd_min_work (traits::complex_d, int m, int n) {
00139         int minmn = m < n ? m : n; 
00140         int maxmn = m < n ? n : m; 
00141         return 2 * minmn + maxmn; 
00142       }
00143 
00144       inline 
00145       int gesvd_rwork (float, int, int) { return 1; }
00146       inline 
00147       int gesvd_rwork (double, int, int) { return 1; }
00148       inline 
00149       int gesvd_rwork (traits::complex_f, int m, int n) {
00150         return 5 * (m < n ? m : n);
00151       }
00152       inline 
00153       int gesvd_rwork (traits::complex_d, int m, int n) {
00154         return 5 * (m < n ? m : n);
00155       }
00156 
00157     } // detail 
00158 
00159 
00160     template <typename MatrA> 
00161     inline
00162     int gesvd_work (char const q, 
00163                     char const jobu, char const jobvt, MatrA const& a) 
00164     {
00165 
00166 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00167       BOOST_STATIC_ASSERT((boost::is_same<
00168         typename traits::matrix_traits<MatrA>::matrix_structure, 
00169         traits::general_t
00170       >::value)); 
00171 #endif 
00172 
00173 #ifdef BOOST_NUMERIC_BINDINGS_LAPACK_2
00174       assert (q == 'M'); 
00175 #else
00176       assert (q == 'M' || q == 'O'); 
00177 #endif 
00178       assert (jobu == 'N' || jobu == 'O' || jobu == 'A' || jobu == 'S'); 
00179       assert (jobvt == 'N' || jobvt == 'O' || jobvt == 'A' || jobvt == 'S'); 
00180       assert (!(jobu == 'O' && jobvt == 'O')); 
00181 
00182       int const m = traits::matrix_size1 (a);
00183       int const n = traits::matrix_size2 (a);
00184       int lw = -13; 
00185 
00186 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00187       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00188 #else 
00189       typedef typename MatrA::value_type val_t; 
00190 #endif 
00191 
00192       if (q == 'M') 
00193         lw = detail::gesvd_min_work (val_t(), m, n);
00194 
00195 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_2
00196       MatrA& a2 = const_cast<MatrA&> (a); 
00197       if (q == 'O') {
00198         // traits::detail::array<val_t> w (0); 
00199         val_t w; 
00200         int info; 
00201         detail::gesvd (jobu, jobvt, m, n, 
00202                        traits::matrix_storage (a2), 
00203                        traits::leading_dimension (a2),
00204                        0, // traits::vector_storage (s),  
00205                        0, // traits::matrix_storage (u),
00206                        m, // traits::leading_dimension (u),
00207                        0, // traits::matrix_storage (vt),
00208                        n, // traits::leading_dimension (vt),
00209                        &w, // traits::vector_storage (w),  
00210                        -1, // traits::vector_size (w),  
00211                        0, // traits::vector_storage (rw),  
00212                        &info);
00213         assert (info == 0); 
00214         lw = traits::detail::to_int (w);  // (w[0]); 
00215       }
00216 #endif 
00217       
00218       return lw; 
00219     }
00220 
00221 
00222     template <typename MatrA> 
00223     inline
00224     int gesvd_rwork (MatrA const& a) {
00225 
00226 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00227       BOOST_STATIC_ASSERT((boost::is_same<
00228         typename traits::matrix_traits<MatrA>::matrix_structure, 
00229         traits::general_t
00230       >::value)); 
00231 #endif 
00232 
00233 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00234       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00235 #else 
00236       typedef typename MatrA::value_type val_t; 
00237 #endif 
00238 
00239       return detail::gesvd_rwork (val_t(), 
00240                                   traits::matrix_size1 (a),
00241                                   traits::matrix_size2 (a));
00242     }
00243 
00244 
00245     template <typename MatrA, typename VecS, 
00246               typename MatrU, typename MatrV, typename VecW>
00247     inline
00248     int gesvd (char const jobu, char const jobvt, 
00249                MatrA& a, VecS& s, MatrU& u, MatrV& vt, VecW& w) 
00250     {
00251 
00252 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00253       BOOST_STATIC_ASSERT((boost::is_same<
00254         typename traits::matrix_traits<MatrA>::matrix_structure, 
00255         traits::general_t
00256       >::value)); 
00257       BOOST_STATIC_ASSERT((boost::is_same<
00258         typename traits::matrix_traits<MatrU>::matrix_structure, 
00259         traits::general_t
00260       >::value)); 
00261       BOOST_STATIC_ASSERT((boost::is_same<
00262         typename traits::matrix_traits<MatrV>::matrix_structure, 
00263         traits::general_t
00264       >::value)); 
00265 
00266       BOOST_STATIC_ASSERT(
00267         (boost::is_same<
00268           typename traits::matrix_traits<MatrA>::value_type, float
00269         >::value
00270         ||
00271         boost::is_same<
00272           typename traits::matrix_traits<MatrA>::value_type, double
00273         >::value));
00274 #endif 
00275 
00276       int const m = traits::matrix_size1 (a);
00277       int const n = traits::matrix_size2 (a);
00278       int const minmn = m < n ? m : n; 
00279 
00280       assert (minmn == traits::vector_size (s)); 
00281       assert (!(jobu == 'O' && jobvt == 'O')); 
00282       assert ((jobu == 'N')
00283               || (jobu == 'O')
00284               || (jobu == 'A' && m == traits::matrix_size2 (u))
00285               || (jobu == 'S' && minmn == traits::matrix_size2 (u))); 
00286       assert ((jobu == 'N' && traits::leading_dimension (u) >= 1)
00287               || (jobu == 'O' && traits::leading_dimension (u) >= 1)
00288               || (jobu == 'A' && traits::leading_dimension (u) >= m)
00289               || (jobu == 'S' && traits::leading_dimension (u) >= m));
00290       assert (n == traits::matrix_size2 (vt)); 
00291       assert ((jobvt == 'N' && traits::leading_dimension (vt) >= 1)
00292               || (jobvt == 'O' && traits::leading_dimension (vt) >= 1)
00293               || (jobvt == 'A' && traits::leading_dimension (vt) >= n)
00294               || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn));
00295 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00296       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00297 #else 
00298       typedef typename MatrA::value_type val_t; 
00299 #endif 
00300       assert (traits::vector_size(w) >= detail::gesvd_min_work(val_t(),m,n)); 
00301 
00302       int info; 
00303       detail::gesvd (jobu, jobvt, m, n, 
00304                      traits::matrix_storage (a), 
00305                      traits::leading_dimension (a),
00306                      traits::vector_storage (s),  
00307                      traits::matrix_storage (u),
00308                      traits::leading_dimension (u),
00309                      traits::matrix_storage (vt),
00310                      traits::leading_dimension (vt),
00311                      traits::vector_storage (w),  
00312                      traits::vector_size (w),  
00313                      0, // dummy argument 
00314                      &info);
00315       return info; 
00316     }
00317 
00318 
00319     template <typename MatrA, typename VecS, 
00320               typename MatrU, typename MatrV, typename VecW, typename VecRW>
00321     inline
00322     int gesvd (char const jobu, char const jobvt, 
00323                MatrA& a, VecS& s, MatrU& u, MatrV& vt, VecW& w, VecRW& rw) 
00324     {
00325 
00326 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00327       BOOST_STATIC_ASSERT((boost::is_same<
00328         typename traits::matrix_traits<MatrA>::matrix_structure, 
00329         traits::general_t
00330       >::value)); 
00331       BOOST_STATIC_ASSERT((boost::is_same<
00332         typename traits::matrix_traits<MatrU>::matrix_structure, 
00333         traits::general_t
00334       >::value)); 
00335       BOOST_STATIC_ASSERT((boost::is_same<
00336         typename traits::matrix_traits<MatrV>::matrix_structure, 
00337         traits::general_t
00338       >::value)); 
00339 #endif 
00340 
00341       int const m = traits::matrix_size1 (a);
00342       int const n = traits::matrix_size2 (a);
00343       int const minmn = m < n ? m : n; 
00344 
00345       assert (minmn == traits::vector_size (s)); 
00346       assert (!(jobu == 'O' && jobvt == 'O')); 
00347       assert ((jobu == 'N')
00348               || (jobu == 'O')
00349               || (jobu == 'A' && m == traits::matrix_size2 (u))
00350               || (jobu == 'S' && minmn == traits::matrix_size2 (u))); 
00351       assert ((jobu == 'N' && traits::leading_dimension (u) >= 1)
00352               || (jobu == 'O' && traits::leading_dimension (u) >= 1)
00353               || (jobu == 'A' && traits::leading_dimension (u) >= m)
00354               || (jobu == 'S' && traits::leading_dimension (u) >= m));
00355       assert (n == traits::matrix_size2 (vt)); 
00356       assert ((jobvt == 'N' && traits::leading_dimension (vt) >= 1)
00357               || (jobvt == 'O' && traits::leading_dimension (vt) >= 1)
00358               || (jobvt == 'A' && traits::leading_dimension (vt) >= n)
00359               || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn));
00360 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00361       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00362 #else 
00363       typedef typename MatrA::value_type val_t; 
00364 #endif 
00365       assert (traits::vector_size(w) >= detail::gesvd_min_work(val_t(),m,n)); 
00366       assert (traits::vector_size(rw) >= detail::gesvd_rwork(val_t(),m,n));
00367 
00368       int info; 
00369       detail::gesvd (jobu, jobvt, m, n, 
00370                      traits::matrix_storage (a), 
00371                      traits::leading_dimension (a),
00372                      traits::vector_storage (s),  
00373                      traits::matrix_storage (u),
00374                      traits::leading_dimension (u),
00375                      traits::matrix_storage (vt),
00376                      traits::leading_dimension (vt),
00377                      traits::vector_storage (w),  
00378                      traits::vector_size (w),  
00379                      traits::vector_storage (rw),  
00380                      &info);
00381       return info; 
00382     }
00383 
00384 
00385     template <typename MatrA, typename VecS, typename MatrU, typename MatrV>
00386     inline
00387     int gesvd (char const opt, char const jobu, char const jobvt, 
00388                MatrA& a, VecS& s, MatrU& u, MatrV& vt) 
00389     {
00390 
00391 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00392       BOOST_STATIC_ASSERT((boost::is_same<
00393         typename traits::matrix_traits<MatrA>::matrix_structure, 
00394         traits::general_t
00395       >::value)); 
00396       BOOST_STATIC_ASSERT((boost::is_same<
00397         typename traits::matrix_traits<MatrU>::matrix_structure, 
00398         traits::general_t
00399       >::value)); 
00400       BOOST_STATIC_ASSERT((boost::is_same<
00401         typename traits::matrix_traits<MatrV>::matrix_structure, 
00402         traits::general_t
00403       >::value)); 
00404 #endif 
00405 
00406       int const m = traits::matrix_size1 (a);
00407       int const n = traits::matrix_size2 (a);
00408       int const minmn = m < n ? m : n; 
00409 
00410       assert (minmn == traits::vector_size (s)); 
00411       assert (!(jobu == 'O' && jobvt == 'O')); 
00412       assert ((jobu == 'N')
00413               || (jobu == 'O')
00414               || (jobu == 'A' && m == traits::matrix_size2 (u))
00415               || (jobu == 'S' && minmn == traits::matrix_size2 (u))); 
00416       assert ((jobu == 'N' && traits::leading_dimension (u) >= 1)
00417               || (jobu == 'O' && traits::leading_dimension (u) >= 1)
00418               || (jobu == 'A' && traits::leading_dimension (u) >= m)
00419               || (jobu == 'S' && traits::leading_dimension (u) >= m));
00420       assert ((jobvt == 'N' || traits::matrix_size2(vt) == n)) ;
00421       assert ((jobvt == 'N' && traits::leading_dimension (vt) >= 1)
00422               || (jobvt == 'O' && traits::leading_dimension (vt) >= 1)
00423               || (jobvt == 'A' && traits::leading_dimension (vt) >= n)
00424               || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn));
00425 
00426 #ifdef BOOST_NUMERIC_BINDINGS_LAPACK_2
00427       assert (opt == 'M'); 
00428 #else
00429       assert (opt == 'M' || opt == 'O'); 
00430 #endif 
00431 
00432 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00433       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00434 #else 
00435       typedef typename MatrA::value_type val_t; 
00436 #endif 
00437       typedef typename traits::type_traits<val_t>::real_type real_t;
00438 
00439       int const lw = gesvd_work (opt, jobu, jobvt, a); 
00440       traits::detail::array<val_t> w (lw); 
00441       if (!w.valid()) return -101; 
00442 
00443       int const lrw = gesvd_rwork (a); 
00444       traits::detail::array<real_t> rw (lrw); 
00445       if (!rw.valid()) return -102; 
00446 
00447       int info; 
00448       detail::gesvd (jobu, jobvt, m, n, 
00449                      traits::matrix_storage (a), 
00450                      traits::leading_dimension (a),
00451                      traits::vector_storage (s),  
00452                      traits::matrix_storage (u),
00453                      traits::leading_dimension (u),
00454                      traits::matrix_storage (vt),
00455                      traits::leading_dimension (vt),
00456                      traits::vector_storage (w),  
00457                      traits::vector_size (w),  
00458                      traits::vector_storage (rw),  
00459                      &info);
00460       return info; 
00461     }
00462 
00463 
00464 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_2
00465 
00466     template <typename MatrA, typename VecS, typename MatrU, typename MatrV>
00467     inline
00468     int gesvd (char const jobu, char const jobvt, 
00469                MatrA& a, VecS& s, MatrU& u, MatrV& vt) 
00470     {
00471       return gesvd ('O', jobu, jobvt, a, s, u, vt); 
00472     }
00473 
00474     template <typename MatrA, typename VecS, typename MatrU, typename MatrV>
00475     inline
00476     int gesvd (MatrA& a, VecS& s, MatrU& u, MatrV& vt) {
00477       return gesvd ('O', 'S', 'S', a, s, u, vt); 
00478     }
00479 
00480     template <typename MatrA, typename VecS> 
00481     inline
00482     int gesvd (MatrA& a, VecS& s) {
00483 
00484 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00485       BOOST_STATIC_ASSERT((boost::is_same<
00486         typename traits::matrix_traits<MatrA>::matrix_structure, 
00487         traits::general_t
00488       >::value)); 
00489 #endif 
00490 
00491       int const m = traits::matrix_size1 (a);
00492       int const n = traits::matrix_size2 (a);
00493       int const minmn = m < n ? m : n; 
00494 
00495       assert (minmn == traits::vector_size (s)); 
00496 
00497 #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS
00498       typedef typename traits::matrix_traits<MatrA>::value_type val_t; 
00499 #else 
00500       typedef typename MatrA::value_type val_t; 
00501 #endif 
00502       typedef typename traits::type_traits<val_t>::real_type real_t;
00503 
00504       int const lw = gesvd_work ('O', 'N', 'N', a); 
00505       traits::detail::array<val_t> w (lw); 
00506       if (!w.valid()) return -101; 
00507 
00508       int const lrw = gesvd_rwork (a); 
00509       traits::detail::array<real_t> rw (lrw); 
00510       if (!rw.valid()) return -102; 
00511 
00512       int info; 
00513       detail::gesvd ('N', 'N', m, n, 
00514                      traits::matrix_storage (a), 
00515                      traits::leading_dimension (a),
00516                      traits::vector_storage (s),  
00517                      0, // traits::matrix_storage (u),
00518                      1, // traits::leading_dimension (u),
00519                      0, // traits::matrix_storage (vt),
00520                      1, // traits::leading_dimension (vt),
00521                      traits::vector_storage (w),  
00522                      traits::vector_size (w),  
00523                      traits::vector_storage (rw),  
00524                      &info);
00525       return info; 
00526     }
00527 
00528 #endif 
00529 
00530   } // namespace lapack
00531 
00532 }}}
00533 
00534 #endif 

Generated on Wed Nov 23 19:00:16 2011 for FreeCAD by  doxygen 1.6.1