26 #if defined (HAVE_CONFIG_H)
33 #include <unordered_map>
61 static F77_INT optimal (
char& joba,
char& jobu,
char& jobv,
65 typedef typename T::element_type
P;
96 #define GEJSV_REAL_QP3_LWORK(f, F) \
97 F77_XFCN (f, F, (m, n, a, lda, jpvt, tau, work, lwork, info))
99 #define GEJSV_REAL_QR_LWORK(f, F) \
100 F77_XFCN (f, F, (m, n, a, lda, tau, work, lwork, info))
102 #define GEJSV_REAL_ORM_LWORK(f, F) \
103 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&side, 1), \
104 F77_CONST_CHAR_ARG2 (&trans, 1), \
105 m, n, k, a, lda, tau, \
106 c, ldc, work, lwork, info \
107 F77_CHAR_ARG_LEN (1) \
108 F77_CHAR_ARG_LEN (1)))
119 return static_cast<F77_INT> (work[0]);
130 return static_cast<F77_INT> (work[0]);
141 return static_cast<F77_INT> (work[0]);
153 return static_cast<F77_INT> (work[0]);
165 return static_cast<F77_INT> (work[0]);
177 return static_cast<F77_INT> (work[0]);
188 return static_cast<F77_INT> (work[0]);
199 return static_cast<F77_INT> (work[0]);
211 return static_cast<F77_INT> (work[0]);
223 return static_cast<F77_INT> (work[0]);
226 #undef GEJSV_REAL_QP3_LWORK
227 #undef GEJSV_REAL_QR_LWORK
228 #undef GEJSV_REAL_ORM_LWORK
236 std::vector<P> work (2);
239 F77_INT lda = std::max<F77_INT> (
m, 1);
243 std::vector<P> mat_a (1);
244 P *a = mat_a.data ();
245 std::vector<F77_INT> vec_jpvt = {0};
246 P *tau = work.data ();
250 bool need_lsvec = jobu ==
'U' || jobu ==
'F';
251 bool need_rsvec = jobv ==
'V' || jobv ==
'J';
254 F77_INT lw_geqp3 = geqp3_lwork (
m,
n, a, lda, vec_jpvt.data (),
255 tau, work.data (), -1,
ierr);
256 F77_INT lw_geqrf = geqrf_lwork (
m,
n, a, lda,
257 tau, work.data (), -1,
ierr);
259 if (! (need_lsvec || need_rsvec) )
262 if (! (joba ==
'E' || joba ==
'G') )
263 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_geqrf, 7});
265 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_geqrf,
266 n +
n*
n + lw_pocon, 7});
268 else if (need_rsvec && ! need_lsvec)
271 F77_INT lw_gelqf = gelqf_lwork (
n,
n, a, lda,
272 tau, work.data (), -1,
ierr);
274 F77_INT lw_ormlq = ormlq_lwork (side, trans,
n,
n,
n, a, lda,
275 tau, v,
n, work.data (), -1,
ierr);
276 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_pocon,
277 n + lw_gelqf, 2*
n + lw_geqrf,
n + lw_ormlq});
279 else if (need_lsvec && ! need_rsvec)
283 F77_INT lw_ormqr = ormqr_lwork (side, trans,
m, n1,
n, a, lda,
284 tau, u,
m, work.data (), -1,
ierr);
285 lwork = std::max<F77_INT> ({2*
m +
n,
n + lw_geqp3,
n + lw_pocon,
286 2*
n + lw_geqrf,
n + lw_ormqr});
292 else if (jobv ==
'J')
293 lwork = std::max<F77_INT> ({2*
m +
n, 4*
n +
n*
n, 2*
n +
n*
n + 6});
296 F77_INT lw_ormqr = ormqr_lwork (side, trans,
m, n1,
n, a, lda,
297 tau, u,
m, work.data (), -1,
ierr);
308 template <
typename T>
313 (*current_liboctave_error_handler)
314 (
"svd: U not computed because type == svd::sigma_only");
319 template <
typename T>
324 (*current_liboctave_error_handler)
325 (
"svd: V not computed because type == svd::sigma_only");
332 #define GESVD_REAL_STEP(f, F) \
333 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
334 F77_CONST_CHAR_ARG2 (&jobv, 1), \
335 m, n, tmp_data, m1, s_vec, u, m1, vt, \
336 nrow_vt1, work.data (), lwork, info \
337 F77_CHAR_ARG_LEN (1) \
338 F77_CHAR_ARG_LEN (1)))
340 #define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG) \
341 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \
342 F77_CONST_CHAR_ARG2 (&jobv, 1), \
343 m, n, CMPLX_ARG (tmp_data), \
344 m1, s_vec, CMPLX_ARG (u), m1, \
345 CMPLX_ARG (vt), nrow_vt1, \
346 CMPLX_ARG (work.data ()), \
347 lwork, rwork.data (), info \
348 F77_CHAR_ARG_LEN (1) \
349 F77_CHAR_ARG_LEN (1)))
355 double *tmp_data,
F77_INT m1,
double *s_vec,
356 double *u,
double *vt,
F77_INT nrow_vt1,
357 std::vector<double>& work,
F77_INT& lwork,
362 lwork =
static_cast<F77_INT> (work[0]);
363 work.reserve (lwork);
372 float *tmp_data,
F77_INT m1,
float *s_vec,
373 float *u,
float *vt,
F77_INT nrow_vt1,
374 std::vector<float>& work,
F77_INT& lwork,
379 lwork =
static_cast<F77_INT> (work[0]);
380 work.reserve (lwork);
391 std::vector<Complex>& work,
F77_INT& lwork,
394 std::vector<double> rwork (5 *
std::max (
m,
n));
398 lwork =
static_cast<F77_INT> (work[0].real ());
399 work.reserve (lwork);
411 std::vector<FloatComplex>& work,
414 std::vector<float> rwork (5 *
std::max (
m,
n));
418 lwork =
static_cast<F77_INT> (work[0].real ());
419 work.reserve (lwork);
424 #undef GESVD_REAL_STEP
425 #undef GESVD_COMPLEX_STEP
429 #define GESDD_REAL_STEP(f, F) \
430 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \
431 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1, \
432 work.data (), lwork, iwork, info \
433 F77_CHAR_ARG_LEN (1)))
435 #define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG) \
436 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n, \
437 CMPLX_ARG (tmp_data), m1, \
438 s_vec, CMPLX_ARG (u), m1, \
439 CMPLX_ARG (vt), nrow_vt1, \
440 CMPLX_ARG (work.data ()), lwork, \
441 rwork.data (), iwork, info \
442 F77_CHAR_ARG_LEN (1)))
448 F77_INT m1,
double *s_vec,
double *u,
double *vt,
449 F77_INT nrow_vt1, std::vector<double>& work,
454 lwork =
static_cast<F77_INT> (work[0]);
455 work.reserve (lwork);
464 F77_INT m1,
float *s_vec,
float *u,
float *vt,
465 F77_INT nrow_vt1, std::vector<float>& work,
470 lwork =
static_cast<F77_INT> (work[0]);
471 work.reserve (lwork);
482 std::vector<Complex>& work,
F77_INT& lwork,
493 lrwork = min_mn *
std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
495 std::vector<double> rwork (lrwork);
499 lwork =
static_cast<F77_INT> (work[0].real ());
500 work.reserve (lwork);
512 std::vector<FloatComplex>& work,
523 lrwork = min_mn *
std::max (5*min_mn+5, 2*max_mn+2*min_mn+1);
524 std::vector<float> rwork (lrwork);
528 lwork =
static_cast<F77_INT> (work[0].real ());
529 work.reserve (lwork);
534 #undef GESDD_REAL_STEP
535 #undef GESDD_COMPLEX_STEP
539 #define GEJSV_REAL_STEP(f, F) \
540 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
541 F77_CONST_CHAR_ARG2 (&jobu, 1), \
542 F77_CONST_CHAR_ARG2 (&jobv, 1), \
543 F77_CONST_CHAR_ARG2 (&jobr, 1), \
544 F77_CONST_CHAR_ARG2 (&jobt, 1), \
545 F77_CONST_CHAR_ARG2 (&jobp, 1), \
546 m, n, tmp_data, m1, s_vec, u, m1, v, nrow_v1, \
547 work.data (), lwork, iwork.data (), info \
548 F77_CHAR_ARG_LEN (1) \
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)))
555 #define GEJSV_COMPLEX_STEP(f, F, CMPLX_ARG) \
556 F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \
557 F77_CONST_CHAR_ARG2 (&jobu, 1), \
558 F77_CONST_CHAR_ARG2 (&jobv, 1), \
559 F77_CONST_CHAR_ARG2 (&jobr, 1), \
560 F77_CONST_CHAR_ARG2 (&jobt, 1), \
561 F77_CONST_CHAR_ARG2 (&jobp, 1), \
562 m, n, CMPLX_ARG (tmp_data), m1, \
563 s_vec, CMPLX_ARG (u), m1, \
564 CMPLX_ARG (v), nrow_v1, \
565 CMPLX_ARG (work.data ()), lwork, \
566 rwork.data (), lrwork, iwork.data (), info \
567 F77_CHAR_ARG_LEN (1) \
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)))
578 char& jobr,
char& jobt,
char& jobp,
581 P *v,
F77_INT nrow_v1, std::vector<P>& work,
582 F77_INT& lwork, std::vector<F77_INT>& iwork,
586 work.reserve (lwork);
595 char& jobr,
char& jobt,
char& jobp,
598 P *v,
F77_INT nrow_v1, std::vector<P>& work,
599 F77_INT& lwork, std::vector<F77_INT>& iwork,
603 work.reserve (lwork);
612 char& jobr,
char& jobt,
char& jobp,
615 P *v,
F77_INT nrow_v1, std::vector<P>& work,
616 F77_INT& lwork, std::vector<F77_INT>& iwork,
620 std::vector<double> rwork (1);
625 lwork =
static_cast<F77_INT> (work[0].real ());
626 work.reserve (lwork);
628 lrwork =
static_cast<F77_INT> (rwork[0]);
629 rwork.reserve (lrwork);
632 iwork.reserve (liwork);
641 char& jobr,
char& jobt,
char& jobp,
644 F77_INT nrow_v1, std::vector<P>& work,
646 std::vector<F77_INT>& iwork,
F77_INT& info)
649 std::vector<float> rwork (1);
654 lwork =
static_cast<F77_INT> (work[0].real ());
655 work.reserve (lwork);
657 lrwork =
static_cast<F77_INT> (rwork[0]);
658 rwork.reserve (lrwork);
661 iwork.reserve (liwork);
666 #undef GEJSV_REAL_STEP
667 #undef GEJSV_COMPLEX_STEP
671 : m_type (type), m_driver (driver), m_left_sm (), m_sigma (),
679 if (
m == 0 ||
n == 0)
708 P *tmp_data = atmp.fortran_vec ();
724 ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
737 ncol_u = nrow_vt = 1;
744 if (! (jobu ==
'N' || jobu ==
'O'))
749 m_sigma.resize (nrow_s, ncol_s);
752 if (! (jobv ==
'N' || jobv ==
'O'))
766 std::vector<P> work (1);
773 gesvd (jobu, jobv,
m,
n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
777 assert (jobu == jobv);
780 std::vector<F77_INT> iwork (8 *
std::min (
m,
n));
782 gesdd (jobz,
m,
n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
783 work, lwork, iwork.data (), info);
787 bool transposed =
false;
798 std::swap (jobu, jobv);
800 atmp = atmp.hermitian ();
801 tmp_data = atmp.fortran_vec ();
809 std::unordered_map<char, std::string> job_svd2jsv;
810 job_svd2jsv[
'A'] =
"FJ";
811 job_svd2jsv[
'S'] =
"UV";
812 job_svd2jsv[
'O'] =
"WW";
813 job_svd2jsv[
'N'] =
"NN";
814 jobu = job_svd2jsv[jobu][0];
815 jobv = job_svd2jsv[jobv][1];
822 std::vector<F77_INT> iwork (std::max<F77_INT> (
m + 3*
n, 1));
824 gejsv (joba, jobu, jobv, jobr, jobt, jobp,
m,
n, tmp_data, m1,
825 s_vec, u, vt, nrow_vt1, work, lwork, iwork, info);
828 (*current_liboctave_warning_with_id_handler)
829 (
"Octave:convergence",
"svd: (driver: GEJSV) "
830 "Denormal occurred, possible loss of accuracy.");
833 (*current_liboctave_error_handler)
834 (
"svd: (driver: GEJSV) Illegal argument at #%d",
835 static_cast<int> (-info));
837 (*current_liboctave_warning_with_id_handler)
838 (
"Octave:convergence",
"svd: (driver: GEJSV) "
839 "Fail to converge within max sweeps, "
840 "possible inaccurate result.");
charNDArray max(char d, const charNDArray &m)
charNDArray min(char d, const charNDArray &m)
static F77_INT gelqf_lwork(F77_INT m, F77_INT n, P *a, F77_INT lda, P *tau, P *work, F77_INT lwork, F77_INT &info)
static F77_INT ormlq_lwork(char &side, char &trans, F77_INT m, F77_INT n, F77_INT k, P *a, F77_INT lda, P *tau, P *c, F77_INT ldc, P *work, F77_INT lwork, F77_INT &info)
static F77_INT geqp3_lwork(F77_INT m, F77_INT n, P *a, F77_INT lda, F77_INT *jpvt, P *tau, P *work, F77_INT lwork, F77_INT &info)
static F77_INT optimal(char &joba, char &jobu, char &jobv, F77_INT m, F77_INT n)
static F77_INT ormqr_lwork(char &side, char &trans, F77_INT m, F77_INT n, F77_INT k, P *a, F77_INT lda, P *tau, P *c, F77_INT ldc, P *work, F77_INT lwork, F77_INT &info)
static F77_INT geqrf_lwork(F77_INT m, F77_INT n, P *a, F77_INT lda, P *tau, P *work, F77_INT lwork, F77_INT &info)
void gesdd(char &jobz, octave_f77_int_type m, octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, P *vt, octave_f77_int_type nrow_vt1, std::vector< P > &work, octave_f77_int_type &lwork, octave_f77_int_type *iwork, octave_f77_int_type &info)
void gejsv(char &joba, char &jobu, char &jobv, char &jobr, char &jobt, char &jobp, octave_f77_int_type m, octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, P *v, octave_f77_int_type nrow_v1, std::vector< P > &work, octave_f77_int_type &lwork, std::vector< octave_f77_int_type > &iwork, octave_f77_int_type &info)
T::real_diag_matrix_type DM_T
void gesvd(char &jobu, char &jobv, octave_f77_int_type m, octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, P *vt, octave_f77_int_type nrow_vt1, std::vector< P > &work, octave_f77_int_type &lwork, octave_f77_int_type &info)
T right_singular_matrix(void) const
T left_singular_matrix(void) 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