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, NS
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, 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 REAL ABSTOL, EPS, 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 .AND. ldz.LT.n*2 ) ) info = -14
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' )
342 sqrt2 = sqrt( 2.0e0 )
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,
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 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,
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 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 )
subroutine sbdsvdx(UPLO, JOBZ, RANGE, N, D, E, VL, VU, IL, IU, NS, S, Z, LDZ, WORK, IWORK, INFO)
SBDSVDX
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine sswap(N, SX, INCX, SY, INCY)
SSWAP
subroutine slaset(UPLO, M, N, ALPHA, BETA, A, LDA)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values...
subroutine scopy(N, SX, INCX, SY, INCY)
SCOPY
subroutine saxpy(N, SA, SX, INCX, SY, INCY)
SAXPY
subroutine sscal(N, SA, SX, INCX)
SSCAL
subroutine sstevx(JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL, M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO)
SSTEVX computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matric...