Mercurial > octave
comparison liboctave/numeric/svd.cc @ 31607:aac27ad79be6 stable
maint: Re-indent code after switch to using namespace macros.
* build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc,
__ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc,
__pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h,
besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc,
call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc,
debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc,
dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h,
error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h,
event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc,
file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h,
gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h,
graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc,
gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h,
interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h,
inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc,
latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h,
lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc,
matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h,
oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc,
oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h,
oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h,
octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc,
pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc,
settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc,
sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc,
syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h,
symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h,
text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc,
url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h,
variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc,
__init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc,
gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc,
cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h,
cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h,
cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc,
ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc,
ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc,
ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h,
ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc,
ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc,
ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc,
ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc,
ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h,
ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc,
ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc,
ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h,
octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc,
op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h,
anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h,
comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h,
parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h,
pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h,
pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc,
pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc,
pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h,
pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h,
pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h,
pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h,
pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h,
pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h,
pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h,
pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h,
idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h,
aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h,
gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc,
lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h,
oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc,
oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h,
randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h,
sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc,
sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h,
file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h,
lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h,
oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc,
oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h,
action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h,
cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h,
lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h,
lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc,
oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc,
oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc,
oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc,
pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc,
url-transfer.h:
Re-indent code after switch to using namespace macros.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 01 Dec 2022 18:02:15 -0800 |
parents | e88a07dec498 |
children | 597f3ee61a48 |
comparison
equal
deleted
inserted
replaced
31605:e88a07dec498 | 31607:aac27ad79be6 |
---|---|
303 | 303 |
304 OCTAVE_BEGIN_NAMESPACE(octave) | 304 OCTAVE_BEGIN_NAMESPACE(octave) |
305 | 305 |
306 OCTAVE_BEGIN_NAMESPACE(math) | 306 OCTAVE_BEGIN_NAMESPACE(math) |
307 | 307 |
308 template <typename T> | 308 template <typename T> |
309 T | 309 T |
310 svd<T>::left_singular_matrix (void) const | 310 svd<T>::left_singular_matrix (void) const |
311 { | 311 { |
312 if (m_type == svd::Type::sigma_only) | 312 if (m_type == svd::Type::sigma_only) |
313 (*current_liboctave_error_handler) | 313 (*current_liboctave_error_handler) |
314 ("svd: U not computed because type == svd::sigma_only"); | 314 ("svd: U not computed because type == svd::sigma_only"); |
315 | 315 |
316 return m_left_sm; | 316 return m_left_sm; |
317 } | 317 } |
318 | 318 |
319 template <typename T> | 319 template <typename T> |
320 T | 320 T |
321 svd<T>::right_singular_matrix (void) const | 321 svd<T>::right_singular_matrix (void) const |
322 { | 322 { |
323 if (m_type == svd::Type::sigma_only) | 323 if (m_type == svd::Type::sigma_only) |
324 (*current_liboctave_error_handler) | 324 (*current_liboctave_error_handler) |
325 ("svd: V not computed because type == svd::sigma_only"); | 325 ("svd: V not computed because type == svd::sigma_only"); |
326 | 326 |
327 return m_right_sm; | 327 return m_right_sm; |
328 } | 328 } |
329 | 329 |
330 // GESVD specializations | 330 // GESVD specializations |
331 | 331 |
332 #define GESVD_REAL_STEP(f, F) \ | 332 #define GESVD_REAL_STEP(f, F) \ |
333 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \ | 333 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \ |
334 F77_CONST_CHAR_ARG2 (&jobv, 1), \ | 334 F77_CONST_CHAR_ARG2 (&jobv, 1), \ |
335 m, n, tmp_data, m1, s_vec, u, m1, vt, \ | 335 m, n, tmp_data, m1, s_vec, u, m1, vt, \ |
346 CMPLX_ARG (work.data ()), \ | 346 CMPLX_ARG (work.data ()), \ |
347 lwork, rwork.data (), info \ | 347 lwork, rwork.data (), info \ |
348 F77_CHAR_ARG_LEN (1) \ | 348 F77_CHAR_ARG_LEN (1) \ |
349 F77_CHAR_ARG_LEN (1))) | 349 F77_CHAR_ARG_LEN (1))) |
350 | 350 |
351 // DGESVD | 351 // DGESVD |
352 template<> | 352 template<> |
353 OCTAVE_API void | 353 OCTAVE_API void |
354 svd<Matrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, | 354 svd<Matrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, |
355 double *tmp_data, F77_INT m1, double *s_vec, | 355 double *tmp_data, F77_INT m1, double *s_vec, |
356 double *u, double *vt, F77_INT nrow_vt1, | 356 double *u, double *vt, F77_INT nrow_vt1, |
357 std::vector<double>& work, F77_INT& lwork, | 357 std::vector<double>& work, F77_INT& lwork, |
358 F77_INT& info) | 358 F77_INT& info) |
359 { | 359 { |
360 GESVD_REAL_STEP (dgesvd, DGESVD); | 360 GESVD_REAL_STEP (dgesvd, DGESVD); |
361 | 361 |
362 lwork = static_cast<F77_INT> (work[0]); | 362 lwork = static_cast<F77_INT> (work[0]); |
363 work.reserve (lwork); | 363 work.reserve (lwork); |
364 | 364 |
365 GESVD_REAL_STEP (dgesvd, DGESVD); | 365 GESVD_REAL_STEP (dgesvd, DGESVD); |
366 } | 366 } |
367 | 367 |
368 // SGESVD | 368 // SGESVD |
369 template<> | 369 template<> |
370 OCTAVE_API void | 370 OCTAVE_API void |
371 svd<FloatMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, | 371 svd<FloatMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, |
372 float *tmp_data, F77_INT m1, float *s_vec, | 372 float *tmp_data, F77_INT m1, float *s_vec, |
373 float *u, float *vt, F77_INT nrow_vt1, | 373 float *u, float *vt, F77_INT nrow_vt1, |
374 std::vector<float>& work, F77_INT& lwork, | 374 std::vector<float>& work, F77_INT& lwork, |
375 F77_INT& info) | 375 F77_INT& info) |
376 { | 376 { |
377 GESVD_REAL_STEP (sgesvd, SGESVD); | 377 GESVD_REAL_STEP (sgesvd, SGESVD); |
378 | 378 |
379 lwork = static_cast<F77_INT> (work[0]); | 379 lwork = static_cast<F77_INT> (work[0]); |
380 work.reserve (lwork); | 380 work.reserve (lwork); |
381 | 381 |
382 GESVD_REAL_STEP (sgesvd, SGESVD); | 382 GESVD_REAL_STEP (sgesvd, SGESVD); |
383 } | 383 } |
384 | 384 |
385 // ZGESVD | 385 // ZGESVD |
386 template<> | 386 template<> |
387 OCTAVE_API void | 387 OCTAVE_API void |
388 svd<ComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, | 388 svd<ComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, |
389 Complex *tmp_data, F77_INT m1, double *s_vec, | 389 Complex *tmp_data, F77_INT m1, double *s_vec, |
390 Complex *u, Complex *vt, F77_INT nrow_vt1, | 390 Complex *u, Complex *vt, F77_INT nrow_vt1, |
391 std::vector<Complex>& work, F77_INT& lwork, | 391 std::vector<Complex>& work, F77_INT& lwork, |
392 F77_INT& info) | 392 F77_INT& info) |
393 { | 393 { |
394 std::vector<double> rwork (5 * std::max (m, n)); | 394 std::vector<double> rwork (5 * std::max (m, n)); |
395 | 395 |
396 GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); | 396 GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); |
397 | 397 |
398 lwork = static_cast<F77_INT> (work[0].real ()); | 398 lwork = static_cast<F77_INT> (work[0].real ()); |
399 work.reserve (lwork); | 399 work.reserve (lwork); |
400 | 400 |
401 GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); | 401 GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); |
402 } | 402 } |
403 | 403 |
404 // CGESVD | 404 // CGESVD |
405 template<> | 405 template<> |
406 OCTAVE_API void | 406 OCTAVE_API void |
407 svd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, | 407 svd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv, F77_INT m, |
408 F77_INT n, FloatComplex *tmp_data, | 408 F77_INT n, FloatComplex *tmp_data, |
409 F77_INT m1, float *s_vec, FloatComplex *u, | 409 F77_INT m1, float *s_vec, FloatComplex *u, |
410 FloatComplex *vt, F77_INT nrow_vt1, | 410 FloatComplex *vt, F77_INT nrow_vt1, |
411 std::vector<FloatComplex>& work, | 411 std::vector<FloatComplex>& work, |
412 F77_INT& lwork, F77_INT& info) | 412 F77_INT& lwork, F77_INT& info) |
413 { | 413 { |
414 std::vector<float> rwork (5 * std::max (m, n)); | 414 std::vector<float> rwork (5 * std::max (m, n)); |
415 | 415 |
416 GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); | 416 GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); |
417 | 417 |
418 lwork = static_cast<F77_INT> (work[0].real ()); | 418 lwork = static_cast<F77_INT> (work[0].real ()); |
419 work.reserve (lwork); | 419 work.reserve (lwork); |
420 | 420 |
421 GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); | 421 GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); |
422 } | 422 } |
423 | 423 |
424 #undef GESVD_REAL_STEP | 424 #undef GESVD_REAL_STEP |
425 #undef GESVD_COMPLEX_STEP | 425 #undef GESVD_COMPLEX_STEP |
426 | 426 |
427 // GESDD specializations | 427 // GESDD specializations |
428 | 428 |
429 #define GESDD_REAL_STEP(f, F) \ | 429 #define GESDD_REAL_STEP(f, F) \ |
430 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \ | 430 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \ |
431 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \ | 431 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \ |
432 work.data (), lwork, iwork, info \ | 432 work.data (), lwork, iwork, info \ |
439 CMPLX_ARG (vt), nrow_vt1, \ | 439 CMPLX_ARG (vt), nrow_vt1, \ |
440 CMPLX_ARG (work.data ()), lwork, \ | 440 CMPLX_ARG (work.data ()), lwork, \ |
441 rwork.data (), iwork, info \ | 441 rwork.data (), iwork, info \ |
442 F77_CHAR_ARG_LEN (1))) | 442 F77_CHAR_ARG_LEN (1))) |
443 | 443 |
444 // DGESDD | 444 // DGESDD |
445 template<> | 445 template<> |
446 OCTAVE_API void | 446 OCTAVE_API void |
447 svd<Matrix>::gesdd (char& jobz, F77_INT m, F77_INT n, double *tmp_data, | 447 svd<Matrix>::gesdd (char& jobz, F77_INT m, F77_INT n, double *tmp_data, |
448 F77_INT m1, double *s_vec, double *u, double *vt, | 448 F77_INT m1, double *s_vec, double *u, double *vt, |
449 F77_INT nrow_vt1, std::vector<double>& work, | 449 F77_INT nrow_vt1, std::vector<double>& work, |
450 F77_INT& lwork, F77_INT *iwork, F77_INT& info) | 450 F77_INT& lwork, F77_INT *iwork, F77_INT& info) |
451 { | 451 { |
452 GESDD_REAL_STEP (dgesdd, DGESDD); | 452 GESDD_REAL_STEP (dgesdd, DGESDD); |
453 | 453 |
454 lwork = static_cast<F77_INT> (work[0]); | 454 lwork = static_cast<F77_INT> (work[0]); |
455 work.reserve (lwork); | 455 work.reserve (lwork); |
456 | 456 |
457 GESDD_REAL_STEP (dgesdd, DGESDD); | 457 GESDD_REAL_STEP (dgesdd, DGESDD); |
458 } | 458 } |
459 | 459 |
460 // SGESDD | 460 // SGESDD |
461 template<> | 461 template<> |
462 OCTAVE_API void | 462 OCTAVE_API void |
463 svd<FloatMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, float *tmp_data, | 463 svd<FloatMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, float *tmp_data, |
464 F77_INT m1, float *s_vec, float *u, float *vt, | 464 F77_INT m1, float *s_vec, float *u, float *vt, |
465 F77_INT nrow_vt1, std::vector<float>& work, | 465 F77_INT nrow_vt1, std::vector<float>& work, |
466 F77_INT& lwork, F77_INT *iwork, F77_INT& info) | 466 F77_INT& lwork, F77_INT *iwork, F77_INT& info) |
467 { | 467 { |
468 GESDD_REAL_STEP (sgesdd, SGESDD); | 468 GESDD_REAL_STEP (sgesdd, SGESDD); |
469 | 469 |
470 lwork = static_cast<F77_INT> (work[0]); | 470 lwork = static_cast<F77_INT> (work[0]); |
471 work.reserve (lwork); | 471 work.reserve (lwork); |
472 | 472 |
473 GESDD_REAL_STEP (sgesdd, SGESDD); | 473 GESDD_REAL_STEP (sgesdd, SGESDD); |
474 } | 474 } |
475 | 475 |
476 // ZGESDD | 476 // ZGESDD |
477 template<> | 477 template<> |
478 OCTAVE_API void | 478 OCTAVE_API void |
479 svd<ComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, | 479 svd<ComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, |
480 Complex *tmp_data, F77_INT m1, double *s_vec, | 480 Complex *tmp_data, F77_INT m1, double *s_vec, |
481 Complex *u, Complex *vt, F77_INT nrow_vt1, | 481 Complex *u, Complex *vt, F77_INT nrow_vt1, |
482 std::vector<Complex>& work, F77_INT& lwork, | 482 std::vector<Complex>& work, F77_INT& lwork, |
483 F77_INT *iwork, F77_INT& info) | 483 F77_INT *iwork, F77_INT& info) |
484 { | 484 { |
485 | 485 |
486 F77_INT min_mn = std::min (m, n); | 486 F77_INT min_mn = std::min (m, n); |
487 F77_INT max_mn = std::max (m, n); | 487 F77_INT max_mn = std::max (m, n); |
488 | 488 |
489 F77_INT lrwork; | 489 F77_INT lrwork; |
490 if (jobz == 'N') | 490 if (jobz == 'N') |
491 lrwork = 7*min_mn; | 491 lrwork = 7*min_mn; |
492 else | 492 else |
493 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); | 493 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); |
494 | 494 |
495 std::vector<double> rwork (lrwork); | 495 std::vector<double> rwork (lrwork); |
496 | 496 |
497 GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); | 497 GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); |
498 | 498 |
499 lwork = static_cast<F77_INT> (work[0].real ()); | 499 lwork = static_cast<F77_INT> (work[0].real ()); |
500 work.reserve (lwork); | 500 work.reserve (lwork); |
501 | 501 |
502 GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); | 502 GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); |
503 } | 503 } |
504 | 504 |
505 // CGESDD | 505 // CGESDD |
506 template<> | 506 template<> |
507 OCTAVE_API void | 507 OCTAVE_API void |
508 svd<FloatComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, | 508 svd<FloatComplexMatrix>::gesdd (char& jobz, F77_INT m, F77_INT n, |
509 FloatComplex *tmp_data, F77_INT m1, | 509 FloatComplex *tmp_data, F77_INT m1, |
510 float *s_vec, FloatComplex *u, | 510 float *s_vec, FloatComplex *u, |
511 FloatComplex *vt, F77_INT nrow_vt1, | 511 FloatComplex *vt, F77_INT nrow_vt1, |
512 std::vector<FloatComplex>& work, | 512 std::vector<FloatComplex>& work, |
513 F77_INT& lwork, F77_INT *iwork, | 513 F77_INT& lwork, F77_INT *iwork, |
514 F77_INT& info) | 514 F77_INT& info) |
515 { | 515 { |
516 F77_INT min_mn = std::min (m, n); | 516 F77_INT min_mn = std::min (m, n); |
517 F77_INT max_mn = std::max (m, n); | 517 F77_INT max_mn = std::max (m, n); |
518 | 518 |
519 F77_INT lrwork; | 519 F77_INT lrwork; |
520 if (jobz == 'N') | 520 if (jobz == 'N') |
521 lrwork = 7*min_mn; | 521 lrwork = 7*min_mn; |
522 else | 522 else |
523 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); | 523 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); |
524 std::vector<float> rwork (lrwork); | 524 std::vector<float> rwork (lrwork); |
525 | 525 |
526 GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); | 526 GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); |
527 | 527 |
528 lwork = static_cast<F77_INT> (work[0].real ()); | 528 lwork = static_cast<F77_INT> (work[0].real ()); |
529 work.reserve (lwork); | 529 work.reserve (lwork); |
530 | 530 |
531 GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); | 531 GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); |
532 } | 532 } |
533 | 533 |
534 #undef GESDD_REAL_STEP | 534 #undef GESDD_REAL_STEP |
535 #undef GESDD_COMPLEX_STEP | 535 #undef GESDD_COMPLEX_STEP |
536 | 536 |
537 // GEJSV specializations | 537 // GEJSV specializations |
538 | 538 |
539 #define GEJSV_REAL_STEP(f, F) \ | 539 #define GEJSV_REAL_STEP(f, F) \ |
540 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \ | 540 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \ |
541 F77_CONST_CHAR_ARG2 (&jobu, 1), \ | 541 F77_CONST_CHAR_ARG2 (&jobu, 1), \ |
542 F77_CONST_CHAR_ARG2 (&jobv, 1), \ | 542 F77_CONST_CHAR_ARG2 (&jobv, 1), \ |
569 F77_CHAR_ARG_LEN (1) \ | 569 F77_CHAR_ARG_LEN (1) \ |
570 F77_CHAR_ARG_LEN (1) \ | 570 F77_CHAR_ARG_LEN (1) \ |
571 F77_CHAR_ARG_LEN (1) \ | 571 F77_CHAR_ARG_LEN (1) \ |
572 F77_CHAR_ARG_LEN (1))) | 572 F77_CHAR_ARG_LEN (1))) |
573 | 573 |
574 // DGEJSV | 574 // DGEJSV |
575 template<> | 575 template<> |
576 void | 576 void |
577 svd<Matrix>::gejsv (char& joba, char& jobu, char& jobv, | 577 svd<Matrix>::gejsv (char& joba, char& jobu, char& jobv, |
578 char& jobr, char& jobt, char& jobp, | 578 char& jobr, char& jobt, char& jobp, |
579 F77_INT m, F77_INT n, | 579 F77_INT m, F77_INT n, |
580 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, | 580 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, |
581 P *v, F77_INT nrow_v1, std::vector<P>& work, | 581 P *v, F77_INT nrow_v1, std::vector<P>& work, |
582 F77_INT& lwork, std::vector<F77_INT>& iwork, | 582 F77_INT& lwork, std::vector<F77_INT>& iwork, |
583 F77_INT& info) | 583 F77_INT& info) |
584 { | 584 { |
585 lwork = gejsv_lwork<Matrix>::optimal (joba, jobu, jobv, m, n); | 585 lwork = gejsv_lwork<Matrix>::optimal (joba, jobu, jobv, m, n); |
586 work.reserve (lwork); | 586 work.reserve (lwork); |
587 | 587 |
588 GEJSV_REAL_STEP (dgejsv, DGEJSV); | 588 GEJSV_REAL_STEP (dgejsv, DGEJSV); |
589 } | 589 } |
590 | 590 |
591 // SGEJSV | 591 // SGEJSV |
592 template<> | 592 template<> |
593 void | 593 void |
594 svd<FloatMatrix>::gejsv (char& joba, char& jobu, char& jobv, | 594 svd<FloatMatrix>::gejsv (char& joba, char& jobu, char& jobv, |
595 char& jobr, char& jobt, char& jobp, | 595 char& jobr, char& jobt, char& jobp, |
596 F77_INT m, F77_INT n, | 596 F77_INT m, F77_INT n, |
597 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, | 597 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, |
598 P *v, F77_INT nrow_v1, std::vector<P>& work, | 598 P *v, F77_INT nrow_v1, std::vector<P>& work, |
599 F77_INT& lwork, std::vector<F77_INT>& iwork, | 599 F77_INT& lwork, std::vector<F77_INT>& iwork, |
600 F77_INT& info) | 600 F77_INT& info) |
601 { | 601 { |
602 lwork = gejsv_lwork<FloatMatrix>::optimal (joba, jobu, jobv, m, n); | 602 lwork = gejsv_lwork<FloatMatrix>::optimal (joba, jobu, jobv, m, n); |
603 work.reserve (lwork); | 603 work.reserve (lwork); |
604 | 604 |
605 GEJSV_REAL_STEP (sgejsv, SGEJSV); | 605 GEJSV_REAL_STEP (sgejsv, SGEJSV); |
606 } | 606 } |
607 | 607 |
608 // ZGEJSV | 608 // ZGEJSV |
609 template<> | 609 template<> |
610 void | 610 void |
611 svd<ComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv, | 611 svd<ComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv, |
612 char& jobr, char& jobt, char& jobp, | 612 char& jobr, char& jobt, char& jobp, |
613 F77_INT m, F77_INT n, | 613 F77_INT m, F77_INT n, |
614 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, | 614 P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, |
615 P *v, F77_INT nrow_v1, std::vector<P>& work, | 615 P *v, F77_INT nrow_v1, std::vector<P>& work, |
616 F77_INT& lwork, std::vector<F77_INT>& iwork, | 616 F77_INT& lwork, std::vector<F77_INT>& iwork, |
617 F77_INT& info) | 617 F77_INT& info) |
618 { | 618 { |
619 F77_INT lrwork = -1; // work space size query | 619 F77_INT lrwork = -1; // work space size query |
620 std::vector<double> rwork (1); | 620 std::vector<double> rwork (1); |
621 work.reserve (2); | 621 work.reserve (2); |
622 | 622 |
623 GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); | 623 GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); |
624 | 624 |
625 lwork = static_cast<F77_INT> (work[0].real ()); | 625 lwork = static_cast<F77_INT> (work[0].real ()); |
626 work.reserve (lwork); | 626 work.reserve (lwork); |
627 | 627 |
628 lrwork = static_cast<F77_INT> (rwork[0]); | 628 lrwork = static_cast<F77_INT> (rwork[0]); |
629 rwork.reserve (lrwork); | 629 rwork.reserve (lrwork); |
630 | 630 |
631 F77_INT liwork = static_cast<F77_INT> (iwork[0]); | 631 F77_INT liwork = static_cast<F77_INT> (iwork[0]); |
632 iwork.reserve (liwork); | 632 iwork.reserve (liwork); |
633 | 633 |
634 GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); | 634 GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); |
635 } | 635 } |
636 | 636 |
637 // CGEJSV | 637 // CGEJSV |
638 template<> | 638 template<> |
639 void | 639 void |
640 svd<FloatComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv, | 640 svd<FloatComplexMatrix>::gejsv (char& joba, char& jobu, char& jobv, |
641 char& jobr, char& jobt, char& jobp, | 641 char& jobr, char& jobt, char& jobp, |
642 F77_INT m, F77_INT n, P *tmp_data, | 642 F77_INT m, F77_INT n, P *tmp_data, |
643 F77_INT m1, DM_P *s_vec, P *u, P *v, | 643 F77_INT m1, DM_P *s_vec, P *u, P *v, |
644 F77_INT nrow_v1, std::vector<P>& work, | 644 F77_INT nrow_v1, std::vector<P>& work, |
645 F77_INT& lwork, | 645 F77_INT& lwork, |
646 std::vector<F77_INT>& iwork, F77_INT& info) | 646 std::vector<F77_INT>& iwork, F77_INT& info) |
647 { | 647 { |
648 F77_INT lrwork = -1; // work space size query | 648 F77_INT lrwork = -1; // work space size query |
649 std::vector<float> rwork (1); | 649 std::vector<float> rwork (1); |
650 work.reserve (2); | 650 work.reserve (2); |
651 | 651 |
652 GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); | 652 GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); |
653 | 653 |
654 lwork = static_cast<F77_INT> (work[0].real ()); | 654 lwork = static_cast<F77_INT> (work[0].real ()); |
655 work.reserve (lwork); | 655 work.reserve (lwork); |
656 | 656 |
657 lrwork = static_cast<F77_INT> (rwork[0]); | 657 lrwork = static_cast<F77_INT> (rwork[0]); |
658 rwork.reserve (lrwork); | 658 rwork.reserve (lrwork); |
659 | 659 |
660 F77_INT liwork = static_cast<F77_INT> (iwork[0]); | 660 F77_INT liwork = static_cast<F77_INT> (iwork[0]); |
661 iwork.reserve (liwork); | 661 iwork.reserve (liwork); |
662 | 662 |
663 GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); | 663 GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); |
664 } | 664 } |
665 | 665 |
666 #undef GEJSV_REAL_STEP | 666 #undef GEJSV_REAL_STEP |
667 #undef GEJSV_COMPLEX_STEP | 667 #undef GEJSV_COMPLEX_STEP |
668 | 668 |
669 template<typename T> | 669 template<typename T> |
670 svd<T>::svd (const T& a, svd::Type type, svd::Driver driver) | 670 svd<T>::svd (const T& a, svd::Type type, svd::Driver driver) |
671 : m_type (type), m_driver (driver), m_left_sm (), m_sigma (), | 671 : m_type (type), m_driver (driver), m_left_sm (), m_sigma (), |
672 m_right_sm () | 672 m_right_sm () |
673 { | 673 { |
674 F77_INT info; | 674 F77_INT info; |
675 | 675 |
676 F77_INT m = to_f77_int (a.rows ()); | 676 F77_INT m = to_f77_int (a.rows ()); |
677 F77_INT n = to_f77_int (a.cols ()); | 677 F77_INT n = to_f77_int (a.cols ()); |
678 | 678 |
679 if (m == 0 || n == 0) | 679 if (m == 0 || n == 0) |
680 { | 680 { |
681 switch (m_type) | |
682 { | |
683 case svd::Type::std: | |
684 m_left_sm = T (m, m, 0); | |
685 for (F77_INT i = 0; i < m; i++) | |
686 m_left_sm.xelem (i, i) = 1; | |
687 m_sigma = DM_T (m, n); | |
688 m_right_sm = T (n, n, 0); | |
689 for (F77_INT i = 0; i < n; i++) | |
690 m_right_sm.xelem (i, i) = 1; | |
691 break; | |
692 | |
693 case svd::Type::economy: | |
694 m_left_sm = T (m, 0, 0); | |
695 m_sigma = DM_T (0, 0); | |
696 m_right_sm = T (n, 0, 0); | |
697 break; | |
698 | |
699 case svd::Type::sigma_only: | |
700 default: | |
701 m_sigma = DM_T (0, 1); | |
702 break; | |
703 } | |
704 return; | |
705 } | |
706 | |
707 T atmp = a; | |
708 P *tmp_data = atmp.fortran_vec (); | |
709 | |
710 F77_INT min_mn = (m < n ? m : n); | |
711 | |
712 char jobu = 'A'; | |
713 char jobv = 'A'; | |
714 | |
715 F77_INT ncol_u = m; | |
716 F77_INT nrow_vt = n; | |
717 F77_INT nrow_s = m; | |
718 F77_INT ncol_s = n; | |
719 | |
720 switch (m_type) | 681 switch (m_type) |
721 { | 682 { |
683 case svd::Type::std: | |
684 m_left_sm = T (m, m, 0); | |
685 for (F77_INT i = 0; i < m; i++) | |
686 m_left_sm.xelem (i, i) = 1; | |
687 m_sigma = DM_T (m, n); | |
688 m_right_sm = T (n, n, 0); | |
689 for (F77_INT i = 0; i < n; i++) | |
690 m_right_sm.xelem (i, i) = 1; | |
691 break; | |
692 | |
722 case svd::Type::economy: | 693 case svd::Type::economy: |
723 jobu = jobv = 'S'; | 694 m_left_sm = T (m, 0, 0); |
724 ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; | 695 m_sigma = DM_T (0, 0); |
696 m_right_sm = T (n, 0, 0); | |
725 break; | 697 break; |
726 | 698 |
727 case svd::Type::sigma_only: | 699 case svd::Type::sigma_only: |
728 | |
729 // Note: for this case, both jobu and jobv should be 'N', but there | |
730 // seems to be a bug in dgesvd from Lapack V2.0. To demonstrate the | |
731 // bug, set both jobu and jobv to 'N' and find the singular values of | |
732 // [eye(3), eye(3)]. The result is [-sqrt(2), -sqrt(2), -sqrt(2)]. | |
733 // | |
734 // For Lapack 3.0, this problem seems to be fixed. | |
735 | |
736 jobu = jobv = 'N'; | |
737 ncol_u = nrow_vt = 1; | |
738 break; | |
739 | |
740 default: | 700 default: |
701 m_sigma = DM_T (0, 1); | |
741 break; | 702 break; |
742 } | 703 } |
743 | 704 return; |
744 if (! (jobu == 'N' || jobu == 'O')) | 705 } |
745 m_left_sm.resize (m, ncol_u); | 706 |
746 | 707 T atmp = a; |
747 P *u = m_left_sm.fortran_vec (); | 708 P *tmp_data = atmp.fortran_vec (); |
748 | 709 |
749 m_sigma.resize (nrow_s, ncol_s); | 710 F77_INT min_mn = (m < n ? m : n); |
750 DM_P *s_vec = m_sigma.fortran_vec (); | 711 |
751 | 712 char jobu = 'A'; |
752 if (! (jobv == 'N' || jobv == 'O')) | 713 char jobv = 'A'; |
714 | |
715 F77_INT ncol_u = m; | |
716 F77_INT nrow_vt = n; | |
717 F77_INT nrow_s = m; | |
718 F77_INT ncol_s = n; | |
719 | |
720 switch (m_type) | |
721 { | |
722 case svd::Type::economy: | |
723 jobu = jobv = 'S'; | |
724 ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; | |
725 break; | |
726 | |
727 case svd::Type::sigma_only: | |
728 | |
729 // Note: for this case, both jobu and jobv should be 'N', but there | |
730 // seems to be a bug in dgesvd from Lapack V2.0. To demonstrate the | |
731 // bug, set both jobu and jobv to 'N' and find the singular values of | |
732 // [eye(3), eye(3)]. The result is [-sqrt(2), -sqrt(2), -sqrt(2)]. | |
733 // | |
734 // For Lapack 3.0, this problem seems to be fixed. | |
735 | |
736 jobu = jobv = 'N'; | |
737 ncol_u = nrow_vt = 1; | |
738 break; | |
739 | |
740 default: | |
741 break; | |
742 } | |
743 | |
744 if (! (jobu == 'N' || jobu == 'O')) | |
745 m_left_sm.resize (m, ncol_u); | |
746 | |
747 P *u = m_left_sm.fortran_vec (); | |
748 | |
749 m_sigma.resize (nrow_s, ncol_s); | |
750 DM_P *s_vec = m_sigma.fortran_vec (); | |
751 | |
752 if (! (jobv == 'N' || jobv == 'O')) | |
753 { | |
754 if (m_driver == svd::Driver::GEJSV) | |
755 m_right_sm.resize (n, nrow_vt); | |
756 else | |
757 m_right_sm.resize (nrow_vt, n); | |
758 } | |
759 | |
760 P *vt = m_right_sm.fortran_vec (); | |
761 | |
762 // Query _GESVD for the correct dimension of WORK. | |
763 | |
764 F77_INT lwork = -1; | |
765 | |
766 std::vector<P> work (1); | |
767 | |
768 const F77_INT f77_int_one = static_cast<F77_INT> (1); | |
769 F77_INT m1 = std::max (m, f77_int_one); | |
770 F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one); | |
771 | |
772 if (m_driver == svd::Driver::GESVD) | |
773 gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, | |
774 work, lwork, info); | |
775 else if (m_driver == svd::Driver::GESDD) | |
776 { | |
777 assert (jobu == jobv); | |
778 char jobz = jobu; | |
779 | |
780 std::vector<F77_INT> iwork (8 * std::min (m, n)); | |
781 | |
782 gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, | |
783 work, lwork, iwork.data (), info); | |
784 } | |
785 else if (m_driver == svd::Driver::GEJSV) | |
786 { | |
787 bool transposed = false; | |
788 if (n > m) | |
753 { | 789 { |
754 if (m_driver == svd::Driver::GEJSV) | 790 // GEJSV only accepts m >= n, thus we need to transpose here |
755 m_right_sm.resize (n, nrow_vt); | 791 transposed = true; |
756 else | 792 |
757 m_right_sm.resize (nrow_vt, n); | 793 std::swap (m, n); |
794 m1 = std::max (m, f77_int_one); | |
795 nrow_vt1 = std::max (n, f77_int_one); // we have m > n | |
796 if (m_type == svd::Type::sigma_only) | |
797 nrow_vt1 = 1; | |
798 std::swap (jobu, jobv); | |
799 | |
800 atmp = atmp.hermitian (); | |
801 tmp_data = atmp.fortran_vec (); | |
802 | |
803 // Swap pointers of U and V. | |
804 u = m_right_sm.fortran_vec (); | |
805 vt = m_left_sm.fortran_vec (); | |
758 } | 806 } |
759 | 807 |
760 P *vt = m_right_sm.fortran_vec (); | 808 // translate jobu and jobv from gesvd to gejsv. |
761 | 809 std::unordered_map<char, std::string> job_svd2jsv; |
762 // Query _GESVD for the correct dimension of WORK. | 810 job_svd2jsv['A'] = "FJ"; |
763 | 811 job_svd2jsv['S'] = "UV"; |
764 F77_INT lwork = -1; | 812 job_svd2jsv['O'] = "WW"; |
765 | 813 job_svd2jsv['N'] = "NN"; |
766 std::vector<P> work (1); | 814 jobu = job_svd2jsv[jobu][0]; |
767 | 815 jobv = job_svd2jsv[jobv][1]; |
768 const F77_INT f77_int_one = static_cast<F77_INT> (1); | 816 |
769 F77_INT m1 = std::max (m, f77_int_one); | 817 char joba = 'F'; // 'F': most conservative |
770 F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one); | 818 char jobr = 'R'; // 'R' is recommended. |
771 | 819 char jobt = 'N'; // or 'T', but that requires U and V appear together |
772 if (m_driver == svd::Driver::GESVD) | 820 char jobp = 'N'; // use 'P' if denormal is poorly implemented. |
773 gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, | 821 |
774 work, lwork, info); | 822 std::vector<F77_INT> iwork (std::max<F77_INT> (m + 3*n, 1)); |
775 else if (m_driver == svd::Driver::GESDD) | 823 |
776 { | 824 gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1, |
777 assert (jobu == jobv); | 825 s_vec, u, vt, nrow_vt1, work, lwork, iwork, info); |
778 char jobz = jobu; | 826 |
779 | 827 if (iwork[2] == 1) |
780 std::vector<F77_INT> iwork (8 * std::min (m, n)); | 828 (*current_liboctave_warning_with_id_handler) |
781 | 829 ("Octave:convergence", "svd: (driver: GEJSV) " |
782 gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, | 830 "Denormal occurred, possible loss of accuracy."); |
783 work, lwork, iwork.data (), info); | 831 |
784 } | 832 if (info < 0) |
785 else if (m_driver == svd::Driver::GEJSV) | 833 (*current_liboctave_error_handler) |
786 { | 834 ("svd: (driver: GEJSV) Illegal argument at #%d", |
787 bool transposed = false; | 835 static_cast<int> (-info)); |
788 if (n > m) | 836 else if (info > 0) |
789 { | 837 (*current_liboctave_warning_with_id_handler) |
790 // GEJSV only accepts m >= n, thus we need to transpose here | 838 ("Octave:convergence", "svd: (driver: GEJSV) " |
791 transposed = true; | 839 "Fail to converge within max sweeps, " |
792 | 840 "possible inaccurate result."); |
793 std::swap (m, n); | 841 |
794 m1 = std::max (m, f77_int_one); | 842 if (transposed) // put things that need to transpose back here |
795 nrow_vt1 = std::max (n, f77_int_one); // we have m > n | 843 std::swap (m, n); |
796 if (m_type == svd::Type::sigma_only) | 844 } |
797 nrow_vt1 = 1; | 845 else |
798 std::swap (jobu, jobv); | 846 (*current_liboctave_error_handler) ("svd: unknown driver"); |
799 | 847 |
800 atmp = atmp.hermitian (); | 848 // LAPACK can return -0 which is a small problem (bug #55710). |
801 tmp_data = atmp.fortran_vec (); | 849 for (octave_idx_type i = 0; i < m_sigma.diag_length (); i++) |
802 | 850 { |
803 // Swap pointers of U and V. | 851 if (! m_sigma.dgxelem (i)) |
804 u = m_right_sm.fortran_vec (); | 852 m_sigma.dgxelem (i) = DM_P (0); |
805 vt = m_left_sm.fortran_vec (); | 853 } |
806 } | 854 |
807 | 855 // GESVD and GESDD return VT instead of V, GEJSV return V. |
808 // translate jobu and jobv from gesvd to gejsv. | 856 if (! (jobv == 'N' || jobv == 'O') && (m_driver != svd::Driver::GEJSV)) |
809 std::unordered_map<char, std::string> job_svd2jsv; | 857 m_right_sm = m_right_sm.hermitian (); |
810 job_svd2jsv['A'] = "FJ"; | 858 } |
811 job_svd2jsv['S'] = "UV"; | 859 |
812 job_svd2jsv['O'] = "WW"; | 860 // Instantiations we need. |
813 job_svd2jsv['N'] = "NN"; | 861 |
814 jobu = job_svd2jsv[jobu][0]; | 862 template class svd<Matrix>; |
815 jobv = job_svd2jsv[jobv][1]; | 863 |
816 | 864 template class svd<FloatMatrix>; |
817 char joba = 'F'; // 'F': most conservative | 865 |
818 char jobr = 'R'; // 'R' is recommended. | 866 template class svd<ComplexMatrix>; |
819 char jobt = 'N'; // or 'T', but that requires U and V appear together | 867 |
820 char jobp = 'N'; // use 'P' if denormal is poorly implemented. | 868 template class svd<FloatComplexMatrix>; |
821 | |
822 std::vector<F77_INT> iwork (std::max<F77_INT> (m + 3*n, 1)); | |
823 | |
824 gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1, | |
825 s_vec, u, vt, nrow_vt1, work, lwork, iwork, info); | |
826 | |
827 if (iwork[2] == 1) | |
828 (*current_liboctave_warning_with_id_handler) | |
829 ("Octave:convergence", "svd: (driver: GEJSV) " | |
830 "Denormal occurred, possible loss of accuracy."); | |
831 | |
832 if (info < 0) | |
833 (*current_liboctave_error_handler) | |
834 ("svd: (driver: GEJSV) Illegal argument at #%d", | |
835 static_cast<int> (-info)); | |
836 else if (info > 0) | |
837 (*current_liboctave_warning_with_id_handler) | |
838 ("Octave:convergence", "svd: (driver: GEJSV) " | |
839 "Fail to converge within max sweeps, " | |
840 "possible inaccurate result."); | |
841 | |
842 if (transposed) // put things that need to transpose back here | |
843 std::swap (m, n); | |
844 } | |
845 else | |
846 (*current_liboctave_error_handler) ("svd: unknown driver"); | |
847 | |
848 // LAPACK can return -0 which is a small problem (bug #55710). | |
849 for (octave_idx_type i = 0; i < m_sigma.diag_length (); i++) | |
850 { | |
851 if (! m_sigma.dgxelem (i)) | |
852 m_sigma.dgxelem (i) = DM_P (0); | |
853 } | |
854 | |
855 // GESVD and GESDD return VT instead of V, GEJSV return V. | |
856 if (! (jobv == 'N' || jobv == 'O') && (m_driver != svd::Driver::GEJSV)) | |
857 m_right_sm = m_right_sm.hermitian (); | |
858 } | |
859 | |
860 // Instantiations we need. | |
861 | |
862 template class svd<Matrix>; | |
863 | |
864 template class svd<FloatMatrix>; | |
865 | |
866 template class svd<ComplexMatrix>; | |
867 | |
868 template class svd<FloatComplexMatrix>; | |
869 | 869 |
870 OCTAVE_END_NAMESPACE(math) | 870 OCTAVE_END_NAMESPACE(math) |
871 OCTAVE_END_NAMESPACE(octave) | 871 OCTAVE_END_NAMESPACE(octave) |