00001 SUBROUTINE ZLAQR3( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ,
00002 $ IHIZ, Z, LDZ, NS, ND, SH, V, LDV, NH, T, LDT,
00003 $ 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 COMPLEX*16 H( LDH, * ), SH( * ), T( LDT, * ), V( LDV, * ),
00016 $ WORK( * ), WV( LDWV, * ), Z( LDZ, * )
00017
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 COMPLEX*16 ZERO, ONE
00154 PARAMETER ( ZERO = ( 0.0d0, 0.0d0 ),
00155 $ ONE = ( 1.0d0, 0.0d0 ) )
00156 DOUBLE PRECISION RZERO, RONE
00157 PARAMETER ( RZERO = 0.0d0, RONE = 1.0d0 )
00158
00159
00160 COMPLEX*16 BETA, CDUM, S, TAU
00161 DOUBLE PRECISION FOO, SAFMAX, SAFMIN, SMLNUM, ULP
00162 INTEGER I, IFST, ILST, INFO, INFQR, J, JW, KCOL, KLN,
00163 $ KNT, KROW, KWTOP, LTOP, LWK1, LWK2, LWK3,
00164 $ LWKOPT, NMIN
00165
00166
00167 DOUBLE PRECISION DLAMCH
00168 INTEGER ILAENV
00169 EXTERNAL DLAMCH, ILAENV
00170
00171
00172 EXTERNAL DLABAD, ZCOPY, ZGEHRD, ZGEMM, ZLACPY, ZLAHQR,
00173 $ ZLAQR4, ZLARF, ZLARFG, ZLASET, ZTREXC, ZUNMHR
00174
00175
00176 INTRINSIC ABS, DBLE, DCMPLX, DCONJG, DIMAG, INT, MAX, MIN
00177
00178
00179 DOUBLE PRECISION CABS1
00180
00181
00182 CABS1( CDUM ) = ABS( DBLE( CDUM ) ) + ABS( DIMAG( CDUM ) )
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 ZGEHRD( JW, 1, JW-1, T, LDT, WORK, WORK, -1, INFO )
00196 LWK1 = INT( WORK( 1 ) )
00197
00198
00199
00200 CALL ZUNMHR( '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 CALL ZLAQR4( .true., .true., JW, 1, JW, T, LDT, SH, 1, JW, V,
00207 $ LDV, WORK, -1, INFQR )
00208 LWK3 = INT( WORK( 1 ) )
00209
00210
00211
00212 LWKOPT = MAX( JW+MAX( LWK1, LWK2 ), LWK3 )
00213 END IF
00214
00215
00216
00217 IF( LWORK.EQ.-1 ) THEN
00218 WORK( 1 ) = DCMPLX( LWKOPT, 0 )
00219 RETURN
00220 END IF
00221
00222
00223
00224 NS = 0
00225 ND = 0
00226 WORK( 1 ) = ONE
00227 IF( KTOP.GT.KBOT )
00228 $ RETURN
00229
00230 IF( NW.LT.1 )
00231 $ RETURN
00232
00233
00234
00235 SAFMIN = DLAMCH( 'SAFE MINIMUM' )
00236 SAFMAX = RONE / SAFMIN
00237 CALL DLABAD( SAFMIN, SAFMAX )
00238 ULP = DLAMCH( 'PRECISION' )
00239 SMLNUM = SAFMIN*( DBLE( N ) / ULP )
00240
00241
00242
00243 JW = MIN( NW, KBOT-KTOP+1 )
00244 KWTOP = KBOT - JW + 1
00245 IF( KWTOP.EQ.KTOP ) THEN
00246 S = ZERO
00247 ELSE
00248 S = H( KWTOP, KWTOP-1 )
00249 END IF
00250
00251 IF( KBOT.EQ.KWTOP ) THEN
00252
00253
00254
00255 SH( KWTOP ) = H( KWTOP, KWTOP )
00256 NS = 1
00257 ND = 0
00258 IF( CABS1( S ).LE.MAX( SMLNUM, ULP*CABS1( H( KWTOP,
00259 $ KWTOP ) ) ) ) THEN
00260 NS = 0
00261 ND = 1
00262 IF( KWTOP.GT.KTOP )
00263 $ H( KWTOP, KWTOP-1 ) = ZERO
00264 END IF
00265 WORK( 1 ) = ONE
00266 RETURN
00267 END IF
00268
00269
00270
00271
00272
00273
00274
00275 CALL ZLACPY( 'U', JW, JW, H( KWTOP, KWTOP ), LDH, T, LDT )
00276 CALL ZCOPY( JW-1, H( KWTOP+1, KWTOP ), LDH+1, T( 2, 1 ), LDT+1 )
00277
00278 CALL ZLASET( 'A', JW, JW, ZERO, ONE, V, LDV )
00279 NMIN = ILAENV( 12, 'ZLAQR3', 'SV', JW, 1, JW, LWORK )
00280 IF( JW.GT.NMIN ) THEN
00281 CALL ZLAQR4( .true., .true., JW, 1, JW, T, LDT, SH( KWTOP ), 1,
00282 $ JW, V, LDV, WORK, LWORK, INFQR )
00283 ELSE
00284 CALL ZLAHQR( .true., .true., JW, 1, JW, T, LDT, SH( KWTOP ), 1,
00285 $ JW, V, LDV, INFQR )
00286 END IF
00287
00288
00289
00290 NS = JW
00291 ILST = INFQR + 1
00292 DO 10 KNT = INFQR + 1, JW
00293
00294
00295
00296 FOO = CABS1( T( NS, NS ) )
00297 IF( FOO.EQ.RZERO )
00298 $ FOO = CABS1( S )
00299 IF( CABS1( S )*CABS1( V( 1, NS ) ).LE.MAX( SMLNUM, ULP*FOO ) )
00300 $ THEN
00301
00302
00303
00304 NS = NS - 1
00305 ELSE
00306
00307
00308
00309
00310 IFST = NS
00311 CALL ZTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, INFO )
00312 ILST = ILST + 1
00313 END IF
00314 10 CONTINUE
00315
00316
00317
00318 IF( NS.EQ.0 )
00319 $ S = ZERO
00320
00321 IF( NS.LT.JW ) THEN
00322
00323
00324
00325
00326 DO 30 I = INFQR + 1, NS
00327 IFST = I
00328 DO 20 J = I + 1, NS
00329 IF( CABS1( T( J, J ) ).GT.CABS1( T( IFST, IFST ) ) )
00330 $ IFST = J
00331 20 CONTINUE
00332 ILST = I
00333 IF( IFST.NE.ILST )
00334 $ CALL ZTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, INFO )
00335 30 CONTINUE
00336 END IF
00337
00338
00339
00340 DO 40 I = INFQR + 1, JW
00341 SH( KWTOP+I-1 ) = T( I, I )
00342 40 CONTINUE
00343
00344
00345 IF( NS.LT.JW .OR. S.EQ.ZERO ) THEN
00346 IF( NS.GT.1 .AND. S.NE.ZERO ) THEN
00347
00348
00349
00350 CALL ZCOPY( NS, V, LDV, WORK, 1 )
00351 DO 50 I = 1, NS
00352 WORK( I ) = DCONJG( WORK( I ) )
00353 50 CONTINUE
00354 BETA = WORK( 1 )
00355 CALL ZLARFG( NS, BETA, WORK( 2 ), 1, TAU )
00356 WORK( 1 ) = ONE
00357
00358 CALL ZLASET( 'L', JW-2, JW-2, ZERO, ZERO, T( 3, 1 ), LDT )
00359
00360 CALL ZLARF( 'L', NS, JW, WORK, 1, DCONJG( TAU ), T, LDT,
00361 $ WORK( JW+1 ) )
00362 CALL ZLARF( 'R', NS, NS, WORK, 1, TAU, T, LDT,
00363 $ WORK( JW+1 ) )
00364 CALL ZLARF( 'R', JW, NS, WORK, 1, TAU, V, LDV,
00365 $ WORK( JW+1 ) )
00366
00367 CALL ZGEHRD( JW, 1, NS, T, LDT, WORK, WORK( JW+1 ),
00368 $ LWORK-JW, INFO )
00369 END IF
00370
00371
00372
00373 IF( KWTOP.GT.1 )
00374 $ H( KWTOP, KWTOP-1 ) = S*DCONJG( V( 1, 1 ) )
00375 CALL ZLACPY( 'U', JW, JW, T, LDT, H( KWTOP, KWTOP ), LDH )
00376 CALL ZCOPY( JW-1, T( 2, 1 ), LDT+1, H( KWTOP+1, KWTOP ),
00377 $ LDH+1 )
00378
00379
00380
00381
00382 IF( NS.GT.1 .AND. S.NE.ZERO )
00383 $ CALL ZUNMHR( 'R', 'N', JW, NS, 1, NS, T, LDT, WORK, V, LDV,
00384 $ WORK( JW+1 ), LWORK-JW, INFO )
00385
00386
00387
00388 IF( WANTT ) THEN
00389 LTOP = 1
00390 ELSE
00391 LTOP = KTOP
00392 END IF
00393 DO 60 KROW = LTOP, KWTOP - 1, NV
00394 KLN = MIN( NV, KWTOP-KROW )
00395 CALL ZGEMM( 'N', 'N', KLN, JW, JW, ONE, H( KROW, KWTOP ),
00396 $ LDH, V, LDV, ZERO, WV, LDWV )
00397 CALL ZLACPY( 'A', KLN, JW, WV, LDWV, H( KROW, KWTOP ), LDH )
00398 60 CONTINUE
00399
00400
00401
00402 IF( WANTT ) THEN
00403 DO 70 KCOL = KBOT + 1, N, NH
00404 KLN = MIN( NH, N-KCOL+1 )
00405 CALL ZGEMM( 'C', 'N', JW, KLN, JW, ONE, V, LDV,
00406 $ H( KWTOP, KCOL ), LDH, ZERO, T, LDT )
00407 CALL ZLACPY( 'A', JW, KLN, T, LDT, H( KWTOP, KCOL ),
00408 $ LDH )
00409 70 CONTINUE
00410 END IF
00411
00412
00413
00414 IF( WANTZ ) THEN
00415 DO 80 KROW = ILOZ, IHIZ, NV
00416 KLN = MIN( NV, IHIZ-KROW+1 )
00417 CALL ZGEMM( 'N', 'N', KLN, JW, JW, ONE, Z( KROW, KWTOP ),
00418 $ LDZ, V, LDV, ZERO, WV, LDWV )
00419 CALL ZLACPY( 'A', KLN, JW, WV, LDWV, Z( KROW, KWTOP ),
00420 $ LDZ )
00421 80 CONTINUE
00422 END IF
00423 END IF
00424
00425
00426
00427 ND = JW - NS
00428
00429
00430
00431
00432
00433
00434
00435 NS = NS - INFQR
00436
00437
00438
00439 WORK( 1 ) = DCMPLX( LWKOPT, 0 )
00440
00441
00442
00443 END