Correct bug 0065.
authorjulie <julielangou@users.noreply.github.com>
Mon, 7 Nov 2011 20:19:53 +0000 (20:19 +0000)
committerjulie <julielangou@users.noreply.github.com>
Mon, 7 Nov 2011 20:19:53 +0000 (20:19 +0000)
Replace Workspace calculations by calls to the routines with LWORK=-1.
This impacts only three routines: xGESVD, xGELSS, x[OR/UN]GBR
Testing have been run to check that the workspace size return is the same.

In a further effort (next major release probably), LAPACK will need to stick
to that LWORK=-1 rule to compute Workspace size.

12 files changed:
SRC/cgelss.f
SRC/cgesvd.f
SRC/cungbr.f
SRC/dgelss.f
SRC/dgesvd.f
SRC/dorgbr.f
SRC/sgelss.f
SRC/sgesvd.f
SRC/sorgbr.f
SRC/zgelss.f
SRC/zgesvd.f
SRC/zungbr.f

index 85c4f98..6212208 100644 (file)
       INTEGER            BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
      $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
      $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
+      INTEGER            LWORK_CGEQRF, LWORK_CUNMQR, LWORK_CGEBRD,
+     $                   LWORK_CUNMBR, LWORK_CUNGBR, LWORK_CUNMLQ,
+     $                   LWORK_CGELQF
       REAL               ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
 *     ..
 *     .. Local Arrays ..
-      COMPLEX            VDUM( 1 )
+      COMPLEX            DUM( 1 )
 *     ..
 *     .. External Subroutines ..
       EXTERNAL           CBDSQR, CCOPY, CGEBRD, CGELQF, CGEMM, CGEMV,
 *              Path 1a - overdetermined, with many more rows than
 *                        columns
 *
+*              Compute space needed for CGEQRF
+               CALL CGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, INFO )
+               LWORK_CGEQRF=DUM(1)
+*              Compute space needed for CUNMQR
+               CALL CUNMQR( 'L', 'C', M, NRHS, N, A, LDA, DUM(1), B,
+     $                   LDB, DUM(1), -1, INFO )
+               LWORK_CUNMQR=DUM(1)
                MM = N
                MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'CGEQRF', ' ', M,
      $                       N, -1, -1 ) )
 *
 *              Path 1 - overdetermined or exactly determined
 *
-               MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1,
-     $                       'CGEBRD', ' ', MM, N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'CUNMBR',
-     $                       'QLC', MM, NRHS, N, -1 ) )
-               MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
-     $                       'CUNGBR', 'P', N, N, N, -1 ) )
+*              Compute space needed for CGEBRD
+               CALL CGEBRD( MM, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+               LWORK_CGEBRD=DUM(1)
+*              Compute space needed for CUNMBR
+               CALL CUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, DUM(1),
+     $                B, LDB, DUM(1), -1, INFO )
+               LWORK_CUNMBR=DUM(1)
+*              Compute space needed for CUNGBR
+               CALL CUNGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+               LWORK_CUNGBR=DUM(1)
+*              Compute total workspace needed 
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CGEBRD )
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CUNMBR )
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_CUNGBR )
                MAXWRK = MAX( MAXWRK, N*NRHS )
                MINWRK = 2*N + MAX( NRHS, M )
             END IF
 *                 Path 2a - underdetermined, with many more columns
 *                 than rows
 *
-                  MAXWRK = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + 2*M*ILAENV( 1,
-     $                          'CGEBRD', ' ', M, M, -1, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + NRHS*ILAENV( 1,
-     $                          'CUNMBR', 'QLC', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + ( M - 1 )*ILAENV( 1,
-     $                          'CUNGBR', 'P', M, M, M, -1 ) )
+*                 Compute space needed for CGELQF
+                  CALL CGELQF( M, N, A, LDA, DUM(1), DUM(1),
+     $                -1, INFO )
+                  LWORK_CGELQF=DUM(1)
+*                 Compute space needed for CGEBRD
+                  CALL CGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_CGEBRD=DUM(1)
+*                 Compute space needed for CUNMBR
+                  CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_CUNMBR=DUM(1)
+*                 Compute space needed for CUNGBR
+                  CALL CUNGBR( 'P', M, M, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_CUNGBR=DUM(1)
+*                 Compute space needed for CUNMLQ
+                  CALL CUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, DUM(1),
+     $                 B, LDB, DUM(1), -1, INFO )
+                  LWORK_CUNMLQ=DUM(1)
+*                 Compute total workspace needed 
+                  MAXWRK = M + LWORK_CGELQF
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CGEBRD )
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CUNMBR )
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_CUNGBR )
                   IF( NRHS.GT.1 ) THEN
                      MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
                   ELSE
                      MAXWRK = MAX( MAXWRK, M*M + 2*M )
                   END IF
-                  MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'CUNMLQ',
-     $                          'LC', N, NRHS, M, -1 ) )
+                  MAXWRK = MAX( MAXWRK, M + LWORK_CUNMLQ )
                ELSE
 *
 *                 Path 2 - underdetermined
 *
-                  MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'CGEBRD', ' ', M,
-     $                     N, -1, -1 )
-                  MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'CUNMBR',
-     $                          'QLC', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'CUNGBR',
-     $                          'P', M, N, M, -1 ) )
+*                 Compute space needed for CGEBRD
+                  CALL CGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_CGEBRD=DUM(1)
+*                 Compute space needed for CUNMBR
+                  CALL CUNMBR( 'Q', 'L', 'C', M, NRHS, M, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_CUNMBR=DUM(1)
+*                 Compute space needed for CUNGBR
+                  CALL CUNGBR( 'P', M, N, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_CUNGBR=DUM(1)
+                  MAXWRK = 2*M + LWORK_CGEBRD
+                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_CUNMBR )
+                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_CUNGBR )
                   MAXWRK = MAX( MAXWRK, N*NRHS )
                END IF
             END IF
 *        (CWorkspace: none)
 *        (RWorkspace: need BDSPAC)
 *
-         CALL CBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
+         CALL CBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
      $                1, B, LDB, RWORK( IRWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
 *        (CWorkspace: none)
 *        (RWorkspace: need BDSPAC)
 *
-         CALL CBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
+         CALL CBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
      $                1, B, LDB, RWORK( IRWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
index c1158d6..dc4f8e1 100644 (file)
      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
      $                   NRVT, WRKBL
+      INTEGER            LWORK_CGEQRF, LWORK_CUNGQR_N, LWORK_CUNGQR_M,
+     $                   LWORK_CGEBRD, LWORK_CUNGBR_P, LWORK_CUNGBR_Q,
+     $                   LWORK_CGELQF, LWORK_CUNGLQ_N, LWORK_CUNGLQ_M
       REAL               ANRM, BIGNUM, EPS, SMLNUM
 *     ..
 *     .. Local Arrays ..
          MAXWRK = 1
          IF( M.GE.N .AND. MINMN.GT.0 ) THEN
 *
-*           Space needed for CBDSQR is BDSPAC = 5*N
+*           Space needed for ZBDSQR is BDSPAC = 5*N
+*
+            MNTHR = ILAENV( 6, 'CGESVD', JOBU // JOBVT, M, N, 0, 0 )
+*           Compute space needed for CGEQRF
+            CALL CGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_CGEQRF=DUM(1)
+*           Compute space needed for CUNGQR
+            CALL CUNGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_CUNGQR_N=DUM(1)
+            CALL CUNGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_CUNGQR_M=DUM(1)
+*           Compute space needed for CGEBRD
+            CALL CGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_CGEBRD=DUM(1)
+*           Compute space needed for CUNGBR
+            CALL CUNGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_CUNGBR_P=DUM(1)
+            CALL CUNGBR( 'Q', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_CUNGBR_Q=DUM(1)
 *
             MNTHR = ILAENV( 6, 'CGESVD', JOBU // JOBVT, M, N, 0, 0 )
             IF( M.GE.MNTHR ) THEN
 *
 *                 Path 1 (M much larger than N, JOBU='N')
 *
-                  MAXWRK = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 2*N+2*N*
-     $                     ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
+                  MAXWRK = N + LWORK_CGEQRF
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_CGEBRD )
                   IF( WNTVO .OR. WNTVAS )
-     $               MAXWRK = MAX( MAXWRK, 2*N+( N-1 )*
-     $                        ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 2*N+LWORK_CUNGBR_P )
                   MINWRK = 3*N
                ELSE IF( WNTUO .AND. WNTVN ) THEN
 *
 *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N )
                   MINWRK = 2*N + M
                ELSE IF( WNTUO .AND. WNTVAS ) THEN
 *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_P )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N )
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVN ) THEN
 *
 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVO ) THEN
 *
 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_P )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVAS ) THEN
 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_P )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVN ) THEN
 *
 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVO ) THEN
 *
 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_P )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVAS ) THEN
 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'CGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'CUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'CGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_CGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_CUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_CUNGBR_P )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                END IF
 *
 *              Path 10 (M at least N, but not much larger)
 *
