00001 SUBROUTINE DLAQR2( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ,
00002 $ IHIZ, Z, LDZ, NS, ND, SR, SI, V, LDV, NH, T,
00003 $ LDT, NV, WV, LDWV, WORK, LWORK )
00004
00005
00006
00007
00008
00009
00010 INTEGER IHIZ, ILOZ, KBOT, KTOP, LDH, LDT, LDV, LDWV,
00011 $ LDZ, LWORK, N, ND, NH, NS, NV, NW
00012 LOGICAL WANTT, WANTZ
00013
00014
00015 DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), T( LDT, * ),
00016 $ V( LDV, * ), WORK( * ), WV( LDWV, * ),
00017 $ Z( LDZ, * )
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 DOUBLE PRECISION ZERO, ONE
00163 PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 )
00164
00165
00166 DOUBLE PRECISION AA, BB, BETA, CC, CS, DD, EVI, EVK, FOO, S,
00167 $ SAFMAX, SAFMIN, SMLNUM, SN, TAU, ULP
00168 INTEGER I, IFST, ILST, INFO, INFQR, J, JW, K, KCOL,
00169 $ KEND, KLN, KROW, KWTOP, LTOP, LWK1, LWK2,
00170 $ LWKOPT
00171 LOGICAL BULGE, SORTED
00172
00173
00174 DOUBLE PRECISION DLAMCH
00175 EXTERNAL DLAMCH
00176
00177
00178 EXTERNAL DCOPY, DGEHRD, DGEMM, DLABAD, DLACPY, DLAHQR,
00179 $ DLANV2, DLARF, DLARFG, DLASET, DORMHR, DTREXC
00180
00181
00182 INTRINSIC ABS, DBLE, INT, MAX, MIN, SQRT
00183
00184
00185
00186
00187
00188 JW = MIN( NW, KBOT-KTOP+1 )
00189 IF( JW.LE.2 ) THEN
00190 LWKOPT = 1
00191 ELSE
00192
00193
00194
00195 CALL DGEHRD( JW, 1, JW-1, T, LDT, WORK, WORK, -1, INFO )
00196 LWK1 = INT( WORK( 1 ) )
00197
00198
00199
00200 CALL DORMHR( 'R', 'N', JW, JW, 1, JW-1, T, LDT, WORK, V, LDV,
00201 $ WORK, -1, INFO )
00202 LWK2 = INT( WORK( 1 ) )
00203
00204
00205
00206 LWKOPT = JW + MAX( LWK1, LWK2 )
00207 END IF
00208
00209
00210
00211 IF( LWORK.EQ.-1 ) THEN
00212 WORK( 1 ) = DBLE( LWKOPT )
00213 RETURN
00214 END IF
00215
00216
00217
00218 NS = 0
00219 ND = 0
00220 WORK( 1 ) = ONE
00221 IF( KTOP.GT.KBOT )
00222 $ RETURN
00223
00224 IF( NW.LT.1 )
00225 $ RETURN
00226
00227
00228
00229 SAFMIN = DLAMCH( 'SAFE MINIMUM' )
00230 SAFMAX = ONE / SAFMIN
00231 CALL DLABAD( SAFMIN, SAFMAX )
00232 ULP = DLAMCH( 'PRECISION' )
00233 SMLNUM = SAFMIN*( DBLE( N ) / ULP )
00234
00235
00236
00237 JW = MIN( NW, KBOT-KTOP+1 )
00238 KWTOP = KBOT - JW + 1
00239 IF( KWTOP.EQ.KTOP ) THEN
00240 S = ZERO
00241 ELSE
00242 S = H( KWTOP, KWTOP-1 )
00243 END IF
00244
00245 IF( KBOT.EQ.KWTOP ) THEN
00246
00247
00248
00249 SR( KWTOP ) = H( KWTOP, KWTOP )
00250 SI( KWTOP ) = ZERO
00251 NS = 1
00252 ND = 0
00253 IF( ABS( S ).LE.MAX( SMLNUM, ULP*ABS( H( KWTOP, KWTOP ) ) ) )
00254 $ THEN
00255 NS = 0
00256 ND = 1
00257 IF( KWTOP.GT.KTOP )
00258 $ H( KWTOP, KWTOP-1 ) = ZERO
00259 END IF
00260 WORK( 1 ) = ONE
00261 RETURN
00262 END IF
00263
00264
00265
00266
00267
00268
00269
00270 CALL DLACPY( 'U', JW, JW, H( KWTOP, KWTOP ), LDH, T, LDT )
00271 CALL DCOPY( JW-1, H( KWTOP+1, KWTOP ), LDH+1, T( 2, 1 ), LDT+1 )
00272
00273 CALL DLASET( 'A', JW, JW, ZERO, ONE, V, LDV )
00274 CALL DLAHQR( .true., .true., JW, 1, JW, T, LDT, SR( KWTOP ),
00275 $ SI( KWTOP ), 1, JW, V, LDV, INFQR )
00276
00277
00278
00279 DO 10 J = 1, JW - 3
00280 T( J+2, J ) = ZERO
00281 T( J+3, J ) = ZERO
00282 10 CONTINUE
00283 IF( JW.GT.2 )
00284 $ T( JW, JW-2 ) = ZERO
00285
00286
00287
00288 NS = JW
00289 ILST = INFQR + 1
00290 20 CONTINUE
00291 IF( ILST.LE.NS ) THEN
00292 IF( NS.EQ.1 ) THEN
00293 BULGE = .FALSE.
00294 ELSE
00295 BULGE = T( NS, NS-1 ).NE.ZERO
00296 END IF
00297
00298
00299
00300 IF( .NOT.BULGE ) THEN
00301
00302
00303
00304 FOO = ABS( T( NS, NS ) )
00305 IF( FOO.EQ.ZERO )
00306 $ FOO = ABS( S )
00307 IF( ABS( S*V( 1, NS ) ).LE.MAX( SMLNUM, ULP*FOO ) ) THEN
00308
00309
00310
00311 NS = NS - 1
00312 ELSE
00313
00314
00315
00316
00317 IFST = NS
00318 CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK,
00319 $ INFO )
00320 ILST = ILST + 1
00321 END IF
00322 ELSE
00323
00324
00325
00326 FOO = ABS( T( NS, NS ) ) + SQRT( ABS( T( NS, NS-1 ) ) )*
00327 $ SQRT( ABS( T( NS-1, NS ) ) )
00328 IF( FOO.EQ.ZERO )
00329 $ FOO = ABS( S )
00330 IF( MAX( ABS( S*V( 1, NS ) ), ABS( S*V( 1, NS-1 ) ) ).LE.
00331 $ MAX( SMLNUM, ULP*FOO ) ) THEN
00332
00333
00334
00335 NS = NS - 2
00336 ELSE
00337
00338
00339
00340
00341
00342 IFST = NS
00343 CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK,
00344 $ INFO )
00345 ILST = ILST + 2
00346 END IF
00347 END IF
00348
00349
00350
00351 GO TO 20
00352 END IF
00353
00354
00355
00356 IF( NS.EQ.0 )
00357 $ S = ZERO
00358
00359 IF( NS.LT.JW ) THEN
00360
00361
00362
00363
00364
00365 SORTED = .false.
00366 I = NS + 1
00367 30 CONTINUE
00368 IF( SORTED )
00369 $ GO TO 50
00370 SORTED = .true.
00371
00372 KEND = I - 1
00373 I = INFQR + 1
00374 IF( I.EQ.NS ) THEN
00375 K = I + 1
00376 ELSE IF( T( I+1, I ).EQ.ZERO ) THEN
00377 K = I + 1
00378 ELSE
00379 K = I + 2
00380 END IF
00381 40 CONTINUE
00382 IF( K.LE.KEND ) THEN
00383 IF( K.EQ.I+1 ) THEN
00384 EVI = ABS( T( I, I ) )
00385 ELSE
00386 EVI = ABS( T( I, I ) ) + SQRT( ABS( T( I+1, I ) ) )*
00387 $ SQRT( ABS( T( I, I+1 ) ) )
00388 END IF
00389
00390 IF( K.EQ.KEND ) THEN
00391 EVK = ABS( T( K, K ) )
00392 ELSE IF( T( K+1, K ).EQ.ZERO ) THEN
00393 EVK = ABS( T( K, K ) )
00394 ELSE
00395 EVK = ABS( T( K, K ) ) + SQRT( ABS( T( K+1, K ) ) )*
00396 $ SQRT( ABS( T( K, K+1 ) ) )
00397 END IF
00398
00399 IF( EVI.GE.EVK ) THEN
00400 I = K
00401 ELSE
00402 SORTED = .false.
00403 IFST = I
00404 ILST = K
00405 CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK,
00406 $ INFO )
00407 IF( INFO.EQ.0 ) THEN
00408 I = ILST
00409 ELSE
00410 I = K
00411 END IF
00412 END IF
00413 IF( I.EQ.KEND ) THEN
00414 K = I + 1
00415 ELSE IF( T( I+1, I ).EQ.ZERO ) THEN
00416 K = I + 1
00417 ELSE
00418 K = I + 2
00419 END IF
00420 GO TO 40
00421 END IF
00422 GO TO 30
00423 50 CONTINUE
00424 END IF
00425
00426
00427
00428 I = JW
00429 60 CONTINUE
00430 IF( I.GE.INFQR+1 ) THEN
00431 IF( I.EQ.INFQR+1 ) THEN
00432 SR( KWTOP+I-1 ) = T( I, I )
00433 SI( KWTOP+I-1 ) = ZERO
00434 I = I - 1
00435 ELSE IF( T( I, I-1 ).EQ.ZERO ) THEN
00436 SR( KWTOP+I-1 ) = T( I, I )
00437 SI( KWTOP+I-1 ) = ZERO
00438 I = I - 1
00439 ELSE
00440 AA = T( I-1, I-1 )
00441 CC = T( I, I-1 )
00442 BB = T( I-1, I )
00443 DD = T( I, I )
00444 CALL DLANV2( AA, BB, CC, DD, SR( KWTOP+I-2 ),
00445 $ SI( KWTOP+I-2 ), SR( KWTOP+I-1 ),
00446 $ SI( KWTOP+I-1 ), CS, SN )
00447 I = I - 2
00448 END IF
00449 GO TO 60
00450 END IF
00451
00452 IF( NS.LT.JW .OR. S.EQ.ZERO ) THEN
00453 IF( NS.GT.1 .AND. S.NE.ZERO ) THEN
00454
00455
00456
00457 CALL DCOPY( NS, V, LDV, WORK, 1 )
00458 BETA = WORK( 1 )
00459 CALL DLARFG( NS, BETA, WORK( 2 ), 1, TAU )
00460 WORK( 1 ) = ONE
00461
00462 CALL DLASET( 'L', JW-2, JW-2, ZERO, ZERO, T( 3, 1 ), LDT )
00463
00464 CALL DLARF( 'L', NS, JW, WORK, 1, TAU, T, LDT,
00465 $ WORK( JW+1 ) )
00466 CALL DLARF( 'R', NS, NS, WORK, 1, TAU, T, LDT,
00467 $ WORK( JW+1 ) )
00468 CALL DLARF( 'R', JW, NS, WORK, 1, TAU, V, LDV,
00469 $ WORK( JW+1 ) )
00470
00471 CALL DGEHRD( JW, 1, NS, T, LDT, WORK, WORK( JW+1 ),
00472 $ LWORK-JW, INFO )
00473 END IF
00474
00475
00476
00477 IF( KWTOP.GT.1 )
00478 $ H( KWTOP, KWTOP-1 ) = S*V( 1, 1 )
00479 CALL DLACPY( 'U', JW, JW, T, LDT, H( KWTOP, KWTOP ), LDH )
00480 CALL DCOPY( JW-1, T( 2, 1 ), LDT+1, H( KWTOP+1, KWTOP ),
00481 $ LDH+1 )
00482
00483
00484
00485
00486 IF( NS.GT.1 .AND. S.NE.ZERO )
00487 $ CALL DORMHR( 'R', 'N', JW, NS, 1, NS, T, LDT, WORK, V, LDV,
00488 $ WORK( JW+1 ), LWORK-JW, INFO )
00489
00490
00491
00492 IF( WANTT ) THEN
00493 LTOP = 1
00494 ELSE
00495 LTOP = KTOP
00496 END IF
00497 DO 70 KROW = LTOP, KWTOP - 1, NV
00498 KLN = MIN( NV, KWTOP-KROW )
00499 CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, H( KROW, KWTOP ),
00500 $ LDH, V, LDV, ZERO, WV, LDWV )
00501 CALL DLACPY( 'A', KLN, JW, WV, LDWV, H( KROW, KWTOP ), LDH )
00502 70 CONTINUE
00503
00504
00505
00506 IF( WANTT ) THEN
00507 DO 80 KCOL = KBOT + 1, N, NH
00508 KLN = MIN( NH, N-KCOL+1 )
00509 CALL DGEMM( 'C', 'N', JW, KLN, JW, ONE, V, LDV,
00510 $ H( KWTOP, KCOL ), LDH, ZERO, T, LDT )
00511 CALL DLACPY( 'A', JW, KLN, T, LDT, H( KWTOP, KCOL ),
00512 $ LDH )
00513 80 CONTINUE
00514 END IF
00515
00516
00517
00518 IF( WANTZ ) THEN
00519 DO 90 KROW = ILOZ, IHIZ, NV
00520 KLN = MIN( NV, IHIZ-KROW+1 )
00521 CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, Z( KROW, KWTOP ),
00522 $ LDZ, V, LDV, ZERO, WV, LDWV )
00523 CALL DLACPY( 'A', KLN, JW, WV, LDWV, Z( KROW, KWTOP ),
00524 $ LDZ )
00525 90 CONTINUE
00526 END IF
00527 END IF
00528
00529
00530
00531 ND = JW - NS
00532
00533
00534
00535
00536
00537
00538
00539 NS = NS - INFQR
00540
00541
00542
00543 WORK( 1 ) = DBLE( LWKOPT )
00544
00545
00546
00547 END