496 SUBROUTINE cgedmd( JOBS, JOBZ, JOBR, JOBF, WHTSVD, &
497 M, N, X, LDX, Y, LDY, NRNK, TOL, &
498 K, EIGS, Z, LDZ, RES, B, LDB, &
499 W, LDW, S, LDS, ZWORK, LZWORK, &
500 RWORK, LRWORK, IWORK, LIWORK, INFO )
509 use,
INTRINSIC :: iso_fortran_env, only: real32
511 INTEGER,
PARAMETER :: WP = real32
515 CHARACTER,
INTENT(IN) :: JOBS, JOBZ, JOBR, JOBF
516 INTEGER,
INTENT(IN) :: WHTSVD, M, N, LDX, LDY, &
517 NRNK, LDZ, LDB, LDW, LDS, &
518 LIWORK, LRWORK, LZWORK
519 INTEGER,
INTENT(OUT) :: K, INFO
520 REAL(KIND=wp),
INTENT(IN) :: tol
524 COMPLEX(KIND=WP),
INTENT(INOUT) :: X(LDX,*), Y(LDY,*)
525 COMPLEX(KIND=WP),
INTENT(OUT) :: Z(LDZ,*), B(LDB,*), &
527 COMPLEX(KIND=WP),
INTENT(OUT) :: EIGS(*)
528 COMPLEX(KIND=WP),
INTENT(OUT) :: ZWORK(*)
529 REAL(KIND=wp),
INTENT(OUT) :: res(*)
530 REAL(KIND=wp),
INTENT(OUT) :: rwork(*)
531 INTEGER,
INTENT(OUT) :: IWORK(*)
535 REAL(KIND=wp),
PARAMETER :: one = 1.0_wp
536 REAL(KIND=wp),
PARAMETER :: zero = 0.0_wp
537 COMPLEX(KIND=WP),
PARAMETER :: ZONE = ( 1.0_wp, 0.0_wp )
538 COMPLEX(KIND=WP),
PARAMETER :: ZZERO = ( 0.0_wp, 0.0_wp )
542 REAL(KIND=wp) :: ofl, rootsc, scale, small, &
544 INTEGER :: i, j, IMINWR, INFO1, INFO2, &
545 LWRKEV, LWRSDD, LWRSVD, LWRSVJ, &
546 lwrsvq, mlwork, mwrkev, mwrsdd, &
547 mwrsvd, mwrsvj, mwrsvq, numrnk, &
549 LOGICAL :: BADXY, LQUERY, SCCOLX, SCCOLY, &
550 wntex, wntref, wntres, wntvec
551 CHARACTER :: JOBZL, T_OR_N
556 REAL(KIND=wp) :: rdummy(2)
563 LOGICAL SISNAN, LSAME
564 EXTERNAL sisnan, lsame
574 INTRINSIC float, int, max, sqrt
579 wntres = lsame(jobr,
'R')
580 sccolx = lsame(jobs,
'S') .OR. lsame(jobs,
'C')
581 sccoly = lsame(jobs,
'Y')
582 wntvec = lsame(jobz,
'V')
583 wntref = lsame(jobf,
'R')
584 wntex = lsame(jobf,
'E')
586 lquery = ( ( lzwork == -1 ) .OR. ( liwork == -1 ) &
587 .OR. ( lrwork == -1 ) )
589 IF ( .NOT. (sccolx .OR. sccoly .OR. &
590 lsame(jobs,
'N')) )
THEN
592 ELSE IF ( .NOT. (wntvec .OR. lsame(jobz,
'N') &
593 .OR. lsame(jobz,
'F')) )
THEN
595 ELSE IF ( .NOT. (wntres .OR. lsame(jobr,
'N')) .OR. &
596 ( wntres .AND. (.NOT.wntvec) ) )
THEN
598 ELSE IF ( .NOT. (wntref .OR. wntex .OR. &
599 lsame(jobf,
'N') ) )
THEN
601 ELSE IF ( .NOT.((whtsvd == 1) .OR. (whtsvd == 2) .OR. &
602 (whtsvd == 3) .OR. (whtsvd == 4) ))
THEN
604 ELSE IF ( m < 0 )
THEN
606 ELSE IF ( ( n < 0 ) .OR. ( n > m ) )
THEN
608 ELSE IF ( ldx < m )
THEN
610 ELSE IF ( ldy < m )
THEN
612 ELSE IF ( .NOT. (( nrnk == -2).OR.(nrnk == -1).OR. &
613 ((nrnk >= 1).AND.(nrnk <=n ))) )
THEN
615 ELSE IF ( ( tol < zero ) .OR. ( tol >= one ) )
THEN
617 ELSE IF ( ldz < m )
THEN
619 ELSE IF ( (wntref .OR. wntex ) .AND. ( ldb < m ) )
THEN
621 ELSE IF ( ldw < n )
THEN
623 ELSE IF ( lds < n )
THEN
627 IF ( info == 0 )
THEN
653 SELECT CASE ( whtsvd )
658 mwrsvd = max(1,2*min(m,n)+max(m,n))
659 mlwork = max(mlwork,mwrsvd)
660 mlrwrk = max(mlrwrk,n + 5*min(m,n))
662 CALL cgesvd(
'O',
'S', m, n, x, ldx, rwork, &
663 b, ldb, w, ldw, zwork, -1, rdummy, info1 )
664 lwrsvd = int( zwork(1) )
665 olwork = max(olwork,lwrsvd)
675 mwrsdd = 2*min(m,n)*min(m,n)+2*min(m,n)+max(m,n)
676 mlwork = max(mlwork,mwrsdd)
678 mlrwrk = max( mlrwrk, n + &
679 max( 5*min(m,n)*min(m,n)+7*min(m,n), &
680 5*min(m,n)*min(m,n)+5*min(m,n), &
681 2*max(m,n)*min(m,n)+ &
682 2*min(m,n)*min(m,n)+min(m,n) ) )
684 CALL cgesdd(
'O', m, n, x, ldx, rwork, b, &
685 ldb, w, ldw, zwork, -1, rdummy, iwork, info1 )
686 lwrsdd = max(mwrsdd,int( zwork(1) ))
687 olwork = max(olwork,lwrsdd)
690 CALL cgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
691 x, ldx, rwork, z, ldz, w, ldw, numrnk, &
692 iwork, -1, zwork, -1, rdummy, -1, info1 )
694 mwrsvq = int(zwork(2))
695 mlwork = max(mlwork,mwrsvq)
696 mlrwrk = max(mlrwrk,n + int(rdummy(1)))
698 lwrsvq = int(zwork(1))
699 olwork = max(olwork,lwrsvq)
703 CALL cgejsv(
'F',
'U', jsvopt,
'N',
'N',
'P', m, &
704 n, x, ldx, rwork, z, ldz, w, ldw, &
705 zwork, -1, rdummy, -1, iwork, info1 )
707 mwrsvj = int(zwork(2))
708 mlwork = max(mlwork,mwrsvj)
709 mlrwrk = max(mlrwrk,n + max(7,int(rdummy(1))))
711 lwrsvj = int(zwork(1))
712 olwork = max(olwork,lwrsvj)
715 IF ( wntvec .OR. wntex .OR. lsame(jobz,
'F') )
THEN
721 mwrkev = max( 1, 2*n )
722 mlwork = max(mlwork,mwrkev)
723 mlrwrk = max(mlrwrk,n+2*n)
725 CALL cgeev(
'N', jobzl, n, s, lds, eigs, &
726 w, ldw, w, ldw, zwork, -1, rwork, info1 )
727 lwrkev = int(zwork(1))
728 olwork = max( olwork, lwrkev )
729 olwork = max( 2, olwork )
732 IF ( liwork < iminwr .AND. (.NOT.lquery) ) info = -30
733 IF ( lrwork < mlrwrk .AND. (.NOT.lquery) ) info = -28
734 IF ( lzwork < mlwork .AND. (.NOT.lquery) ) info = -26
739 CALL xerbla(
'CGEDMD', -info )
741 ELSE IF ( lquery )
THEN
744 rwork(1) = real(mlrwrk)
745 zwork(1) = cmplx(mlwork)
746 zwork(2) = cmplx(olwork)
766 CALL classq( m, x(1,i), 1, scale, ssum )
767 IF ( sisnan(scale) .OR. sisnan(ssum) )
THEN
770 CALL xerbla(
'CGEDMD',-info)
772 IF ( (scale /= zero) .AND. (ssum /= zero) )
THEN
774 IF ( scale .GE. (ofl / rootsc) )
THEN
785 CALL clascl(
'G', 0, 0, scale, one/rootsc, &
786 m, 1, x(1,i), ldx, info2 )
787 rwork(i) = - scale * ( rootsc / float(m) )
790 rwork(i) = scale * rootsc
791 CALL clascl(
'G',0, 0, rwork(i), one, m, 1, &
805 CALL xerbla(
'CGEDMD',-info)
810 IF ( rwork(i) > zero )
THEN
811 CALL csscal( m, one/rwork(i), y(1,i), 1 )
813 ELSE IF ( rwork(i) < zero )
THEN
814 CALL clascl(
'G', 0, 0, -rwork(i), &
815 one/float(m), m, 1, y(1,i), ldy, info2 )
816 ELSE IF ( abs(y(icamax(m, y(1,i),1),i )) &
826 IF ( lsame(jobs,
'C')) &
827 CALL csscal( m, zero, y(1,i), 1 )
840 CALL classq( m, y(1,i), 1, scale, ssum )
841 IF ( sisnan(scale) .OR. sisnan(ssum) )
THEN
844 CALL xerbla(
'CGEDMD',-info)
846 IF ( scale /= zero .AND. (ssum /= zero) )
THEN
848 IF ( scale .GE. (ofl / rootsc) )
THEN
859 CALL clascl(
'G', 0, 0, scale, one/rootsc, &
860 m, 1, y(1,i), ldy, info2 )
861 rwork(i) = - scale * ( rootsc / float(m) )
864 rwork(i) = scale * rootsc
865 CALL clascl(
'G',0, 0, rwork(i), one, m, 1, &
875 IF ( rwork(i) > zero )
THEN
876 CALL csscal( m, one/rwork(i), x(1,i), 1 )
878 ELSE IF ( rwork(i) < zero )
THEN
879 CALL clascl(
'G', 0, 0, -rwork(i), &
880 one/float(m), m, 1, x(1,i), ldx, info2 )
881 ELSE IF ( abs(x(icamax(m, x(1,i),1),i )) &
899 SELECT CASE ( whtsvd )
901 CALL cgesvd(
'O',
'S', m, n, x, ldx, rwork, b, &
902 ldb, w, ldw, zwork, lzwork, rwork(n+1), info1 )
905 CALL cgesdd(
'O', m, n, x, ldx, rwork, b, ldb, w, &
906 ldw, zwork, lzwork, rwork(n+1), iwork, info1 )
909 CALL cgesvdq(
'H',
'P',
'N',
'R',
'R', m, n, &
910 x, ldx, rwork, z, ldz, w, ldw, &
911 numrnk, iwork, liwork, zwork, &
912 lzwork, rwork(n+1), lrwork-n, info1)
913 CALL clacpy(
'A', m, numrnk, z, ldz, x, ldx )
916 CALL cgejsv(
'F',
'U', jsvopt,
'N',
'N',
'P', m, &
917 n, x, ldx, rwork, z, ldz, w, ldw, &
918 zwork, lzwork, rwork(n+1), lrwork-n, iwork, info1 )
919 CALL clacpy(
'A', m, n, z, ldz, x, ldx )
923 IF ( xscl1 /= xscl2 )
THEN
930 CALL clascl(
'G', 0, 0, xscl1, xscl2, m, n, y, ldy, info2
934 IF ( info1 > 0 )
THEN
941 IF ( rwork(1) == zero )
THEN
947 CALL xerbla(
'CGEDMD',-info)
959 IF ( ( rwork(i) <= rwork(1)*tol ) .OR. &
960 ( rwork(i) <= small ) )
EXIT
966 IF ( ( rwork(i+1) <= rwork(i)*tol ) .OR. &
967 ( rwork(i) <= small ) )
EXIT
973 IF ( rwork(i) <= small )
EXIT
988 IF ( lsame(t_or_n,
'N') )
THEN
990 CALL csscal( n, one/rwork(i), w(1,i), 1 )
1002 rwork(n+i) = one/rwork(i)
1006 w(i,j) = cmplx(rwork(n+i),zero,kind=wp)*w(i,j)
1016 CALL cgemm(
'N', t_or_n, m, k, n, zone, y, ldy, w, &
1017 ldw, zzero, z, ldz )
1026 CALL clacpy(
'A', m, k, z, ldz, b, ldb )
1029 CALL cgemm(
'C',
'N', k, k, m, zone, x, ldx, z, &
1030 ldz, zzero, s, lds )
1037 CALL cgemm(
'C',
'N', k, n, m, zone, x, ldx, y, ldy, &
1041 CALL cgemm(
'N', t_or_n, k, k, n, zone, z, ldz, w, &
1042 ldw, zzero, s, lds )
1048 IF ( wntres .OR. wntex )
THEN
1049 IF ( lsame(t_or_n,
'N') )
THEN
1050 CALL clacpy(
'A', n, k, w, ldw, z, ldz )
1052 CALL clacpy(
'A', k, n, w, ldw, z, ldz )
1060 CALL cgeev(
'N', jobzl, k, s, lds, eigs, w, &
1061 ldw, w, ldw, zwork, lzwork, rwork(n+1), info1 )
1066 IF ( info1 > 0 )
THEN
1076 IF ( wntvec .OR. wntex )
THEN
1082 CALL cgemm(
'N',
'N', m, k, k, zone, z, ldz, w, &
1083 ldw, zzero, y, ldy )
1089 CALL cgemm( t_or_n,
'N', n, k, k, zone, z, ldz, &
1090 w, ldw, zzero, s, lds)
1094 CALL cgemm(
'N',
'N', m, k, n, zone, y, ldy, s, &
1098 CALL clacpy(
'A', m, k, z, ldz, y, ldy )
1099 IF ( wntex )
CALL clacpy(
'A', m, k, z, ldz, b, ldb )
1101 ELSE IF ( wntex )
THEN
1104 CALL cgemm( t_or_n,
'N', n, k, k, zone, z, ldz, &
1105 w, ldw, zzero, s, lds)
1109 CALL cgemm(
'N',
'N', m, k, n, zone, y, ldy, s, &
1121 IF ( wntvec )
CALL cgemm(
'N',
'N', m, k, k, zone, x, ldx, w, ldw
1127 CALL caxpy( m, -eigs(i), z(1,i), 1, y(1,i), 1 )
1129 res(i) =
scnrm2( m, y(1,i), 1)
1134 IF ( whtsvd == 4 )
THEN
1140 IF ( .NOT. badxy )
THEN