530 SUBROUTINE dgedmd( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
531 M, N, X, LDX, Y, LDY, NRNK, TOL, &
532 K, REIG, IMEIG, Z, LDZ, RES, &
533 B, LDB, W, LDW, S, LDS, &
534 WORK, LWORK, IWORK, LIWORK, INFO )
543 use,
INTRINSIC :: iso_fortran_env, only: real64
545 INTEGER,
PARAMETER :: WP = real64
549 CHARACTER,
INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
550 INTEGER,
INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
551 NRNK, LDZ, LDB, LDW, LDS, &
553 INTEGER,
INTENT(OUT) :: K, INFO
554 REAL(KIND=wp),
INTENT(IN) :: tol
558 REAL(KIND=wp),
INTENT(INOUT) :: x(ldx,*), y(ldy,*)
559 REAL(KIND=wp),
INTENT(OUT) :: z(ldz,*), b(ldb,*), &
561 REAL(KIND=wp),
INTENT(OUT) :: reig(*), imeig(*), &
563 REAL(KIND=wp),
INTENT(OUT) :: work(*)
564 INTEGER,
INTENT(OUT) :: IWORK(*)
568 REAL(KIND=wp),
PARAMETER :: one = 1.0_wp
569 REAL(KIND=wp),
PARAMETER :: zero = 0.0_wp
573 REAL(KIND=wp) :: ofl, rootsc, scale, small, &
575 INTEGER :: i, j, IMINWR, INFO1, INFO2, &
576 LWRKEV, LWRSDD, LWRSVD, &
577 lwrsvq, mlwork, mwrkev, mwrsdd, &
578 mwrsvd, mwrsvj, mwrsvq, numrnk, &
580 LOGICAL :: BADXY, LQUERY, SCCOLX, SCCOLY, &
581 wntex, wntref, wntres, wntvec
582 CHARACTER :: JOBZL, T_OR_N
587 REAL(KIND=wp) :: ab(2,2), rdummy(2), rdummy2(2)
594 LOGICAL DISNAN, LSAME
595 EXTERNAL disnan, lsame
605 INTRINSIC dble, int, max, sqrt
610 wntres = lsame(jobr,
'R')
611 sccolx = lsame(jobs,
'S') .OR. lsame(jobs,
'C')
612 sccoly = lsame(jobs,
'Y')
613 wntvec = lsame(jobz,
'V')
614 wntref = lsame(jobf,
'R')
615 wntex = lsame(jobf,
'E')
617 lquery = ( ( lwork == -1 ) .OR. ( liwork == -1 ) )
619 IF ( .NOT. (sccolx .OR. sccoly .OR. &
620 lsame(jobs,
'N')) )
THEN
622 ELSE IF ( .NOT. (wntvec .OR. lsame(jobz,
'N') &
623 .OR. lsame(jobz,
'F')) )
THEN
625 ELSE IF ( .NOT. (wntres .OR. lsame(jobr,
'N')) .OR. &
626 ( wntres .AND. (.NOT.wntvec) ) )
THEN
628 ELSE IF ( .NOT. (wntref .OR. wntex .OR. &
629 lsame(jobf,
'N') ) )
THEN
631 ELSE IF ( .NOT.((whtsvd == 1) .OR. (whtsvd == 2) .OR. &
632 (whtsvd == 3) .OR. (whtsvd == 4) ))
THEN
634 ELSE IF ( m < 0 )
THEN
636 ELSE IF ( ( n < 0 ) .OR. ( n > m ) )
THEN
638 ELSE IF ( ldx < m )
THEN
640 ELSE IF ( ldy < m )
THEN
642 ELSE IF ( .NOT. (( nrnk == -2).OR.(nrnk == -1).OR. &
643 ((nrnk >= 1).AND.(nrnk <=n ))) )
THEN
645 ELSE IF ( ( tol < zero ) .OR. ( tol >= one ) )
THEN
647 ELSE IF ( ldz < m )
THEN
649 ELSE IF ( (wntref .OR. wntex ) .AND. ( ldb < m ) )
THEN
651 ELSE IF ( ldw < n )
THEN
653 ELSE IF ( lds < n )
THEN
657 IF ( info == 0 )
THEN
680 SELECT CASE ( whtsvd )
685 mwrsvd = max(1,3*min(m,n)+max(m,n),5*min(m,n))
686 mlwork = max(mlwork,n + mwrsvd)
688 CALL dgesvd(
'O',
'S', m, n, x, ldx, work, &
689 b, ldb, w, ldw, rdummy, -1, info1 )
690 lwrsvd = max( mwrsvd, int( rdummy(1) ) )
691 olwork = max(olwork,n + lwrsvd)
699 mwrsdd = 3*min(m,n)*min(m,n) + &
700 max( max(m,n),5*min(m,n)*min(m,n)+4*min(m,n) )
701 mlwork = max(mlwork,n + mwrsdd)
704 CALL dgesdd(
'O', m, n, x, ldx, work, b, &
705 ldb, w, ldw, rdummy, -1, iwork, info1 )
706 lwrsdd = max( mwrsdd, int( rdummy(1) ) )
707 olwork = max(olwork,n + lwrsdd)
716 CALL dgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
717 x, ldx, work, z, ldz, w, ldw, &
718 numrnk, iwork, liwork, rdummy, &
719 -1, rdummy2, -1, info1 )
721 mwrsvq = int(rdummy(2))
722 mlwork = max(mlwork,n+mwrsvq+int(rdummy2(1)))
724 lwrsvq = max( mwrsvq, int(rdummy(1)) )
725 olwork = max(olwork,n+lwrsvq+int(rdummy2(1)))
730 mwrsvj = max( 7, 2*m+n, 4*n+n*n, 2*n+n*n+6 )
731 mlwork = max(mlwork,n+mwrsvj)
732 iminwr = max( 3, m+3*n )
734 olwork = max(olwork,n+mwrsvj)
737 IF ( wntvec .OR. wntex .OR. lsame(jobz,
'F') )
THEN
743 IF ( lsame(jobzl,
'V') )
THEN
744 mwrkev = max( 1, 4*n )
746 mwrkev = max( 1, 3*n )
748 mlwork = max(mlwork,n+mwrkev)
750 CALL dgeev(
'N', jobzl, n, s, lds, reig, &
751 imeig, w, ldw, w, ldw, rdummy, -1, info1 )
752 lwrkev = max( mwrkev, int(rdummy(1)) )
753 olwork = max( olwork, n+lwrkev )
756 IF ( liwork < iminwr .AND. (.NOT.lquery) ) info = -29
757 IF ( lwork < mlwork .AND. (.NOT.lquery) ) info = -27
761 CALL xerbla(
'DGEDMD', -info )
763 ELSE IF ( lquery )
THEN
787 CALL dlassq( m, x(1,i), 1, scale, ssum )
788 IF ( disnan(scale) .OR. disnan(ssum) )
THEN
791 CALL xerbla(
'DGEDMD',-info)
793 IF ( (scale /= zero) .AND. (ssum /= zero) )
THEN
795 IF ( scale .GE. (ofl / rootsc) )
THEN
806 CALL dlascl(
'G', 0, 0, scale, one/rootsc, &
807 m, 1, x(1,i), m, info2 )
808 work(i) = - scale * ( rootsc / dble(m) )
811 work(i) = scale * rootsc
812 CALL dlascl(
'G',0, 0, work(i), one, m, 1, &
826 CALL xerbla(
'DGEDMD',-info)
831 IF ( work(i) > zero )
THEN
832 CALL dscal( m, one/work(i), y(1,i), 1 )
834 ELSE IF ( work(i) < zero )
THEN
835 CALL dlascl(
'G', 0, 0, -work(i), &
836 one/dble(m), m, 1, y(1,i), m, info2 )
837 ELSE IF ( y(idamax(m, y(1,i),1),i ) &
847 IF ( lsame(jobs,
'C')) &
848 CALL dscal( m, zero, y(1,i), 1 )
861 CALL dlassq( m, y(1,i), 1, scale, ssum )
862 IF ( disnan(scale) .OR. disnan(ssum) )
THEN
865 CALL xerbla(
'DGEDMD',-info)
867 IF ( scale /= zero .AND. (ssum /= zero) )
THEN
869 IF ( scale .GE. (ofl / rootsc) )
THEN
880 CALL dlascl(
'G', 0, 0, scale, one/rootsc, &
881 m, 1, y(1,i), m, info2 )
882 work(i) = - scale * ( rootsc / dble(m) )
885 work(i) = scale * rootsc
886 CALL dlascl(
'G',0, 0, work(i), one, m, 1, &
896 IF ( work(i) > zero )
THEN
897 CALL dscal( m, one/work(i), x(1,i), 1 )
899 ELSE IF ( work(i) < zero )
THEN
900 CALL dlascl(
'G', 0, 0, -work(i), &
901 one/dble(m), m, 1, x(1,i), m, info2 )
902 ELSE IF ( x(idamax(m, x(1,i),1),i ) &
920 SELECT CASE ( whtsvd )
922 CALL dgesvd(
'O',
'S', m, n, x, ldx, work, b, &
923 ldb, w, ldw, work(n+1), lwork-n, info1 )
926 CALL dgesdd(
'O', m, n, x, ldx, work, b, ldb, w, &
927 ldw, work(n+1), lwork-n, iwork, info1 )
930 CALL dgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
931 x, ldx, work, z, ldz, w, ldw, &
932 numrnk, iwork, liwork, work(n+max(2,m)+1),&
933 lwork-n-max(2,m), work(n+1), max(2,m), info1)
934 CALL dlacpy(
'A', m, numrnk, z, ldz, x, ldx )
937 CALL dgejsv(
'F',
'U', jsvopt,
'N',
'N',
'P', m, &
938 n, x, ldx, work, z, ldz, w, ldw, &
939 work(n+1), lwork-n, iwork, info1 )
940 CALL dlacpy(
'A', m, n, z, ldz, x, ldx )
944 IF ( xscl1 /= xscl2 )
THEN
951 CALL dlascl(
'G', 0, 0, xscl1, xscl2, m, n, y, ldy, info2
955 IF ( info1 > 0 )
THEN
962 IF ( work(1) == zero )
THEN
968 CALL xerbla(
'DGEDMD',-info)
980 IF ( ( work(i) <= work(1)*tol ) .OR. &
981 ( work(i) <= small ) )
EXIT
987 IF ( ( work(i+1) <= work(i)*tol ) .OR. &
988 ( work(i) <= small ) )
EXIT
994 IF ( work(i) <= small )
EXIT
1009 IF ( lsame(t_or_n,
'N') )
THEN
1011 CALL dscal( n, one/work(i), w(1,i), 1 )
1023 work(n+i) = one/work(i)
1027 w(i,j) = (work(n+i))*w(i,j)
1037 CALL dgemm(
'N', t_or_n, m, k, n, one, y, ldy, w, &
1047 CALL dlacpy(
'A', m, k, z, ldz, b, ldb )
1050 CALL dgemm(
'T',
'N', k, k, m, one, x, ldx, z, &
1058 CALL dgemm(
'T',
'N', k, n, m, one, x, ldx, y, ldy, &
1062 CALL dgemm(
'N', t_or_n, k, k, n, one, z, ldz, w, &
1069 IF ( wntres .OR. wntex )
THEN
1070 IF ( lsame(t_or_n,
'N') )
THEN
1071 CALL dlacpy(
'A', n, k, w, ldw, z, ldz )
1073 CALL dlacpy(
'A', k, n, w, ldw, z, ldz )
1081 CALL dgeev(
'N', jobzl, k, s, lds, reig, imeig, w, &
1082 ldw, w, ldw, work(n+1), lwork-n, info1 )
1097 IF ( info1 > 0 )
THEN
1107 IF ( wntvec .OR. wntex )
THEN
1113 CALL dgemm(
'N',
'N', m, k, k, one, z, ldz, w, &
1120 CALL dgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1121 w, ldw, zero, s, lds)
1125 CALL dgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1129 CALL dlacpy(
'A', m, k, z, ldz, y, ldy )
1130 IF ( wntex )
CALL dlacpy(
'A', m, k, z, ldz, b, ldb )
1132 ELSE IF ( wntex )
THEN
1135 CALL dgemm( t_or_n,
'N', n, k, k, one, z, ldz, &
1136 w, ldw, zero, s, lds )
1140 CALL dgemm(
'N',
'N', m, k, n, one, y, ldy, s, &
1152 IF ( wntvec )
CALL dgemm(
'N',
'N', m, k, k, one, x, ldx, w, ldw,
1159 IF ( imeig(i) == zero )
THEN
1161 CALL daxpy( m, -reig(i), z(1,i), 1, y(1,i), 1 )
1163 res(i) =
dnrm2( m, y(1,i), 1)
1177 CALL dgemm(
'N',
'N', m, 2, 2, -one, z(1,i), &
1178 ldz, ab, 2, one, y(1,i), ldy )
1180 res(i) =
dlange(
'F', m, 2, y(1,i), ldy, &
1189 IF ( whtsvd == 4 )
THEN
1195 IF ( .NOT. badxy )
THEN