-               MAXWRK = 2*N + ( M+N )*ILAENV( 1, 'CGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTUS .OR. WNTUO )
-     $            MAXWRK = MAX( MAXWRK, 2*N+N*
-     $                     ILAENV( 1, 'CUNGBR', 'Q', M, N, N, -1 ) )
-               IF( WNTUA )
-     $            MAXWRK = MAX( MAXWRK, 2*N+M*
-     $                     ILAENV( 1, 'CUNGBR', 'Q', M, M, N, -1 ) )
-               IF( .NOT.WNTVN )
-     $            MAXWRK = MAX( MAXWRK, 2*N+( N-1 )*
-     $                     ILAENV( 1, 'CUNGBR', 'P', N, N, N, -1 ) )
+               CALL CGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_CGEBRD=DUM(1)
+               MAXWRK = 2*N + LWORK_CGEBRD
+               IF( WNTUS .OR. WNTUO ) THEN
+                  CALL CUNGBR( 'Q', M, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_CUNGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_CUNGBR_Q )
+               END IF
+               IF( WNTUA ) THEN
+                  CALL CUNGBR( 'Q', M, M, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_CUNGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_CUNGBR_Q )
+               END IF
+               IF( .NOT.WNTVN ) THEN
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_CUNGBR_P )
                MINWRK = 2*N + M
+               END IF
             END IF
          ELSE IF( MINMN.GT.0 ) THEN
 *
 *           Space needed for CBDSQR is BDSPAC = 5*M
 *
             MNTHR = ILAENV( 6, 'CGESVD', JOBU // JOBVT, M, N, 0, 0 )
+*           Compute space needed for CGELQF
+            CALL CGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_CGELQF=DUM(1)
+*           Compute space needed for CUNGLQ
+            CALL CUNGLQ( N, N, M, VT, LDVT, DUM(1), DUM(1), -1, IERR )
+            LWORK_CUNGLQ_N=DUM(1)
+            CALL CUNGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_CUNGLQ_M=DUM(1)
+*           Compute space needed for CGEBRD
+            CALL CGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_CGEBRD=DUM(1)
+*            Compute space needed for CUNGBR P
+            CALL CUNGBR( 'P', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_CUNGBR_P=DUM(1)
+*           Compute space needed for CUNGBR Q
+            CALL CUNGBR( 'Q', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_CUNGBR_Q=DUM(1)
             IF( N.GE.MNTHR ) THEN
                IF( WNTVN ) THEN
 *
 *                 Path 1t(N much larger than M, JOBVT='N')
 *
-                  MAXWRK = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 2*M+2*M*
-     $                     ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
+                  MAXWRK = M + LWORK_CGELQF
+                  MAXWRK = MAX( MAXWRK, 2*M+LWORK_CGEBRD )
                   IF( WNTUO .OR. WNTUAS )
-     $               MAXWRK = MAX( MAXWRK, 2*M+M*
-     $                        ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 2*M+LWORK_CUNGBR_Q )
                   MINWRK = 3*M
                ELSE IF( WNTVO .AND. WNTUN ) THEN
 *
 *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'CUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N )
                   MINWRK = 2*M + N
                ELSE IF( WNTVO .AND. WNTUAS ) THEN
 *                 Path 3t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'CUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_Q )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N )
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUN ) THEN
 *
 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'CUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUO ) THEN
 *
 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'CUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_Q )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUAS ) THEN
 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'CUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_Q )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUN ) THEN
 *
 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'CUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUO ) THEN
 *
 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'CUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_Q )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUAS ) THEN
 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'CGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'CUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'CGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'CUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_CGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_CUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_CUNGBR_Q )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                END IF
 *
 *              Path 10t(N greater than M, but not much larger)
 *
-               MAXWRK = 2*M + ( M+N )*ILAENV( 1, 'CGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTVS .OR. WNTVO )
-     $            MAXWRK = MAX( MAXWRK, 2*M+M*
-     $                     ILAENV( 1, 'CUNGBR', 'P', M, N, M, -1 ) )
-               IF( WNTVA )
-     $            MAXWRK = MAX( MAXWRK, 2*M+N*
-     $                     ILAENV( 1, 'CUNGBR', 'P', N, N, M, -1 ) )
-               IF( .NOT.WNTUN )
-     $            MAXWRK = MAX( MAXWRK, 2*M+( M-1 )*
-     $                     ILAENV( 1, 'CUNGBR', 'Q', M, M, M, -1 ) )
+               CALL CGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_CGEBRD=DUM(1)
+               MAXWRK = 2*M + LWORK_CGEBRD
+               IF( WNTVS .OR. WNTVO ) THEN
+*                Compute space needed for CUNGBR P
+                 CALL CUNGBR( 'P', M, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_CUNGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 2*M+LWORK_CUNGBR_P )
+               END IF
+               IF( WNTVA ) THEN
+                 CALL CUNGBR( 'P', N,  N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_CUNGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 2*M+LWORK_CUNGBR_P )
+               END IF
+               IF( .NOT.WNTUN ) THEN
+                  MAXWRK = MAX( MAXWRK, 2*M+LWORK_CUNGBR_Q )
                MINWRK = 2*M + N
+               END IF
             END IF
          END IF
          MAXWRK = MAX( MINWRK, MAXWRK )
index cd76c8e..b516e94 100644 (file)
 *
       IF( INFO.EQ.0 ) THEN
          IF( WANTQ ) THEN
-            NB = ILAENV( 1, 'CUNGQR', ' ', M, N, K, -1 )
+            IF( M.GE.K ) THEN
+               CALL CUNGQR( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL CUNGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          ELSE
-            NB = ILAENV( 1, 'CUNGLQ', ' ', M, N, K, -1 )
+            IF( K.LT.N ) THEN
+               CALL CUNGLQ( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL CUNGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          END IF
-         LWKOPT = MAX( 1, MN )*NB
-         WORK( 1 ) = LWKOPT
+         LWKOPT = WORK( 1 )
       END IF
 *
       IF( INFO.NE.0 ) THEN
index 60aeb8e..3e82b5a 100644 (file)
       INTEGER            BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
      $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
      $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
+      INTEGER            LWORK_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
+     $                   LWORK_DORMBR, LWORK_DORGBR, LWORK_DORMLQ,
+     $                   LWORK_DGELQF
       DOUBLE PRECISION   ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
 *     ..
 *     .. Local Arrays ..
-      DOUBLE PRECISION   VDUM( 1 )
+      DOUBLE PRECISION   DUM( 1 )
 *     ..
 *     .. External Subroutines ..
       EXTERNAL           DBDSQR, DCOPY, DGEBRD, DGELQF, DGEMM, DGEMV,
 *              Path 1a - overdetermined, with many more rows than
 *                        columns
 *
+*              Compute space needed for DGEQRF
+               CALL DGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, INFO )
+               LWORK_DGEQRF=DUM(1)
+*              Compute space needed for DORMQR
+               CALL DORMQR( 'L', 'T', M, NRHS, N, A, LDA, DUM(1), B,
+     $                   LDB, DUM(1), -1, INFO )
+               LWORK_DORMQR=DUM(1)
                MM = N
-               MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'DGEQRF', ' ', M,
-     $                       N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, N + NRHS*ILAENV( 1, 'DORMQR', 'LT',
-     $                       M, NRHS, N, -1 ) )
+               MAXWRK = MAX( MAXWRK, N + LWORK_DGEQRF )
+               MAXWRK = MAX( MAXWRK, N + LWORK_DORMQR )
             END IF
             IF( M.GE.N ) THEN
 *
 *              Compute workspace needed for DBDSQR
 *
                BDSPAC = MAX( 1, 5*N )
-               MAXWRK = MAX( MAXWRK, 3*N + ( MM + N )*ILAENV( 1,
-     $                       'DGEBRD', ' ', MM, N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, 3*N + NRHS*ILAENV( 1, 'DORMBR',
-     $                       'QLT', MM, NRHS, N, -1 ) )
-               MAXWRK = MAX( MAXWRK, 3*N + ( N - 1 )*ILAENV( 1,
-     $                       'DORGBR', 'P', N, N, N, -1 ) )
+*              Compute space needed for DGEBRD
+               CALL DGEBRD( MM, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+               LWORK_DGEBRD=DUM(1)
+*              Compute space needed for DORMBR
+               CALL DORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, DUM(1),
+     $                B, LDB, DUM(1), -1, INFO )
+               LWORK_DORMBR=DUM(1)
+*              Compute space needed for DORGBR
+               CALL DORGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+               LWORK_DORGBR=DUM(1)
+*              Compute total workspace needed 
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_DGEBRD )
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORMBR )
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_DORGBR )
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MAXWRK = MAX( MAXWRK, N*NRHS )
                MINWRK = MAX( 3*N + MM, 3*N + NRHS, BDSPAC )
 *                 Path 2a - underdetermined, with many more columns
 *                 than rows
 *
