222 SUBROUTINE dbdsvdx( UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
223 $ NS, S, Z, LDZ, WORK, IWORK, INFO)
230 CHARACTER JOBZ, RANGE, UPLO
231 INTEGER IL, INFO, IU, LDZ, N, NS
232 DOUBLE PRECISION VL, VU
236 DOUBLE PRECISION D( * ), E( * ), S( * ), WORK( * ),
243 DOUBLE PRECISION ZERO, ONE, TEN, HNDRD, MEIGTH
244 parameter( zero = 0.0d0, one = 1.0d0, ten = 10.0d0,
245 $ hndrd = 100.0d0, meigth = -0.1250d0 )
246 DOUBLE PRECISION FUDGE
247 parameter( fudge = 2.0d0 )
251 LOGICAL ALLSV, INDSV, LOWER, SPLIT, SVEQ0, VALSV, WANTZ
252 INTEGER I, ICOLZ, IDBEG, IDEND, IDTGK, IDPTR, IEPTR,
253 $ ietgk, iifail, iiwork, iltgk, irowu, irowv,
254 $ irowz, isbeg, isplt, itemp, iutgk, j, k,
255 $ ntgk, nru, nrv, nsl
256 DOUBLE PRECISION ABSTOL, EPS, EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
257 $ smin, sqrt2, thresh, tol, ulp,
258 $ vltgk, vutgk, zjtji
263 DOUBLE PRECISION DDOT, DLAMCH, DNRM2
264 EXTERNAL idamax, lsame,
daxpy, ddot, dlamch,
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,
429 ELSE IF( indsv )
THEN
441 work( idtgk:idtgk+2*n-1 ) = zero
442 CALL dcopy( n, d, 1, work( ietgk ), 2 )
443 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
444 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
445 $ vltgk, vltgk, iltgk, iltgk, abstol, ns, s,
446 $ z, ldz, work( itemp ), iwork( iiwork ),
447 $ iwork( iifail ), info )
448 vltgk = s( 1 ) - fudge*smax*ulp*n
449 work( idtgk:idtgk+2*n-1 ) = zero
450 CALL dcopy( n, d, 1, work( ietgk ), 2 )
451 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
452 CALL dstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
453 $ vutgk, vutgk, iutgk, iutgk, abstol, ns, s,
454 $ z, ldz, work( itemp ), iwork( iiwork ),
455 $ iwork( iifail ), info )
456 vutgk = s( 1 ) + fudge*smax*ulp*n
457 vutgk = min( vutgk, zero )
462 IF( vltgk.EQ.vutgk ) vltgk = vltgk - tol
464 IF( wantz )
CALL dlaset(
'F', n*2, iu-il+1, zero, zero, z,
490 work( ietgk+2*n-1 ) = zero
491 work( idtgk:idtgk+2*n-1 ) = zero
492 CALL dcopy( n, d, 1, work( ietgk ), 2 )
493 CALL dcopy( n-1, e, 1, work( ietgk+1 ), 2 )
500 IF( work( ietgk+ieptr-1 ).EQ.zero )
THEN
507 DO idptr = idbeg, idend, 2
508 IF( work( ietgk+idptr-1 ).EQ.zero )
THEN
513 IF( idptr.EQ.idbeg )
THEN
518 IF( idbeg.EQ.idend)
THEN
522 ELSE IF( idptr.EQ.idend )
THEN
527 nru = (idend-isplt)/2 + 1
529 IF( isplt.NE.idbeg )
THEN
533 IF( isplt.EQ.idbeg )
THEN
537 nru = (idptr-idbeg)/2
543 nru = (idptr-isplt)/2 + 1
547 ELSE IF( idptr.EQ.idend )
THEN
551 IF( isplt.EQ.idbeg )
THEN
555 nru = (idend-idbeg)/2 + 1
561 nrv = (idend-isplt)/2 + 1
578 IF( allsv .OR. vutgk.EQ.zero )
THEN
581 $ mod(ntgk,2).GT.0 )
THEN
592 CALL dstevx( jobz, rngvx, ntgk,
593 $ 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,
650 $ 2, z( irowu, icolz+i ), 2 )
651 CALL daxpy( nru, zjtji,
652 $ z( irowu, icolz+j ), 2,
653 $ z( irowu, icolz+i ), 2 )
655 nrmu = dnrm2( nru, z( irowu, icolz+i ),
657 CALL dscal( nru, one/nrmu,
658 $ z( irowu,icolz+i ), 2 )
661 DO i = 0, min( nsl-1, nrv-1 )
662 nrmv = dnrm2( nrv, z( irowv, icolz+i ), 2 )
663 IF( nrmv.EQ.zero )
THEN
667 CALL dscal( nrv, -one/nrmv,
668 $ z( irowv,icolz+i ), 2 )
669 IF( nrmv.NE.one .AND.
670 $ abs( nrmv-ortol )*sqrt2.GT.one )
673 zjtji = -ddot( nrv, z( irowv,
675 $ 2, z( irowv, icolz+i ), 2 )
676 CALL daxpy( nru, zjtji,
677 $ z( irowv, icolz+j ), 2,
678 $ z( irowv, icolz+i ), 2 )
680 nrmv = dnrm2( nrv, z( irowv, icolz+i ),
682 CALL dscal( nrv, one/nrmv,
683 $ z( irowv,icolz+i ), 2 )
686 IF( vutgk.EQ.zero .AND.
687 $ idptr.LT.idend .AND.
688 $ mod(ntgk,2).GT.0 )
THEN
696 z( irowz:irowz+ntgk-1,n+1 ) =
697 $ z( irowz:irowz+ntgk-1,ns+nsl )
698 z( irowz:irowz+ntgk-1,ns+nsl ) =
703 nsl = min( nsl, nru )
709 s( isbeg+i ) = abs( s( isbeg+i ) )
724 IF( irowz.LT.n*2 .AND. wantz )
THEN
725 z( 1:irowz-1, icolz ) = zero
728 IF( split .AND. wantz )
THEN
733 z( idbeg:idend-ntgk+1,isbeg-1 ) =
734 $ z( idbeg:idend-ntgk+1,isbeg-1 ) +
735 $ z( idbeg:idend-ntgk+1,n+1 )
736 z( idbeg:idend-ntgk+1,n+1 ) = 0
753 IF( s( j ).LE.smin )
THEN
758 IF( k.NE.ns+1-i )
THEN
761 IF( wantz )
CALL dswap( n*2, z( 1,k ), 1, z( 1,ns+1-i ),
772 IF( wantz ) z( 1:n*2,k+1:ns ) = zero
782 CALL dcopy( n*2, z( 1,i ), 1, work, 1 )
784 CALL dcopy( n, work( 2 ), 2, z( n+1,i ), 1 )
785 CALL dcopy( n, work( 1 ), 2, z( 1 ,i ), 1 )
787 CALL dcopy( n, work( 2 ), 2, z( 1 ,i ), 1 )
788 CALL dcopy( n, work( 1 ), 2, z( n+1,i ), 1 )