286
287
288
289
290
291
292 INTEGER DOL, DOU, INFO, LDZ, M, N
293 REAL MINRGP, PIVMIN, RTOL1, RTOL2, VL, VU
294
295
296 INTEGER IBLOCK( * ), INDEXW( * ), ISPLIT( * ),
297 $ ISUPPZ( * ), IWORK( * )
298 REAL D( * ), GERS( * ), L( * ), W( * ), WERR( * ),
299 $ WGAP( * ), WORK( * )
300 COMPLEX Z( LDZ, * )
301
302
303
304
305
306 INTEGER MAXITR
307 parameter( maxitr = 10 )
308 COMPLEX CZERO
309 parameter( czero = ( 0.0e0, 0.0e0 ) )
310 REAL ZERO, ONE, TWO, THREE, FOUR, HALF
311 parameter( zero = 0.0e0, one = 1.0e0,
312 $ two = 2.0e0, three = 3.0e0,
313 $ four = 4.0e0, half = 0.5e0)
314
315
316 LOGICAL ESKIP, NEEDBS, STP2II, TRYRQC, USEDBS, USEDRQ
317 INTEGER DONE, I, IBEGIN, IDONE, IEND, II, IINDC1,
318 $ IINDC2, IINDR, IINDWK, IINFO, IM, IN, INDEIG,
319 $ INDLD, INDLLD, INDWRK, ISUPMN, ISUPMX, ITER,
320 $ ITMP1, J, JBLK, K, MINIWSIZE, MINWSIZE, NCLUS,
321 $ NDEPTH, NEGCNT, NEWCLS, NEWFST, NEWFTT, NEWLST,
322 $ NEWSIZ, OFFSET, OLDCLS, OLDFST, OLDIEN, OLDLST,
323 $ OLDNCL, P, PARITY, Q, WBEGIN, WEND, WINDEX,
324 $ WINDMN, WINDPL, ZFROM, ZTO, ZUSEDL, ZUSEDU,
325 $ ZUSEDW
326 INTEGER INDIN1, INDIN2
327 REAL BSTRES, BSTW, EPS, FUDGE, GAP, GAPTOL, GL, GU,
328 $ LAMBDA, LEFT, LGAP, MINGMA, NRMINV, RESID,
329 $ RGAP, RIGHT, RQCORR, RQTOL, SAVGAP, SGNDEF,
330 $ SIGMA, SPDIAM, SSIGMA, TAU, TMP, TOL, ZTZ
331
332
333 REAL SLAMCH
335
336
339
340
341 INTRINSIC abs, real, max, min
342 INTRINSIC cmplx
343
344
345
346
347 info = 0
348
349
350
351 IF( (n.LE.0).OR.(m.LE.0) ) THEN
352 RETURN
353 END IF
354
355
356 indld = n+1
357 indlld= 2*n+1
358 indin1 = 3*n + 1
359 indin2 = 4*n + 1
360 indwrk = 5*n + 1
361 minwsize = 12 * n
362
363 DO 5 i= 1,minwsize
364 work( i ) = zero
365 5 CONTINUE
366
367
368
369 iindr = 0
370
371
372 iindc1 = n
373 iindc2 = 2*n
374 iindwk = 3*n + 1
375
376 miniwsize = 7 * n
377 DO 10 i= 1,miniwsize
378 iwork( i ) = 0
379 10 CONTINUE
380
381 zusedl = 1
382 IF(dol.GT.1) THEN
383
384 zusedl = dol-1
385 ENDIF
386 zusedu = m
387 IF(dou.LT.m) THEN
388
389 zusedu = dou+1
390 ENDIF
391
392 zusedw = zusedu - zusedl + 1
393
394
395 CALL claset(
'Full', n, zusedw, czero, czero,
396 $ z(1,zusedl), ldz )
397
398 eps =
slamch(
'Precision' )
399 rqtol = two * eps
400
401
402 tryrqc = .true.
403
404 IF((dol.EQ.1).AND.(dou.EQ.m)) THEN
405 ELSE
406
407
408
409 rtol1 = four * eps
410 rtol2 = four * eps
411 ENDIF
412
413
414
415
416
417
418
419
420 done = 0
421 ibegin = 1
422 wbegin = 1
423 DO 170 jblk = 1, iblock( m )
424 iend = isplit( jblk )
425 sigma = l( iend )
426
427
428 wend = wbegin - 1
429 15 CONTINUE
430 IF( wend.LT.m ) THEN
431 IF( iblock( wend+1 ).EQ.jblk ) THEN
432 wend = wend + 1
433 GO TO 15
434 END IF
435 END IF
436 IF( wend.LT.wbegin ) THEN
437 ibegin = iend + 1
438 GO TO 170
439 ELSEIF( (wend.LT.dol).OR.(wbegin.GT.dou) ) THEN
440 ibegin = iend + 1
441 wbegin = wend + 1
442 GO TO 170
443 END IF
444
445
446 gl = gers( 2*ibegin-1 )
447 gu = gers( 2*ibegin )
448 DO 20 i = ibegin+1 , iend
449 gl = min( gers( 2*i-1 ), gl )
450 gu = max( gers( 2*i ), gu )
451 20 CONTINUE
452 spdiam = gu - gl
453
454
455 oldien = ibegin - 1
456
457 in = iend - ibegin + 1
458
459 im = wend - wbegin + 1
460
461
462 IF( ibegin.EQ.iend ) THEN
463 done = done+1
464 z( ibegin, wbegin ) = cmplx( one, zero )
465 isuppz( 2*wbegin-1 ) = ibegin
466 isuppz( 2*wbegin ) = ibegin
467 w( wbegin ) = w( wbegin ) + sigma
468 work( wbegin ) = w( wbegin )
469 ibegin = iend + 1
470 wbegin = wbegin + 1
471 GO TO 170
472 END IF
473
474
475
476
477
478
479
480 CALL scopy( im, w( wbegin ), 1,
481 $ work( wbegin ), 1 )
482
483
484
485 DO 30 i=1,im
486 w(wbegin+i-1) = w(wbegin+i-1)+sigma
487 30 CONTINUE
488
489
490
491 ndepth = 0
492
493 parity = 1
494
495
496 nclus = 1
497 iwork( iindc1+1 ) = 1
498 iwork( iindc1+2 ) = im
499
500
501
502 idone = 0
503
504
505
506 40 CONTINUE
507 IF( idone.LT.im ) THEN
508
509 IF( ndepth.GT.m ) THEN
510 info = -2
511 RETURN
512 ENDIF
513
514
515 oldncl = nclus
516
517 nclus = 0
518
519 parity = 1 - parity
520 IF( parity.EQ.0 ) THEN
521 oldcls = iindc1
522 newcls = iindc2
523 ELSE
524 oldcls = iindc2
525 newcls = iindc1
526 END IF
527
528 DO 150 i = 1, oldncl
529 j = oldcls + 2*i
530
531
532
533 oldfst = iwork( j-1 )
534 oldlst = iwork( j )
535 IF( ndepth.GT.0 ) THEN
536
537
538
539
540
541 IF((dol.EQ.1).AND.(dou.EQ.m)) THEN
542
543
544 j = wbegin + oldfst - 1
545 ELSE
546 IF(wbegin+oldfst-1.LT.dol) THEN
547
548 j = dol - 1
549 ELSEIF(wbegin+oldfst-1.GT.dou) THEN
550
551 j = dou
552 ELSE
553 j = wbegin + oldfst - 1
554 ENDIF
555 ENDIF
556 DO 45 k = 1, in - 1
557 d( ibegin+k-1 ) = real( z( ibegin+k-1,
558 $ j ) )
559 l( ibegin+k-1 ) = real( z( ibegin+k-1,
560 $ j+1 ) )
561 45 CONTINUE
562 d( iend ) = real( z( iend, j ) )
563 sigma = real( z( iend, j+1 ) )
564
565
566 CALL claset(
'Full', in, 2, czero, czero,
567 $ z( ibegin, j), ldz )
568 END IF
569
570
571 DO 50 j = ibegin, iend-1
572 tmp = d( j )*l( j )
573 work( indld-1+j ) = tmp
574 work( indlld-1+j ) = tmp*l( j )
575 50 CONTINUE
576
577 IF( ndepth.GT.0 ) THEN
578
579
580 p = indexw( wbegin-1+oldfst )
581 q = indexw( wbegin-1+oldlst )
582
583
584
585 offset = indexw( wbegin ) - 1
586
587
588 CALL slarrb( in, d( ibegin ),
589 $ work(indlld+ibegin-1),
590 $ p, q, rtol1, rtol2, offset,
591 $ work(wbegin),wgap(wbegin),werr(wbegin),
592 $ work( indwrk ), iwork( iindwk ),
593 $ pivmin, spdiam, in, iinfo )
594 IF( iinfo.NE.0 ) THEN
595 info = -1
596 RETURN
597 ENDIF
598
599
600
601
602
603
604
605 IF( oldfst.GT.1) THEN
606 wgap( wbegin+oldfst-2 ) =
607 $ max(wgap(wbegin+oldfst-2),
608 $ w(wbegin+oldfst-1)-werr(wbegin+oldfst-1)
609 $ - w(wbegin+oldfst-2)-werr(wbegin+oldfst-2) )
610 ENDIF
611 IF( wbegin + oldlst -1 .LT. wend ) THEN
612 wgap( wbegin+oldlst-1 ) =
613 $ max(wgap(wbegin+oldlst-1),
614 $ w(wbegin+oldlst)-werr(wbegin+oldlst)
615 $ - w(wbegin+oldlst-1)-werr(wbegin+oldlst-1) )
616 ENDIF
617
618
619 DO 53 j=oldfst,oldlst
620 w(wbegin+j-1) = work(wbegin+j-1)+sigma
621 53 CONTINUE
622 END IF
623
624
625 newfst = oldfst
626 DO 140 j = oldfst, oldlst
627 IF( j.EQ.oldlst ) THEN
628
629
630 newlst = j
631 ELSE IF ( wgap( wbegin + j -1).GE.
632 $ minrgp* abs( work(wbegin + j -1) ) ) THEN
633
634
635 newlst = j
636 ELSE
637
638
639 GOTO 140
640 END IF
641
642
643 newsiz = newlst - newfst + 1
644
645
646
647 IF((dol.EQ.1).AND.(dou.EQ.m)) THEN
648
649
650 newftt = wbegin + newfst - 1
651 ELSE
652 IF(wbegin+newfst-1.LT.dol) THEN
653
654 newftt = dol - 1
655 ELSEIF(wbegin+newfst-1.GT.dou) THEN
656
657 newftt = dou
658 ELSE
659 newftt = wbegin + newfst - 1
660 ENDIF
661 ENDIF
662
663 IF( newsiz.GT.1) THEN
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 IF( newfst.EQ.1 ) THEN
679 lgap = max( zero,
680 $ w(wbegin)-werr(wbegin) - vl )
681 ELSE
682 lgap = wgap( wbegin+newfst-2 )
683 ENDIF
684 rgap = wgap( wbegin+newlst-1 )
685
686
687
688
689
690
691 DO 55 k =1,2
692 IF(k.EQ.1) THEN
693 p = indexw( wbegin-1+newfst )
694 ELSE
695 p = indexw( wbegin-1+newlst )
696 ENDIF
697 offset = indexw( wbegin ) - 1
698 CALL slarrb( in, d(ibegin),
699 $ work( indlld+ibegin-1 ),p,p,
700 $ rqtol, rqtol, offset,
701 $ work(wbegin),wgap(wbegin),
702 $ werr(wbegin),work( indwrk ),
703 $ iwork( iindwk ), pivmin, spdiam,
704 $ in, iinfo )
705 55 CONTINUE
706
707 IF((wbegin+newlst-1.LT.dol).OR.
708 $ (wbegin+newfst-1.GT.dou)) THEN
709
710
711
712
713
714
715
716 idone = idone + newlst - newfst + 1
717 GOTO 139
718 ENDIF
719
720
721
722
723
724 CALL slarrf( in, d( ibegin ), l( ibegin ),
725 $ work(indld+ibegin-1),
726 $ newfst, newlst, work(wbegin),
727 $ wgap(wbegin), werr(wbegin),
728 $ spdiam, lgap, rgap, pivmin, tau,
729 $ work( indin1 ), work( indin2 ),
730 $ work( indwrk ), iinfo )
731
732
733
734 DO 56 k = 1, in-1
735 z( ibegin+k-1, newftt ) =
736 $ cmplx( work( indin1+k-1 ), zero )
737 z( ibegin+k-1, newftt+1 ) =
738 $ cmplx( work( indin2+k-1 ), zero )
739 56 CONTINUE
740 z( iend, newftt ) =
741 $ cmplx( work( indin1+in-1 ), zero )
742 IF( iinfo.EQ.0 ) THEN
743
744
745 ssigma = sigma + tau
746 z( iend, newftt+1 ) = cmplx( ssigma, zero )
747
748
749 DO 116 k = newfst, newlst
750 fudge =
751 $ three*eps*abs(work(wbegin+k-1))
752 work( wbegin + k - 1 ) =
753 $ work( wbegin + k - 1) - tau
754 fudge = fudge +
755 $ four*eps*abs(work(wbegin+k-1))
756
757 werr( wbegin + k - 1 ) =
758 $ werr( wbegin + k - 1 ) + fudge
759
760
761
762
763
764
765
766 116 CONTINUE
767
768 nclus = nclus + 1
769 k = newcls + 2*nclus
770 iwork( k-1 ) = newfst
771 iwork( k ) = newlst
772 ELSE
773 info = -2
774 RETURN
775 ENDIF
776 ELSE
777
778
779
780 iter = 0
781
782 tol = four * log(real(in)) * eps
783
784 k = newfst
785 windex = wbegin + k - 1
786 windmn = max(windex - 1,1)
787 windpl = min(windex + 1,m)
788 lambda = work( windex )
789 done = done + 1
790
791 IF((windex.LT.dol).OR.
792 $ (windex.GT.dou)) THEN
793 eskip = .true.
794 GOTO 125
795 ELSE
796 eskip = .false.
797 ENDIF
798 left = work( windex ) - werr( windex )
799 right = work( windex ) + werr( windex )
800 indeig = indexw( windex )
801
802
803
804
805
806
807
808 IF( k .EQ. 1) THEN
809
810
811
812
813
814
815 lgap = eps*max(abs(left),abs(right))
816 ELSE
817 lgap = wgap(windmn)
818 ENDIF
819 IF( k .EQ. im) THEN
820
821
822
823
824
825 rgap = eps*max(abs(left),abs(right))
826 ELSE
827 rgap = wgap(windex)
828 ENDIF
829 gap = min( lgap, rgap )
830 IF(( k .EQ. 1).OR.(k .EQ. im)) THEN
831
832
833
834 gaptol = zero
835 ELSE
836 gaptol = gap * eps
837 ENDIF
838 isupmn = in
839 isupmx = 1
840
841
842
843
844
845 savgap = wgap(windex)
846 wgap(windex) = gap
847
848
849
850
851
852
853 usedbs = .false.
854 usedrq = .false.
855
856 needbs = .NOT.tryrqc
857 120 CONTINUE
858
859 IF(needbs) THEN
860
861 usedbs = .true.
862 itmp1 = iwork( iindr+windex )
863 offset = indexw( wbegin ) - 1
864 CALL slarrb( in, d(ibegin),
865 $ work(indlld+ibegin-1),indeig,indeig,
866 $ zero, two*eps, offset,
867 $ work(wbegin),wgap(wbegin),
868 $ werr(wbegin),work( indwrk ),
869 $ iwork( iindwk ), pivmin, spdiam,
870 $ itmp1, iinfo )
871 IF( iinfo.NE.0 ) THEN
872 info = -3
873 RETURN
874 ENDIF
875 lambda = work( windex )
876
877
878 iwork( iindr+windex ) = 0
879 ENDIF
880
881 CALL clar1v( in, 1, in, lambda, d( ibegin ),
882 $ l( ibegin ), work(indld+ibegin-1),
883 $ work(indlld+ibegin-1),
884 $ pivmin, gaptol, z( ibegin, windex ),
885 $ .NOT.usedbs, negcnt, ztz, mingma,
886 $ iwork( iindr+windex ), isuppz( 2*windex-1 ),
887 $ nrminv, resid, rqcorr, work( indwrk ) )
888 IF(iter .EQ. 0) THEN
889 bstres = resid
890 bstw = lambda
891 ELSEIF(resid.LT.bstres) THEN
892 bstres = resid
893 bstw = lambda
894 ENDIF
895 isupmn = min(isupmn,isuppz( 2*windex-1 ))
896 isupmx = max(isupmx,isuppz( 2*windex ))
897 iter = iter + 1
898
899
900
901
902
903
904
905
906
907
908 IF( resid.GT.tol*gap .AND. abs( rqcorr ).GT.
909 $ rqtol*abs( lambda ) .AND. .NOT. usedbs)
910 $ THEN
911
912
913
914 IF(indeig.LE.negcnt) THEN
915
916 sgndef = -one
917 ELSE
918
919 sgndef = one
920 ENDIF
921
922
923 IF( ( rqcorr*sgndef.GE.zero )
924 $ .AND.( lambda + rqcorr.LE. right)
925 $ .AND.( lambda + rqcorr.GE. left)
926 $ ) THEN
927 usedrq = .true.
928
929 IF(sgndef.EQ.one) THEN
930
931
932 left = lambda
933
934
935
936
937
938
939 ELSE
940
941
942 right = lambda
943
944
945
946 ENDIF
947 work( windex ) =
948 $ half * (right + left)
949
950
951 lambda = lambda + rqcorr
952
953 werr( windex ) =
954 $ half * (right-left)
955 ELSE
956 needbs = .true.
957 ENDIF
958 IF(right-left.LT.rqtol*abs(lambda)) THEN
959
960
961 usedbs = .true.
962 GOTO 120
963 ELSEIF( iter.LT.maxitr ) THEN
964 GOTO 120
965 ELSEIF( iter.EQ.maxitr ) THEN
966 needbs = .true.
967 GOTO 120
968 ELSE
969 info = 5
970 RETURN
971 END IF
972 ELSE
973 stp2ii = .false.
974 IF(usedrq .AND. usedbs .AND.
975 $ bstres.LE.resid) THEN
976 lambda = bstw
977 stp2ii = .true.
978 ENDIF
979 IF (stp2ii) THEN
980
981 CALL clar1v( in, 1, in, lambda,
982 $ d( ibegin ), l( ibegin ),
983 $ work(indld+ibegin-1),
984 $ work(indlld+ibegin-1),
985 $ pivmin, gaptol, z( ibegin, windex ),
986 $ .NOT.usedbs, negcnt, ztz, mingma,
987 $ iwork( iindr+windex ),
988 $ isuppz( 2*windex-1 ),
989 $ nrminv, resid, rqcorr, work( indwrk ) )
990 ENDIF
991 work( windex ) = lambda
992 END IF
993
994
995
996 isuppz( 2*windex-1 ) = isuppz( 2*windex-1 )+oldien
997 isuppz( 2*windex ) = isuppz( 2*windex )+oldien
998 zfrom = isuppz( 2*windex-1 )
999 zto = isuppz( 2*windex )
1000 isupmn = isupmn + oldien
1001 isupmx = isupmx + oldien
1002
1003 IF(isupmn.LT.zfrom) THEN
1004 DO 122 ii = isupmn,zfrom-1
1005 z( ii, windex ) = zero
1006 122 CONTINUE
1007 ENDIF
1008 IF(isupmx.GT.zto) THEN
1009 DO 123 ii = zto+1,isupmx
1010 z( ii, windex ) = zero
1011 123 CONTINUE
1012 ENDIF
1013 CALL csscal( zto-zfrom+1, nrminv,
1014 $ z( zfrom, windex ), 1 )
1015 125 CONTINUE
1016
1017 w( windex ) = lambda+sigma
1018
1019
1020
1021
1022
1023
1024 IF(.NOT.eskip) THEN
1025 IF( k.GT.1) THEN
1026 wgap( windmn ) = max( wgap(windmn),
1027 $ w(windex)-werr(windex)
1028 $ - w(windmn)-werr(windmn) )
1029 ENDIF
1030 IF( windex.LT.wend ) THEN
1031 wgap( windex ) = max( savgap,
1032 $ w( windpl )-werr( windpl )
1033 $ - w( windex )-werr( windex) )
1034 ENDIF
1035 ENDIF
1036 idone = idone + 1
1037 ENDIF
1038
1039
1040 139 CONTINUE
1041
1042 newfst = j + 1
1043 140 CONTINUE
1044 150 CONTINUE
1045 ndepth = ndepth + 1
1046 GO TO 40
1047 END IF
1048 ibegin = iend + 1
1049 wbegin = wend + 1
1050 170 CONTINUE
1051
1052
1053 RETURN
1054
1055
1056
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
real function slamch(cmach)
SLAMCH
subroutine clar1v(n, b1, bn, lambda, d, l, ld, lld, pivmin, gaptol, z, wantnc, negcnt, ztz, mingma, r, isuppz, nrminv, resid, rqcorr, work)
CLAR1V computes the (scaled) r-th column of the inverse of the submatrix in rows b1 through bn of the...
subroutine slarrb(n, d, lld, ifirst, ilast, rtol1, rtol2, offset, w, wgap, werr, work, iwork, pivmin, spdiam, twist, info)
SLARRB provides limited bisection to locate eigenvalues for more accuracy.
subroutine slarrf(n, d, l, ld, clstrt, clend, w, wgap, werr, spdiam, clgapl, clgapr, pivmin, sigma, dplus, lplus, work, info)
SLARRF finds a new relatively robust representation such that at least one of the eigenvalues is rela...
subroutine claset(uplo, m, n, alpha, beta, a, lda)
CLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine csscal(n, sa, cx, incx)
CSSCAL