224 SUBROUTINE dbdsvdx( UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
225 $ NS, S, Z, LDZ, WORK, IWORK, INFO)
232 CHARACTER JOBZ, RANGE, UPLO
233 INTEGER IL, INFO, IU, LDZ, N, NS
234 DOUBLE PRECISION VL, VU
238 DOUBLE PRECISION D( * ), E( * ), S( * ), WORK( * ),
245 DOUBLE PRECISION ZERO, ONE, TEN, HNDRD, MEIGTH
246 parameter( zero = 0.0d0, one = 1.0d0, ten = 10.0d0,
247 $ hndrd = 100.0d0, meigth = -0.1250d0 )
248 DOUBLE PRECISION FUDGE
249 parameter( fudge = 2.0d0 )
253 LOGICAL ALLSV, INDSV, LOWER, SPLIT, SVEQ0, VALSV, WANTZ
254 INTEGER I, ICOLZ, IDBEG, IDEND, IDTGK, IDPTR, IEPTR,
255 $ ietgk, iifail, iiwork, iltgk, irowu, irowv,
256 $ irowz, isbeg, isplt, itemp, iutgk, j, k,
257 $ ntgk, nru, nrv, nsl
258 DOUBLE PRECISION ABSTOL, EPS, EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
259 $ smin, sqrt2, thresh, tol, ulp,
260 $ vltgk, vutgk, zjtji
265 DOUBLE PRECISION DDOT, DLAMCH, DNRM2
266 EXTERNAL idamax, lsame,
daxpy, ddot, dlamch, dnrm2
272 INTRINSIC abs, dble, sign, sqrt
278 allsv = lsame( range,
'A' )
279 valsv = lsame( range,
'V' )
280 indsv = lsame( range,
'I' )
281 wantz = lsame( jobz,
'V' )
282 lower = lsame( uplo,
'L' )
285 IF( .NOT.lsame( uplo,
'U' ) .AND. .NOT.lower )
THEN 287 ELSE IF( .NOT.( wantz .OR. lsame( jobz,
'N' ) ) )
THEN 289 ELSE IF( .NOT.( allsv .OR. valsv .OR. indsv ) )
THEN 291 ELSE IF( n.LT.0 )
THEN 293 ELSE IF( n.GT.0 )
THEN 295 IF( vl.LT.zero )
THEN 297 ELSE IF( vu.LE.vl )
THEN 300 ELSE IF( indsv )
THEN 301 IF( il.LT.1 .OR. il.GT.max( 1, n ) )
THEN 303 ELSE IF( iu.LT.min( n, il ) .OR. iu.GT.n )
THEN 309 IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n*2 ) ) info = -14
313 CALL xerbla(
'DBDSVDX', -info )
323 IF( allsv .OR. indsv )
THEN 325 s( 1 ) = abs( d( 1 ) )
327 IF( vl.LT.abs( d( 1 ) ) .AND. vu.GE.abs( d( 1 ) ) )
THEN 329 s( 1 ) = abs( d( 1 ) )
333 z( 1, 1 ) = sign( one, d( 1 ) )
339 abstol = 2*dlamch(
'Safe Minimum' )
340 ulp = dlamch(
'Precision' )
341 eps = dlamch(
'Epsilon' )
342 sqrt2 = sqrt( 2.0d0 )
350 tol = max( ten, min( hndrd, eps**meigth ) )*eps
354 i = idamax( n, d, 1 )
356 i = idamax( n-1, e, 1 )
357 smax = max( smax, abs( e( i ) ) )
362 IF( smin.NE.zero )
THEN 365 mu = abs( d( i ) )*( mu / ( mu+abs( e( i-1 ) ) ) )
366 smin = min( smin, mu )
367 IF( smin.EQ.zero )
EXIT 370 smin = smin / sqrt( dble( n ) )
376 IF( abs( d( i ) ).LE.thresh ) d( i ) = zero
377 IF( abs( e( i ) ).LE.thresh ) e( i ) = zero
379 IF( abs( d( n ) ).LE.thresh ) d( n ) = zero
387 iiwork = iifail + n*2
406 IF( wantz )
CALL dlaset(
'F', n*2, n+1, zero, zero, z, ldz )
407 ELSE IF( valsv )
THEN 416 work( idtgk:idtgk+2*n-1 ) = zero
417 CALL dcopy( n, d, 1, work( ietgk ), 2 )
418 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
419 CALL dstevx(
'N',
'V', n*2, work( idtgk ), work( ietgk ),
420 $ vltgk, vutgk, iltgk, iltgk, abstol, ns, s,
421 $ z, ldz, work( itemp ), iwork( iiwork ),
422 $ iwork( iifail ), info )
426 IF( wantz )
CALL dlaset(
'F', n*2, ns, zero, zero, z, ldz )
428 ELSE IF( indsv )
THEN 440 work( idtgk:idtgk+2*n-1 ) = zero
441 CALL dcopy( n, d, 1, work( ietgk ), 2 )
442 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
443 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
444 $ vltgk, vltgk, iltgk, iltgk, abstol, ns, s,
445 $ z, ldz, work( itemp ), iwork( iiwork ),
446 $ iwork( iifail ), info )
447 vltgk = s( 1 ) - fudge*smax*ulp*n
448 work( idtgk:idtgk+2*n-1 ) = zero
449 CALL dcopy( n, d, 1, work( ietgk ), 2 )
450 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
451 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
452 $ vutgk, vutgk, iutgk, iutgk, abstol, ns, s,
453 $ z, ldz, work( itemp ), iwork( iiwork ),
454 $ iwork( iifail ), info )
455 vutgk = s( 1 ) + fudge*smax*ulp*n
456 vutgk = min( vutgk, zero )
461 IF( vltgk.EQ.vutgk ) vltgk = vltgk - tol
463 IF( wantz )
CALL dlaset(
'F', n*2, iu-il+1, zero, zero, z, ldz)
488 work( ietgk+2*n-1 ) = zero
489 work( idtgk:idtgk+2*n-1 ) = zero
490 CALL dcopy( n, d, 1, work( ietgk ), 2 )
491 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
498 IF( work( ietgk+ieptr-1 ).EQ.zero )
THEN 505 DO idptr = idbeg, idend, 2
506 IF( work( ietgk+idptr-1 ).EQ.zero )
THEN 511 IF( idptr.EQ.idbeg )
THEN 516 IF( idbeg.EQ.idend)
THEN 520 ELSE IF( idptr.EQ.idend )
THEN 525 nru = (idend-isplt)/2 + 1
527 IF( isplt.NE.idbeg )
THEN 531 IF( isplt.EQ.idbeg )
THEN 535 nru = (idptr-idbeg)/2
541 nru = (idptr-isplt)/2 + 1
545 ELSE IF( idptr.EQ.idend )
THEN 549 IF( isplt.EQ.idbeg )
THEN 553 nru = (idend-idbeg)/2 + 1
559 nrv = (idend-isplt)/2 + 1
576 IF( allsv .OR. vutgk.EQ.zero )
THEN 579 $ mod(ntgk,2).GT.0 )
THEN 590 CALL dstevx( jobz, rngvx, ntgk, work( idtgk+isplt-1 ),
591 $ work( ietgk+isplt-1 ), vltgk, vutgk,
592 $ iltgk, iutgk, abstol, nsl, s( isbeg ),
593 $ z( irowz,icolz ), ldz, work( itemp ),
594 $ iwork( iiwork ), iwork( iifail ),
600 emin = abs( maxval( s( isbeg:isbeg+nsl-1 ) ) )
602 IF( nsl.GT.0 .AND. wantz )
THEN 613 $ vutgk.EQ.zero .AND.
614 $ mod(ntgk,2).EQ.0 .AND.
615 $ emin.EQ.0 .AND. .NOT.split )
THEN 622 z( irowz:irowz+ntgk-1,icolz+nsl-2 ) =
623 $ z( irowz:irowz+ntgk-1,icolz+nsl-2 ) +
624 $ z( irowz:irowz+ntgk-1,icolz+nsl-1 )
625 z( irowz:irowz+ntgk-1,icolz+nsl-1 ) =
633 DO i = 0, min( nsl-1, nru-1 )
634 nrmu = dnrm2( nru, z( irowu, icolz+i ), 2 )
635 IF( nrmu.EQ.zero )
THEN 639 CALL dscal( nru, one/nrmu,
640 $ z( irowu,icolz+i ), 2 )
641 IF( nrmu.NE.one .AND.
642 $ abs( nrmu-ortol )*sqrt2.GT.one )
645 zjtji = -ddot( nru, z( irowu, icolz+j ),
646 $ 2, z( irowu, icolz+i ), 2 )
647 CALL daxpy( nru, zjtji,
648 $ z( irowu, icolz+j ), 2,
649 $ z( irowu, icolz+i ), 2 )
651 nrmu = dnrm2( nru, z( irowu, icolz+i ), 2 )
652 CALL dscal( nru, one/nrmu,
653 $ z( irowu,icolz+i ), 2 )
656 DO i = 0, min( nsl-1, nrv-1 )
657 nrmv = dnrm2( nrv, z( irowv, icolz+i ), 2 )
658 IF( nrmv.EQ.zero )
THEN 662 CALL dscal( nrv, -one/nrmv,
663 $ z( irowv,icolz+i ), 2 )
664 IF( nrmv.NE.one .AND.
665 $ abs( nrmv-ortol )*sqrt2.GT.one )
668 zjtji = -ddot( nrv, z( irowv, icolz+j ),
669 $ 2, z( irowv, icolz+i ), 2 )
670 CALL daxpy( nru, zjtji,
671 $ z( irowv, icolz+j ), 2,
672 $ z( irowv, icolz+i ), 2 )
674 nrmv = dnrm2( nrv, z( irowv, icolz+i ), 2 )
675 CALL dscal( nrv, one/nrmv,
676 $ z( irowv,icolz+i ), 2 )
679 IF( vutgk.EQ.zero .AND.
680 $ idptr.LT.idend .AND.
681 $ mod(ntgk,2).GT.0 )
THEN 689 z( irowz:irowz+ntgk-1,n+1 ) =
690 $ z( irowz:irowz+ntgk-1,ns+nsl )
691 z( irowz:irowz+ntgk-1,ns+nsl ) =
696 nsl = min( nsl, nru )
702 s( isbeg+i ) = abs( s( isbeg+i ) )
717 IF( irowz.LT.n*2 .AND. wantz )
THEN 718 z( 1:irowz-1, icolz ) = zero
721 IF( split .AND. wantz )
THEN 726 z( idbeg:idend-ntgk+1,isbeg-1 ) =
727 $ z( idbeg:idend-ntgk+1,isbeg-1 ) +
728 $ z( idbeg:idend-ntgk+1,n+1 )
729 z( idbeg:idend-ntgk+1,n+1 ) = 0
746 IF( s( j ).LE.smin )
THEN 751 IF( k.NE.ns+1-i )
THEN 754 IF( wantz )
CALL dswap( n*2, z( 1,k ), 1, z( 1,ns+1-i ), 1 )
764 IF( wantz ) z( 1:n*2,k+1:ns ) = zero
774 CALL dcopy( n*2, z( 1,i ), 1, work, 1 )
776 CALL dcopy( n, work( 2 ), 2, z( n+1,i ), 1 )
777 CALL dcopy( n, work( 1 ), 2, z( 1 ,i ), 1 )
779 CALL dcopy( n, work( 2 ), 2, z( 1 ,i ), 1 )
780 CALL dcopy( n, work( 1 ), 2, z( n+1,i ), 1 )
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine daxpy(N, DA, DX, INCX, DY, INCY)
DAXPY
subroutine dscal(N, DA, DX, INCX)
DSCAL
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 dcopy(N, DX, INCX, DY, INCY)
DCOPY
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...
subroutine dbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
DBDSVDX