260 SUBROUTINE dgesvdx( JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU,
261 $ IL, IU, NS, S, U, LDU, VT, LDVT, WORK,
262 $ LWORK, IWORK, INFO )
269 CHARACTER JOBU, JOBVT, RANGE
270 INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
271 DOUBLE PRECISION VL, VU
275 DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ),
276 $ vt( ldvt, * ), work( * )
282 DOUBLE PRECISION ZERO, ONE
283 PARAMETER ( ZERO = 0.0d0, one = 1.0d0 )
286 CHARACTER JOBZ, RNGTGK
287 LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
288 INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
289 $ itau, itaup, itauq, itemp, itgkz, iutgk,
290 $ j, maxwrk, minmn, minwrk, mnthr
291 DOUBLE PRECISION ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
294 DOUBLE PRECISION DUM( 1 )
304 DOUBLE PRECISION DLAMCH, DLANGE
305 EXTERNAL lsame, ilaenv, dlamch, dlange
308 INTRINSIC max, min, sqrt
316 abstol = 2*dlamch(
'S')
317 lquery = ( lwork.EQ.-1 )
320 wantu = lsame( jobu,
'V' )
321 wantvt = lsame( jobvt,
'V' )
322 IF( wantu .OR. wantvt )
THEN
327 alls = lsame( range,
'A' )
328 vals = lsame( range,
'V' )
329 inds = lsame( range,
'I' )
332 IF( .NOT.lsame( jobu,
'V' ) .AND.
333 $ .NOT.lsame( jobu,
'N' ) )
THEN
335 ELSE IF( .NOT.lsame( jobvt,
'V' ) .AND.
336 $ .NOT.lsame( jobvt,
'N' ) )
THEN
338 ELSE IF( .NOT.( alls .OR. vals .OR. inds ) )
THEN
340 ELSE IF( m.LT.0 )
THEN
342 ELSE IF( n.LT.0 )
THEN
344 ELSE IF( m.GT.lda )
THEN
346 ELSE IF( minmn.GT.0 )
THEN
348 IF( vl.LT.zero )
THEN
350 ELSE IF( vu.LE.vl )
THEN
354 IF( il.LT.1 .OR. il.GT.max( 1, minmn ) )
THEN
356 ELSE IF( iu.LT.min( minmn, il ) .OR. iu.GT.minmn )
THEN
361 IF( wantu .AND. ldu.LT.m )
THEN
363 ELSE IF( wantvt )
THEN
365 IF( ldvt.LT.iu-il+1 )
THEN
368 ELSE IF( ldvt.LT.minmn )
THEN
385 IF( minmn.GT.0 )
THEN
387 mnthr = ilaenv( 6,
'DGESVD', jobu // jobvt, m, n, 0, 0 )
388 IF( m.GE.mnthr )
THEN
393 $ n*ilaenv( 1,
'DGEQRF',
' ', m, n, -1, -1 )
394 maxwrk = max( maxwrk, n*(n+5) + 2*n*
395 $ ilaenv( 1,
'DGEBRD',
' ', n, n, -1, -1 ) )
397 maxwrk = max(maxwrk,n*(n*3+6)+n*
398 $ ilaenv( 1,
'DORMQR',
' ', n, n, -1, -1 ) )
401 maxwrk = max(maxwrk,n*(n*3+6)+n*
402 $ ilaenv( 1,
'DORMLQ',
' ', n, n, -1, -1 ) )
409 maxwrk = 4*n + ( m+n )*
410 $ ilaenv( 1,
'DGEBRD',
' ', m, n, -1, -1 )
412 maxwrk = max(maxwrk,n*(n*2+5)+n*
413 $ ilaenv( 1,
'DORMQR',
' ', n, n, -1, -1 ) )
416 maxwrk = max(maxwrk,n*(n*2+5)+n*
417 $ ilaenv( 1,
'DORMLQ',
' ', n, n, -1, -1 ) )
419 minwrk = max(n*(n*2+19),4*n+m)
422 mnthr = ilaenv( 6,
'DGESVD', jobu // jobvt, m, n, 0, 0 )
423 IF( n.GE.mnthr )
THEN
428 $ m*ilaenv( 1,
'DGELQF',
' ', m, n, -1, -1 )
429 maxwrk = max( maxwrk, m*(m+5) + 2*m*
430 $ ilaenv( 1,
'DGEBRD',
' ', m, m, -1, -1 ) )
432 maxwrk = max(maxwrk,m*(m*3+6)+m*
433 $ ilaenv( 1,
'DORMQR',
' ', m, m, -1, -1 ) )
436 maxwrk = max(maxwrk,m*(m*3+6)+m*
437 $ ilaenv( 1,
'DORMLQ',
' ', m, m, -1, -1 ) )
444 maxwrk = 4*m + ( m+n )*
445 $ ilaenv( 1,
'DGEBRD',
' ', m, n, -1, -1 )
447 maxwrk = max(maxwrk,m*(m*2+5)+m*
448 $ ilaenv( 1,
'DORMQR',
' ', m, m, -1, -1 ) )
451 maxwrk = max(maxwrk,m*(m*2+5)+m*
452 $ ilaenv( 1,
'DORMLQ',
' ', m, m, -1, -1 ) )
454 minwrk = max(m*(m*2+19),4*m+n)
458 maxwrk = max( maxwrk, minwrk )
459 work( 1 ) = dble( maxwrk )
461 IF( lwork.LT.minwrk .AND. .NOT.lquery )
THEN
467 CALL xerbla(
'DGESVDX', -info )
469 ELSE IF( lquery )
THEN
475 IF( m.EQ.0 .OR. n.EQ.0 )
THEN
498 smlnum = sqrt( dlamch(
'S' ) ) / eps
499 bignum = one / smlnum
503 anrm = dlange(
'M', m, n, a, lda, dum )
505 IF( anrm.GT.zero .AND. anrm.LT.smlnum )
THEN
507 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
508 ELSE IF( anrm.GT.bignum )
THEN
510 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
519 IF( m.GE.mnthr )
THEN
531 CALL dgeqrf( m, n, a, lda, work( itau ), work( itemp ),
532 $ lwork-itemp+1, info )
543 CALL dlacpy(
'U', n, n, a, lda, work( iqrf ), n )
544 CALL dlaset(
'L', n-1, n-1, zero, zero, work( iqrf+1 ), n )
545 CALL dgebrd( n, n, work( iqrf ), n, work( id ), work( ie ),
546 $ work( itauq ), work( itaup ), work( itemp ),
547 $ lwork-itemp+1, info )
553 itemp = itgkz + n*(n*2+1)
554 CALL dbdsvdx(
'U', jobz, rngtgk, n, work( id ), work( ie ),
555 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
556 $ n*2, work( itemp ), iwork, info)
563 CALL dcopy( n, work( j ), 1, u( 1,i ), 1 )
566 CALL dlaset(
'A', m-n, ns, zero, zero, u( n+1,1 ), ldu )
571 CALL dormbr(
'Q',
'L',
'N', n, ns, n, work( iqrf ), n,
572 $ work( itauq ), u, ldu, work( itemp ),
573 $ lwork-itemp+1, info )
578 CALL dormqr(
'L',
'N', m, ns, n, a, lda,
579 $ work( itau ), u, ldu, work( itemp ),
580 $ lwork-itemp+1, info )
588 CALL dcopy( n, work( j ), 1, vt( i,1 ), ldvt )
595 CALL dormbr(
'P',
'R',
'T', ns, n, n, work( iqrf ), n,
596 $ work( itaup ), vt, ldvt, work( itemp ),
597 $ lwork-itemp+1, info )
614 CALL dgebrd( m, n, a, lda, work( id ), work( ie ),
615 $ work( itauq ), work( itaup ), work( itemp ),
616 $ lwork-itemp+1, info )
622 itemp = itgkz + n*(n*2+1)
623 CALL dbdsvdx(
'U', jobz, rngtgk, n, work( id ), work( ie ),
624 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
625 $ n*2, work( itemp ), iwork, info)
632 CALL dcopy( n, work( j ), 1, u( 1,i ), 1 )
635 CALL dlaset(
'A', m-n, ns, zero, zero, u( n+1,1 ), ldu )
640 CALL dormbr(
'Q',
'L',
'N', m, ns, n, a, lda,
641 $ work( itauq ), u, ldu, work( itemp ),
642 $ lwork-itemp+1, ierr )
650 CALL dcopy( n, work( j ), 1, vt( i,1 ), ldvt )
657 CALL dormbr(
'P',
'R',
'T', ns, n, n, a, lda,
658 $ work( itaup ), vt, ldvt, work( itemp ),
659 $ lwork-itemp+1, ierr )
667 IF( n.GE.mnthr )
THEN
679 CALL dgelqf( m, n, a, lda, work( itau ), work( itemp ),
680 $ lwork-itemp+1, info )
691 CALL dlacpy(
'L', m, m, a, lda, work( ilqf ), m )
692 CALL dlaset(
'U', m-1, m-1, zero, zero, work( ilqf+m ), m )
693 CALL dgebrd( m, m, work( ilqf ), m, work( id ), work( ie ),
694 $ work( itauq ), work( itaup ), work( itemp ),
695 $ lwork-itemp+1, info )
701 itemp = itgkz + m*(m*2+1)
702 CALL dbdsvdx(
'U', jobz, rngtgk, m, work( id ), work( ie ),
703 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
704 $ m*2, work( itemp ), iwork, info)
711 CALL dcopy( m, work( j ), 1, u( 1,i ), 1 )
718 CALL dormbr(
'Q',
'L',
'N', m, ns, m, work( ilqf ), m,
719 $ work( itauq ), u, ldu, work( itemp ),
720 $ lwork-itemp+1, info )
728 CALL dcopy( m, work( j ), 1, vt( i,1 ), ldvt )
731 CALL dlaset(
'A', ns, n-m, zero, zero, vt( 1,m+1 ), ldvt)
736 CALL dormbr(
'P',
'R',
'T', ns, m, m, work( ilqf ), m,
737 $ work( itaup ), vt, ldvt, work( itemp ),
738 $ lwork-itemp+1, info )
743 CALL dormlq(
'R',
'N', ns, n, m, a, lda,
744 $ work( itau ), vt, ldvt, work( itemp ),
745 $ lwork-itemp+1, info )
762 CALL dgebrd( m, n, a, lda, work( id ), work( ie ),
763 $ work( itauq ), work( itaup ), work( itemp ),
764 $ lwork-itemp+1, info )
770 itemp = itgkz + m*(m*2+1)
771 CALL dbdsvdx(
'L', jobz, rngtgk, m, work( id ), work( ie ),
772 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
773 $ m*2, work( itemp ), iwork, info)
780 CALL dcopy( m, work( j ), 1, u( 1,i ), 1 )
787 CALL dormbr(
'Q',
'L',
'N', m, ns, n, a, lda,
788 $ work( itauq ), u, ldu, work( itemp ),
789 $ lwork-itemp+1, info )
797 CALL dcopy( m, work( j ), 1, vt( i,1 ), ldvt )
800 CALL dlaset(
'A', ns, n-m, zero, zero, vt( 1,m+1 ), ldvt)
805 CALL dormbr(
'P',
'R',
'T', ns, n, m, a, lda,
806 $ work( itaup ), vt, ldvt, work( itemp ),
807 $ lwork-itemp+1, info )
816 $
CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1,
819 $
CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1,
825 work( 1 ) = dble( maxwrk )
subroutine dlascl(TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlaset(UPLO, M, N, ALPHA, BETA, A, LDA)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGELQF
subroutine dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
DGEBRD
subroutine dgesvdx(JOBU, JOBVT, RANGE, M, N, A, LDA, VL, VU, IL, IU, NS, S, U, LDU, VT, LDVT, WORK, LWORK, IWORK, INFO)
DGESVDX computes the singular value decomposition (SVD) for GE matrices
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMQR
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMLQ
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR
subroutine dbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
DBDSVDX