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)
subroutine daxpy(n, da, dx, incx, dy, incy)
DAXPY
subroutine dbdsvdx(uplo, jobz, range, n, d, e, vl, vu, il, iu, ns, s, z, ldz, work, iwork, info)
DBDSVDX
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
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 dscal(n, da, dx, incx)
DSCAL
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 matrice...
subroutine dswap(n, dx, incx, dy, incy)
DSWAP