-                  MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
-     $                                  -1 )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1,
-     $                          'DGEBRD', ' ', M, M, -1, -1 ) )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1,
-     $                          'DORMBR', 'QLT', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M +
-     $                          ( M - 1 )*ILAENV( 1, 'DORGBR', 'P', M,
-     $                          M, M, -1 ) )
+*                 Compute space needed for DGELQF
+                  CALL DGELQF( M, N, A, LDA, DUM(1), DUM(1),
+     $                -1, INFO )
+                  LWORK_DGELQF=DUM(1)
+*                 Compute space needed for DGEBRD
+                  CALL DGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_DGEBRD=DUM(1)
+*                 Compute space needed for DORMBR
+                  CALL DORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_DORMBR=DUM(1)
+*                 Compute space needed for DORGBR
+                  CALL DORGBR( 'P', M, M, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_DORGBR=DUM(1)
+*                 Compute space needed for DORMLQ
+                  CALL DORMLQ( 'L', 'T', N, NRHS, M, A, LDA, DUM(1),
+     $                 B, LDB, DUM(1), -1, INFO )
+                  LWORK_DORMLQ=DUM(1)
+*                 Compute total workspace needed 
+                  MAXWRK = M + LWORK_DGELQF
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_DGEBRD )
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_DORMBR )
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_DORGBR )
                   MAXWRK = MAX( MAXWRK, M*M + M + BDSPAC )
                   IF( NRHS.GT.1 ) THEN
                      MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
                   ELSE
                      MAXWRK = MAX( MAXWRK, M*M + 2*M )
                   END IF
-                  MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'DORMLQ',
-     $                          'LT', N, NRHS, M, -1 ) )
+                  MAXWRK = MAX( MAXWRK, M + LWORK_DORMLQ )
                ELSE
 *
 *                 Path 2 - underdetermined
 *
-                  MAXWRK = 3*M + ( N + M )*ILAENV( 1, 'DGEBRD', ' ', M,
-     $                     N, -1, -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M + NRHS*ILAENV( 1, 'DORMBR',
-     $                          'QLT', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*ILAENV( 1, 'DORGBR',
-     $                          'P', M, N, M, -1 ) )
+*                 Compute space needed for DGEBRD
+                  CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_DGEBRD=DUM(1)
+*                 Compute space needed for DORMBR
+                  CALL DORMBR( 'Q', 'L', 'T', M, NRHS, M, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_DORMBR=DUM(1)
+*                 Compute space needed for DORGBR
+                  CALL DORGBR( 'P', M, N, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_DORGBR=DUM(1)
+                  MAXWRK = 3*M + LWORK_DGEBRD
+                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORMBR )
+                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_DORGBR )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MAXWRK = MAX( MAXWRK, N*NRHS )
                END IF
 *          compute right singular vectors in A
 *        (Workspace: need BDSPAC)
 *
-         CALL DBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
+         CALL DBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, DUM,
      $                1, B, LDB, WORK( IWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
 *           multiplying B by transpose of left singular vectors
 *        (Workspace: need BDSPAC)
 *
-         CALL DBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
+         CALL DBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, DUM,
      $                1, B, LDB, WORK( IWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
index 3ab77a0..84558d1 100644 (file)
 *> \ingroup doubleGEsing
 *
 *  =====================================================================
-      SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
-     $                   WORK, LWORK, INFO )
+      SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU,
+     $                   VT, LDVT, WORK, LWORK, INFO )
 *
 *  -- LAPACK driver routine (version 3.3.1) --
 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
      $                   NRVT, WRKBL
+      INTEGER            LWORK_DGEQRF, LWORK_DORGQR_N, LWORK_DORGQR_M,
+     $                   LWORK_DGEBRD, LWORK_DORGBR_P, LWORK_DORGBR_Q,
+     $                   LWORK_DGELQF, LWORK_DORGLQ_N, LWORK_DORGLQ_M
       DOUBLE PRECISION   ANRM, BIGNUM, EPS, SMLNUM
 *     ..
 *     .. Local Arrays ..
 *
             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
             BDSPAC = 5*N
+*           Compute space needed for DGEQRF
+            CALL DGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_DGEQRF=DUM(1)
+*           Compute space needed for DORGQR
+            CALL DORGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_DORGQR_N=DUM(1)
+            CALL DORGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_DORGQR_M=DUM(1)
+*           Compute space needed for DGEBRD
+            CALL DGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_DGEBRD=DUM(1)
+*           Compute space needed for DORGBR P
+            CALL DORGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_DORGBR_P=DUM(1)
+*           Compute space needed for DORGBR Q
+            CALL DORGBR( 'Q', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_DORGBR_Q=DUM(1)
+*
             IF( M.GE.MNTHR ) THEN
                IF( WNTUN ) THEN
 *
 *                 Path 1 (M much larger than N, JOBU='N')
 *
-                  MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*N+2*N*
-     $                     ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
+                  MAXWRK = N + LWORK_DGEQRF
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_DGEBRD )
                   IF( WNTVO .OR. WNTVAS )
-     $               MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
-     $                        ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_P )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MINWRK = MAX( 4*N, BDSPAC )
                ELSE IF( WNTUO .AND. WNTVN ) THEN
 *
 *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_DGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_DORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *              Path 10 (M at least N, but not much larger)
 *
