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