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