-               MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTUS .OR. WNTUO )
-     $            MAXWRK = MAX( MAXWRK, 3*N+N*
-     $                     ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) )
-               IF( WNTUA )
-     $            MAXWRK = MAX( MAXWRK, 3*N+M*
-     $                     ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) )
-               IF( .NOT.WNTVN )
-     $            MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
-     $                     ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) )
+               CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_DGEBRD=DUM(1)
+               MAXWRK = 3*N + LWORK_DGEBRD
+               IF( WNTUS .OR. WNTUO ) THEN
+                  CALL DORGBR( 'Q', M, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_DORGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_Q )
+               END IF
+               IF( WNTUA ) THEN
+                  CALL DORGBR( 'Q', M, M, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_DORGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_Q )
+               END IF
+               IF( .NOT.WNTVN ) THEN
+                 MAXWRK = MAX( MAXWRK, 3*N+LWORK_DORGBR_P )
+               END IF
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MINWRK = MAX( 3*N+M, BDSPAC )
             END IF
 *
             MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 )
             BDSPAC = 5*M
+*           Compute space needed for DGELQF
+            CALL DGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_DGELQF=DUM(1)
+*           Compute space needed for DORGLQ
+            CALL DORGLQ( N, N, M, VT, LDVT, DUM(1), DUM(1), -1, IERR )
+            LWORK_DORGLQ_N=DUM(1)
+            CALL DORGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_DORGLQ_M=DUM(1)
+*           Compute space needed for DGEBRD
+            CALL DGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_DGEBRD=DUM(1)
+*            Compute space needed for DORGBR P
+            CALL DORGBR( 'P', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_DORGBR_P=DUM(1)
+*           Compute space needed for DORGBR Q
+            CALL DORGBR( 'Q', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_DORGBR_Q=DUM(1)
             IF( N.GE.MNTHR ) THEN
                IF( WNTVN ) THEN
 *
 *                 Path 1t(N much larger than M, JOBVT='N')
 *
-                  MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M+2*M*
-     $                     ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
+                  MAXWRK = M + LWORK_DGELQF
+                  MAXWRK = MAX( MAXWRK, 3*M+LWORK_DGEBRD )
                   IF( WNTUO .OR. WNTUAS )
-     $               MAXWRK = MAX( MAXWRK, 3*M+M*
-     $                        ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_Q )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MINWRK = MAX( 4*M, BDSPAC )
                ELSE IF( WNTVO .AND. WNTUN ) THEN
 *
 *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 3t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_DGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_DORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_DORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *              Path 10t(N greater than M, but not much larger)
 *
-               MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTVS .OR. WNTVO )
-     $            MAXWRK = MAX( MAXWRK, 3*M+M*
-     $                     ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) )
-               IF( WNTVA )
-     $            MAXWRK = MAX( MAXWRK, 3*M+N*
-     $                     ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) )
-               IF( .NOT.WNTUN )
-     $            MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*
-     $                     ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) )
+               CALL DGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_DGEBRD=DUM(1)
+               MAXWRK = 3*M + LWORK_DGEBRD
+               IF( WNTVS .OR. WNTVO ) THEN
+*                Compute space needed for DORGBR P
+                 CALL DORGBR( 'P', M, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_DORGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_P )
+               END IF
+               IF( WNTVA ) THEN
+                 CALL DORGBR( 'P', N, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_DORGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_P )
+               END IF
+               IF( .NOT.WNTUN ) THEN
+                  MAXWRK = MAX( MAXWRK, 3*M+LWORK_DORGBR_Q )
+               END IF
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MINWRK = MAX( 3*M+N, BDSPAC )
             END IF
index 8cb9344..c6390b9 100644 (file)
 *
       IF( INFO.EQ.0 ) THEN
          IF( WANTQ ) THEN
-            NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 )
+            IF( M.GE.K ) THEN
+               CALL DORGQR( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL DORGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          ELSE
-            NB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 )
+            IF( K.LT.N ) THEN
+               CALL DORGLQ( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL DORGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          END IF
-         LWKOPT = MAX( 1, MN )*NB
-         WORK( 1 ) = LWKOPT
+         LWKOPT = WORK( 1 )
       END IF
 *
       IF( INFO.NE.0 ) THEN
index 1c2c241..322bb82 100644 (file)
       INTEGER            BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
      $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
      $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
+      INTEGER            LWORK_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
+     $                   LWORK_SORMBR, LWORK_SORGBR, LWORK_SORMLQ 
       REAL               ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
 *     ..
 *     .. Local Arrays ..
-      REAL               VDUM( 1 )
+      REAL               DUM( 1 )
 *     ..
 *     .. External Subroutines ..
       EXTERNAL           SBDSQR, SCOPY, SGEBRD, SGELQF, SGEMM, SGEMV,
 *              Path 1a - overdetermined, with many more rows than
 *                        columns
 *
+*              Compute space needed for SGEQRF
+               CALL SGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, INFO )
+               LWORK_SGEQRF=DUM(1)
+*              Compute space needed for SORMQR
+               CALL SORMQR( 'L', 'T', M, NRHS, N, A, LDA, DUM(1), B,
+     $                   LDB, DUM(1), -1, INFO )
+               LWORK_SORMQR=DUM(1)
                MM = N
-               MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'SGEQRF', ' ', M,
-     $                       N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, N + NRHS*ILAENV( 1, 'SORMQR', 'LT',
-     $                       M, NRHS, N, -1 ) )
+               MAXWRK = MAX( MAXWRK, N + LWORK_SGEQRF )
+               MAXWRK = MAX( MAXWRK, N + LWORK_SORMQR )
             END IF
             IF( M.GE.N ) THEN
 *
 *              Compute workspace needed for SBDSQR
 *
                BDSPAC = MAX( 1, 5*N )
-               MAXWRK = MAX( MAXWRK, 3*N + ( MM + N )*ILAENV( 1,
-     $                       'SGEBRD', ' ', MM, N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, 3*N + NRHS*ILAENV( 1, 'SORMBR',
-     $                       'QLT', MM, NRHS, N, -1 ) )
-               MAXWRK = MAX( MAXWRK, 3*N + ( N - 1 )*ILAENV( 1,
-     $                       'SORGBR', 'P', N, N, N, -1 ) )
+*              Compute space needed for SGEBRD
+               CALL SGEBRD( MM, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+               LWORK_SGEBRD=DUM(1)
+*              Compute space needed for SORMBR
+               CALL SORMBR( 'Q', 'L', 'T', MM, NRHS, N, A, LDA, DUM(1),
+     $                B, LDB, DUM(1), -1, INFO )
+               LWORK_SORMBR=DUM(1)
+*              Compute space needed for SORGBR
+               CALL SORGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+               LWORK_SORGBR=DUM(1)
+*              Compute total workspace needed 
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_SGEBRD )
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_SORMBR )
+               MAXWRK = MAX( MAXWRK, 3*N + LWORK_SORGBR )
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MAXWRK = MAX( MAXWRK, N*NRHS )
                MINWRK = MAX( 3*N + MM, 3*N + NRHS, BDSPAC )
 *                 Path 2a - underdetermined, with many more columns
 *                 than rows
 *
