|
SRC\pdstebz.f |
|
| #lines: 1458 size: 51 Kb creation: 18/01/2006 23:36:04 last modification: 08/05/2008 18:37:59 attribute: ARCH Find Reload | |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 689: 690: 691: 692: 693: 694: 695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767: 768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815: 816: 817: 818: 819: 820: 821: 822: 823: 824: 825: 826: 827: 828: 829: 830: 831: 832: 833: 834: 835: 836: 837: 838: 839: 840: 841: 842: 843: 844: 845: 846: 847: 848: 849: 850: 851: 852: 853: 854: 855: 856: 857: 858: 859: 860: 861: 862: 863: 864: 865: 866: 867: 868: 869: 870: 871: 872: 873: 874: 875: 876: 877: 878: 879: 880: 881: 882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892: 893: 894: 895: 896: 897: 898: 899: 900: 901: 902: 903: 904: 905: 906: 907: 908: 909: 910: 911: 912: 913: 914: 915: 916: 917: 918: 919: 920: 921: 922: 923: 924: 925: 926: 927: 928: 929: 930: 931: 932: 933: 934: 935: 936: 937: 938: 939: 940: 941: 942: 943: 944: 945: 946: 947: 948: 949: 950: 951: 952: 953: 954: 955: 956: 957: 958: 959: 960: 961: 962: 963: 964: 965: 966: 967: 968: 969: 970: 971: 972: 973: 974: 975: 976: 977: 978: 979: 980: 981: 982: 983: 984: 985: 986: 987: 988: 989: 990: 991: 992: 993: 994: 995: 996: 997: 998: 999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194: 1195: 1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205: 1206: 1207: 1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234: 1235: 1236: 1237: 1238: 1239: 1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254: 1255: 1256: 1257: 1258: 1259: 1260: 1261: 1262: 1263: 1264: 1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290: 1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355: 1356: 1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364: 1365: 1366: 1367: 1368: 1369: 1370: 1371: 1372: 1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392: 1393: 1394: 1395: 1396: 1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414: 1415: 1416: 1417: 1418: 1419: 1420: 1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430: 1431: 1432: 1433: 1434: 1435: 1436: 1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458: |
SUBROUTINE PDSTEBZ( ICTXT, RANGE, ORDER, N, VL, VU, IL, IU,
$ ABSTOL, D, E, M, NSPLIT, W, IBLOCK, ISPLIT,
$ WORK, LWORK, IWORK, LIWORK, INFO )
*
* -- ScaLAPACK routine (version 1.7) --
* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
* and University of California, Berkeley.
* November 15, 1997
*
* .. Scalar Arguments ..
CHARACTER ORDER, RANGE
INTEGER ICTXT, IL, INFO, IU, LIWORK, LWORK, M, N,
$ NSPLIT
DOUBLE PRECISION ABSTOL, VL, VU
* ..
* .. Array Arguments ..
INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
* ..
*
* Purpose
* =======
*
* PDSTEBZ computes the eigenvalues of a symmetric tridiagonal matrix in
* parallel. The user may ask for all eigenvalues, all eigenvalues in
* the interval [VL, VU], or the eigenvalues indexed IL through IU. A
* static partitioning of work is done at the beginning of PDSTEBZ which
* results in all processes finding an (almost) equal number of
* eigenvalues.
*
* NOTE : It is assumed that the user is on an IEEE machine. If the user
* is not on an IEEE mchine, set the compile time flag NO_IEEE
* to 1 (in SLmake.inc). The features of IEEE arithmetic that
* are needed for the "fast" Sturm Count are : (a) infinity
* arithmetic (b) the sign bit of a single precision floating
* point number is assumed be in the 32nd bit position
* (c) the sign of negative zero.
*
* See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
* Matrix", Report CS41, Computer Science Dept., Stanford
* University, July 21, 1966.
*
* Arguments
* =========
*
* ICTXT (global input) INTEGER
* The BLACS context handle.
*
* RANGE (global input) CHARACTER
* Specifies which eigenvalues are to be found.
* = 'A': ("All") all eigenvalues will be found.
* = 'V': ("Value") all eigenvalues in the interval
* [VL, VU] will be found.
* = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
* entire matrix) will be found.
*
* ORDER (global input) CHARACTER
* Specifies the order in which the eigenvalues and their block
* numbers are stored in W and IBLOCK.
* = 'B': ("By Block") the eigenvalues will be grouped by
* split-off block (see IBLOCK, ISPLIT) and
* ordered from smallest to largest within
* the block.
* = 'E': ("Entire matrix")
* the eigenvalues for the entire matrix
* will be ordered from smallest to largest.
*
* N (global input) INTEGER
* The order of the tridiagonal matrix T. N >= 0.
*
* VL (global input) DOUBLE PRECISION
* If RANGE='V', the lower bound of the interval to be searched
* for eigenvalues. Eigenvalues less than VL will not be
* returned. Not referenced if RANGE='A' or 'I'.
*
* VU (global input) DOUBLE PRECISION
* If RANGE='V', the upper bound of the interval to be searched
* for eigenvalues. Eigenvalues greater than VU will not be
* returned. VU must be greater than VL. Not referenced if
* RANGE='A' or 'I'.
*
* IL (global input) INTEGER
* If RANGE='I', the index (from smallest to largest) of the
* smallest eigenvalue to be returned. IL must be at least 1.
* Not referenced if RANGE='A' or 'V'.
*
* IU (global input) INTEGER
* If RANGE='I', the index (from smallest to largest) of the
* largest eigenvalue to be returned. IU must be at least IL
* and no greater than N. Not referenced if RANGE='A' or 'V'.
*
* ABSTOL (global input) DOUBLE PRECISION
* The absolute tolerance for the eigenvalues. An eigenvalue
* (or cluster) is considered to be located if it has been
* determined to lie in an interval whose width is ABSTOL or
* less. If ABSTOL is less than or equal to zero, then ULP*|T|
* will be used, where |T| means the 1-norm of T.
* Eigenvalues will be computed most accurately when ABSTOL is
* set to the underflow threshold DLAMCH('U'), not zero.
* Note : If eigenvectors are desired later by inverse iteration
* ( PDSTEIN ), ABSTOL should be set to 2*PDLAMCH('S').
*
* D (global input) DOUBLE PRECISION array, dimension (N)
* The n diagonal elements of the tridiagonal matrix T. To
* avoid overflow, the matrix must be scaled so that its largest
* entry is no greater than overflow**(1/2) * underflow**(1/4)
* in absolute value, and for greatest accuracy, it should not
* be much smaller than that.
*
* E (global input) DOUBLE PRECISION array, dimension (N-1)
* The (n-1) off-diagonal elements of the tridiagonal matrix T.
* To avoid overflow, the matrix must be scaled so that its
* largest entry is no greater than overflow**(1/2) *
* underflow**(1/4) in absolute value, and for greatest
* accuracy, it should not be much smaller than that.
*
* M (global output) INTEGER
* The actual number of eigenvalues found. 0 <= M <= N.
* (See also the description of INFO=2)
*
* NSPLIT (global output) INTEGER
* The number of diagonal blocks in the matrix T.
* 1 <= NSPLIT <= N.
*
* W (global output) DOUBLE PRECISION array, dimension (N)
* On exit, the first M elements of W contain the eigenvalues
* on all processes.
*
* IBLOCK (global output) INTEGER array, dimension (N)
* At each row/column j where E(j) is zero or small, the
* matrix T is considered to split into a block diagonal
* matrix. On exit IBLOCK(i) specifies which block (from 1
* to the number of blocks) the eigenvalue W(i) belongs to.
* NOTE: in the (theoretically impossible) event that bisection
* does not converge for some or all eigenvalues, INFO is set
* to 1 and the ones for which it did not are identified by a
* negative block number.
*
* ISPLIT (global output) INTEGER array, dimension (N)
* The splitting points, at which T breaks up into submatrices.
* The first submatrix consists of rows/columns 1 to ISPLIT(1),
* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
* etc., and the NSPLIT-th consists of rows/columns
* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
* (Only the first NSPLIT elements will actually be used, but
* since the user cannot know a priori what value NSPLIT will
* have, N words must be reserved for ISPLIT.)
*
* WORK (local workspace) DOUBLE PRECISION array,
* dimension ( MAX( 5*N, 7 ) )
*
* LWORK (local input) INTEGER
* size of array WORK must be >= MAX( 5*N, 7 )
* If LWORK = -1, then LWORK is global input and a workspace
* query is assumed; the routine only calculates the minimum
* and optimal size for all work arrays. Each of these
* values is returned in the first entry of the corresponding
* work array, and no error message is issued by PXERBLA.
*
* IWORK (local workspace) INTEGER array, dimension ( MAX( 4*N, 14 ) )
*
* LIWORK (local input) INTEGER
* size of array IWORK must be >= MAX( 4*N, 14, NPROCS )
* If LIWORK = -1, then LIWORK is global input and a workspace
* query is assumed; the routine only calculates the minimum
* and optimal size for all work arrays. Each of these
* values is returned in the first entry of the corresponding
* work array, and no error message is issued by PXERBLA.
*
* INFO (global output) INTEGER
* = 0 : successful exit
* < 0 : if INFO = -i, the i-th argument had an illegal value
* > 0 : some or all of the eigenvalues failed to converge or
* were not computed:
* = 1 : Bisection failed to converge for some eigenvalues;
* these eigenvalues are flagged by a negative block
* number. The effect is that the eigenvalues may not
* be as accurate as the absolute and relative
* tolerances. This is generally caused by arithmetic
* which is less accurate than PDLAMCH says.
* = 2 : There is a mismatch between the number of
* eigenvalues output and the number desired.
* = 3 : RANGE='i', and the Gershgorin interval initially
* used was incorrect. No eigenvalues were computed.
* Probable cause: your machine has sloppy floating
* point arithmetic.
* Cure: Increase the PARAMETER "FUDGE", recompile,
* and try again.
*
* Internal Parameters
* ===================
*
* RELFAC DOUBLE PRECISION, default = 2.0
* The relative tolerance. An interval [a,b] lies within
* "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|),
* where "ulp" is the machine precision (distance from 1 to
* the next larger floating point number.)
*
* FUDGE DOUBLE PRECISION, default = 2.0
* A "fudge factor" to widen the Gershgorin intervals. Ideally,
* a value of 1 should work, but on machines with sloppy
* arithmetic, this needs to be larger. The default for
* publicly released versions should be large enough to handle
* the worst machine around. Note that this has no effect
* on the accuracy of the solution.
*
* =====================================================================
*
* .. Intrinsic Functions ..
INTRINSIC ABS, DBLE, ICHAR, MAX, MIN, MOD
* ..
* .. External Functions ..
LOGICAL LSAME
INTEGER BLACS_PNUM
DOUBLE PRECISION PDLAMCH
EXTERNAL LSAME, BLACS_PNUM, PDLAMCH
* ..
* .. External Subroutines ..
EXTERNAL BLACS_FREEBUFF, BLACS_GET, BLACS_GRIDEXIT,
$ BLACS_GRIDINFO, BLACS_GRIDMAP, DGEBR2D,
$ DGEBS2D, DGERV2D, DGESD2D, DLASRT2, GLOBCHK,
$ IGEBR2D, IGEBS2D, IGERV2D, IGESD2D, IGSUM2D,
$ PDLAEBZ, PDLAIECTB, PDLAIECTL, PDLAPDCT,
$ PDLASNBT, PXERBLA
* ..
* .. Parameters ..
INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
$ MB_, NB_, RSRC_, CSRC_, LLD_
PARAMETER ( BLOCK_CYCLIC_2D = 1, DLEN_ = 9, DTYPE_ = 1,
$ CTXT_ = 2, M_ = 3, N_ = 4, MB_ = 5, NB_ = 6,
$ RSRC_ = 7, CSRC_ = 8, LLD_ = 9 )
INTEGER BIGNUM, DESCMULT
PARAMETER ( BIGNUM = 10000, DESCMULT = 100 )
DOUBLE PRECISION ZERO, ONE, TWO, FIVE, HALF
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0,
$ FIVE = 5.0D+0, HALF = 1.0D+0 / TWO )
DOUBLE PRECISION FUDGE, RELFAC
PARAMETER ( FUDGE = 2.0D+0, RELFAC = 2.0D+0 )
* ..
* .. Local Scalars ..
LOGICAL LQUERY
INTEGER BLKNO, FOUND, I, IBEGIN, IEFLAG, IEND, IFRST,
$ IINFO, ILAST, ILOAD, IM, IMYLOAD, IN, INDRIW1,
$ INDRIW2, INDRW1, INDRW2, INXTLOAD, IOFF,
$ IORDER, IOUT, IRANGE, IRECV, IREM, ITMP1,
$ ITMP2, J, JB, K, LAST, LEXTRA, LREQ, MYCOL,
$ MYROW, NALPHA, NBETA, NCMP, NEIGINT, NEXT, NGL,
$ NGLOB, NGU, NINT, NPCOL, NPROW, OFFSET,
$ ONEDCONTEXT, P, PREV, REXTRA, RREQ, SELF,
$ TORECV
DOUBLE PRECISION ALPHA, ATOLI, BETA, BNORM, DRECV, DSEND, GL,
$ GU, INITVL, INITVU, LSAVE, MID, PIVMIN, RELTOL,
$ SAFEMN, TMP1, TMP2, TNORM, ULP
* ..
* .. Local Arrays ..
INTEGER IDUM( 5, 2 )
* ..
* .. Executable Statements ..
* This is just to keep ftnchek happy
IF( BLOCK_CYCLIC_2D*CSRC_*CTXT_*DLEN_*DTYPE_*LLD_*MB_*M_*NB_*N_*
$ RSRC_.LT.0 )RETURN
*
* Set up process grid
*
CALL BLACS_GRIDINFO( ICTXT, NPROW, NPCOL, MYROW, MYCOL )
*
INFO = 0
M = 0
*
* Decode RANGE
*
IF( LSAME( RANGE, 'A' ) ) THEN
IRANGE = 1
ELSE IF( LSAME( RANGE, 'V' ) ) THEN
IRANGE = 2
ELSE IF( LSAME( RANGE, 'I' ) ) THEN
IRANGE = 3
ELSE
IRANGE = 0
END IF
*
* Decode ORDER
*
IF( LSAME( ORDER, 'B' ) ) THEN
IORDER = 2
ELSE IF( LSAME( ORDER, 'E' ) .OR. LSAME( ORDER, 'A' ) ) THEN
IORDER = 1
ELSE
IORDER = 0
END IF
*
* Check for Errors
*
IF( NPROW.EQ.-1 ) THEN
INFO = -1
ELSE
*
* Get machine constants
*
SAFEMN = PDLAMCH( ICTXT, 'S' )
ULP = PDLAMCH( ICTXT, 'P' )
RELTOL = ULP*RELFAC
IDUM( 1, 1 ) = ICHAR( RANGE )
IDUM( 1, 2 ) = 2
IDUM( 2, 1 ) = ICHAR( ORDER )
IDUM( 2, 2 ) = 3
IDUM( 3, 1 ) = N
IDUM( 3, 2 ) = 4
NGLOB = 5
IF( IRANGE.EQ.3 ) THEN
IDUM( 4, 1 ) = IL
IDUM( 4, 2 ) = 7
IDUM( 5, 1 ) = IU
IDUM( 5, 2 ) = 8
ELSE
IDUM( 4, 1 ) = 0
IDUM( 4, 2 ) = 0
IDUM( 5, 1 ) = 0
IDUM( 5, 2 ) = 0
END IF
IF( MYROW.EQ.0 .AND. MYCOL.EQ.0 ) THEN
WORK( 1 ) = ABSTOL
IF( IRANGE.EQ.2 ) THEN
WORK( 2 ) = VL
WORK( 3 ) = VU
ELSE
WORK( 2 ) = ZERO
WORK( 3 ) = ZERO
END IF
CALL DGEBS2D( ICTXT, 'ALL', ' ', 3, 1, WORK, 3 )
ELSE
CALL DGEBR2D( ICTXT, 'ALL', ' ', 3, 1, WORK, 3, 0, 0 )
END IF
LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
IF( INFO.EQ.0 ) THEN
IF( IRANGE.EQ.0 ) THEN
INFO = -2
ELSE IF( IORDER.EQ.0 ) THEN
INFO = -3
ELSE IF( IRANGE.EQ.2 .AND. VL.GE.VU ) THEN
INFO = -5
ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1,
$ N ) ) ) THEN
INFO = -6
ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N,
$ IL ) .OR. IU.GT.N ) ) THEN
INFO = -7
ELSE IF( LWORK.LT.MAX( 5*N, 7 ) .AND. .NOT.LQUERY ) THEN
INFO = -18
ELSE IF( LIWORK.LT.MAX( 4*N, 14, NPROW*NPCOL ) .AND. .NOT.
$ LQUERY ) THEN
INFO = -20
ELSE IF( IRANGE.EQ.2 .AND. ( ABS( WORK( 2 )-VL ).GT.FIVE*
$ ULP*ABS( VL ) ) ) THEN
INFO = -5
ELSE IF( IRANGE.EQ.2 .AND. ( ABS( WORK( 3 )-VU ).GT.FIVE*
$ ULP*ABS( VU ) ) ) THEN
INFO = -6
ELSE IF( ABS( WORK( 1 )-ABSTOL ).GT.FIVE*ULP*ABS( ABSTOL ) )
$ THEN
INFO = -9
END IF
END IF
IF( INFO.EQ.0 )
$ INFO = BIGNUM
CALL GLOBCHK( ICTXT, NGLOB, IDUM, 5, IWORK, INFO )
IF( INFO.EQ.BIGNUM ) THEN
INFO = 0
ELSE IF( MOD( INFO, DESCMULT ).EQ.0 ) THEN
INFO = -INFO / DESCMULT
ELSE
INFO = -INFO
END IF
END IF
WORK( 1 ) = DBLE( MAX( 5*N, 7 ) )
IWORK( 1 ) = MAX( 4*N, 14, NPROW*NPCOL )
*
IF( INFO.NE.0 ) THEN
CALL PXERBLA( ICTXT, 'PDSTEBZ', -INFO )
RETURN
ELSE IF( LWORK.EQ.-1 .AND. LIWORK.EQ.-1 ) THEN
RETURN
END IF
*
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
*
K = 1
DO 20 I = 0, NPROW - 1
DO 10 J = 0, NPCOL - 1
IWORK( K ) = BLACS_PNUM( ICTXT, I, J )
K = K + 1
10 CONTINUE
20 CONTINUE
*
P = NPROW*NPCOL
NPROW = 1
NPCOL = P
*
CALL BLACS_GET( ICTXT, 10, ONEDCONTEXT )
CALL BLACS_GRIDMAP( ONEDCONTEXT, IWORK, NPROW, NPROW, NPCOL )
CALL BLACS_GRIDINFO( ONEDCONTEXT, I, J, K, SELF )
*
* Simplifications:
*
IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
$ IRANGE = 1
*
NEXT = MOD( SELF+1, P )
PREV = MOD( P+SELF-1, P )
*
* Compute squares of off-diagonals, splitting points and pivmin.
* Interleave diagonals and off-diagonals.
*
INDRW1 = MAX( 2*N, 4 )
INDRW2 = INDRW1 + 2*N
INDRIW1 = MAX( 2*N, 8 )
NSPLIT = 1
WORK( INDRW1+2*N ) = ZERO
PIVMIN = ONE
*
DO 30 I = 1, N - 1
TMP1 = E( I )**2
J = 2*I
WORK( INDRW1+J-1 ) = D( I )
IF( ABS( D( I+1 )*D( I ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN
ISPLIT( NSPLIT ) = I
NSPLIT = NSPLIT + 1
WORK( INDRW1+J ) = ZERO
ELSE
WORK( INDRW1+J ) = TMP1
PIVMIN = MAX( PIVMIN, TMP1 )
END IF
30 CONTINUE
WORK( INDRW1+2*N-1 ) = D( N )
ISPLIT( NSPLIT ) = N
PIVMIN = PIVMIN*SAFEMN
*
* Compute Gershgorin interval [gl,gu] for entire matrix
*
GU = D( 1 )
GL = D( 1 )
TMP1 = ZERO
*
DO 40 I = 1, N - 1
TMP2 = ABS( E( I ) )
GU = MAX( GU, D( I )+TMP1+TMP2 )
GL = MIN( GL, D( I )-TMP1-TMP2 )
TMP1 = TMP2
40 CONTINUE
GU = MAX( GU, D( N )+TMP1 )
GL = MIN( GL, D( N )-TMP1 )
TNORM = MAX( ABS( GL ), ABS( GU ) )
GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
*
IF( ABSTOL.LE.ZERO ) THEN
ATOLI = ULP*TNORM
ELSE
ATOLI = ABSTOL
END IF
*
* Find out if on an IEEE machine, the sign bit is the
* 32nd bit (Big Endian) or the 64th bit (Little Endian)
*
IF( IRANGE.EQ.1 .OR. NSPLIT.EQ.1 ) THEN
CALL PDLASNBT( IEFLAG )
ELSE
IEFLAG = 0
END IF
LEXTRA = 0
REXTRA = 0
*
* Form Initial Interval containing desired eigenvalues
*
IF( IRANGE.EQ.1 ) THEN
INITVL = GL
INITVU = GU
WORK( 1 ) = GL
WORK( 2 ) = GU
IWORK( 1 ) = 0
IWORK( 2 ) = N
IFRST = 1
ILAST = N
ELSE IF( IRANGE.EQ.2 ) THEN
IF( VL.GT.GL ) THEN
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( VL, N, WORK( INDRW1+1 ), PIVMIN, IFRST )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( VL, N, WORK( INDRW1+1 ), IFRST )
ELSE
CALL PDLAIECTL( VL, N, WORK( INDRW1+1 ), IFRST )
END IF
IFRST = IFRST + 1
INITVL = VL
ELSE
INITVL = GL
IFRST = 1
END IF
IF( VU.LT.GU ) THEN
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( VU, N, WORK( INDRW1+1 ), PIVMIN, ILAST )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( VU, N, WORK( INDRW1+1 ), ILAST )
ELSE
CALL PDLAIECTL( VU, N, WORK( INDRW1+1 ), ILAST )
END IF
INITVU = VU
ELSE
INITVU = GU
ILAST = N
END IF
WORK( 1 ) = INITVL
WORK( 2 ) = INITVU
IWORK( 1 ) = IFRST - 1
IWORK( 2 ) = ILAST
ELSE IF( IRANGE.EQ.3 ) THEN
WORK( 1 ) = GL
WORK( 2 ) = GU
IWORK( 1 ) = 0
IWORK( 2 ) = N
IWORK( 5 ) = IL - 1
IWORK( 6 ) = IU
CALL PDLAEBZ( 0, N, 2, 1, ATOLI, RELTOL, PIVMIN,
$ WORK( INDRW1+1 ), IWORK( 5 ), WORK, IWORK, NINT,
$ LSAVE, IEFLAG, IINFO )
IF( IINFO.NE.0 ) THEN
INFO = 3
GO TO 230
END IF
IF( NINT.GT.1 ) THEN
IF( IWORK( 5 ).EQ.IL-1 ) THEN
WORK( 2 ) = WORK( 4 )
IWORK( 2 ) = IWORK( 4 )
ELSE
WORK( 1 ) = WORK( 3 )
IWORK( 1 ) = IWORK( 3 )
END IF
IF( IWORK( 1 ).LT.0 .OR. IWORK( 1 ).GT.IL-1 .OR.
$ IWORK( 2 ).LE.MIN( IU-1, IWORK( 1 ) ) .OR.
$ IWORK( 2 ).GT.N ) THEN
INFO = 3
GO TO 230
END IF
END IF
LEXTRA = IL - 1 - IWORK( 1 )
REXTRA = IWORK( 2 ) - IU
INITVL = WORK( 1 )
INITVU = WORK( 2 )
IFRST = IL
ILAST = IU
END IF
* NVL = IFRST - 1
* NVU = ILAST
GL = INITVL
GU = INITVU
NGL = IWORK( 1 )
NGU = IWORK( 2 )
IM = 0
FOUND = 0
INDRIW2 = INDRIW1 + NGU - NGL
IEND = 0
IF( IFRST.GT.ILAST )
$ GO TO 100
IF( IFRST.EQ.1 .AND. ILAST.EQ.N )
$ IRANGE = 1
*
* Find Eigenvalues -- Loop Over Blocks
*
DO 90 JB = 1, NSPLIT
IOFF = IEND
IBEGIN = IOFF + 1
IEND = ISPLIT( JB )
IN = IEND - IOFF
IF( JB.NE.1 ) THEN
IF( IRANGE.NE.1 ) THEN
FOUND = IM
*
* Find total number of eigenvalues found thus far
*
CALL IGSUM2D( ONEDCONTEXT, 'All', ' ', 1, 1, FOUND, 1,
$ -1, -1 )
ELSE
FOUND = IOFF
END IF
END IF
* IF( SELF.GE.P )
* $ GO TO 30
IF( IN.NE.N ) THEN
*
* Compute Gershgorin interval [gl,gu] for split matrix
*
GU = D( IBEGIN )
GL = D( IBEGIN )
TMP1 = ZERO
*
DO 50 J = IBEGIN, IEND - 1
TMP2 = ABS( E( J ) )
GU = MAX( GU, D( J )+TMP1+TMP2 )
GL = MIN( GL, D( J )-TMP1-TMP2 )
TMP1 = TMP2
50 CONTINUE
*
GU = MAX( GU, D( IEND )+TMP1 )
GL = MIN( GL, D( IEND )-TMP1 )
BNORM = MAX( ABS( GL ), ABS( GU ) )
GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
*
* Compute ATOLI for the current submatrix
*
IF( ABSTOL.LE.ZERO ) THEN
ATOLI = ULP*BNORM
ELSE
ATOLI = ABSTOL
END IF
*
IF( GL.LT.INITVL ) THEN
GL = INITVL
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( GL, IN, WORK( INDRW1+2*IOFF+1 ),
$ PIVMIN, NGL )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( GL, IN, WORK( INDRW1+2*IOFF+1 ), NGL )
ELSE
CALL PDLAIECTL( GL, IN, WORK( INDRW1+2*IOFF+1 ), NGL )
END IF
ELSE
NGL = 0
END IF
IF( GU.GT.INITVU ) THEN
GU = INITVU
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( GU, IN, WORK( INDRW1+2*IOFF+1 ),
$ PIVMIN, NGU )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( GU, IN, WORK( INDRW1+2*IOFF+1 ), NGU )
ELSE
CALL PDLAIECTL( GU, IN, WORK( INDRW1+2*IOFF+1 ), NGU )
END IF
ELSE
NGU = IN
END IF
IF( NGL.GE.NGU )
$ GO TO 90
WORK( 1 ) = GL
WORK( 2 ) = GU
IWORK( 1 ) = NGL
IWORK( 2 ) = NGU
END IF
OFFSET = FOUND - NGL
BLKNO = JB
*
* Do a static partitioning of work so that each process
* has to find an (almost) equal number of eigenvalues
*
NCMP = NGU - NGL
ILOAD = NCMP / P
IREM = NCMP - ILOAD*P
ITMP1 = MOD( SELF-FOUND, P )
IF( ITMP1.LT.0 )
$ ITMP1 = ITMP1 + P
IF( ITMP1.LT.IREM ) THEN
IMYLOAD = ILOAD + 1
ELSE
IMYLOAD = ILOAD
END IF
IF( IMYLOAD.EQ.0 ) THEN
GO TO 90
ELSE IF( IN.EQ.1 ) THEN
WORK( INDRW2+IM+1 ) = WORK( INDRW1+2*IOFF+1 )
IWORK( INDRIW1+IM+1 ) = BLKNO
IWORK( INDRIW2+IM+1 ) = OFFSET + 1
IM = IM + 1
GO TO 90
ELSE
INXTLOAD = ILOAD
ITMP2 = MOD( SELF+1-FOUND, P )
IF( ITMP2.LT.0 )
$ ITMP2 = ITMP2 + P
IF( ITMP2.LT.IREM )
$ INXTLOAD = INXTLOAD + 1
LREQ = NGL + ITMP1*ILOAD + MIN( IREM, ITMP1 )
RREQ = LREQ + IMYLOAD
IWORK( 5 ) = LREQ
IWORK( 6 ) = RREQ
TMP1 = WORK( 1 )
ITMP1 = IWORK( 1 )
CALL PDLAEBZ( 1, IN, 1, 1, ATOLI, RELTOL, PIVMIN,
$ WORK( INDRW1+2*IOFF+1 ), IWORK( 5 ), WORK,
$ IWORK, NINT, LSAVE, IEFLAG, IINFO )
ALPHA = WORK( 1 )
BETA = WORK( 2 )
NALPHA = IWORK( 1 )
NBETA = IWORK( 2 )
DSEND = BETA
IF( NBETA.GT.RREQ+INXTLOAD ) THEN
NBETA = RREQ
DSEND = ALPHA
END IF
LAST = MOD( FOUND+MIN( NGU-NGL, P )-1, P )
IF( LAST.LT.0 )
$ LAST = LAST + P
IF( SELF.NE.LAST ) THEN
CALL DGESD2D( ONEDCONTEXT, 1, 1, DSEND, 1, 0, NEXT )
CALL IGESD2D( ONEDCONTEXT, 1, 1, NBETA, 1, 0, NEXT )
END IF
IF( SELF.NE.MOD( FOUND, P ) ) THEN
CALL DGERV2D( ONEDCONTEXT, 1, 1, DRECV, 1, 0, PREV )
CALL IGERV2D( ONEDCONTEXT, 1, 1, IRECV, 1, 0, PREV )
ELSE
DRECV = TMP1
IRECV = ITMP1
END IF
WORK( 1 ) = MAX( LSAVE, DRECV )
IWORK( 1 ) = IRECV
ALPHA = MAX( ALPHA, WORK( 1 ) )
NALPHA = MAX( NALPHA, IRECV )
IF( BETA-ALPHA.LE.MAX( ATOLI, RELTOL*MAX( ABS( ALPHA ),
$ ABS( BETA ) ) ) ) THEN
MID = HALF*( ALPHA+BETA )
DO 60 J = OFFSET + NALPHA + 1, OFFSET + NBETA
WORK( INDRW2+IM+1 ) = MID
IWORK( INDRIW1+IM+1 ) = BLKNO
IWORK( INDRIW2+IM+1 ) = J
IM = IM + 1
60 CONTINUE
WORK( 2 ) = ALPHA
IWORK( 2 ) = NALPHA
END IF
END IF
NEIGINT = IWORK( 2 ) - IWORK( 1 )
IF( NEIGINT.LE.0 )
$ GO TO 90
*
* Call the main computational routine
*
CALL PDLAEBZ( 2, IN, NEIGINT, 1, ATOLI, RELTOL, PIVMIN,
$ WORK( INDRW1+2*IOFF+1 ), IWORK, WORK, IWORK,
$ IOUT, LSAVE, IEFLAG, IINFO )
IF( IINFO.NE.0 ) THEN
INFO = 1
END IF
DO 80 I = 1, IOUT
MID = HALF*( WORK( 2*I-1 )+WORK( 2*I ) )
IF( I.GT.IOUT-IINFO )
$ BLKNO = -BLKNO
DO 70 J = OFFSET + IWORK( 2*I-1 ) + 1,
$ OFFSET + IWORK( 2*I )
WORK( INDRW2+IM+1 ) = MID
IWORK( INDRIW1+IM+1 ) = BLKNO
IWORK( INDRIW2+IM+1 ) = J
IM = IM + 1
70 CONTINUE
80 CONTINUE
90 CONTINUE
*
* Find out total number of eigenvalues computed
*
100 CONTINUE
M = IM
CALL IGSUM2D( ONEDCONTEXT, 'ALL', ' ', 1, 1, M, 1, -1, -1 )
*
* Move the eigenvalues found to their final destinations
*
DO 130 I = 1, P
IF( SELF.EQ.I-1 ) THEN
CALL IGEBS2D( ONEDCONTEXT, 'ALL', ' ', 1, 1, IM, 1 )
IF( IM.NE.0 ) THEN
CALL IGEBS2D( ONEDCONTEXT, 'ALL', ' ', IM, 1,
$ IWORK( INDRIW2+1 ), IM )
CALL DGEBS2D( ONEDCONTEXT, 'ALL', ' ', IM, 1,
$ WORK( INDRW2+1 ), IM )
CALL IGEBS2D( ONEDCONTEXT, 'ALL', ' ', IM, 1,
$ IWORK( INDRIW1+1 ), IM )
DO 110 J = 1, IM
W( IWORK( INDRIW2+J ) ) = WORK( INDRW2+J )
IBLOCK( IWORK( INDRIW2+J ) ) = IWORK( INDRIW1+J )
110 CONTINUE
END IF
ELSE
CALL IGEBR2D( ONEDCONTEXT, 'ALL', ' ', 1, 1, TORECV, 1, 0,
$ I-1 )
IF( TORECV.NE.0 ) THEN
CALL IGEBR2D( ONEDCONTEXT, 'ALL', ' ', TORECV, 1, IWORK,
$ TORECV, 0, I-1 )
CALL DGEBR2D( ONEDCONTEXT, 'ALL', ' ', TORECV, 1, WORK,
$ TORECV, 0, I-1 )
CALL IGEBR2D( ONEDCONTEXT, 'ALL', ' ', TORECV, 1,
$ IWORK( N+1 ), TORECV, 0, I-1 )
DO 120 J = 1, TORECV
W( IWORK( J ) ) = WORK( J )
IBLOCK( IWORK( J ) ) = IWORK( N+J )
120 CONTINUE
END IF
END IF
130 CONTINUE
IF( NSPLIT.GT.1 .AND. IORDER.EQ.1 ) THEN
*
* Sort the eigenvalues
*
*
DO 140 I = 1, M
IWORK( M+I ) = I
140 CONTINUE
CALL DLASRT2( 'I', M, W, IWORK( M+1 ), IINFO )
DO 150 I = 1, M
IWORK( I ) = IBLOCK( I )
150 CONTINUE
DO 160 I = 1, M
IBLOCK( I ) = IWORK( IWORK( M+I ) )
160 CONTINUE
END IF
IF( IRANGE.EQ.3 .AND. ( LEXTRA.GT.0 .OR. REXTRA.GT.0 ) ) THEN
*
* Discard unwanted eigenvalues (occurs only when RANGE = 'I',
* and eigenvalues IL, and/or IU are in a cluster)
*
DO 170 I = 1, M
WORK( I ) = W( I )
IWORK( I ) = I
IWORK( M+I ) = I
170 CONTINUE
DO 190 I = 1, LEXTRA
ITMP1 = I
DO 180 J = I + 1, M
IF( WORK( J ).LT.WORK( ITMP1 ) ) THEN
ITMP1 = J
END IF
180 CONTINUE
TMP1 = WORK( I )
WORK( I ) = WORK( ITMP1 )
WORK( ITMP1 ) = TMP1
IWORK( IWORK( M+ITMP1 ) ) = I
IWORK( IWORK( M+I ) ) = ITMP1
ITMP2 = IWORK( M+I )
IWORK( M+I ) = IWORK( M+ITMP1 )
IWORK( M+ITMP1 ) = ITMP2
190 CONTINUE
DO 210 I = 1, REXTRA
ITMP1 = M - I + 1
DO 200 J = M - I, LEXTRA + 1, -1
IF( WORK( J ).GT.WORK( ITMP1 ) ) THEN
ITMP1 = J
END IF
200 CONTINUE
TMP1 = WORK( M-I+1 )
WORK( M-I+1 ) = WORK( ITMP1 )
WORK( ITMP1 ) = TMP1
IWORK( IWORK( M+ITMP1 ) ) = M - I + 1
IWORK( IWORK( 2*M-I+1 ) ) = ITMP1
ITMP2 = IWORK( 2*M-I+1 )
IWORK( 2*M-I+1 ) = IWORK( M+ITMP1 )
IWORK( M+ITMP1 ) = ITMP2
* IWORK( ITMP1 ) = 1
210 CONTINUE
J = 0
DO 220 I = 1, M
IF( IWORK( I ).GT.LEXTRA .AND. IWORK( I ).LE.M-REXTRA ) THEN
J = J + 1
W( J ) = WORK( IWORK( I ) )
IBLOCK( J ) = IBLOCK( I )
END IF
220 CONTINUE
M = M - LEXTRA - REXTRA
END IF
IF( M.NE.ILAST-IFRST+1 ) THEN
INFO = 2
END IF
*
230 CONTINUE
CALL BLACS_FREEBUFF( ONEDCONTEXT, 1 )
CALL BLACS_GRIDEXIT( ONEDCONTEXT )
RETURN
*
* End of PDSTEBZ
*
END
*
SUBROUTINE PDLAEBZ( IJOB, N, MMAX, MINP, ABSTOL, RELTOL, PIVMIN,
$ D, NVAL, INTVL, INTVLCT, MOUT, LSAVE, IEFLAG,
$ INFO )
*
* -- ScaLAPACK routine (version 1.7) --
* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
* and University of California, Berkeley.
* November 15, 1997
*
*
* .. Scalar Arguments ..
INTEGER IEFLAG, IJOB, INFO, MINP, MMAX, MOUT, N
DOUBLE PRECISION ABSTOL, LSAVE, PIVMIN, RELTOL
* ..
* .. Array Arguments ..
INTEGER INTVLCT( * ), NVAL( * )
DOUBLE PRECISION D( * ), INTVL( * )
* ..
*
* Purpose
* =======
*
* PDLAEBZ contains the iteration loop which computes the eigenvalues
* contained in the input intervals [ INTVL(2*j-1), INTVL(2*j) ] where
* j = 1,...,MINP. It uses and computes the function N(w), which is
* the count of eigenvalues of a symmetric tridiagonal matrix less than
* or equal to its argument w.
*
* This is a ScaLAPACK internal subroutine and arguments are not
* checked for unreasonable values.
*
* Arguments
* =========
*
* IJOB (input) INTEGER
* Specifies the computation done by PDLAEBZ
* = 0 : Find an interval with desired values of N(w) at the
* endpoints of the interval.
* = 1 : Find a floating point number contained in the initial
* interval with a desired value of N(w).
* = 2 : Perform bisection iteration to find eigenvalues of T.
*
* N (input) INTEGER
* The order of the tridiagonal matrix T. N >= 1.
*
* MMAX (input) INTEGER
* The maximum number of intervals that may be generated. If
* more than MMAX intervals are generated, then PDLAEBZ will
* quit with INFO = MMAX+1.
*
* MINP (input) INTEGER
* The initial number of intervals. MINP <= MMAX.
*
* ABSTOL (input) DOUBLE PRECISION
* The minimum (absolute) width of an interval. When an interval
* is narrower than ABSTOL, or than RELTOL times the larger (in
* magnitude) endpoint, then it is considered to be sufficiently
* small, i.e., converged.
* This must be at least zero.
*
* RELTOL (input) DOUBLE PRECISION
* The minimum relative width of an interval. When an interval
* is narrower than ABSTOL, or than RELTOL times the larger (in
* magnitude) endpoint, then it is considered to be sufficiently
* small, i.e., converged.
* Note : This should be at least radix*machine epsilon.
*
* PIVMIN (input) DOUBLE PRECISION
* The minimum absolute of a "pivot" in the "paranoid"
* implementation of the Sturm sequence loop. This must be at
* least max_j |e(j)^2| *safe_min, and at least safe_min, where
* safe_min is at least the smallest number that can divide 1.0
* without overflow.
* See PDLAPDCT for the "paranoid" implementation of the Sturm
* sequence loop.
*
* D (input) DOUBLE PRECISION array, dimension (2*N - 1)
* Contains the diagonals and the squares of the off-diagonal
* elements of the tridiagonal matrix T. These elements are
* assumed to be interleaved in memory for better cache
* performance. The diagonal entries of T are in the entries
* D(1),D(3),...,D(2*N-1), while the squares of the off-diagonal
* entries are D(2),D(4),...,D(2*N-2). To avoid overflow, the
* matrix must be scaled so that its largest entry is no greater
* than overflow**(1/2) * underflow**(1/4) in absolute value,
* and for greatest accuracy, it should not be much smaller
* than that.
*
* NVAL (input/output) INTEGER array, dimension (4)
* If IJOB = 0, the desired values of N(w) are in NVAL(1) and
* NVAL(2).
* If IJOB = 1, NVAL(2) is the desired value of N(w).
* If IJOB = 2, not referenced.
* This array will, in general, be reordered on output.
*
* INTVL (input/output) DOUBLE PRECISION array, dimension (2*MMAX)
* The endpoints of the intervals. INTVL(2*j-1) is the left
* endpoint of the j-th interval, and INTVL(2*j) is the right
* endpoint of the j-th interval. The input intervals will,
* in general, be modified, split and reordered by the
* calculation.
* On input, INTVL contains the MINP input intervals.
* On output, INTVL contains the converged intervals.
*
* INTVLCT (input/output) INTEGER array, dimension (2*MMAX)
* The counts at the endpoints of the intervals. INTVLCT(2*j-1)
* is the count at the left endpoint of the j-th interval, i.e.,
* the function value N(INTVL(2*j-1)), and INTVLCT(2*j) is the
* count at the right endpoint of the j-th interval.
* On input, INTVLCT contains the counts at the endpoints of
* the MINP input intervals.
* On output, INTVLCT contains the counts at the endpoints of
* the converged intervals.
*
* MOUT (output) INTEGER
* The number of intervals output.
*
* LSAVE (output) DOUBLE PRECISION
* If IJOB = 0 or 2, not referenced.
* If IJOB = 1, this is the largest floating point number
* encountered which has count N(w) = NVAL(1).
*
* IEFLAG (input) INTEGER
* A flag which indicates whether N(w) should be speeded up by
* exploiting IEEE Arithmetic.
*
* INFO (output) INTEGER
* = 0 : All intervals converged.
* = 1 - MMAX : The last INFO intervals did not converge.
* = MMAX + 1 : More than MMAX intervals were generated.
*
* =====================================================================
*
* .. Intrinsic Functions ..
INTRINSIC ABS, INT, LOG, MAX, MIN
* ..
* .. External Subroutines ..
EXTERNAL PDLAECV, PDLAIECTB, PDLAIECTL, PDLAPDCT
* ..
* .. Parameters ..
DOUBLE PRECISION ZERO, TWO, HALF
PARAMETER ( ZERO = 0.0D+0, TWO = 2.0D+0,
$ HALF = 1.0D+0 / TWO )
* ..
* .. Local Scalars ..
INTEGER I, ITMAX, J, K, KF, KL, KLNEW, L, LCNT, LREQ,
$ NALPHA, NBETA, NMID, RCNT, RREQ
DOUBLE PRECISION ALPHA, BETA, MID
* ..
* .. Executable Statements ..
*
KF = 1
KL = MINP + 1
INFO = 0
IF( INTVL( 2 )-INTVL( 1 ).LE.ZERO ) THEN
INFO = MINP
MOUT = KF
RETURN
END IF
IF( IJOB.EQ.0 ) THEN
*
* Check if some input intervals have "converged"
*
CALL PDLAECV( 0, KF, KL, INTVL, INTVLCT, NVAL,
$ MAX( ABSTOL, PIVMIN ), RELTOL )
IF( KF.GE.KL )
$ GO TO 60
*
* Compute upper bound on number of iterations needed
*
ITMAX = INT( ( LOG( INTVL( 2 )-INTVL( 1 )+PIVMIN )-
$ LOG( PIVMIN ) ) / LOG( TWO ) ) + 2
*
* Iteration Loop
*
DO 20 I = 1, ITMAX
KLNEW = KL
DO 10 J = KF, KL - 1
K = 2*J
*
* Bisect the interval and find the count at that point
*
MID = HALF*( INTVL( K-1 )+INTVL( K ) )
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( MID, N, D, PIVMIN, NMID )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( MID, N, D, NMID )
ELSE
CALL PDLAIECTL( MID, N, D, NMID )
END IF
LREQ = NVAL( K-1 )
RREQ = NVAL( K )
IF( KL.EQ.1 )
$ NMID = MIN( INTVLCT( K ),
$ MAX( INTVLCT( K-1 ), NMID ) )
IF( NMID.LE.NVAL( K-1 ) ) THEN
INTVL( K-1 ) = MID
INTVLCT( K-1 ) = NMID
END IF
IF( NMID.GE.NVAL( K ) ) THEN
INTVL( K ) = MID
INTVLCT( K ) = NMID
END IF
IF( NMID.GT.LREQ .AND. NMID.LT.RREQ ) THEN
L = 2*KLNEW
INTVL( L-1 ) = MID
INTVL( L ) = INTVL( K )
INTVLCT( L-1 ) = NVAL( K )
INTVLCT( L ) = INTVLCT( K )
INTVL( K ) = MID
INTVLCT( K ) = NVAL( K-1 )
NVAL( L-1 ) = NVAL( K )
NVAL( L ) = NVAL( L-1 )
NVAL( K ) = NVAL( K-1 )
KLNEW = KLNEW + 1
END IF
10 CONTINUE
KL = KLNEW
CALL PDLAECV( 0, KF, KL, INTVL, INTVLCT, NVAL,
$ MAX( ABSTOL, PIVMIN ), RELTOL )
IF( KF.GE.KL )
$ GO TO 60
20 CONTINUE
ELSE IF( IJOB.EQ.1 ) THEN
ALPHA = INTVL( 1 )
BETA = INTVL( 2 )
NALPHA = INTVLCT( 1 )
NBETA = INTVLCT( 2 )
LSAVE = ALPHA
LREQ = NVAL( 1 )
RREQ = NVAL( 2 )
30 CONTINUE
IF( NBETA.NE.RREQ .AND. BETA-ALPHA.GT.
$ MAX( ABSTOL, RELTOL*MAX( ABS( ALPHA ), ABS( BETA ) ) ) )
$ THEN
*
* Bisect the interval and find the count at that point
*
MID = HALF*( ALPHA+BETA )
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( MID, N, D, PIVMIN, NMID )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( MID, N, D, NMID )
ELSE
CALL PDLAIECTL( MID, N, D, NMID )
END IF
NMID = MIN( NBETA, MAX( NALPHA, NMID ) )
IF( NMID.GE.RREQ ) THEN
BETA = MID
NBETA = NMID
ELSE
ALPHA = MID
NALPHA = NMID
IF( NMID.EQ.LREQ )
$ LSAVE = ALPHA
END IF
GO TO 30
END IF
KL = KF
INTVL( 1 ) = ALPHA
INTVL( 2 ) = BETA
INTVLCT( 1 ) = NALPHA
INTVLCT( 2 ) = NBETA
ELSE IF( IJOB.EQ.2 ) THEN
*
* Check if some input intervals have "converged"
*
CALL PDLAECV( 1, KF, KL, INTVL, INTVLCT, NVAL,
$ MAX( ABSTOL, PIVMIN ), RELTOL )
IF( KF.GE.KL )
$ GO TO 60
*
* Compute upper bound on number of iterations needed
*
ITMAX = INT( ( LOG( INTVL( 2 )-INTVL( 1 )+PIVMIN )-
$ LOG( PIVMIN ) ) / LOG( TWO ) ) + 2
*
* Iteration Loop
*
DO 50 I = 1, ITMAX
KLNEW = KL
DO 40 J = KF, KL - 1
K = 2*J
MID = HALF*( INTVL( K-1 )+INTVL( K ) )
IF( IEFLAG.EQ.0 ) THEN
CALL PDLAPDCT( MID, N, D, PIVMIN, NMID )
ELSE IF( IEFLAG.EQ.1 ) THEN
CALL PDLAIECTB( MID, N, D, NMID )
ELSE
CALL PDLAIECTL( MID, N, D, NMID )
END IF
LCNT = INTVLCT( K-1 )
RCNT = INTVLCT( K )
NMID = MIN( RCNT, MAX( LCNT, NMID ) )
*
* Form New Interval(s)
*
IF( NMID.EQ.LCNT ) THEN
INTVL( K-1 ) = MID
ELSE IF( NMID.EQ.RCNT ) THEN
INTVL( K ) = MID
ELSE IF( KLNEW.LT.MMAX+1 ) THEN
L = 2*KLNEW
INTVL( L-1 ) = MID
INTVL( L ) = INTVL( K )
INTVLCT( L-1 ) = NMID
INTVLCT( L ) = INTVLCT( K )
INTVL( K ) = MID
INTVLCT( K ) = NMID
KLNEW = KLNEW + 1
ELSE
INFO = MMAX + 1
RETURN
END IF
40 CONTINUE
KL = KLNEW
CALL PDLAECV( 1, KF, KL, INTVL, INTVLCT, NVAL,
$ MAX( ABSTOL, PIVMIN ), RELTOL )
IF( KF.GE.KL )
$ GO TO 60
50 CONTINUE
END IF
60 CONTINUE
INFO = MAX( KL-KF, 0 )
MOUT = KL - 1
RETURN
*
* End of PDLAEBZ
*
END
*
*
SUBROUTINE PDLAECV( IJOB, KF, KL, INTVL, INTVLCT, NVAL, ABSTOL,
$ RELTOL )
*
* -- ScaLAPACK routine (version 1.7) --
* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
* and University of California, Berkeley.
* November 15, 1997
*
*
* .. Scalar Arguments ..
INTEGER IJOB, KF, KL
DOUBLE PRECISION ABSTOL, RELTOL
* ..
* .. Array Arguments ..
INTEGER INTVLCT( * ), NVAL( * )
DOUBLE PRECISION INTVL( * )
* ..
*
* Purpose
* =======
*
* PDLAECV checks if the input intervals [ INTVL(2*i-1), INTVL(2*i) ],
* i = KF, ... , KL-1, have "converged".
* PDLAECV modifies KF to be the index of the last converged interval,
* i.e., on output, all intervals [ INTVL(2*i-1), INTVL(2*i) ], i < KF,
* have converged. Note that the input intervals may be reordered by
* PDLAECV.
*
* This is a SCALAPACK internal procedure and arguments are not checked
* for unreasonable values.
*
* Arguments
* =========
*
* IJOB (input) INTEGER
* Specifies the criterion for "convergence" of an interval.
* = 0 : When an interval is narrower than ABSTOL, or than
* RELTOL times the larger (in magnitude) endpoint, then
* it is considered to have "converged".
* = 1 : When an interval is narrower than ABSTOL, or than
* RELTOL times the larger (in magnitude) endpoint, or if
* the counts at the endpoints are identical to the counts
* specified by NVAL ( see NVAL ) then the interval is
* considered to have "converged".
*
* KF (input/output) INTEGER
* On input, the index of the first input interval is 2*KF-1.
* On output, the index of the last converged interval
* is 2*KF-3.
*
* KL (input) INTEGER
* The index of the last input interval is 2*KL-3.
*
* INTVL (input/output) DOUBLE PRECISION array, dimension (2*(KL-KF))
* The endpoints of the intervals. INTVL(2*j-1) is the left
* oendpoint f the j-th interval, and INTVL(2*j) is the right
* endpoint of the j-th interval. The input intervals will,
* in general, be reordered on output.
* On input, INTVL contains the KL-KF input intervals.
* On output, INTVL contains the converged intervals, 1 thru'
* KF-1, and the unconverged intervals, KF thru' KL-1.
*
* INTVLCT (input/output) INTEGER array, dimension (2*(KL-KF))
* The counts at the endpoints of the intervals. INTVLCT(2*j-1)
* is the count at the left endpoint of the j-th interval, i.e.,
* the function value N(INTVL(2*j-1)), and INTVLCT(2*j) is the
* count at the right endpoint of the j-th interval. This array
* will, in general, be reordered on output.
* See the comments in PDLAEBZ for more on the function N(w).
*
* NVAL (input/output) INTEGER array, dimension (2*(KL-KF))
* The desired counts, N(w), at the endpoints of the
* corresponding intervals. This array will, in general,
* be reordered on output.
*
* ABSTOL (input) DOUBLE PRECISION
* The minimum (absolute) width of an interval. When an interval
* is narrower than ABSTOL, or than RELTOL times the larger (in
* magnitude) endpoint, then it is considered to be sufficiently
* small, i.e., converged.
* Note : This must be at least zero.
*
* RELTOL (input) DOUBLE PRECISION
* The minimum relative width of an interval. When an interval
* is narrower than ABSTOL, or than RELTOL times the larger (in
* magnitude) endpoint, then it is considered to be sufficiently
* small, i.e., converged.
* Note : This should be at least radix*machine epsilon.
*
* =====================================================================
*
* .. Intrinsic Functions ..
INTRINSIC ABS, MAX
* ..
* .. Local Scalars ..
LOGICAL CONDN
INTEGER I, ITMP1, ITMP2, J, K, KFNEW
DOUBLE PRECISION TMP1, TMP2, TMP3, TMP4
* ..
* .. Executable Statements ..
*
KFNEW = KF
DO 10 I = KF, KL - 1
K = 2*I
TMP3 = INTVL( K-1 )
TMP4 = INTVL( K )
TMP1 = ABS( TMP4-TMP3 )
TMP2 = MAX( ABS( TMP3 ), ABS( TMP4 ) )
CONDN = TMP1.LT.MAX( ABSTOL, RELTOL*TMP2 )
IF( IJOB.EQ.0 )
$ CONDN = CONDN .OR. ( ( INTVLCT( K-1 ).EQ.NVAL( K-1 ) ) .AND.
$ INTVLCT( K ).EQ.NVAL( K ) )
IF( CONDN ) THEN
IF( I.GT.KFNEW ) THEN
*
* Reorder Intervals
*
J = 2*KFNEW
TMP1 = INTVL( K-1 )
TMP2 = INTVL( K )
ITMP1 = INTVLCT( K-1 )
ITMP2 = INTVLCT( K )
INTVL( K-1 ) = INTVL( J-1 )
INTVL( K ) = INTVL( J )
INTVLCT( K-1 ) = INTVLCT( J-1 )
INTVLCT( K ) = INTVLCT( J )
INTVL( J-1 ) = TMP1
INTVL( J ) = TMP2
INTVLCT( J-1 ) = ITMP1
INTVLCT( J ) = ITMP2
IF( IJOB.EQ.0 ) THEN
ITMP1 = NVAL( K-1 )
NVAL( K-1 ) = NVAL( J-1 )
NVAL( J-1 ) = ITMP1
ITMP1 = NVAL( K )
NVAL( K ) = NVAL( J )
NVAL( J ) = ITMP1
END IF
END IF
KFNEW = KFNEW + 1
END IF
10 CONTINUE
KF = KFNEW
RETURN
*
* End of PDLAECV
*
END
*
SUBROUTINE PDLAPDCT( SIGMA, N, D, PIVMIN, COUNT )
*
* -- ScaLAPACK routine (version 1.7) --
* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
* and University of California, Berkeley.
* November 15, 1997
*
*
* .. Scalar Arguments ..
INTEGER COUNT, N
DOUBLE PRECISION PIVMIN, SIGMA
* ..
* .. Array Arguments ..
DOUBLE PRECISION D( * )
* ..
*
* Purpose
* =======
*
* PDLAPDCT counts the number of negative eigenvalues of (T - SIGMA I).
* This implementation of the Sturm Sequence loop has conditionals in
* the innermost loop to avoid overflow and determine the sign of a
* floating point number. PDLAPDCT will be referred to as the "paranoid"
* implementation of the Sturm Sequence loop.
*
* This is a SCALAPACK internal procedure and arguments are not checked
* for unreasonable values.
*
* Arguments
* =========
*
* SIGMA (input) DOUBLE PRECISION
* The shift. PDLAPDCT finds the number of eigenvalues of T less
* than or equal to SIGMA.
*
* N (input) INTEGER
* The order of the tridiagonal matrix T. N >= 1.
*
* D (input) DOUBLE PRECISION array, dimension (2*N - 1)
* Contains the diagonals and the squares of the off-diagonal
* elements of the tridiagonal matrix T. These elements are
* assumed to be interleaved in memory for better cache
* performance. The diagonal entries of T are in the entries
* D(1),D(3),...,D(2*N-1), while the squares of the off-diagonal
* entries are D(2),D(4),...,D(2*N-2). To avoid overflow, the
* matrix must be scaled so that its largest entry is no greater
* than overflow**(1/2) * underflow**(1/4) in absolute value,
* and for greatest accuracy, it should not be much smaller
* than that.
*
* PIVMIN (input) DOUBLE PRECISION
* The minimum absolute of a "pivot" in this "paranoid"
* implementation of the Sturm sequence loop. This must be at
* least max_j |e(j)^2| *safe_min, and at least safe_min, where
* safe_min is at least the smallest number that can divide 1.0
* without overflow.
*
* COUNT (output) INTEGER
* The count of the number of eigenvalues of T less than or
* equal to SIGMA.
*
* =====================================================================
*
* .. Intrinsic Functions ..
INTRINSIC ABS
* ..
* .. Parameters ..
DOUBLE PRECISION ZERO
PARAMETER ( ZERO = 0.0D+0 )
* ..
* .. Local Scalars ..
INTEGER I
DOUBLE PRECISION TMP
* ..
* .. Executable Statements ..
*
TMP = D( 1 ) - SIGMA
IF( ABS( TMP ).LE.PIVMIN )
$ TMP = -PIVMIN
COUNT = 0
IF( TMP.LE.ZERO )
$ COUNT = 1
DO 10 I = 3, 2*N - 1, 2
TMP = D( I ) - D( I-1 ) / TMP - SIGMA
IF( ABS( TMP ).LE.PIVMIN )
$ TMP = -PIVMIN
IF( TMP.LE.ZERO )
$ COUNT = COUNT + 1
10 CONTINUE
*
RETURN
*
* End of PDLAPDCT
*
END
|