1 *> \brief <b> SGESVDX computes the singular value decomposition (SVD) for GE matrices</b>
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SGESVDX + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgesvdx.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgesvdx.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesvdx.f">
21 * SUBROUTINE SGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
22 * $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
23 * $ LWORK, IWORK, INFO )
26 * .. Scalar Arguments ..
27 * CHARACTER JOBU, JOBVT, RANGE
28 * INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
31 * .. Array Arguments ..
33 * REAL A( LDA, * ), S( * ), U( LDU, * ),
34 * $ VT( LDVT, * ), WORK( * )
43 *> SGESVDX computes the singular value decomposition (SVD) of a real
44 *> M-by-N matrix A, optionally computing the left and/or right singular
45 *> vectors. The SVD is written
47 *> A = U * SIGMA * transpose(V)
49 *> where SIGMA is an M-by-N matrix which is zero except for its
50 *> min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
51 *> V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
52 *> are the singular values of A; they are real and non-negative, and
53 *> are returned in descending order. The first min(m,n) columns of
54 *> U and V are the left and right singular vectors of A.
56 *> SGESVDX uses an eigenvalue problem for obtaining the SVD, which
57 *> allows for the computation of a subset of singular values and
58 *> vectors. See SBDSVDX for details.
60 *> Note that the routine returns V**T, not V.
68 *> JOBU is CHARACTER*1
69 *> Specifies options for computing all or part of the matrix U:
70 *> = 'V': the first min(m,n) columns of U (the left singular
71 *> vectors) or as specified by RANGE are returned in
73 *> = 'N': no columns of U (no left singular vectors) are
79 *> JOBVT is CHARACTER*1
80 *> Specifies options for computing all or part of the matrix
82 *> = 'V': the first min(m,n) rows of V**T (the right singular
83 *> vectors) or as specified by RANGE are returned in
85 *> = 'N': no rows of V**T (no right singular vectors) are
91 *> RANGE is CHARACTER*1
92 *> = 'A': all singular values will be found.
93 *> = 'V': all singular values in the half-open interval (VL,VU]
95 *> = 'I': the IL-th through IU-th singular values will be found.
101 *> The number of rows of the input matrix A. M >= 0.
107 *> The number of columns of the input matrix A. N >= 0.
112 *> A is REAL array, dimension (LDA,N)
113 *> On entry, the M-by-N matrix A.
114 *> On exit, the contents of A are destroyed.
120 *> The leading dimension of the array A. LDA >= max(1,M).
126 *> If RANGE='V', the lower bound of the interval to
127 *> be searched for singular values. VU > VL.
128 *> Not referenced if RANGE = 'A' or 'I'.
134 *> If RANGE='V', the upper bound of the interval to
135 *> be searched for singular values. VU > VL.
136 *> Not referenced if RANGE = 'A' or 'I'.
142 *> If RANGE='I', the index of the
143 *> smallest singular value to be returned.
144 *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
145 *> Not referenced if RANGE = 'A' or 'V'.
151 *> If RANGE='I', the index of the
152 *> largest singular value to be returned.
153 *> 1 <= IL <= IU <= min(M,N), if min(M,N) > 0.
154 *> Not referenced if RANGE = 'A' or 'V'.
160 *> The total number of singular values found,
161 *> 0 <= NS <= min(M,N).
162 *> If RANGE = 'A', NS = min(M,N); if RANGE = 'I', NS = IU-IL+1.
167 *> S is REAL array, dimension (min(M,N))
168 *> The singular values of A, sorted so that S(i) >= S(i+1).
173 *> U is REAL array, dimension (LDU,UCOL)
174 *> If JOBU = 'V', U contains columns of U (the left singular
175 *> vectors, stored columnwise) as specified by RANGE; if
176 *> JOBU = 'N', U is not referenced.
177 *> Note: The user must ensure that UCOL >= NS; if RANGE = 'V',
178 *> the exact value of NS is not known in advance and an upper
179 *> bound must be used.
185 *> The leading dimension of the array U. LDU >= 1; if
186 *> JOBU = 'V', LDU >= M.
191 *> VT is REAL array, dimension (LDVT,N)
192 *> If JOBVT = 'V', VT contains the rows of V**T (the right singular
193 *> vectors, stored rowwise) as specified by RANGE; if JOBVT = 'N',
194 *> VT is not referenced.
195 *> Note: The user must ensure that LDVT >= NS; if RANGE = 'V',
196 *> the exact value of NS is not known in advance and an upper
197 *> bound must be used.
203 *> The leading dimension of the array VT. LDVT >= 1; if
204 *> JOBVT = 'V', LDVT >= NS (see above).
209 *> WORK is REAL array, dimension (MAX(1,LWORK))
210 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
216 *> The dimension of the array WORK.
217 *> LWORK >= MAX(1,MIN(M,N)*(MIN(M,N)+4)) for the paths (see
218 *> comments inside the code):
219 *> - PATH 1 (M much larger than N)
220 *> - PATH 1t (N much larger than M)
221 *> LWORK >= MAX(1,MIN(M,N)*2+MAX(M,N)) for the other paths.
222 *> For good performance, LWORK should generally be larger.
224 *> If LWORK = -1, then a workspace query is assumed; the routine
225 *> only calculates the optimal size of the WORK array, returns
226 *> this value as the first entry of the WORK array, and no error
227 *> message related to LWORK is issued by XERBLA.
232 *> IWORK is INTEGER array, dimension (12*MIN(M,N))
233 *> If INFO = 0, the first NS elements of IWORK are zero. If INFO > 0,
234 *> then IWORK contains the indices of the eigenvectors that failed
235 *> to converge in SBDSVDX/SSTEVX.
241 *> = 0: successful exit
242 *> < 0: if INFO = -i, the i-th argument had an illegal value
243 *> > 0: if INFO = i, then i eigenvectors failed to converge
244 *> in SBDSVDX/SSTEVX.
245 *> if INFO = N*2 + 1, an internal error occurred in
252 *> \author Univ. of Tennessee
253 *> \author Univ. of California Berkeley
254 *> \author Univ. of Colorado Denver
259 *> \ingroup realGEsing
261 * =====================================================================
262 SUBROUTINE SGESVDX( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
263 $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
264 $ LWORK, IWORK, INFO )
266 * -- LAPACK driver routine (version 3.6.1) --
267 * -- LAPACK is a software package provided by Univ. of Tennessee, --
268 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
271 * .. Scalar Arguments ..
272 CHARACTER JOBU, JOBVT, RANGE
273 INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
276 * .. Array Arguments ..
278 REAL A( LDA, * ), S( * ), U( LDU, * ),
279 $ VT( LDVT, * ), WORK( * )
282 * =====================================================================
286 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 )
288 * .. Local Scalars ..
289 CHARACTER JOBZ, RNGTGK
290 LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
291 INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
292 $ ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
293 $ J, MAXWRK, MINMN, MINWRK, MNTHR
294 REAL ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
299 * .. External Subroutines ..
300 EXTERNAL SBDSVDX, SGEBRD, SGELQF, SGEQRF, SLACPY,
301 $ SLASCL, SLASET, SORMBR, SORMLQ, SORMQR,
304 * .. External Functions ..
308 EXTERNAL LSAME, ILAENV, SLAMCH, SLANGE
310 * .. Intrinsic Functions ..
311 INTRINSIC MAX, MIN, SQRT
313 * .. Executable Statements ..
315 * Test the input arguments.
319 ABSTOL = 2*SLAMCH('S')
320 LQUERY = ( LWORK.EQ.-1 )
323 WANTU = LSAME( JOBU, 'V' )
324 WANTVT = LSAME( JOBVT, 'V' )
325 IF( WANTU .OR. WANTVT ) THEN
330 ALLS = LSAME( RANGE, 'A' )
331 VALS = LSAME( RANGE, 'V' )
332 INDS = LSAME( RANGE, 'I' )
335 IF( .NOT.LSAME( JOBU, 'V' ) .AND.
336 $ .NOT.LSAME( JOBU, 'N' ) ) THEN
338 ELSE IF( .NOT.LSAME( JOBVT, 'V' ) .AND.
339 $ .NOT.LSAME( JOBVT, 'N' ) ) THEN
341 ELSE IF( .NOT.( ALLS .OR. VALS .OR. INDS ) ) THEN
343 ELSE IF( M.LT.0 ) THEN
345 ELSE IF( N.LT.0 ) THEN
347 ELSE IF( M.GT.LDA ) THEN
349 ELSE IF( MINMN.GT.0 ) THEN
351 IF( VL.LT.ZERO ) THEN
353 ELSE IF( VU.LE.VL ) THEN
357 IF( IL.LT.1 .OR. IL.GT.MAX( 1, MINMN ) ) THEN
359 ELSE IF( IU.LT.MIN( MINMN, IL ) .OR. IU.GT.MINMN ) THEN
364 IF( WANTU .AND. LDU.LT.M ) THEN
366 ELSE IF( WANTVT ) THEN
368 IF( LDVT.LT.IU-IL+1 ) THEN
371 ELSE IF( LDVT.LT.MINMN ) THEN
379 * (Note: Comments in the code beginning "Workspace:" describe the
380 * minimal amount of workspace needed at that point in the code,
381 * as well as the preferred amount for good performance.
382 * NB refers to the optimal block size for the immediately
383 * following subroutine, as returned by ILAENV.)
388 IF( MINMN.GT.0 ) THEN
390 MNTHR = ILAENV( 6, 'SGESVD', JOBU // JOBVT, M, N, 0, 0 )
391 IF( M.GE.MNTHR ) THEN
393 * Path 1 (M much larger than N)
396 $ N*ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
397 MAXWRK = MAX( MAXWRK, N*(N+5) + 2*N*
398 $ ILAENV( 1, 'SGEBRD', ' ', N, N, -1, -1 ) )
400 MAXWRK = MAX(MAXWRK,N*(N*3+6)+N*
401 $ ILAENV( 1, 'SORMQR', ' ', N, N, -1, -1 ) )
404 MAXWRK = MAX(MAXWRK,N*(N*3+6)+N*
405 $ ILAENV( 1, 'SORMLQ', ' ', N, N, -1, -1 ) )
410 * Path 2 (M at least N, but not much larger)
412 MAXWRK = 4*N + ( M+N )*
413 $ ILAENV( 1, 'SGEBRD', ' ', M, N, -1, -1 )
415 MAXWRK = MAX(MAXWRK,N*(N*2+5)+N*
416 $ ILAENV( 1, 'SORMQR', ' ', N, N, -1, -1 ) )
419 MAXWRK = MAX(MAXWRK,N*(N*2+5)+N*
420 $ ILAENV( 1, 'SORMLQ', ' ', N, N, -1, -1 ) )
422 MINWRK = MAX(N*(N*2+19),4*N+M)
425 MNTHR = ILAENV( 6, 'SGESVD', JOBU // JOBVT, M, N, 0, 0 )
426 IF( N.GE.MNTHR ) THEN
428 * Path 1t (N much larger than M)
431 $ M*ILAENV( 1, 'SGELQF', ' ', M, N, -1, -1 )
432 MAXWRK = MAX( MAXWRK, M*(M+5) + 2*M*
433 $ ILAENV( 1, 'SGEBRD', ' ', M, M, -1, -1 ) )
435 MAXWRK = MAX(MAXWRK,M*(M*3+6)+M*
436 $ ILAENV( 1, 'SORMQR', ' ', M, M, -1, -1 ) )
439 MAXWRK = MAX(MAXWRK,M*(M*3+6)+M*
440 $ ILAENV( 1, 'SORMLQ', ' ', M, M, -1, -1 ) )
445 * Path 2t (N at least M, but not much larger)
447 MAXWRK = 4*M + ( M+N )*
448 $ ILAENV( 1, 'SGEBRD', ' ', M, N, -1, -1 )
450 MAXWRK = MAX(MAXWRK,M*(M*2+5)+M*
451 $ ILAENV( 1, 'SORMQR', ' ', M, M, -1, -1 ) )
454 MAXWRK = MAX(MAXWRK,M*(M*2+5)+M*
455 $ ILAENV( 1, 'SORMLQ', ' ', M, M, -1, -1 ) )
457 MINWRK = MAX(M*(M*2+19),4*M+N)
461 MAXWRK = MAX( MAXWRK, MINWRK )
462 WORK( 1 ) = REAL( MAXWRK )
464 IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
470 CALL XERBLA( 'SGESVDX', -INFO )
472 ELSE IF( LQUERY ) THEN
476 * Quick return if possible
478 IF( M.EQ.0 .OR. N.EQ.0 ) THEN
482 * Set singular values indices accord to RANGE.
498 * Get machine constants
501 SMLNUM = SQRT( SLAMCH( 'S' ) ) / EPS
502 BIGNUM = ONE / SMLNUM
504 * Scale A if max element outside range [SMLNUM,BIGNUM]
506 ANRM = SLANGE( 'M', M, N, A, LDA, DUM )
508 IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
510 CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
511 ELSE IF( ANRM.GT.BIGNUM ) THEN
513 CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
518 * A has at least as many rows as columns. If A has sufficiently
519 * more rows than columns, first reduce A using the QR
522 IF( M.GE.MNTHR ) THEN
524 * Path 1 (M much larger than N):
525 * A = Q * R = Q * ( QB * B * PB**T )
526 * = Q * ( QB * ( UB * S * VB**T ) * PB**T )
527 * U = Q * QB * UB; V**T = VB**T * PB**T
530 * (Workspace: need 2*N, prefer N+N*NB)
534 CALL SGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
535 $ LWORK-ITEMP+1, INFO )
537 * Copy R into WORK and bidiagonalize it:
538 * (Workspace: need N*N+5*N, prefer N*N+4*N+2*N*NB)
546 CALL SLACPY( 'U', N, N, A, LDA, WORK( IQRF ), N )
547 CALL SLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IQRF+1 ), N )
548 CALL SGEBRD( N, N, WORK( IQRF ), N, WORK( ID ), WORK( IE ),
549 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
550 $ LWORK-ITEMP+1, INFO )
552 * Solve eigenvalue problem TGK*Z=Z*S.
553 * (Workspace: need 14*N + 2*N*(N+1))
556 ITEMP = ITGKZ + N*(N*2+1)
557 CALL SBDSVDX( 'U', JOBZ, RNGTGK, N, WORK( ID ), WORK( IE ),
558 $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
559 $ N*2, WORK( ITEMP ), IWORK, INFO)
561 * If needed, compute left singular vectors.
566 CALL SCOPY( N, WORK( J ), 1, U( 1,I ), 1 )
569 CALL SLASET( 'A', M-N, NS, ZERO, ZERO, U( N+1,1 ), LDU )
571 * Call SORMBR to compute QB*UB.
572 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
574 CALL SORMBR( 'Q', 'L', 'N', N, NS, N, WORK( IQRF ), N,
575 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
576 $ LWORK-ITEMP+1, INFO )
578 * Call SORMQR to compute Q*(QB*UB).
579 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
581 CALL SORMQR( 'L', 'N', M, NS, N, A, LDA,
582 $ WORK( ITAU ), U, LDU, WORK( ITEMP ),
583 $ LWORK-ITEMP+1, INFO )
586 * If needed, compute right singular vectors.
591 CALL SCOPY( N, WORK( J ), 1, VT( I,1 ), LDVT )
595 * Call SORMBR to compute VB**T * PB**T
596 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
598 CALL SORMBR( 'P', 'R', 'T', NS, N, N, WORK( IQRF ), N,
599 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
600 $ LWORK-ITEMP+1, INFO )
604 * Path 2 (M at least N, but not much larger)
605 * Reduce A to bidiagonal form without QR decomposition
606 * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
607 * U = QB * UB; V**T = VB**T * PB**T
610 * (Workspace: need 4*N+M, prefer 4*N+(M+N)*NB)
617 CALL SGEBRD( M, N, A, LDA, WORK( ID ), WORK( IE ),
618 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
619 $ LWORK-ITEMP+1, INFO )
621 * Solve eigenvalue problem TGK*Z=Z*S.
622 * (Workspace: need 14*N + 2*N*(N+1))
625 ITEMP = ITGKZ + N*(N*2+1)
626 CALL SBDSVDX( 'U', JOBZ, RNGTGK, N, WORK( ID ), WORK( IE ),
627 $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
628 $ N*2, WORK( ITEMP ), IWORK, INFO)
630 * If needed, compute left singular vectors.
635 CALL SCOPY( N, WORK( J ), 1, U( 1,I ), 1 )
638 CALL SLASET( 'A', M-N, NS, ZERO, ZERO, U( N+1,1 ), LDU )
640 * Call SORMBR to compute QB*UB.
641 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
643 CALL SORMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
644 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
645 $ LWORK-ITEMP+1, IERR )
648 * If needed, compute right singular vectors.
653 CALL SCOPY( N, WORK( J ), 1, VT( I,1 ), LDVT )
657 * Call SORMBR to compute VB**T * PB**T
658 * (Workspace in WORK( ITEMP ): need N, prefer N*NB)
660 CALL SORMBR( 'P', 'R', 'T', NS, N, N, A, LDA,
661 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
662 $ LWORK-ITEMP+1, IERR )
667 * A has more columns than rows. If A has sufficiently more
668 * columns than rows, first reduce A using the LQ decomposition.
670 IF( N.GE.MNTHR ) THEN
672 * Path 1t (N much larger than M):
673 * A = L * Q = ( QB * B * PB**T ) * Q
674 * = ( QB * ( UB * S * VB**T ) * PB**T ) * Q
675 * U = QB * UB ; V**T = VB**T * PB**T * Q
678 * (Workspace: need 2*M, prefer M+M*NB)
682 CALL SGELQF( M, N, A, LDA, WORK( ITAU ), WORK( ITEMP ),
683 $ LWORK-ITEMP+1, INFO )
685 * Copy L into WORK and bidiagonalize it:
686 * (Workspace in WORK( ITEMP ): need M*M+5*N, prefer M*M+4*M+2*M*NB)
694 CALL SLACPY( 'L', M, M, A, LDA, WORK( ILQF ), M )
695 CALL SLASET( 'U', M-1, M-1, ZERO, ZERO, WORK( ILQF+M ), M )
696 CALL SGEBRD( M, M, WORK( ILQF ), M, WORK( ID ), WORK( IE ),
697 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
698 $ LWORK-ITEMP+1, INFO )
700 * Solve eigenvalue problem TGK*Z=Z*S.
701 * (Workspace: need 2*M*M+14*M)
704 ITEMP = ITGKZ + M*(M*2+1)
705 CALL SBDSVDX( 'U', JOBZ, RNGTGK, M, WORK( ID ), WORK( IE ),
706 $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
707 $ M*2, WORK( ITEMP ), IWORK, INFO)
709 * If needed, compute left singular vectors.
714 CALL SCOPY( M, WORK( J ), 1, U( 1,I ), 1 )
718 * Call SORMBR to compute QB*UB.
719 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
721 CALL SORMBR( 'Q', 'L', 'N', M, NS, M, WORK( ILQF ), M,
722 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
723 $ LWORK-ITEMP+1, INFO )
726 * If needed, compute right singular vectors.
731 CALL SCOPY( M, WORK( J ), 1, VT( I,1 ), LDVT )
734 CALL SLASET( 'A', NS, N-M, ZERO, ZERO, VT( 1,M+1 ), LDVT)
736 * Call SORMBR to compute (VB**T)*(PB**T)
737 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
739 CALL SORMBR( 'P', 'R', 'T', NS, M, M, WORK( ILQF ), M,
740 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
741 $ LWORK-ITEMP+1, INFO )
743 * Call SORMLQ to compute ((VB**T)*(PB**T))*Q.
744 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
746 CALL SORMLQ( 'R', 'N', NS, N, M, A, LDA,
747 $ WORK( ITAU ), VT, LDVT, WORK( ITEMP ),
748 $ LWORK-ITEMP+1, INFO )
752 * Path 2t (N greater than M, but not much larger)
753 * Reduce to bidiagonal form without LQ decomposition
754 * A = QB * B * PB**T = QB * ( UB * S * VB**T ) * PB**T
755 * U = QB * UB; V**T = VB**T * PB**T
758 * (Workspace: need 4*M+N, prefer 4*M+(M+N)*NB)
765 CALL SGEBRD( M, N, A, LDA, WORK( ID ), WORK( IE ),
766 $ WORK( ITAUQ ), WORK( ITAUP ), WORK( ITEMP ),
767 $ LWORK-ITEMP+1, INFO )
769 * Solve eigenvalue problem TGK*Z=Z*S.
770 * (Workspace: need 2*M*M+14*M)
773 ITEMP = ITGKZ + M*(M*2+1)
774 CALL SBDSVDX( 'L', JOBZ, RNGTGK, M, WORK( ID ), WORK( IE ),
775 $ VL, VU, ILTGK, IUTGK, NS, S, WORK( ITGKZ ),
776 $ M*2, WORK( ITEMP ), IWORK, INFO)
778 * If needed, compute left singular vectors.
783 CALL SCOPY( M, WORK( J ), 1, U( 1,I ), 1 )
787 * Call SORMBR to compute QB*UB.
788 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
790 CALL SORMBR( 'Q', 'L', 'N', M, NS, N, A, LDA,
791 $ WORK( ITAUQ ), U, LDU, WORK( ITEMP ),
792 $ LWORK-ITEMP+1, INFO )
795 * If needed, compute right singular vectors.
800 CALL SCOPY( M, WORK( J ), 1, VT( I,1 ), LDVT )
803 CALL SLASET( 'A', NS, N-M, ZERO, ZERO, VT( 1,M+1 ), LDVT)
805 * Call SORMBR to compute VB**T * PB**T
806 * (Workspace in WORK( ITEMP ): need M, prefer M*NB)
808 CALL SORMBR( 'P', 'R', 'T', NS, N, M, A, LDA,
809 $ WORK( ITAUP ), VT, LDVT, WORK( ITEMP ),
810 $ LWORK-ITEMP+1, INFO )
815 * Undo scaling if necessary
819 $ CALL SLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1,
822 $ CALL SLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1,
826 * Return optimal workspace in WORK(1)
828 WORK( 1 ) = REAL( MAXWRK )