26#if defined (HAVE_CONFIG_H)
31#include <unordered_map>
49 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (gejsv_lwork)
59 static F77_INT optimal (
char& joba,
char& jobu,
char& jobv,
63 typedef typename T::element_type P;
81 static F77_INT ormlq_lwork (
char& side,
char& trans,
87 static F77_INT ormqr_lwork (
char& side,
char& trans,
94#define GEJSV_REAL_QP3_LWORK(f, F) \
95 F77_XFCN (f, F, (m, n, a, lda, jpvt, tau, work, lwork, info))
97#define GEJSV_REAL_QR_LWORK(f, F) \
98 F77_XFCN (f, F, (m, n, a, lda, tau, work, lwork, info))
100#define GEJSV_REAL_ORM_LWORK(f, F) \
101 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&side, 1), \
102 F77_CONST_CHAR_ARG2 (&trans, 1), \
103 m, n, k, a, lda, tau, \
104 c, ldc, work, lwork, info \
105 F77_CHAR_ARG_LEN (1) \
106 F77_CHAR_ARG_LEN (1)))
113 F77_INT *jpvt, P *tau, P *work,
117 return static_cast<F77_INT> (work[0]);
128 return static_cast<F77_INT> (work[0]);
139 return static_cast<F77_INT> (work[0]);
144gejsv_lwork<Matrix>::ormlq_lwork (
char& side,
char& trans,
151 return static_cast<F77_INT> (work[0]);
156gejsv_lwork<Matrix>::ormqr_lwork (
char& side,
char& trans,
163 return static_cast<F77_INT> (work[0]);
171 F77_INT *jpvt, P *tau, P *work,
175 return static_cast<F77_INT> (work[0]);
186 return static_cast<F77_INT> (work[0]);
197 return static_cast<F77_INT> (work[0]);
202gejsv_lwork<FloatMatrix>::ormlq_lwork (
char& side,
char& trans,
209 return static_cast<F77_INT> (work[0]);
214gejsv_lwork<FloatMatrix>::ormqr_lwork (
char& side,
char& trans,
221 return static_cast<F77_INT> (work[0]);
224#undef GEJSV_REAL_QP3_LWORK
225#undef GEJSV_REAL_QR_LWORK
226#undef GEJSV_REAL_ORM_LWORK
230gejsv_lwork<T>::optimal (
char& joba,
char& jobu,
char& jobv,
234 std::vector<P> work (2);
237 F77_INT lda = std::max<F77_INT> (m, 1);
241 std::vector<P> mat_a (1);
242 P *a = mat_a.data ();
243 std::vector<F77_INT> vec_jpvt = {0};
244 P *tau = work.data ();
248 bool need_lsvec = jobu ==
'U' || jobu ==
'F';
249 bool need_rsvec = jobv ==
'V' || jobv ==
'J';
252 F77_INT lw_geqp3 = geqp3_lwork (m, n, a, lda, vec_jpvt.data (),
253 tau, work.data (), -1,
ierr);
254 F77_INT lw_geqrf = geqrf_lwork (m, n, a, lda,
255 tau, work.data (), -1,
ierr);
257 if (! (need_lsvec || need_rsvec) )
260 if (! (joba ==
'E' || joba ==
'G') )
261 lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_geqrf, 7});
263 lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_geqrf,
264 n + n*n + lw_pocon, 7});
266 else if (need_rsvec && ! need_lsvec)
269 F77_INT lw_gelqf = gelqf_lwork (n, n, a, lda,
270 tau, work.data (), -1,
ierr);
272 F77_INT lw_ormlq = ormlq_lwork (side, trans, n, n, n, a, lda,
273 tau, v, n, work.data (), -1,
ierr);
274 lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_pocon,
275 n + lw_gelqf, 2*n + lw_geqrf, n + lw_ormlq});
277 else if (need_lsvec && ! need_rsvec)
280 F77_INT n1 = (jobu ==
'U') ? n : m;
281 F77_INT lw_ormqr = ormqr_lwork (side, trans, m, n1, n, a, lda,
282 tau, u, m, work.data (), -1,
ierr);
283 lwork = std::max<F77_INT> ({2*m + n, n + lw_geqp3, n + lw_pocon,
284 2*n + lw_geqrf, n + lw_ormqr});
289 lwork = std::max (2*m + n, 6*n + 2*n*n);
290 else if (jobv ==
'J')
291 lwork = std::max<F77_INT> ({2*m + n, 4*n + n*n, 2*n + n*n + 6});
293 F77_INT n1 = (jobu ==
'U') ? n : m;
294 F77_INT lw_ormqr = ormqr_lwork (side, trans, m, n1, n, a, lda,
295 tau, u, m, work.data (), -1,
ierr);
296 lwork = std::max (lwork, n + lw_ormqr);
310 (*current_liboctave_error_handler)
311 (
"svd: U not computed because type == svd::sigma_only");
321 (*current_liboctave_error_handler)
322 (
"svd: V not computed because type == svd::sigma_only");
329#define GESVD_REAL_STEP(f, F) \
330 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
331 F77_CONST_CHAR_ARG2 (&jobv, 1), \
332 m, n, tmp_data, m1, s_vec, u, m1, vt, \
333 nrow_vt1, work.data (), lwork, info \
334 F77_CHAR_ARG_LEN (1) \
335 F77_CHAR_ARG_LEN (1)))
337#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG) \
338 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
339 F77_CONST_CHAR_ARG2 (&jobv, 1), \
340 m, n, CMPLX_ARG (tmp_data), \
341 m1, s_vec, CMPLX_ARG (u), m1, \
342 CMPLX_ARG (vt), nrow_vt1, \
343 CMPLX_ARG (work.data ()), \
344 lwork, rwork.data (), info \
345 F77_CHAR_ARG_LEN (1) \
346 F77_CHAR_ARG_LEN (1)))
352 double *tmp_data,
F77_INT m1,
double *s_vec,
353 double *u,
double *vt,
F77_INT nrow_vt1,
354 std::vector<double>& work,
F77_INT& lwork,
359 lwork =
static_cast<F77_INT> (work[0]);
369 float *tmp_data,
F77_INT m1,
float *s_vec,
370 float *u,
float *vt,
F77_INT nrow_vt1,
371 std::vector<float>& work,
F77_INT& lwork,
376 lwork =
static_cast<F77_INT> (work[0]);
388 std::vector<Complex>& work,
F77_INT& lwork,
391 std::vector<double> rwork (5 * std::max (m, n));
395 lwork =
static_cast<F77_INT> (work[0].real ());
408 std::vector<FloatComplex>& work,
411 std::vector<float> rwork (5 * std::max (m, n));
415 lwork =
static_cast<F77_INT> (work[0].real ());
421#undef GESVD_REAL_STEP
422#undef GESVD_COMPLEX_STEP
426#define GESDD_REAL_STEP(f, F) \
427 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \
428 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \
429 work.data (), lwork, iwork, info \
430 F77_CHAR_ARG_LEN (1)))
432#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG) \
433 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n, \
434 CMPLX_ARG (tmp_data), m1, \
435 s_vec, CMPLX_ARG (u), m1, \
436 CMPLX_ARG (vt), nrow_vt1, \
437 CMPLX_ARG (work.data ()), lwork, \
438 rwork.data (), iwork, info \
439 F77_CHAR_ARG_LEN (1)))
445 F77_INT m1,
double *s_vec,
double *u,
double *vt,
446 F77_INT nrow_vt1, std::vector<double>& work,
451 lwork =
static_cast<F77_INT> (work[0]);
461 F77_INT m1,
float *s_vec,
float *u,
float *vt,
462 F77_INT nrow_vt1, std::vector<float>& work,
467 lwork =
static_cast<F77_INT> (work[0]);
479 std::vector<Complex>& work,
F77_INT& lwork,
483 F77_INT min_mn = std::min (m, n);
484 F77_INT max_mn = std::max (m, n);
490 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
492 std::vector<double> rwork (lrwork);
496 lwork =
static_cast<F77_INT> (work[0].real ());
509 std::vector<FloatComplex>& work,
513 F77_INT min_mn = std::min (m, n);
514 F77_INT max_mn = std::max (m, n);
520 lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
521 std::vector<float> rwork (lrwork);
525 lwork =
static_cast<F77_INT> (work[0].real ());
531#undef GESDD_REAL_STEP
532#undef GESDD_COMPLEX_STEP
536#define GEJSV_REAL_STEP(f, F) \
537 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
538 F77_CONST_CHAR_ARG2 (&jobu, 1), \
539 F77_CONST_CHAR_ARG2 (&jobv, 1), \
540 F77_CONST_CHAR_ARG2 (&jobr, 1), \
541 F77_CONST_CHAR_ARG2 (&jobt, 1), \
542 F77_CONST_CHAR_ARG2 (&jobp, 1), \
543 m, n, tmp_data, m1, s_vec, u, m1, v, nrow_v1, \
544 work.data (), lwork, iwork.data (), info \
545 F77_CHAR_ARG_LEN (1) \
546 F77_CHAR_ARG_LEN (1) \
547 F77_CHAR_ARG_LEN (1) \
548 F77_CHAR_ARG_LEN (1) \
549 F77_CHAR_ARG_LEN (1) \
550 F77_CHAR_ARG_LEN (1)))
552#define GEJSV_COMPLEX_STEP(f, F, CMPLX_ARG) \
553 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
554 F77_CONST_CHAR_ARG2 (&jobu, 1), \
555 F77_CONST_CHAR_ARG2 (&jobv, 1), \
556 F77_CONST_CHAR_ARG2 (&jobr, 1), \
557 F77_CONST_CHAR_ARG2 (&jobt, 1), \
558 F77_CONST_CHAR_ARG2 (&jobp, 1), \
559 m, n, CMPLX_ARG (tmp_data), m1, \
560 s_vec, CMPLX_ARG (u), m1, \
561 CMPLX_ARG (v), nrow_v1, \
562 CMPLX_ARG (work.data ()), lwork, \
563 rwork.data (), lrwork, iwork.data (), info \
564 F77_CHAR_ARG_LEN (1) \
565 F77_CHAR_ARG_LEN (1) \
566 F77_CHAR_ARG_LEN (1) \
567 F77_CHAR_ARG_LEN (1) \
568 F77_CHAR_ARG_LEN (1) \
569 F77_CHAR_ARG_LEN (1)))
575 char& jobr,
char& jobt,
char& jobp,
577 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
578 P *v,
F77_INT nrow_v1, std::vector<P>& work,
579 F77_INT& lwork, std::vector<F77_INT>& iwork,
582 lwork = gejsv_lwork<Matrix>::optimal (joba, jobu, jobv, m, n);
592 char& jobr,
char& jobt,
char& jobp,
594 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
595 P *v,
F77_INT nrow_v1, std::vector<P>& work,
596 F77_INT& lwork, std::vector<F77_INT>& iwork,
599 lwork = gejsv_lwork<FloatMatrix>::optimal (joba, jobu, jobv, m, n);
609 char& jobr,
char& jobt,
char& jobp,
611 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
612 P *v,
F77_INT nrow_v1, std::vector<P>& work,
613 F77_INT& lwork, std::vector<F77_INT>& iwork,
617 std::vector<double> rwork (1);
622 lwork =
static_cast<F77_INT> (work[0].real ());
625 lrwork =
static_cast<F77_INT> (rwork[0]);
626 rwork.resize (lrwork);
629 iwork.resize (liwork);
638 char& jobr,
char& jobt,
char& jobp,
640 F77_INT m1, DM_P *s_vec, P *u, P *v,
641 F77_INT nrow_v1, std::vector<P>& work,
643 std::vector<F77_INT>& iwork,
F77_INT& info)
646 std::vector<float> rwork (1);
651 lwork =
static_cast<F77_INT> (work[0].real ());
654 lrwork =
static_cast<F77_INT> (rwork[0]);
655 rwork.resize (lrwork);
658 iwork.resize (liwork);
663#undef GEJSV_REAL_STEP
664#undef GEJSV_COMPLEX_STEP
668 : m_type (type), m_driver (driver), m_left_sm (), m_sigma (),
673 F77_INT m = to_f77_int (a.rows ());
674 F77_INT n = to_f77_int (a.cols ());
676 if (m == 0 || n == 0)
681 m_left_sm = T (m, m, 0);
682 for (
F77_INT i = 0; i < m; i++)
683 m_left_sm.xelem (i, i) = 1;
684 m_sigma =
DM_T (m, n);
685 m_right_sm = T (n, n, 0);
686 for (
F77_INT i = 0; i < n; i++)
687 m_right_sm.xelem (i, i) = 1;
691 m_left_sm = T (m, 0, 0);
692 m_sigma =
DM_T (0, 0);
693 m_right_sm = T (n, 0, 0);
698 m_sigma =
DM_T (0, 1);
705 P *tmp_data = atmp.rwdata ();
707 F77_INT min_mn = (m < n ? m : n);
721 ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
734 ncol_u = nrow_vt = 1;
741 if (! (jobu ==
'N' || jobu ==
'O'))
742 m_left_sm.resize (m, ncol_u);
744 P *u = m_left_sm.rwdata ();
746 m_sigma.resize (nrow_s, ncol_s);
747 DM_P *s_vec = m_sigma.rwdata ();
749 if (! (jobv ==
'N' || jobv ==
'O'))
752 m_right_sm.resize (n, nrow_vt);
754 m_right_sm.resize (nrow_vt, n);
757 P *vt = m_right_sm.rwdata ();
772 std::vector<P> work (1);
775 F77_INT m1 = std::max (m, f77_int_one);
776 F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one);
779 gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
786 std::vector<F77_INT> iwork (8 * std::min (m, n));
788 gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
789 work, lwork, iwork.data (), info);
793 bool transposed =
false;
800 m1 = std::max (m, f77_int_one);
801 nrow_vt1 = std::max (n, f77_int_one);
804 std::swap (jobu, jobv);
806 atmp = atmp.hermitian ();
807 tmp_data = atmp.rwdata ();
810 u = m_right_sm.rwdata ();
811 vt = m_left_sm.rwdata ();
815 std::unordered_map<char, std::string> job_svd2jsv;
816 job_svd2jsv[
'A'] =
"FJ";
817 job_svd2jsv[
'S'] =
"UV";
818 job_svd2jsv[
'O'] =
"WW";
819 job_svd2jsv[
'N'] =
"NN";
820 jobu = job_svd2jsv[jobu][0];
821 jobv = job_svd2jsv[jobv][1];
828 std::vector<F77_INT> iwork (std::max<F77_INT> (m + 3*n, 1));
830 gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1,
831 s_vec, u, vt, nrow_vt1, work, lwork, iwork, info);
834 (*current_liboctave_warning_with_id_handler)
835 (
"Octave:convergence",
"svd: (driver: GEJSV) "
836 "Denormal occurred, possible loss of accuracy.");
839 (*current_liboctave_error_handler)
840 (
"svd: (driver: GEJSV) Illegal argument at #%d",
841 static_cast<int> (-info));
843 (*current_liboctave_warning_with_id_handler)
844 (
"Octave:convergence",
"svd: (driver: GEJSV) "
845 "Fail to converge within max sweeps, "
846 "possible inaccurate result.");
857 if (! m_sigma.dgxelem (i))
858 m_sigma.dgxelem (i) = DM_P (0);
863 m_right_sm = m_right_sm.hermitian ();
876OCTAVE_END_NAMESPACE(math)
877OCTAVE_END_NAMESPACE(octave)
T::real_diag_matrix_type DM_T
T right_singular_matrix() const
T left_singular_matrix() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define F77_DBLE_CMPLX_ARG(x)
octave_f77_int_type F77_INT
#define GESVD_REAL_STEP(f, F)
#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG)
#define GEJSV_REAL_STEP(f, F)
#define GEJSV_REAL_ORM_LWORK(f, F)
#define GEJSV_REAL_QR_LWORK(f, F)
#define GEJSV_COMPLEX_STEP(f, F, CMPLX_ARG)
#define GEJSV_REAL_QP3_LWORK(f, F)
#define GESDD_REAL_STEP(f, F)
#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
std::complex< double > Complex
std::complex< float > FloatComplex
#define liboctave_panic_unless(cond)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE const F77_INT F77_INT & ierr