226 SUBROUTINE sbdsvdx( 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
241 REAL D( * ), E( * ), S( * ), WORK( * ),
248 REAL ZERO, ONE, TEN, HNDRD, MEIGTH
249 parameter( zero = 0.0e0, one = 1.0e0, ten = 10.0e0,
250 $ hndrd = 100.0e0, meigth = -0.1250e0 )
252 parameter( fudge = 2.0e0 )
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 REAL ABSTOL, EPS, EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
262 $ smin, sqrt2, thresh, tol, ulp,
263 $ vltgk, vutgk, zjtji
268 REAL SDOT, SLAMCH, SNRM2
269 EXTERNAL isamax, lsame,
saxpy, sdot, slamch, snrm2
275 INTRINSIC abs, real, 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(
'SBDSVDX', -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*slamch(
'Safe Minimum' )
343 ulp = slamch(
'Precision' )
344 eps = slamch(
'Epsilon' )
345 sqrt2 = sqrt( 2.0e0 )
353 tol = max( ten, min( hndrd, eps**meigth ) )*eps
357 i = isamax( n, d, 1 )
359 i = isamax( 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( real( 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 slaset(
'F', n*2, n+1, zero, zero, z, ldz )
410 ELSE IF( valsv )
THEN
419 work( idtgk:idtgk+2*n-1 ) = zero
420 CALL scopy( n, d, 1, work( ietgk ), 2 )
421 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
422 CALL sstevx(
'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 slaset(
'F', n*2, ns, zero, zero, z, ldz )
431 ELSE IF( indsv )
THEN
443 work( idtgk:idtgk+2*n-1 ) = zero
444 CALL scopy( n, d, 1, work( ietgk ), 2 )
445 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
446 CALL sstevx(
'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 scopy( n, d, 1, work( ietgk ), 2 )
453 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
454 CALL sstevx(
'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 slaset(
'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 scopy( n, d, 1, work( ietgk ), 2 )
494 CALL scopy( 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 sstevx( 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 = snrm2( nru, z( irowu, icolz+i ), 2 )
638 IF( nrmu.EQ.zero )
THEN
642 CALL sscal( nru, one/nrmu,
643 $ z( irowu,icolz+i ), 2 )
644 IF( nrmu.NE.one .AND.
645 $ abs( nrmu-ortol )*sqrt2.GT.one )
648 zjtji = -sdot( nru, z( irowu, icolz+j ),
649 $ 2, z( irowu, icolz+i ), 2 )
650 CALL saxpy( nru, zjtji,
651 $ z( irowu, icolz+j ), 2,
652 $ z( irowu, icolz+i ), 2 )
654 nrmu = snrm2( nru, z( irowu, icolz+i ), 2 )
655 CALL sscal( nru, one/nrmu,
656 $ z( irowu,icolz+i ), 2 )
659 DO i = 0, min( nsl-1, nrv-1 )
660 nrmv = snrm2( nrv, z( irowv, icolz+i ), 2 )
661 IF( nrmv.EQ.zero )
THEN
665 CALL sscal( nrv, -one/nrmv,
666 $ z( irowv,icolz+i ), 2 )
667 IF( nrmv.NE.one .AND.
668 $ abs( nrmv-ortol )*sqrt2.GT.one )
671 zjtji = -sdot( nrv, z( irowv, icolz+j ),
672 $ 2, z( irowv, icolz+i ), 2 )
673 CALL saxpy( nru, zjtji,
674 $ z( irowv, icolz+j ), 2,
675 $ z( irowv, icolz+i ), 2 )
677 nrmv = snrm2( nrv, z( irowv, icolz+i ), 2 )
678 CALL sscal( 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 sswap( 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 scopy( n*2, z( 1,i ), 1, work, 1 )
779 CALL scopy( n, work( 2 ), 2, z( n+1,i ), 1 )
780 CALL scopy( n, work( 1 ), 2, z( 1 ,i ), 1 )
782 CALL scopy( n, work( 2 ), 2, z( 1 ,i ), 1 )
783 CALL scopy( n, work( 1 ), 2, z( n+1,i ), 1 )