+*                 Compute space needed for SGEBRD
+                  CALL SGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_SGEBRD=DUM(1)
+*                 Compute space needed for SORMBR
+                  CALL SORMBR( 'Q', 'L', 'T', M, NRHS, N, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_SORMBR=DUM(1)
+*                 Compute space needed for SORGBR
+                  CALL SORGBR( 'P', M, M, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_SORGBR=DUM(1)
+*                 Compute space needed for SORMLQ
+                  CALL SORMLQ( 'L', 'T', N, NRHS, M, A, LDA, DUM(1),
+     $                 B, LDB, DUM(1), -1, INFO )
+                  LWORK_SORMLQ=DUM(1)
+*                 Compute total workspace needed 
                   MAXWRK = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1,
      $                                  -1 )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M + 2*M*ILAENV( 1,
-     $                          'SGEBRD', ' ', M, M, -1, -1 ) )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M + NRHS*ILAENV( 1,
-     $                          'SORMBR', 'QLT', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, M*M + 4*M +
-     $                          ( M - 1 )*ILAENV( 1, 'SORGBR', 'P', M,
-     $                          M, M, -1 ) )
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SGEBRD )
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORMBR )
+                  MAXWRK = MAX( MAXWRK, M*M + 4*M + LWORK_SORGBR )
                   MAXWRK = MAX( MAXWRK, M*M + M + BDSPAC )
                   IF( NRHS.GT.1 ) THEN
                      MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
                   ELSE
                      MAXWRK = MAX( MAXWRK, M*M + 2*M )
                   END IF
-                  MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'SORMLQ',
-     $                          'LT', N, NRHS, M, -1 ) )
+                  MAXWRK = MAX( MAXWRK, M + LWORK_SORMLQ )
                ELSE
 *
 *                 Path 2 - underdetermined
 *
