224 SUBROUTINE sbdsvdx( 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,
238 REAL D( * ), E( * ), S( * ), WORK( * ),
245 REAL ZERO, ONE, TEN, HNDRD, MEIGTH
246 parameter( zero = 0.0e0, one = 1.0e0, ten = 10.0e0,
247 $ hndrd = 100.0e0, meigth = -0.1250e0 )
249 parameter( fudge = 2.0e0 )
253 LOGICAL ALLSV, , LOWER, SPLIT, SVEQ0, VALSV, WANTZ
254 INTEGER I, ICOLZ, IDBEG, IDEND
256 $ irowz, isbeg, isplt, itemp, iutgk, j, k,
257 $ ntgk, nru, nrv, nsl
258 REAL ABSTOL, , EMIN, MU, NRMU, NRMV, ORTOL, SMAX,
259 $ smin, sqrt2, thresh, tol, ulp,
260 $ vltgk, vutgk, zjtji
265 REAL SDOT, SLAMCH, SNRM2
266 EXTERNAL isamax, lsame,
saxpy, sdot, slamch, snrm2
272 INTRINSIC abs, real, 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
313 CALL xerbla(
'SBDSVDX', -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*slamch(
'Safe Minimum' )
340 ulp = slamch(
'Precision' )
341 eps = slamch(
'Epsilon' )
350 tol =
max( ten,
min( hndrd, eps**meigth ) )*eps
354 i = isamax( n, d, 1 )
356 i = isamax( 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( real( 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 slaset(
'F', n*2, n+1, zero, zero, z, ldz )
407 ELSE IF( valsv )
THEN
416 work( idtgk:idtgk+2*n-1 ) = zero
417 CALL scopy( n, d, 1, work( ietgk ), 2 )
418 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
419 CALL sstevx(
'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 slaset(
'F', n*2, ns, zero, zero, z, ldz )
428 ELSE IF( indsv )
THEN
440 work( idtgk:idtgk+2*n-1 ) = zero
441 CALL scopy( n, d, 1, work( ietgk ), 2 )
442 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
443 CALL sstevx(
'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 scopy( n, d, 1, work( ietgk ), 2 )
450 CALL scopy( n-1, e, 1, work( ietgk+1 ), 2 )
451 CALL sstevx(
'N',
'I', n*2, work( idtgk ), work( ietgk ),
452 $ vutgk, vutgk, iutgk, iutgk, abstol, ns, s,
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 slaset(
'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 scopy( n, d, 1, work( ietgk ), 2 )
491 CALL scopy( 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 sstevx( 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 = snrm2( nru, z( irowu, icolz+i ), 2 )
635 IF( nrmu.EQ.zero )
THEN
639 CALL sscal( nru, one/nrmu,
640 $ z( irowu,icolz+i ), 2 )
641 IF( nrmu.NE.one .AND.
642 $ abs( nrmu-ortol )*sqrt2.GT.one )
645 zjtji = -sdot( nru, z( irowu, icolz+j ),
646 $ 2, z( irowu, icolz+i ), 2 )
647 CALL saxpy( nru, zjtji,
648 $ z( irowu, icolz+j ), 2,
649 $ z( irowu, icolz+i ), 2 )
651 nrmu = snrm2( nru, z( irowu, icolz+i ), 2 )
652 CALL sscal( nru, one/nrmu,
653 $ z( irowu,icolz+i ), 2 )
656 DO i = 0,
min( nsl-1, nrv-1 )
657 nrmv = snrm2( nrv, z( irowv, icolz+i ), 2 )
658 IF( nrmv.EQ.zero )
THEN
662 CALL sscal( nrv, -one/nrmv,
663 $ z( irowv,icolz+i ), 2 )
664 IF( nrmv.NE.one .AND.
665 $ abs( nrmv-ortol )*sqrt2.GT.one )
668 zjtji = -sdot( nrv, z( irowv, icolz+j ),
669 $ 2, z( irowv, icolz+i ), 2 )
670 CALL saxpy( nru, zjtji,
671 $ z( irowv, icolz+j ), 2,
672 $ z( irowv, icolz+i ), 2 )
674 nrmv = snrm2( nrv, z( irowv, icolz+i ), 2 )
675 CALL sscal( nrv, one/nrmv,
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 ) =
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
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 sswap( 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 scopy( n*2, z( 1,i ), 1, work, 1 )
776 CALL scopy( n, work( 2 ), 2, z( n+1,i ), 1 )
777 CALL scopy( n, work( 1 ), 2, z( 1 ,i ), 1 )
779 CALL scopy( n, work( 2 ), 2, z( 1 ,i ), 1 )
780 CALL scopy( n, work( 1 ), 2, z( n+1,i ), 1 )