26 #if defined (HAVE_CONFIG_H)
33 #include <unordered_map>
52 OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE_DELETE (gejsv_lwork)
62 static F77_INT optimal (
char& joba,
char& jobu,
char& jobv,
66 typedef typename T::element_type P;
84 static F77_INT ormlq_lwork (
char& side,
char& trans,
90 static F77_INT ormqr_lwork (
char& side,
char& trans,
97 #define GEJSV_REAL_QP3_LWORK(f, F) \
98 F77_XFCN (f, F, (m, n, a, lda, jpvt, tau, work, lwork, info))
100 #define GEJSV_REAL_QR_LWORK(f, F) \
101 F77_XFCN (f, F, (m, n, a, lda, tau, work, lwork, info))
103 #define GEJSV_REAL_ORM_LWORK(f, F) \
104 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&side, 1), \
105 F77_CONST_CHAR_ARG2 (&trans, 1), \
106 m, n, k, a, lda, tau, \
107 c, ldc, work, lwork, info \
108 F77_CHAR_ARG_LEN (1) \
109 F77_CHAR_ARG_LEN (1)))
116 F77_INT *jpvt, P *tau, P *work,
120 return static_cast<F77_INT> (work[0]);
131 return static_cast<F77_INT> (work[0]);
142 return static_cast<F77_INT> (work[0]);
147 gejsv_lwork<Matrix>::ormlq_lwork (
char& side,
char& trans,
154 return static_cast<F77_INT> (work[0]);
159 gejsv_lwork<Matrix>::ormqr_lwork (
char& side,
char& trans,
166 return static_cast<F77_INT> (work[0]);
174 F77_INT *jpvt, P *tau, P *work,
178 return static_cast<F77_INT> (work[0]);
189 return static_cast<F77_INT> (work[0]);
200 return static_cast<F77_INT> (work[0]);
205 gejsv_lwork<FloatMatrix>::ormlq_lwork (
char& side,
char& trans,
212 return static_cast<F77_INT> (work[0]);
217 gejsv_lwork<FloatMatrix>::ormqr_lwork (
char& side,
char& trans,
224 return static_cast<F77_INT> (work[0]);
227 #undef GEJSV_REAL_QP3_LWORK
228 #undef GEJSV_REAL_QR_LWORK
229 #undef GEJSV_REAL_ORM_LWORK
233 gejsv_lwork<T>::optimal (
char& joba,
char& jobu,
char& jobv,
237 std::vector<P> work (2);
240 F77_INT lda = std::max<F77_INT> (
m, 1);
244 std::vector<P> mat_a (1);
245 P *a = mat_a.data ();
246 std::vector<F77_INT> vec_jpvt = {0};
247 P *tau = work.data ();
251 bool need_lsvec = jobu ==
'U' || jobu ==
'F';
252 bool need_rsvec = jobv ==
'V' || jobv ==
'J';
255 F77_INT lw_geqp3 = geqp3_lwork (
m,
n, a, lda, vec_jpvt.data (),
256 tau, work.data (), -1,
ierr);
257 F77_INT lw_geqrf = geqrf_lwork (
m,
n, a, lda,
258 tau, work.data (), -1,
ierr);
260 if (! (need_lsvec || need_rsvec) )
263 if (! (joba ==
'E' || joba ==
'G') )
264 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_geqrf, 7});
266 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_geqrf,
267 n +
n*
n + lw_pocon, 7});
269 else if (need_rsvec && ! need_lsvec)
272 F77_INT lw_gelqf = gelqf_lwork (
n,
n, a, lda,
273 tau, work.data (), -1,
ierr);
275 F77_INT lw_ormlq = ormlq_lwork (side, trans,
n,
n,
n, a, lda,
276 tau, v,
n, work.data (), -1,
ierr);
277 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_pocon,
278 n + lw_gelqf, 2*
n + lw_geqrf,
n + lw_ormlq});
280 else if (need_lsvec && ! need_rsvec)
284 F77_INT lw_ormqr = ormqr_lwork (side, trans,
m, n1,
n, a, lda,
285 tau, u,
m, work.data (), -1,
ierr);
286 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_pocon,
287 2*
n + lw_geqrf,
n + lw_ormqr});
293 else if (jobv ==
'J')
294 lwork = std::max<F77_INT> ({2*
m +
n, 4*
n +
n*
n, 2*
n +
n*
n + 6});
297 F77_INT lw_ormqr = ormqr_lwork (side, trans,
m, n1,
n, a, lda,
298 tau, u,
m, work.data (), -1,
ierr);
309 template <
typename T>
314 (*current_liboctave_error_handler)
315 (
"svd: U not computed because type == svd::sigma_only");
320 template <
typename T>
325 (*current_liboctave_error_handler)
326 (
"svd: V not computed because type == svd::sigma_only");
333 #define GESVD_REAL_STEP(f, F) \
334 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
335 F77_CONST_CHAR_ARG2 (&jobv, 1), \
336 m, n, tmp_data, m1, s_vec, u, m1, vt, \
337 nrow_vt1, work.data (), lwork, info \
338 F77_CHAR_ARG_LEN (1) \
339 F77_CHAR_ARG_LEN (1)))
341 #define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG) \
342 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
343 F77_CONST_CHAR_ARG2 (&jobv, 1), \
344 m, n, CMPLX_ARG (tmp_data), \
345 m1, s_vec, CMPLX_ARG (u), m1, \
346 CMPLX_ARG (vt), nrow_vt1, \
347 CMPLX_ARG (work.data ()), \
348 lwork, rwork.data (), info \
349 F77_CHAR_ARG_LEN (1) \
350 F77_CHAR_ARG_LEN (1)))
356 double *tmp_data,
F77_INT m1,
double *s_vec,
357 double *u,
double *vt,
F77_INT nrow_vt1,
358 std::vector<double>& work,
F77_INT& lwork,
363 lwork =
static_cast<F77_INT> (work[0]);
364 work.reserve (lwork);
373 float *tmp_data,
F77_INT m1,
float *s_vec,
374 float *u,
float *vt,
F77_INT nrow_vt1,
375 std::vector<float>& work,
F77_INT& lwork,
380 lwork =
static_cast<F77_INT> (work[0]);
381 work.reserve (lwork);
392 std::vector<Complex>& work,
F77_INT& lwork,
395 std::vector<double> rwork (5 *
std::max (
m,
n));
399 lwork =
static_cast<F77_INT> (work[0].real ());
400 work.reserve (lwork);
412 std::vector<FloatComplex>& work,
415 std::vector<float> rwork (5 *
std::max (
m,
n));
419 lwork =
static_cast<F77_INT> (work[0].real ());
420 work.reserve (lwork);
425 #undef GESVD_REAL_STEP
426 #undef GESVD_COMPLEX_STEP
430 #define GESDD_REAL_STEP(f, F) \
431 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \
432 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \
433 work.data (), lwork, iwork, info \
434 F77_CHAR_ARG_LEN (1)))
436 #define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG) \
437 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n, \
438 CMPLX_ARG (tmp_data), m1, \
439 s_vec, CMPLX_ARG (u), m1, \
440 CMPLX_ARG (vt), nrow_vt1, \
441 CMPLX_ARG (work.data ()), lwork, \
442 rwork.data (), iwork, info \
443 F77_CHAR_ARG_LEN (1)))
449 F77_INT m1,
double *s_vec,
double *u,
double *vt,
450 F77_INT nrow_vt1, std::vector<double>& work,
455 lwork =
static_cast<F77_INT> (work[0]);
456 work.reserve (lwork);
465 F77_INT m1,
float *s_vec,
float *u,
float *vt,
466 F77_INT nrow_vt1, std::vector<float>& work,
471 lwork =
static_cast<F77_INT> (work[0]);
472 work.reserve (lwork);
483 std::vector<Complex>& work,
F77_INT& lwork,
494 lrwork = min_mn *
std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
496 std::vector<double> rwork (lrwork);
500 lwork =
static_cast<F77_INT> (work[0].real ());
501 work.reserve (lwork);
513 std::vector<FloatComplex>& work,
524 lrwork = min_mn *
std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
525 std::vector<float> rwork (lrwork);
529 lwork =
static_cast<F77_INT> (work[0].real ());
530 work.reserve (lwork);
535 #undef GESDD_REAL_STEP
536 #undef GESDD_COMPLEX_STEP
540 #define GEJSV_REAL_STEP(f, F) \
541 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
542 F77_CONST_CHAR_ARG2 (&jobu, 1), \
543 F77_CONST_CHAR_ARG2 (&jobv, 1), \
544 F77_CONST_CHAR_ARG2 (&jobr, 1), \
545 F77_CONST_CHAR_ARG2 (&jobt, 1), \
546 F77_CONST_CHAR_ARG2 (&jobp, 1), \
547 m, n, tmp_data, m1, s_vec, u, m1, v, nrow_v1, \
548 work.data (), lwork, iwork.data (), info \
549 F77_CHAR_ARG_LEN (1) \
550 F77_CHAR_ARG_LEN (1) \
551 F77_CHAR_ARG_LEN (1) \
552 F77_CHAR_ARG_LEN (1) \
553 F77_CHAR_ARG_LEN (1) \
554 F77_CHAR_ARG_LEN (1)))
556 #define GEJSV_COMPLEX_STEP(f, F, CMPLX_ARG) \
557 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
558 F77_CONST_CHAR_ARG2 (&jobu, 1), \
559 F77_CONST_CHAR_ARG2 (&jobv, 1), \
560 F77_CONST_CHAR_ARG2 (&jobr, 1), \
561 F77_CONST_CHAR_ARG2 (&jobt, 1), \
562 F77_CONST_CHAR_ARG2 (&jobp, 1), \
563 m, n, CMPLX_ARG (tmp_data), m1, \
564 s_vec, CMPLX_ARG (u), m1, \
565 CMPLX_ARG (v), nrow_v1, \
566 CMPLX_ARG (work.data ()), lwork, \
567 rwork.data (), lrwork, iwork.data (), info \
568 F77_CHAR_ARG_LEN (1) \
569 F77_CHAR_ARG_LEN (1) \
570 F77_CHAR_ARG_LEN (1) \
571 F77_CHAR_ARG_LEN (1) \
572 F77_CHAR_ARG_LEN (1) \
573 F77_CHAR_ARG_LEN (1)))
579 char& jobr,
char& jobt,
char& jobp,
581 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
582 P *v,
F77_INT nrow_v1, std::vector<P>& work,
583 F77_INT& lwork, std::vector<F77_INT>& iwork,
586 lwork = gejsv_lwork<Matrix>::optimal (joba, jobu, jobv,
m,
n);
587 work.reserve (lwork);
596 char& jobr,
char& jobt,
char& jobp,
598 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
599 P *v,
F77_INT nrow_v1, std::vector<P>& work,
600 F77_INT& lwork, std::vector<F77_INT>& iwork,
603 lwork = gejsv_lwork<FloatMatrix>::optimal (joba, jobu, jobv,
m,
n);
604 work.reserve (lwork);
613 char& jobr,
char& jobt,
char& jobp,
615 P *tmp_data,
F77_INT m1, DM_P *s_vec, P *u,
616 P *v,
F77_INT nrow_v1, std::vector<P>& work,
617 F77_INT& lwork, std::vector<F77_INT>& iwork,
621 std::vector<double> rwork (1);
626 lwork =
static_cast<F77_INT> (work[0].real ());
627 work.reserve (lwork);
629 lrwork =
static_cast<F77_INT> (rwork[0]);
630 rwork.reserve (lrwork);
633 iwork.reserve (liwork);
642 char& jobr,
char& jobt,
char& jobp,
644 F77_INT m1, DM_P *s_vec, P *u, P *v,
645 F77_INT nrow_v1, std::vector<P>& work,
647 std::vector<F77_INT>& iwork,
F77_INT& info)
650 std::vector<float> rwork (1);
655 lwork =
static_cast<F77_INT> (work[0].real ());
656 work.reserve (lwork);
658 lrwork =
static_cast<F77_INT> (rwork[0]);
659 rwork.reserve (lrwork);
662 iwork.reserve (liwork);
667 #undef GEJSV_REAL_STEP
668 #undef GEJSV_COMPLEX_STEP
672 : m_type (type), m_driver (driver), m_left_sm (), m_sigma (),
680 if (
m == 0 ||
n == 0)
685 m_left_sm = T (
m,
m, 0);
687 m_left_sm.xelem (i, i) = 1;
689 m_right_sm = T (
n,
n, 0);
691 m_right_sm.xelem (i, i) = 1;
695 m_left_sm = T (
m, 0, 0);
696 m_sigma =
DM_T (0, 0);
697 m_right_sm = T (
n, 0, 0);
702 m_sigma =
DM_T (0, 1);
709 P *tmp_data = atmp.fortran_vec ();
725 ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
738 ncol_u = nrow_vt = 1;
745 if (! (jobu ==
'N' || jobu ==
'O'))
746 m_left_sm.resize (
m, ncol_u);
748 P *u = m_left_sm.fortran_vec ();
750 m_sigma.resize (nrow_s, ncol_s);
751 DM_P *s_vec = m_sigma.fortran_vec ();
753 if (! (jobv ==
'N' || jobv ==
'O'))
756 m_right_sm.resize (
n, nrow_vt);
758 m_right_sm.resize (nrow_vt,
n);
761 P *vt = m_right_sm.fortran_vec ();
767 std::vector<P> work (1);
774 gesvd (jobu, jobv,
m,
n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
778 assert (jobu == jobv);
781 std::vector<F77_INT> iwork (8 *
std::min (
m,
n));
783 gesdd (jobz,
m,
n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
784 work, lwork, iwork.data (), info);
788 bool transposed =
false;
799 std::swap (jobu, jobv);
801 atmp = atmp.hermitian ();
802 tmp_data = atmp.fortran_vec ();
805 u = m_right_sm.fortran_vec ();
806 vt = m_left_sm.fortran_vec ();
810 std::unordered_map<char, std::string> job_svd2jsv;
811 job_svd2jsv[
'A'] =
"FJ";
812 job_svd2jsv[
'S'] =
"UV";
813 job_svd2jsv[
'O'] =
"WW";
814 job_svd2jsv[
'N'] =
"NN";
815 jobu = job_svd2jsv[jobu][0];
816 jobv = job_svd2jsv[jobv][1];
823 std::vector<F77_INT> iwork (std::max<F77_INT> (
m + 3*
n, 1));
825 gejsv (joba, jobu, jobv, jobr, jobt, jobp,
m,
n, tmp_data, m1,
826 s_vec, u, vt, nrow_vt1, work, lwork, iwork, info);
829 (*current_liboctave_warning_with_id_handler)
830 (
"Octave:convergence",
"svd: (driver: GEJSV) "
831 "Denormal occurred, possible loss of accuracy.");
834 (*current_liboctave_error_handler)
835 (
"svd: (driver: GEJSV) Illegal argument at #%d",
836 static_cast<int> (-info));
838 (*current_liboctave_warning_with_id_handler)
839 (
"Octave:convergence",
"svd: (driver: GEJSV) "
840 "Fail to converge within max sweeps, "
841 "possible inaccurate result.");
852 if (! m_sigma.dgxelem (i))
853 m_sigma.dgxelem (i) = DM_P (0);
858 m_right_sm = m_right_sm.hermitian ();
871 OCTAVE_END_NAMESPACE(math)
872 OCTAVE_END_NAMESPACE(
octave)
charNDArray max(char d, const charNDArray &m)
charNDArray min(char d, const charNDArray &m)
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
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE const F77_INT F77_INT & ierr
std::complex< double > Complex
std::complex< float > FloatComplex