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,
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
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)
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,
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 )