LAPACK 3.3.1
Linear Algebra PACKage
|
00001 SUBROUTINE CGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, 00002 $ VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO ) 00003 * 00004 * -- LAPACK driver routine (version 3.2) -- 00005 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00006 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00007 * November 2006 00008 * 00009 * .. Scalar Arguments .. 00010 CHARACTER JOBVL, JOBVR 00011 INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N 00012 * .. 00013 * .. Array Arguments .. 00014 REAL RWORK( * ) 00015 COMPLEX A( LDA, * ), ALPHA( * ), B( LDB, * ), 00016 $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ), 00017 $ WORK( * ) 00018 * .. 00019 * 00020 * Purpose 00021 * ======= 00022 * 00023 * This routine is deprecated and has been replaced by routine CGGEV. 00024 * 00025 * CGEGV computes the eigenvalues and, optionally, the left and/or right 00026 * eigenvectors of a complex matrix pair (A,B). 00027 * Given two square matrices A and B, 00028 * the generalized nonsymmetric eigenvalue problem (GNEP) is to find the 00029 * eigenvalues lambda and corresponding (non-zero) eigenvectors x such 00030 * that 00031 * A*x = lambda*B*x. 00032 * 00033 * An alternate form is to find the eigenvalues mu and corresponding 00034 * eigenvectors y such that 00035 * mu*A*y = B*y. 00036 * 00037 * These two forms are equivalent with mu = 1/lambda and x = y if 00038 * neither lambda nor mu is zero. In order to deal with the case that 00039 * lambda or mu is zero or small, two values alpha and beta are returned 00040 * for each eigenvalue, such that lambda = alpha/beta and 00041 * mu = beta/alpha. 00042 * 00043 * The vectors x and y in the above equations are right eigenvectors of 00044 * the matrix pair (A,B). Vectors u and v satisfying 00045 * u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B 00046 * are left eigenvectors of (A,B). 00047 * 00048 * Note: this routine performs "full balancing" on A and B -- see 00049 * "Further Details", below. 00050 * 00051 * Arguments 00052 * ========= 00053 * 00054 * JOBVL (input) CHARACTER*1 00055 * = 'N': do not compute the left generalized eigenvectors; 00056 * = 'V': compute the left generalized eigenvectors (returned 00057 * in VL). 00058 * 00059 * JOBVR (input) CHARACTER*1 00060 * = 'N': do not compute the right generalized eigenvectors; 00061 * = 'V': compute the right generalized eigenvectors (returned 00062 * in VR). 00063 * 00064 * N (input) INTEGER 00065 * The order of the matrices A, B, VL, and VR. N >= 0. 00066 * 00067 * A (input/output) COMPLEX array, dimension (LDA, N) 00068 * On entry, the matrix A. 00069 * If JOBVL = 'V' or JOBVR = 'V', then on exit A 00070 * contains the Schur form of A from the generalized Schur 00071 * factorization of the pair (A,B) after balancing. If no 00072 * eigenvectors were computed, then only the diagonal elements 00073 * of the Schur form will be correct. See CGGHRD and CHGEQZ 00074 * for details. 00075 * 00076 * LDA (input) INTEGER 00077 * The leading dimension of A. LDA >= max(1,N). 00078 * 00079 * B (input/output) COMPLEX array, dimension (LDB, N) 00080 * On entry, the matrix B. 00081 * If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the 00082 * upper triangular matrix obtained from B in the generalized 00083 * Schur factorization of the pair (A,B) after balancing. 00084 * If no eigenvectors were computed, then only the diagonal 00085 * elements of B will be correct. See CGGHRD and CHGEQZ for 00086 * details. 00087 * 00088 * LDB (input) INTEGER 00089 * The leading dimension of B. LDB >= max(1,N). 00090 * 00091 * ALPHA (output) COMPLEX array, dimension (N) 00092 * The complex scalars alpha that define the eigenvalues of 00093 * GNEP. 00094 * 00095 * BETA (output) COMPLEX array, dimension (N) 00096 * The complex scalars beta that define the eigenvalues of GNEP. 00097 * 00098 * Together, the quantities alpha = ALPHA(j) and beta = BETA(j) 00099 * represent the j-th eigenvalue of the matrix pair (A,B), in 00100 * one of the forms lambda = alpha/beta or mu = beta/alpha. 00101 * Since either lambda or mu may overflow, they should not, 00102 * in general, be computed. 00103 00104 * 00105 * VL (output) COMPLEX array, dimension (LDVL,N) 00106 * If JOBVL = 'V', the left eigenvectors u(j) are stored 00107 * in the columns of VL, in the same order as their eigenvalues. 00108 * Each eigenvector is scaled so that its largest component has 00109 * abs(real part) + abs(imag. part) = 1, except for eigenvectors 00110 * corresponding to an eigenvalue with alpha = beta = 0, which 00111 * are set to zero. 00112 * Not referenced if JOBVL = 'N'. 00113 * 00114 * LDVL (input) INTEGER 00115 * The leading dimension of the matrix VL. LDVL >= 1, and 00116 * if JOBVL = 'V', LDVL >= N. 00117 * 00118 * VR (output) COMPLEX array, dimension (LDVR,N) 00119 * If JOBVR = 'V', the right eigenvectors x(j) are stored 00120 * in the columns of VR, in the same order as their eigenvalues. 00121 * Each eigenvector is scaled so that its largest component has 00122 * abs(real part) + abs(imag. part) = 1, except for eigenvectors 00123 * corresponding to an eigenvalue with alpha = beta = 0, which 00124 * are set to zero. 00125 * Not referenced if JOBVR = 'N'. 00126 * 00127 * LDVR (input) INTEGER 00128 * The leading dimension of the matrix VR. LDVR >= 1, and 00129 * if JOBVR = 'V', LDVR >= N. 00130 * 00131 * WORK (workspace/output) COMPLEX array, dimension (MAX(1,LWORK)) 00132 * On exit, if INFO = 0, WORK(1) returns the optimal LWORK. 00133 * 00134 * LWORK (input) INTEGER 00135 * The dimension of the array WORK. LWORK >= max(1,2*N). 00136 * For good performance, LWORK must generally be larger. 00137 * To compute the optimal value of LWORK, call ILAENV to get 00138 * blocksizes (for CGEQRF, CUNMQR, and CUNGQR.) Then compute: 00139 * NB -- MAX of the blocksizes for CGEQRF, CUNMQR, and CUNGQR; 00140 * The optimal LWORK is MAX( 2*N, N*(NB+1) ). 00141 * 00142 * If LWORK = -1, then a workspace query is assumed; the routine 00143 * only calculates the optimal size of the WORK array, returns 00144 * this value as the first entry of the WORK array, and no error 00145 * message related to LWORK is issued by XERBLA. 00146 * 00147 * RWORK (workspace/output) REAL array, dimension (8*N) 00148 * 00149 * INFO (output) INTEGER 00150 * = 0: successful exit 00151 * < 0: if INFO = -i, the i-th argument had an illegal value. 00152 * =1,...,N: 00153 * The QZ iteration failed. No eigenvectors have been 00154 * calculated, but ALPHA(j) and BETA(j) should be 00155 * correct for j=INFO+1,...,N. 00156 * > N: errors that usually indicate LAPACK problems: 00157 * =N+1: error return from CGGBAL 00158 * =N+2: error return from CGEQRF 00159 * =N+3: error return from CUNMQR 00160 * =N+4: error return from CUNGQR 00161 * =N+5: error return from CGGHRD 00162 * =N+6: error return from CHGEQZ (other than failed 00163 * iteration) 00164 * =N+7: error return from CTGEVC 00165 * =N+8: error return from CGGBAK (computing VL) 00166 * =N+9: error return from CGGBAK (computing VR) 00167 * =N+10: error return from CLASCL (various calls) 00168 * 00169 * Further Details 00170 * =============== 00171 * 00172 * Balancing 00173 * --------- 00174 * 00175 * This driver calls CGGBAL to both permute and scale rows and columns 00176 * of A and B. The permutations PL and PR are chosen so that PL*A*PR 00177 * and PL*B*R will be upper triangular except for the diagonal blocks 00178 * A(i:j,i:j) and B(i:j,i:j), with i and j as close together as 00179 * possible. The diagonal scaling matrices DL and DR are chosen so 00180 * that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to 00181 * one (except for the elements that start out zero.) 00182 * 00183 * After the eigenvalues and eigenvectors of the balanced matrices 00184 * have been computed, CGGBAK transforms the eigenvectors back to what 00185 * they would have been (in perfect arithmetic) if they had not been 00186 * balanced. 00187 * 00188 * Contents of A and B on Exit 00189 * -------- -- - --- - -- ---- 00190 * 00191 * If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or 00192 * both), then on exit the arrays A and B will contain the complex Schur 00193 * form[*] of the "balanced" versions of A and B. If no eigenvectors 00194 * are computed, then only the diagonal blocks will be correct. 00195 * 00196 * [*] In other words, upper triangular form. 00197 * 00198 * ===================================================================== 00199 * 00200 * .. Parameters .. 00201 REAL ZERO, ONE 00202 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) 00203 COMPLEX CZERO, CONE 00204 PARAMETER ( CZERO = ( 0.0E0, 0.0E0 ), 00205 $ CONE = ( 1.0E0, 0.0E0 ) ) 00206 * .. 00207 * .. Local Scalars .. 00208 LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY 00209 CHARACTER CHTEMP 00210 INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, 00211 $ IN, IRIGHT, IROWS, IRWORK, ITAU, IWORK, JC, JR, 00212 $ LOPT, LWKMIN, LWKOPT, NB, NB1, NB2, NB3 00213 REAL ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM, 00214 $ BNRM1, BNRM2, EPS, SAFMAX, SAFMIN, SALFAI, 00215 $ SALFAR, SBETA, SCALE, TEMP 00216 COMPLEX X 00217 * .. 00218 * .. Local Arrays .. 00219 LOGICAL LDUMMA( 1 ) 00220 * .. 00221 * .. External Subroutines .. 00222 EXTERNAL CGEQRF, CGGBAK, CGGBAL, CGGHRD, CHGEQZ, CLACPY, 00223 $ CLASCL, CLASET, CTGEVC, CUNGQR, CUNMQR, XERBLA 00224 * .. 00225 * .. External Functions .. 00226 LOGICAL LSAME 00227 INTEGER ILAENV 00228 REAL CLANGE, SLAMCH 00229 EXTERNAL ILAENV, LSAME, CLANGE, SLAMCH 00230 * .. 00231 * .. Intrinsic Functions .. 00232 INTRINSIC ABS, AIMAG, CMPLX, INT, MAX, REAL 00233 * .. 00234 * .. Statement Functions .. 00235 REAL ABS1 00236 * .. 00237 * .. Statement Function definitions .. 00238 ABS1( X ) = ABS( REAL( X ) ) + ABS( AIMAG( X ) ) 00239 * .. 00240 * .. Executable Statements .. 00241 * 00242 * Decode the input arguments 00243 * 00244 IF( LSAME( JOBVL, 'N' ) ) THEN 00245 IJOBVL = 1 00246 ILVL = .FALSE. 00247 ELSE IF( LSAME( JOBVL, 'V' ) ) THEN 00248 IJOBVL = 2 00249 ILVL = .TRUE. 00250 ELSE 00251 IJOBVL = -1 00252 ILVL = .FALSE. 00253 END IF 00254 * 00255 IF( LSAME( JOBVR, 'N' ) ) THEN 00256 IJOBVR = 1 00257 ILVR = .FALSE. 00258 ELSE IF( LSAME( JOBVR, 'V' ) ) THEN 00259 IJOBVR = 2 00260 ILVR = .TRUE. 00261 ELSE 00262 IJOBVR = -1 00263 ILVR = .FALSE. 00264 END IF 00265 ILV = ILVL .OR. ILVR 00266 * 00267 * Test the input arguments 00268 * 00269 LWKMIN = MAX( 2*N, 1 ) 00270 LWKOPT = LWKMIN 00271 WORK( 1 ) = LWKOPT 00272 LQUERY = ( LWORK.EQ.-1 ) 00273 INFO = 0 00274 IF( IJOBVL.LE.0 ) THEN 00275 INFO = -1 00276 ELSE IF( IJOBVR.LE.0 ) THEN 00277 INFO = -2 00278 ELSE IF( N.LT.0 ) THEN 00279 INFO = -3 00280 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN 00281 INFO = -5 00282 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN 00283 INFO = -7 00284 ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN 00285 INFO = -11 00286 ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN 00287 INFO = -13 00288 ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN 00289 INFO = -15 00290 END IF 00291 * 00292 IF( INFO.EQ.0 ) THEN 00293 NB1 = ILAENV( 1, 'CGEQRF', ' ', N, N, -1, -1 ) 00294 NB2 = ILAENV( 1, 'CUNMQR', ' ', N, N, N, -1 ) 00295 NB3 = ILAENV( 1, 'CUNGQR', ' ', N, N, N, -1 ) 00296 NB = MAX( NB1, NB2, NB3 ) 00297 LOPT = MAX( 2*N, N*(NB+1) ) 00298 WORK( 1 ) = LOPT 00299 END IF 00300 * 00301 IF( INFO.NE.0 ) THEN 00302 CALL XERBLA( 'CGEGV ', -INFO ) 00303 RETURN 00304 ELSE IF( LQUERY ) THEN 00305 RETURN 00306 END IF 00307 * 00308 * Quick return if possible 00309 * 00310 IF( N.EQ.0 ) 00311 $ RETURN 00312 * 00313 * Get machine constants 00314 * 00315 EPS = SLAMCH( 'E' )*SLAMCH( 'B' ) 00316 SAFMIN = SLAMCH( 'S' ) 00317 SAFMIN = SAFMIN + SAFMIN 00318 SAFMAX = ONE / SAFMIN 00319 * 00320 * Scale A 00321 * 00322 ANRM = CLANGE( 'M', N, N, A, LDA, RWORK ) 00323 ANRM1 = ANRM 00324 ANRM2 = ONE 00325 IF( ANRM.LT.ONE ) THEN 00326 IF( SAFMAX*ANRM.LT.ONE ) THEN 00327 ANRM1 = SAFMIN 00328 ANRM2 = SAFMAX*ANRM 00329 END IF 00330 END IF 00331 * 00332 IF( ANRM.GT.ZERO ) THEN 00333 CALL CLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO ) 00334 IF( IINFO.NE.0 ) THEN 00335 INFO = N + 10 00336 RETURN 00337 END IF 00338 END IF 00339 * 00340 * Scale B 00341 * 00342 BNRM = CLANGE( 'M', N, N, B, LDB, RWORK ) 00343 BNRM1 = BNRM 00344 BNRM2 = ONE 00345 IF( BNRM.LT.ONE ) THEN 00346 IF( SAFMAX*BNRM.LT.ONE ) THEN 00347 BNRM1 = SAFMIN 00348 BNRM2 = SAFMAX*BNRM 00349 END IF 00350 END IF 00351 * 00352 IF( BNRM.GT.ZERO ) THEN 00353 CALL CLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO ) 00354 IF( IINFO.NE.0 ) THEN 00355 INFO = N + 10 00356 RETURN 00357 END IF 00358 END IF 00359 * 00360 * Permute the matrix to make it more nearly triangular 00361 * Also "balance" the matrix. 00362 * 00363 ILEFT = 1 00364 IRIGHT = N + 1 00365 IRWORK = IRIGHT + N 00366 CALL CGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ), 00367 $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO ) 00368 IF( IINFO.NE.0 ) THEN 00369 INFO = N + 1 00370 GO TO 80 00371 END IF 00372 * 00373 * Reduce B to triangular form, and initialize VL and/or VR 00374 * 00375 IROWS = IHI + 1 - ILO 00376 IF( ILV ) THEN 00377 ICOLS = N + 1 - ILO 00378 ELSE 00379 ICOLS = IROWS 00380 END IF 00381 ITAU = 1 00382 IWORK = ITAU + IROWS 00383 CALL CGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), 00384 $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) 00385 IF( IINFO.GE.0 ) 00386 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) 00387 IF( IINFO.NE.0 ) THEN 00388 INFO = N + 2 00389 GO TO 80 00390 END IF 00391 * 00392 CALL CUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, 00393 $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), 00394 $ LWORK+1-IWORK, IINFO ) 00395 IF( IINFO.GE.0 ) 00396 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) 00397 IF( IINFO.NE.0 ) THEN 00398 INFO = N + 3 00399 GO TO 80 00400 END IF 00401 * 00402 IF( ILVL ) THEN 00403 CALL CLASET( 'Full', N, N, CZERO, CONE, VL, LDVL ) 00404 CALL CLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, 00405 $ VL( ILO+1, ILO ), LDVL ) 00406 CALL CUNGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL, 00407 $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, 00408 $ IINFO ) 00409 IF( IINFO.GE.0 ) 00410 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) 00411 IF( IINFO.NE.0 ) THEN 00412 INFO = N + 4 00413 GO TO 80 00414 END IF 00415 END IF 00416 * 00417 IF( ILVR ) 00418 $ CALL CLASET( 'Full', N, N, CZERO, CONE, VR, LDVR ) 00419 * 00420 * Reduce to generalized Hessenberg form 00421 * 00422 IF( ILV ) THEN 00423 * 00424 * Eigenvectors requested -- work on whole matrix. 00425 * 00426 CALL CGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL, 00427 $ LDVL, VR, LDVR, IINFO ) 00428 ELSE 00429 CALL CGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA, 00430 $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO ) 00431 END IF 00432 IF( IINFO.NE.0 ) THEN 00433 INFO = N + 5 00434 GO TO 80 00435 END IF 00436 * 00437 * Perform QZ algorithm 00438 * 00439 IWORK = ITAU 00440 IF( ILV ) THEN 00441 CHTEMP = 'S' 00442 ELSE 00443 CHTEMP = 'E' 00444 END IF 00445 CALL CHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, 00446 $ ALPHA, BETA, VL, LDVL, VR, LDVR, WORK( IWORK ), 00447 $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO ) 00448 IF( IINFO.GE.0 ) 00449 $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) 00450 IF( IINFO.NE.0 ) THEN 00451 IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN 00452 INFO = IINFO 00453 ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN 00454 INFO = IINFO - N 00455 ELSE 00456 INFO = N + 6 00457 END IF 00458 GO TO 80 00459 END IF 00460 * 00461 IF( ILV ) THEN 00462 * 00463 * Compute Eigenvectors 00464 * 00465 IF( ILVL ) THEN 00466 IF( ILVR ) THEN 00467 CHTEMP = 'B' 00468 ELSE 00469 CHTEMP = 'L' 00470 END IF 00471 ELSE 00472 CHTEMP = 'R' 00473 END IF 00474 * 00475 CALL CTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL, 00476 $ VR, LDVR, N, IN, WORK( IWORK ), RWORK( IRWORK ), 00477 $ IINFO ) 00478 IF( IINFO.NE.0 ) THEN 00479 INFO = N + 7 00480 GO TO 80 00481 END IF 00482 * 00483 * Undo balancing on VL and VR, rescale 00484 * 00485 IF( ILVL ) THEN 00486 CALL CGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ), 00487 $ RWORK( IRIGHT ), N, VL, LDVL, IINFO ) 00488 IF( IINFO.NE.0 ) THEN 00489 INFO = N + 8 00490 GO TO 80 00491 END IF 00492 DO 30 JC = 1, N 00493 TEMP = ZERO 00494 DO 10 JR = 1, N 00495 TEMP = MAX( TEMP, ABS1( VL( JR, JC ) ) ) 00496 10 CONTINUE 00497 IF( TEMP.LT.SAFMIN ) 00498 $ GO TO 30 00499 TEMP = ONE / TEMP 00500 DO 20 JR = 1, N 00501 VL( JR, JC ) = VL( JR, JC )*TEMP 00502 20 CONTINUE 00503 30 CONTINUE 00504 END IF 00505 IF( ILVR ) THEN 00506 CALL CGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ), 00507 $ RWORK( IRIGHT ), N, VR, LDVR, IINFO ) 00508 IF( IINFO.NE.0 ) THEN 00509 INFO = N + 9 00510 GO TO 80 00511 END IF 00512 DO 60 JC = 1, N 00513 TEMP = ZERO 00514 DO 40 JR = 1, N 00515 TEMP = MAX( TEMP, ABS1( VR( JR, JC ) ) ) 00516 40 CONTINUE 00517 IF( TEMP.LT.SAFMIN ) 00518 $ GO TO 60 00519 TEMP = ONE / TEMP 00520 DO 50 JR = 1, N 00521 VR( JR, JC ) = VR( JR, JC )*TEMP 00522 50 CONTINUE 00523 60 CONTINUE 00524 END IF 00525 * 00526 * End of eigenvector calculation 00527 * 00528 END IF 00529 * 00530 * Undo scaling in alpha, beta 00531 * 00532 * Note: this does not give the alpha and beta for the unscaled 00533 * problem. 00534 * 00535 * Un-scaling is limited to avoid underflow in alpha and beta 00536 * if they are significant. 00537 * 00538 DO 70 JC = 1, N 00539 ABSAR = ABS( REAL( ALPHA( JC ) ) ) 00540 ABSAI = ABS( AIMAG( ALPHA( JC ) ) ) 00541 ABSB = ABS( REAL( BETA( JC ) ) ) 00542 SALFAR = ANRM*REAL( ALPHA( JC ) ) 00543 SALFAI = ANRM*AIMAG( ALPHA( JC ) ) 00544 SBETA = BNRM*REAL( BETA( JC ) ) 00545 ILIMIT = .FALSE. 00546 SCALE = ONE 00547 * 00548 * Check for significant underflow in imaginary part of ALPHA 00549 * 00550 IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE. 00551 $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN 00552 ILIMIT = .TRUE. 00553 SCALE = ( SAFMIN / ANRM1 ) / MAX( SAFMIN, ANRM2*ABSAI ) 00554 END IF 00555 * 00556 * Check for significant underflow in real part of ALPHA 00557 * 00558 IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE. 00559 $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN 00560 ILIMIT = .TRUE. 00561 SCALE = MAX( SCALE, ( SAFMIN / ANRM1 ) / 00562 $ MAX( SAFMIN, ANRM2*ABSAR ) ) 00563 END IF 00564 * 00565 * Check for significant underflow in BETA 00566 * 00567 IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE. 00568 $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN 00569 ILIMIT = .TRUE. 00570 SCALE = MAX( SCALE, ( SAFMIN / BNRM1 ) / 00571 $ MAX( SAFMIN, BNRM2*ABSB ) ) 00572 END IF 00573 * 00574 * Check for possible overflow when limiting scaling 00575 * 00576 IF( ILIMIT ) THEN 00577 TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ), 00578 $ ABS( SBETA ) ) 00579 IF( TEMP.GT.ONE ) 00580 $ SCALE = SCALE / TEMP 00581 IF( SCALE.LT.ONE ) 00582 $ ILIMIT = .FALSE. 00583 END IF 00584 * 00585 * Recompute un-scaled ALPHA, BETA if necessary. 00586 * 00587 IF( ILIMIT ) THEN 00588 SALFAR = ( SCALE*REAL( ALPHA( JC ) ) )*ANRM 00589 SALFAI = ( SCALE*AIMAG( ALPHA( JC ) ) )*ANRM 00590 SBETA = ( SCALE*BETA( JC ) )*BNRM 00591 END IF 00592 ALPHA( JC ) = CMPLX( SALFAR, SALFAI ) 00593 BETA( JC ) = SBETA 00594 70 CONTINUE 00595 * 00596 80 CONTINUE 00597 WORK( 1 ) = LWKOPT 00598 * 00599 RETURN 00600 * 00601 * End of CGEGV 00602 * 00603 END