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 dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
DGEBRD
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMLQ
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMQR
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGELQF
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 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 dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
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 dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine dbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
DBDSVDX