-                  MAXWRK = 3*M + ( N + M )*ILAENV( 1, 'SGEBRD', ' ', M,
-     $                     N, -1, -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M + NRHS*ILAENV( 1, 'SORMBR',
-     $                          'QLT', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*ILAENV( 1, 'SORGBR',
-     $                          'P', M, N, M, -1 ) )
+*                 Compute space needed for SGEBRD
+                  CALL SGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_SGEBRD=DUM(1)
+*                 Compute space needed for SORMBR
+                  CALL SORMBR( 'Q', 'L', 'T', M, NRHS, M, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_SORMBR=DUM(1)
+*                 Compute space needed for SORGBR
+                  CALL SORGBR( 'P', M, N, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_SORGBR=DUM(1)
+                  MAXWRK = 3*M + LWORK_SGEBRD
+                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORMBR )
+                  MAXWRK = MAX( MAXWRK, 3*M + LWORK_SORGBR )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MAXWRK = MAX( MAXWRK, N*NRHS )
                END IF
 *          compute right singular vectors in A
 *        (Workspace: need BDSPAC)
 *
-         CALL SBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
+         CALL SBDSQR( 'U', N, N, 0, NRHS, S, WORK( IE ), A, LDA, DUM,
      $                1, B, LDB, WORK( IWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
 *           multiplying B by transpose of left singular vectors
 *        (Workspace: need BDSPAC)
 *
-         CALL SBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, VDUM,
+         CALL SBDSQR( 'L', M, N, 0, NRHS, S, WORK( IE ), A, LDA, DUM,
      $                1, B, LDB, WORK( IWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
index 5ef13c2..8a945af 100644 (file)
      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
      $                   NRVT, WRKBL
+      INTEGER            LWORK_SGEQRF, LWORK_SORGQR_N, LWORK_SORGQR_M,
+     $                   LWORK_SGEBRD, LWORK_SORGBR_P, LWORK_SORGBR_Q,
+     $                   LWORK_SGELQF, LWORK_SORGLQ_N, LWORK_SORGLQ_M
       REAL               ANRM, BIGNUM, EPS, SMLNUM
 *     ..
 *     .. Local Arrays ..
 *
             MNTHR = ILAENV( 6, 'SGESVD', JOBU // JOBVT, M, N, 0, 0 )
             BDSPAC = 5*N
+*           Compute space needed for SGEQRF
+            CALL SGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_SGEQRF=DUM(1)
+*           Compute space needed for SORGQR
+            CALL SORGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_SORGQR_N=DUM(1)
+            CALL SORGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_SORGQR_M=DUM(1)
+*           Compute space needed for SGEBRD
+            CALL SGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_SGEBRD=DUM(1)
+*           Compute space needed for SORGBR P
+            CALL SORGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_SORGBR_P=DUM(1)
+*           Compute space needed for SORGBR Q
+            CALL SORGBR( 'Q', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_SORGBR_Q=DUM(1)
+*
             IF( M.GE.MNTHR ) THEN
                IF( WNTUN ) THEN
 *
 *                 Path 1 (M much larger than N, JOBU='N')
 *
-                  MAXWRK = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*N+2*N*
-     $                     ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
+                  MAXWRK = N + LWORK_SGEQRF
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_SGEBRD )
                   IF( WNTVO .OR. WNTVAS )
-     $               MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
-     $                        ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 3*N+LWORK_SORGBR_P )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MINWRK = MAX( 4*N, BDSPAC )
                ELSE IF( WNTUO .AND. WNTVN ) THEN
 *
 *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N )
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_N )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'SORGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+2*N*
-     $                    ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+N*
-     $                    ILAENV( 1, 'SORGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*N+( N-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_SGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_SORGQR_M )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_Q )
+                  WRKBL = MAX( WRKBL, 3*N+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = N*N + WRKBL
                   MINWRK = MAX( 3*N+M, BDSPAC )
 *
 *              Path 10 (M at least N, but not much larger)
 *
-               MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'SGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTUS .OR. WNTUO )
-     $            MAXWRK = MAX( MAXWRK, 3*N+N*
-     $                     ILAENV( 1, 'SORGBR', 'Q', M, N, N, -1 ) )
-               IF( WNTUA )
-     $            MAXWRK = MAX( MAXWRK, 3*N+M*
-     $                     ILAENV( 1, 'SORGBR', 'Q', M, M, N, -1 ) )
-               IF( .NOT.WNTVN )
-     $            MAXWRK = MAX( MAXWRK, 3*N+( N-1 )*
-     $                     ILAENV( 1, 'SORGBR', 'P', N, N, N, -1 ) )
+               CALL SGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_SGEBRD=DUM(1)
+               MAXWRK = 3*N + LWORK_SGEBRD
+               IF( WNTUS .OR. WNTUO ) THEN
+                  CALL SORGBR( 'Q', M, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_SORGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_SORGBR_Q )
+               END IF
+               IF( WNTUA ) THEN
+                  CALL SORGBR( 'Q', M, M, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_SORGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 3*N+LWORK_SORGBR_Q )
+               END IF
+               IF( .NOT.WNTVN ) THEN
+                 MAXWRK = MAX( MAXWRK, 3*N+LWORK_SORGBR_P )
+               END IF
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MINWRK = MAX( 3*N+M, BDSPAC )
             END IF
 *
             MNTHR = ILAENV( 6, 'SGESVD', JOBU // JOBVT, M, N, 0, 0 )
             BDSPAC = 5*M
+*           Compute space needed for SGELQF
+            CALL SGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_SGELQF=DUM(1)
+*           Compute space needed for SORGLQ
+            CALL SORGLQ( N, N, M, VT, LDVT, DUM(1), DUM(1), -1, IERR )
+            LWORK_SORGLQ_N=DUM(1)
+            CALL SORGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_SORGLQ_M=DUM(1)
+*           Compute space needed for SGEBRD
+            CALL SGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_SGEBRD=DUM(1)
+*            Compute space needed for SORGBR P
+            CALL SORGBR( 'P', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_SORGBR_P=DUM(1)
+*           Compute space needed for SORGBR Q
+            CALL SORGBR( 'Q', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_SORGBR_Q=DUM(1)
             IF( N.GE.MNTHR ) THEN
                IF( WNTVN ) THEN
 *
 *                 Path 1t(N much larger than M, JOBVT='N')
 *
-                  MAXWRK = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M+2*M*
-     $                     ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
+                  MAXWRK = M + LWORK_SGELQF
+                  MAXWRK = MAX( MAXWRK, 3*M+LWORK_SGEBRD )
                   IF( WNTUO .OR. WNTUAS )
-     $               MAXWRK = MAX( MAXWRK, 3*M+M*
-     $                        ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 3*M+LWORK_SORGBR_Q )
                   MAXWRK = MAX( MAXWRK, BDSPAC )
                   MINWRK = MAX( 4*M, BDSPAC )
                ELSE IF( WNTVO .AND. WNTUN ) THEN
 *
 *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 3t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M )
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'SORGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_M )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'SORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'SORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'SORGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+2*M*
-     $                    ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+( M-1 )*
-     $                    ILAENV( 1, 'SORGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 3*M+M*
-     $                    ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_SGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_SORGLQ_N )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SGEBRD )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_P )
+                  WRKBL = MAX( WRKBL, 3*M+LWORK_SORGBR_Q )
                   WRKBL = MAX( WRKBL, BDSPAC )
                   MAXWRK = M*M + WRKBL
                   MINWRK = MAX( 3*M+N, BDSPAC )
 *
 *              Path 10t(N greater than M, but not much larger)
 *
-               MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'SGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTVS .OR. WNTVO )
-     $            MAXWRK = MAX( MAXWRK, 3*M+M*
-     $                     ILAENV( 1, 'SORGBR', 'P', M, N, M, -1 ) )
-               IF( WNTVA )
-     $            MAXWRK = MAX( MAXWRK, 3*M+N*
-     $                     ILAENV( 1, 'SORGBR', 'P', N, N, M, -1 ) )
-               IF( .NOT.WNTUN )
-     $            MAXWRK = MAX( MAXWRK, 3*M+( M-1 )*
-     $                     ILAENV( 1, 'SORGBR', 'Q', M, M, M, -1 ) )
+               CALL SGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_SGEBRD=DUM(1)
+               MAXWRK = 3*M + LWORK_SGEBRD
+               IF( WNTVS .OR. WNTVO ) THEN
+*                Compute space needed for SORGBR P
+                 CALL SORGBR( 'P', M, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_SORGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 3*M+LWORK_SORGBR_P )
+               END IF
+               IF( WNTVA ) THEN
+                 CALL SORGBR( 'P', N, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_SORGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 3*M+LWORK_SORGBR_P )
+               END IF
+               IF( .NOT.WNTUN ) THEN
+                  MAXWRK = MAX( MAXWRK, 3*M+LWORK_SORGBR_Q )
+               END IF
                MAXWRK = MAX( MAXWRK, BDSPAC )
                MINWRK = MAX( 3*M+N, BDSPAC )
             END IF
index 8c66ffc..8bb36a3 100644 (file)
 *
       IF( INFO.EQ.0 ) THEN
          IF( WANTQ ) THEN
-            NB = ILAENV( 1, 'SORGQR', ' ', M, N, K, -1 )
+            IF( M.GE.K ) THEN
+               CALL SORGQR( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL SORGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          ELSE
-            NB = ILAENV( 1, 'SORGLQ', ' ', M, N, K, -1 )
+            IF( K.LT.N ) THEN
+               CALL SORGLQ( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL SORGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          END IF
-         LWKOPT = MAX( 1, MN )*NB
-         WORK( 1 ) = LWKOPT
+         LWKOPT = WORK( 1 )
       END IF
 *
       IF( INFO.NE.0 ) THEN
index ca96cac..fed2fe2 100644 (file)
       INTEGER            BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
      $                   ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
      $                   MAXWRK, MINMN, MINWRK, MM, MNTHR
+      INTEGER            LWORK_ZGEQRF, LWORK_ZUNMQR, LWORK_ZGEBRD,
+     $                   LWORK_ZUNMBR, LWORK_ZUNGBR, LWORK_ZUNMLQ,
+     $                   LWORK_ZGELQF
       DOUBLE PRECISION   ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
 *     ..
 *     .. Local Arrays ..
-      COMPLEX*16         VDUM( 1 )
+      COMPLEX*16         DUM( 1 )
 *     ..
 *     .. External Subroutines ..
       EXTERNAL           DLABAD, DLASCL, DLASET, XERBLA, ZBDSQR, ZCOPY,
 *              Path 1a - overdetermined, with many more rows than
 *                        columns
 *
+*              Compute space needed for ZGEQRF
+               CALL ZGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, INFO )
+               LWORK_ZGEQRF=DUM(1)
+*              Compute space needed for ZUNMQR
+               CALL ZUNMQR( 'L', 'C', M, NRHS, N, A, LDA, DUM(1), B,
+     $                   LDB, DUM(1), -1, INFO )
+               LWORK_ZUNMQR=DUM(1)
                MM = N
                MAXWRK = MAX( MAXWRK, N + N*ILAENV( 1, 'ZGEQRF', ' ', M,
      $                       N, -1, -1 ) )
 *
 *              Path 1 - overdetermined or exactly determined
 *
-               MAXWRK = MAX( MAXWRK, 2*N + ( MM + N )*ILAENV( 1,
-     $                       'ZGEBRD', ' ', MM, N, -1, -1 ) )
-               MAXWRK = MAX( MAXWRK, 2*N + NRHS*ILAENV( 1, 'ZUNMBR',
-     $                       'QLC', MM, NRHS, N, -1 ) )
-               MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
-     $                       'ZUNGBR', 'P', N, N, N, -1 ) )
+*              Compute space needed for ZGEBRD
+               CALL ZGEBRD( MM, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+               LWORK_ZGEBRD=DUM(1)
+*              Compute space needed for ZUNMBR
+               CALL ZUNMBR( 'Q', 'L', 'C', MM, NRHS, N, A, LDA, DUM(1),
+     $                B, LDB, DUM(1), -1, INFO )
+               LWORK_ZUNMBR=DUM(1)
+*              Compute space needed for ZUNGBR
+               CALL ZUNGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+               LWORK_ZUNGBR=DUM(1)
+*              Compute total workspace needed 
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_ZGEBRD )
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_ZUNMBR )
+               MAXWRK = MAX( MAXWRK, 2*N + LWORK_ZUNGBR )
                MAXWRK = MAX( MAXWRK, N*NRHS )
                MINWRK = 2*N + MAX( NRHS, M )
             END IF
 *                 Path 2a - underdetermined, with many more columns
 *                 than rows
 *
-                  MAXWRK = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + 2*M*ILAENV( 1,
-     $                          'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + NRHS*ILAENV( 1,
-     $                          'ZUNMBR', 'QLC', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 3*M + M*M + ( M - 1 )*ILAENV( 1,
-     $                          'ZUNGBR', 'P', M, M, M, -1 ) )
+*                 Compute space needed for ZGELQF
+                  CALL ZGELQF( M, N, A, LDA, DUM(1), DUM(1),
+     $                -1, INFO )
+                  LWORK_ZGELQF=DUM(1)
+*                 Compute space needed for ZGEBRD
+                  CALL ZGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_ZGEBRD=DUM(1)
+*                 Compute space needed for ZUNMBR
+                  CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, N, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_ZUNMBR=DUM(1)
+*                 Compute space needed for ZUNGBR
+                  CALL ZUNGBR( 'P', M, M, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_ZUNGBR=DUM(1)
+*                 Compute space needed for ZUNMLQ
+                  CALL ZUNMLQ( 'L', 'C', N, NRHS, M, A, LDA, DUM(1),
+     $                 B, LDB, DUM(1), -1, INFO )
+                  LWORK_ZUNMLQ=DUM(1)
+*                 Compute total workspace needed 
+                  MAXWRK = M + LWORK_ZGELQF
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_ZGEBRD )
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_ZUNMBR )
+                  MAXWRK = MAX( MAXWRK, 3*M + M*M + LWORK_ZUNGBR )
                   IF( NRHS.GT.1 ) THEN
                      MAXWRK = MAX( MAXWRK, M*M + M + M*NRHS )
                   ELSE
                      MAXWRK = MAX( MAXWRK, M*M + 2*M )
                   END IF
-                  MAXWRK = MAX( MAXWRK, M + NRHS*ILAENV( 1, 'ZUNMLQ',
-     $                          'LC', N, NRHS, M, -1 ) )
+                  MAXWRK = MAX( MAXWRK, M + LWORK_ZUNMLQ )
                ELSE
 *
 *                 Path 2 - underdetermined
 *
-                  MAXWRK = 2*M + ( N + M )*ILAENV( 1, 'ZGEBRD', ' ', M,
-     $                     N, -1, -1 )
-                  MAXWRK = MAX( MAXWRK, 2*M + NRHS*ILAENV( 1, 'ZUNMBR',
-     $                          'QLC', M, NRHS, M, -1 ) )
-                  MAXWRK = MAX( MAXWRK, 2*M + M*ILAENV( 1, 'ZUNGBR',
-     $                          'P', M, N, M, -1 ) )
+*                 Compute space needed for ZGEBRD
+                  CALL ZGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                      DUM(1), DUM(1), -1, INFO )
+                  LWORK_ZGEBRD=DUM(1)
+*                 Compute space needed for ZUNMBR
+                  CALL ZUNMBR( 'Q', 'L', 'C', M, NRHS, M, A, LDA, 
+     $                DUM(1), B, LDB, DUM(1), -1, INFO )
+                  LWORK_ZUNMBR=DUM(1)
+*                 Compute space needed for ZUNGBR
+                  CALL ZUNGBR( 'P', M, N, M, A, LDA, DUM(1),
+     $                   DUM(1), -1, INFO )
+                  LWORK_ZUNGBR=DUM(1)
+                  MAXWRK = 2*M + LWORK_ZGEBRD
+                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_ZUNMBR )
+                  MAXWRK = MAX( MAXWRK, 2*M + LWORK_ZUNGBR )
                   MAXWRK = MAX( MAXWRK, N*NRHS )
                END IF
             END IF
 *        (CWorkspace: none)
 *        (RWorkspace: need BDSPAC)
 *
-         CALL ZBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
+         CALL ZBDSQR( 'U', N, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
      $                1, B, LDB, RWORK( IRWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
 *        (CWorkspace: none)
 *        (RWorkspace: need BDSPAC)
 *
-         CALL ZBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, VDUM,
+         CALL ZBDSQR( 'L', M, N, 0, NRHS, S, RWORK( IE ), A, LDA, DUM,
      $                1, B, LDB, RWORK( IRWORK ), INFO )
          IF( INFO.NE.0 )
      $      GO TO 70
index 875345d..7002279 100644 (file)
 *> \ingroup complex16GEsing
 *
 *  =====================================================================
-      SUBROUTINE ZGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT,
-     $                   WORK, LWORK, RWORK, INFO )
+      SUBROUTINE ZGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, 
+     $                   VT, LDVT, WORK, LWORK, RWORK, INFO )
 *
 *  -- LAPACK driver routine (version 3.2) --
 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
      $                   ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU,
      $                   MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU,
      $                   NRVT, WRKBL
+      INTEGER            LWORK_ZGEQRF, LWORK_ZUNGQR_N, LWORK_ZUNGQR_M,
+     $                   LWORK_ZGEBRD, LWORK_ZUNGBR_P, LWORK_ZUNGBR_Q,
+     $                   LWORK_ZGELQF, LWORK_ZUNGLQ_N, LWORK_ZUNGLQ_M
       DOUBLE PRECISION   ANRM, BIGNUM, EPS, SMLNUM
 *     ..
 *     .. Local Arrays ..
 *           Space needed for ZBDSQR is BDSPAC = 5*N
 *
             MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
+*           Compute space needed for ZGEQRF
+            CALL ZGEQRF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZGEQRF=DUM(1)
+*           Compute space needed for ZUNGQR
+            CALL ZUNGQR( M, N, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZUNGQR_N=DUM(1)
+            CALL ZUNGQR( M, M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZUNGQR_M=DUM(1)
+*           Compute space needed for ZGEBRD
+            CALL ZGEBRD( N, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_ZGEBRD=DUM(1)
+*           Compute space needed for ZUNGBR
+            CALL ZUNGBR( 'P', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_ZUNGBR_P=DUM(1)
+            CALL ZUNGBR( 'Q', N, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_ZUNGBR_Q=DUM(1)
+*
             IF( M.GE.MNTHR ) THEN
                IF( WNTUN ) THEN
 *
 *                 Path 1 (M much larger than N, JOBU='N')
 *
-                  MAXWRK = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 2*N+2*N*
-     $                     ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
+                  MAXWRK = N + LWORK_ZGEQRF
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_ZGEBRD )
                   IF( WNTVO .OR. WNTVAS )
-     $               MAXWRK = MAX( MAXWRK, 2*N+( N-1 )*
-     $                        ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 2*N+LWORK_ZUNGBR_P )
                   MINWRK = 3*N
                ELSE IF( WNTUO .AND. WNTVN ) THEN
 *
 *                 Path 2 (M much larger than N, JOBU='O', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N )
                   MINWRK = 2*N + M
                ELSE IF( WNTUO .AND. WNTVAS ) THEN
 *                 Path 3 (M much larger than N, JOBU='O', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_P )
                   MAXWRK = MAX( N*N+WRKBL, N*N+M*N )
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVN ) THEN
 *
 *                 Path 4 (M much larger than N, JOBU='S', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVO ) THEN
 *
 *                 Path 5 (M much larger than N, JOBU='S', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_P )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUS .AND. WNTVAS ) THEN
 *                 Path 6 (M much larger than N, JOBU='S', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_N )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_P )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVN ) THEN
 *
 *                 Path 7 (M much larger than N, JOBU='A', JOBVT='N')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVO ) THEN
 *
 *                 Path 8 (M much larger than N, JOBU='A', JOBVT='O')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_P )
                   MAXWRK = 2*N*N + WRKBL
                   MINWRK = 2*N + M
                ELSE IF( WNTUA .AND. WNTVAS ) THEN
 *                 Path 9 (M much larger than N, JOBU='A', JOBVT='S' or
 *                 'A')
 *
