00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00037
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
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* ,
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* ,
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 }
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
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,
00205 0,
00206 m,
00207 0,
00208 n,
00209 &w,
00210 -1,
00211 0,
00212 &info);
00213 assert (info == 0);
00214 lw = traits::detail::to_int (w);
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,
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,
00518 1,
00519 0,
00520 1,
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 }
00531
00532 }}}
00533
00534 #endif