226 SUBROUTINE dbdsvdx( UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
227 $ NS, S, Z, LDZ, WORK, IWORK, INFO)
235 CHARACTER JOBZ, RANGE, UPLO
236 INTEGER IL, INFO, IU, LDZ, N, NS
237 DOUBLE PRECISION VL, VU
241 DOUBLE PRECISION D( * ), E( * ), S( * ), WORK( * ),
248 DOUBLE PRECISION ZERO, ONE, TEN, HNDRD, MEIGTH
249 parameter( zero = 0.0d0, one = 1.0d0, ten = 10.0d0,
250 $ hndrd = 100.0d0, meigth = -0.1250d0 )
251 DOUBLE PRECISION FUDGE
252 parameter( fudge = 2.0d0 )
256 LOGICAL ALLSV, INDSV, LOWER, SPLIT, SVEQ0, VALSV, WANTZ
257 INTEGER I, ICOLZ, IDBEG, IDEND, IDTGK, IDPTR, IEPTR,
258 $ ietgk, iifail, iiwork, iltgk, irowu, irowv,
259 $ irowz, isbeg, isplt, itemp, iutgk, j, k,
260 $ ntgk, nru, nrv, nsl
261 DOUBLE PRECISION ABSTOL, EPS, EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
262 $ smin, sqrt2, thresh, tol, ulp,
263 $ vltgk, vutgk, zjtji
268 DOUBLE PRECISION DDOT, DLAMCH, DNRM2
269 EXTERNAL idamax, lsame,
daxpy, ddot, dlamch, dnrm2
275 INTRINSIC abs, dble, sign, sqrt
281 allsv = lsame( range,
'A' )
282 valsv = lsame( range,
'V' )
283 indsv = lsame( range,
'I' )
284 wantz = lsame( jobz,
'V' )
285 lower = lsame( uplo,
'L' )
288 IF( .NOT.lsame( uplo,
'U' ) .AND. .NOT.lower )
THEN 290 ELSE IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN 292 ELSE IF( .NOT.( allsv .OR. valsv .OR. indsv ) )
THEN 294 ELSE IF( n.LT.0 )
THEN 296 ELSE IF( n.GT.0 )
THEN 298 IF( vl.LT.zero )
THEN 300 ELSE IF( vu.LE.vl )
THEN 303 ELSE IF( indsv )
THEN 304 IF( il.LT.1 .OR. il.GT.max( 1, n ) )
THEN 306 ELSE IF( iu.LT.min( n, il ) .OR. iu.GT.n )
THEN 312 IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n*2 ) ) info = -14
316 CALL xerbla(
'DBDSVDX', -info )
326 IF( allsv .OR. indsv )
THEN 328 s( 1 ) = abs( d( 1 ) )
330 IF( vl.LT.abs( d( 1 ) ) .AND. vu.GE.abs( d( 1 ) ) )
THEN 332 s( 1 ) = abs( d( 1 ) )
336 z( 1, 1 ) = sign( one, d( 1 ) )
342 abstol = 2*dlamch(
'Safe Minimum' )
343 ulp = dlamch(
'Precision' )
344 eps = dlamch(
'Epsilon' )
345 sqrt2 = sqrt( 2.0d0 )
353 tol = max( ten, min( hndrd, eps**meigth ) )*eps
357 i = idamax( n, d, 1 )
359 i = idamax( n-1, e, 1 )
360 smax = max( smax, abs( e( i ) ) )
365 IF( smin.NE.zero )
THEN 368 mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) )
369 smin = min( smin, mu )
370 IF( smin.EQ.zero )
EXIT 373 smin = smin / sqrt( dble( n ) )
379 IF( abs( d( i ) ).LE.thresh ) d( i ) = zero
380 IF( abs( e( i ) ).LE.thresh ) e( i ) = zero
382 IF( abs( d( n ) ).LE.thresh ) d( n ) = zero
390 iiwork = iifail + n*2
409 IF( wantz )
CALL dlaset(
'F', n*2, n+1, zero, zero, z, ldz )
410 ELSE IF( valsv )
THEN 419 work( idtgk:idtgk+2*n-1 ) = zero
420 CALL dcopy( n, d, 1, work( ietgk ), 2 )
421 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
422 CALL dstevx(
'N',
'V', n*2, work( idtgk ), work( ietgk ),
423 $ vltgk, vutgk, iltgk, iltgk, abstol, ns, s,
424 $ z, ldz, work( itemp ), iwork( iiwork ),
425 $ iwork( iifail ), info )
429 IF( wantz )
CALL dlaset(
'F', n*2, ns, zero, zero, z, ldz )
431 ELSE IF( indsv )
THEN 443 work( idtgk:idtgk+2*n-1 ) = zero
444 CALL dcopy( n, d, 1, work( ietgk ), 2 )
445 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
446 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
447 $ vltgk, vltgk, iltgk, iltgk, abstol, ns, s,
448 $ z, ldz, work( itemp ), iwork( iiwork ),
449 $ iwork( iifail ), info )
450 vltgk = s( 1 ) - fudge*smax*ulp*n
451 work( idtgk:idtgk+2*n-1 ) = zero
452 CALL dcopy( n, d, 1, work( ietgk ), 2 )
453 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
454 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
455 $ vutgk, vutgk, iutgk, iutgk, abstol, ns, s,
456 $ z, ldz, work( itemp ), iwork( iiwork ),
457 $ iwork( iifail ), info )
458 vutgk = s( 1 ) + fudge*smax*ulp*n
459 vutgk = min( vutgk, zero )
464 IF( vltgk.EQ.vutgk ) vltgk = vltgk - tol
466 IF( wantz )
CALL dlaset(
'F', n*2, iu-il+1, zero, zero, z, ldz)
491 work( ietgk+2*n-1 ) = zero
492 work( idtgk:idtgk+2*n-1 ) = zero
493 CALL dcopy( n, d, 1, work( ietgk ), 2 )
494 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
501 IF( work( ietgk+ieptr-1 ).EQ.zero )
THEN 508 DO idptr = idbeg, idend, 2
509 IF( work( ietgk+idptr-1 ).EQ.zero )
THEN 514 IF( idptr.EQ.idbeg )
THEN 519 IF( idbeg.EQ.idend)
THEN 523 ELSE IF( idptr.EQ.idend )
THEN 528 nru = (idend-isplt)/2 + 1
530 IF( isplt.NE.idbeg )
THEN 534 IF( isplt.EQ.idbeg )
THEN 538 nru = (idptr-idbeg)/2
544 nru = (idptr-isplt)/2 + 1
548 ELSE IF( idptr.EQ.idend )
THEN 552 IF( isplt.EQ.idbeg )
THEN 556 nru = (idend-idbeg)/2 + 1
562 nrv = (idend-isplt)/2 + 1
579 IF( allsv .OR. vutgk.EQ.zero )
THEN 582 $ mod(ntgk,2).GT.0 )
THEN 593 CALL dstevx( jobz, rngvx, ntgk, work( idtgk+isplt-1 ),
594 $ work( ietgk+isplt-1 ), vltgk, vutgk,
595 $ iltgk, iutgk, abstol, nsl, s( isbeg ),
596 $ z( irowz,icolz ), ldz, work( itemp ),
597 $ iwork( iiwork ), iwork( iifail ),
603 emin = abs( maxval( s( isbeg:isbeg+nsl-1 ) ) )
605 IF( nsl.GT.0 .AND. wantz )
THEN 616 $ vutgk.EQ.zero .AND.
617 $ mod(ntgk,2).EQ.0 .AND.
618 $ emin.EQ.0 .AND. .NOT.split )
THEN 625 z( irowz:irowz+ntgk-1,icolz+nsl-2 ) =
626 $ z( irowz:irowz+ntgk-1,icolz+nsl-2 ) +
627 $ z( irowz:irowz+ntgk-1,icolz+nsl-1 )
628 z( irowz:irowz+ntgk-1,icolz+nsl-1 ) =
636 DO i = 0, min( nsl-1, nru-1 )
637 nrmu = dnrm2( nru, z( irowu, icolz+i ), 2 )
638 IF( nrmu.EQ.zero )
THEN 642 CALL dscal( nru, one/nrmu,
643 $ z( irowu,icolz+i ), 2 )
644 IF( nrmu.NE.one .AND.
645 $ abs( nrmu-ortol )*sqrt2.GT.one )
648 zjtji = -ddot( nru, z( irowu, icolz+j ),
649 $ 2, z( irowu, icolz+i ), 2 )
650 CALL daxpy( nru, zjtji,
651 $ z( irowu, icolz+j ), 2,
652 $ z( irowu, icolz+i ), 2 )
654 nrmu = dnrm2( nru, z( irowu, icolz+i ), 2 )
655 CALL dscal( nru, one/nrmu,
656 $ z( irowu,icolz+i ), 2 )
659 DO i = 0, min( nsl-1, nrv-1 )
660 nrmv = dnrm2( nrv, z( irowv, icolz+i ), 2 )
661 IF( nrmv.EQ.zero )
THEN 665 CALL dscal( nrv, -one/nrmv,
666 $ z( irowv,icolz+i ), 2 )
667 IF( nrmv.NE.one .AND.
668 $ abs( nrmv-ortol )*sqrt2.GT.one )
671 zjtji = -ddot( nrv, z( irowv, icolz+j ),
672 $ 2, z( irowv, icolz+i ), 2 )
673 CALL daxpy( nru, zjtji,
674 $ z( irowv, icolz+j ), 2,
675 $ z( irowv, icolz+i ), 2 )
677 nrmv = dnrm2( nrv, z( irowv, icolz+i ), 2 )
678 CALL dscal( nrv, one/nrmv,
679 $ z( irowv,icolz+i ), 2 )
682 IF( vutgk.EQ.zero .AND.
683 $ idptr.LT.idend .AND.
684 $ mod(ntgk,2).GT.0 )
THEN 692 z( irowz:irowz+ntgk-1,n+1 ) =
693 $ z( irowz:irowz+ntgk-1,ns+nsl )
694 z( irowz:irowz+ntgk-1,ns+nsl ) =
699 nsl = min( nsl, nru )
705 s( isbeg+i ) = abs( s( isbeg+i ) )
720 IF( irowz.LT.n*2 .AND. wantz )
THEN 721 z( 1:irowz-1, icolz ) = zero
724 IF( split .AND. wantz )
THEN 729 z( idbeg:idend-ntgk+1,isbeg-1 ) =
730 $ z( idbeg:idend-ntgk+1,isbeg-1 ) +
731 $ z( idbeg:idend-ntgk+1,n+1 )
732 z( idbeg:idend-ntgk+1,n+1 ) = 0
749 IF( s( j ).LE.smin )
THEN 754 IF( k.NE.ns+1-i )
THEN 757 IF( wantz )
CALL dswap( n*2, z( 1,k ), 1, z( 1,ns+1-i ), 1 )
767 IF( wantz ) z( 1:n*2,k+1:ns ) = zero
777 CALL dcopy( n*2, z( 1,i ), 1, work, 1 )
779 CALL dcopy( n, work( 2 ), 2, z( n+1,i ), 1 )
780 CALL dcopy( n, work( 1 ), 2, z( 1 ,i ), 1 )
782 CALL dcopy( n, work( 2 ), 2, z( 1 ,i ), 1 )
783 CALL dcopy( n, work( 1 ), 2, z( n+1,i ), 1 )
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine daxpy(N, DA, DX, INCX, DY, INCY)
DAXPY
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 dswap(N, DX, INCX, DY, INCY)
DSWAP
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine dscal(N, DA, DX, INCX)
DSCAL
subroutine dbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
DBDSVDX
subroutine dstevx(JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL, M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO)
DSTEVX computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matric...