-                  WRKBL = N + N*ILAENV( 1, 'ZGEQRF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'ZUNGQR', ' ', M,
-     $                    M, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+2*N*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', N, N, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+N*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', N, N, N, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*N+( N-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+                  WRKBL = N + LWORK_ZGEQRF
+                  WRKBL = MAX( WRKBL, N+LWORK_ZUNGQR_M )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_Q )
+                  WRKBL = MAX( WRKBL, 2*N+LWORK_ZUNGBR_P )
                   MAXWRK = N*N + WRKBL
                   MINWRK = 2*N + M
                END IF
 *
 *              Path 10 (M at least N, but not much larger)
 *
-               MAXWRK = 2*N + ( M+N )*ILAENV( 1, 'ZGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTUS .OR. WNTUO )
-     $            MAXWRK = MAX( MAXWRK, 2*N+N*
-     $                     ILAENV( 1, 'ZUNGBR', 'Q', M, N, N, -1 ) )
-               IF( WNTUA )
-     $            MAXWRK = MAX( MAXWRK, 2*N+M*
-     $                     ILAENV( 1, 'ZUNGBR', 'Q', M, M, N, -1 ) )
-               IF( .NOT.WNTVN )
-     $            MAXWRK = MAX( MAXWRK, 2*N+( N-1 )*
-     $                     ILAENV( 1, 'ZUNGBR', 'P', N, N, N, -1 ) )
+               CALL ZGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_ZGEBRD=DUM(1)
+               MAXWRK = 2*N + LWORK_ZGEBRD
+               IF( WNTUS .OR. WNTUO ) THEN
+                  CALL ZUNGBR( 'Q', M, N, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_ZUNGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_ZUNGBR_Q )
+               END IF
+               IF( WNTUA ) THEN
+                  CALL ZUNGBR( 'Q', M, M, N, A, LDA, DUM(1),
+     $                   DUM(1), -1, IERR )
+                  LWORK_ZUNGBR_Q=DUM(1)
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_ZUNGBR_Q )
+               END IF
+               IF( .NOT.WNTVN ) THEN
+                  MAXWRK = MAX( MAXWRK, 2*N+LWORK_ZUNGBR_P )
                MINWRK = 2*N + M
+               END IF
             END IF
          ELSE IF( MINMN.GT.0 ) THEN
 *
 *           Space needed for ZBDSQR is BDSPAC = 5*M
 *
             MNTHR = ILAENV( 6, 'ZGESVD', JOBU // JOBVT, M, N, 0, 0 )
+*           Compute space needed for ZGELQF
+            CALL ZGELQF( M, N, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZGELQF=DUM(1)
+*           Compute space needed for ZUNGLQ
+            CALL ZUNGLQ( N, N, M, VT, LDVT, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZUNGLQ_N=DUM(1)
+            CALL ZUNGLQ( M, N, M, A, LDA, DUM(1), DUM(1), -1, IERR )
+            LWORK_ZUNGLQ_M=DUM(1)
+*           Compute space needed for ZGEBRD
+            CALL ZGEBRD( M, M, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+            LWORK_ZGEBRD=DUM(1)
+*            Compute space needed for ZUNGBR P
+            CALL ZUNGBR( 'P', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_ZUNGBR_P=DUM(1)
+*           Compute space needed for ZUNGBR Q
+            CALL ZUNGBR( 'Q', M, M, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+            LWORK_ZUNGBR_Q=DUM(1)
             IF( N.GE.MNTHR ) THEN
                IF( WNTVN ) THEN
 *
 *                 Path 1t(N much larger than M, JOBVT='N')
 *
-                  MAXWRK = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1,
-     $                     -1 )
-                  MAXWRK = MAX( MAXWRK, 2*M+2*M*
-     $                     ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
+                  MAXWRK = M + LWORK_ZGELQF
+                  MAXWRK = MAX( MAXWRK, 2*M+LWORK_ZGEBRD )
                   IF( WNTUO .OR. WNTUAS )
-     $               MAXWRK = MAX( MAXWRK, 2*M+M*
-     $                        ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+     $               MAXWRK = MAX( MAXWRK, 2*M+LWORK_ZUNGBR_Q )
                   MINWRK = 3*M
                ELSE IF( WNTVO .AND. WNTUN ) THEN
 *
 *                 Path 2t(N much larger than M, JOBU='N', JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'ZUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N )
                   MINWRK = 2*M + N
                ELSE IF( WNTVO .AND. WNTUAS ) THEN
 *                 Path 3t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='O')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'ZUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_Q )
                   MAXWRK = MAX( M*M+WRKBL, M*M+M*N )
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUN ) THEN
 *
 *                 Path 4t(N much larger than M, JOBU='N', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'ZUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUO ) THEN
 *
 *                 Path 5t(N much larger than M, JOBU='O', JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'ZUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_Q )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVS .AND. WNTUAS ) THEN
 *                 Path 6t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='S')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'ZUNGLQ', ' ', M,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_M )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_Q )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUN ) THEN
 *
 *                 Path 7t(N much larger than M, JOBU='N', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'ZUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUO ) THEN
 *
 *                 Path 8t(N much larger than M, JOBU='O', JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'ZUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_Q )
                   MAXWRK = 2*M*M + WRKBL
                   MINWRK = 2*M + N
                ELSE IF( WNTVA .AND. WNTUAS ) THEN
 *                 Path 9t(N much larger than M, JOBU='S' or 'A',
 *                 JOBVT='A')
 *
-                  WRKBL = M + M*ILAENV( 1, 'ZGELQF', ' ', M, N, -1, -1 )
-                  WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'ZUNGLQ', ' ', N,
-     $                    N, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+2*M*
-     $                    ILAENV( 1, 'ZGEBRD', ' ', M, M, -1, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+( M-1 )*
-     $                    ILAENV( 1, 'ZUNGBR', 'P', M, M, M, -1 ) )
-                  WRKBL = MAX( WRKBL, 2*M+M*
-     $                    ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+                  WRKBL = M + LWORK_ZGELQF
+                  WRKBL = MAX( WRKBL, M+LWORK_ZUNGLQ_N )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZGEBRD )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_P )
+                  WRKBL = MAX( WRKBL, 2*M+LWORK_ZUNGBR_Q )
                   MAXWRK = M*M + WRKBL
                   MINWRK = 2*M + N
                END IF
 *
 *              Path 10t(N greater than M, but not much larger)
 *
-               MAXWRK = 2*M + ( M+N )*ILAENV( 1, 'ZGEBRD', ' ', M, N,
-     $                  -1, -1 )
-               IF( WNTVS .OR. WNTVO )
-     $            MAXWRK = MAX( MAXWRK, 2*M+M*
-     $                     ILAENV( 1, 'ZUNGBR', 'P', M, N, M, -1 ) )
-               IF( WNTVA )
-     $            MAXWRK = MAX( MAXWRK, 2*M+N*
-     $                     ILAENV( 1, 'ZUNGBR', 'P', N, N, M, -1 ) )
-               IF( .NOT.WNTUN )
-     $            MAXWRK = MAX( MAXWRK, 2*M+( M-1 )*
-     $                     ILAENV( 1, 'ZUNGBR', 'Q', M, M, M, -1 ) )
+               CALL ZGEBRD( M, N, A, LDA, S, DUM(1), DUM(1),
+     $                   DUM(1), DUM(1), -1, IERR )
+               LWORK_ZGEBRD=DUM(1)
+               MAXWRK = 2*M + LWORK_ZGEBRD
+               IF( WNTVS .OR. WNTVO ) THEN
+*                Compute space needed for ZUNGBR P
+                 CALL ZUNGBR( 'P', M, N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_ZUNGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 2*M+LWORK_ZUNGBR_P )
+               END IF
+               IF( WNTVA ) THEN
+                 CALL ZUNGBR( 'P', N,  N, M, A, N, DUM(1),
+     $                   DUM(1), -1, IERR )
+                 LWORK_ZUNGBR_P=DUM(1)
+                 MAXWRK = MAX( MAXWRK, 2*M+LWORK_ZUNGBR_P )
+               END IF
+               IF( .NOT.WNTUN ) THEN
+                  MAXWRK = MAX( MAXWRK, 2*M+LWORK_ZUNGBR_Q )
                MINWRK = 2*M + N
+               END IF
             END IF
          END IF
          MAXWRK = MAX( MAXWRK, MINWRK )
index dd2d9a7..d7d3245 100644 (file)
 *
       IF( INFO.EQ.0 ) THEN
          IF( WANTQ ) THEN
-            NB = ILAENV( 1, 'ZUNGQR', ' ', M, N, K, -1 )
+            IF( M.GE.K ) THEN
+               CALL ZUNGQR( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL ZUNGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          ELSE
-            NB = ILAENV( 1, 'ZUNGLQ', ' ', M, N, K, -1 )
+            IF( K.LT.N ) THEN
+               CALL ZUNGLQ( M, N, K, A, LDA, TAU, WORK, -1, IINFO )
+            ELSE
+               CALL ZUNGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK,
+     $                      -1, IINFO )
+            END IF
          END IF
-         LWKOPT = MAX( 1, MN )*NB
-         WORK( 1 ) = LWKOPT
+         LWKOPT = WORK( 1 )
       END IF
 *
       IF( INFO.NE.0 ) THEN