206 IMPLICIT NONE
207
208
209 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
210 INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
211 $ NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
212
213 COMPLEX*16, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ,
214 $ * ), Z( LDZ, * ), QC( LDQC, * ), ZC( LDZC, * ), WORK( * ),
215 $ ALPHA( * ), BETA( * )
216
217 INTEGER, INTENT( OUT ) :: INFO
218
219
220 COMPLEX*16 CZERO, CONE
221 parameter( czero = ( 0.0d+0, 0.0d+0 ), cone = ( 1.0d+0,
222 $ 0.0d+0 ) )
223 DOUBLE PRECISION :: ZERO, ONE, HALF
224 parameter( zero = 0.0d0, one = 1.0d0, half = 0.5d0 )
225
226
227 INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
228 $ ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
229 DOUBLE PRECISION :: SAFMIN, SAFMAX, C, SCALE
230 COMPLEX*16 :: TEMP, TEMP2, TEMP3, S
231
232
235 DOUBLE PRECISION, EXTERNAL :: DLAMCH
236
237 info = 0
238 IF ( nblock_desired .LT. nshifts+1 ) THEN
239 info = -8
240 END IF
241 IF ( lwork .EQ.-1 ) THEN
242
243 work( 1 ) = n*nblock_desired
244 RETURN
245 ELSE IF ( lwork .LT. n*nblock_desired ) THEN
246 info = -25
247 END IF
248
249 IF( info.NE.0 ) THEN
250 CALL xerbla(
'ZLAQZ3', -info )
251 RETURN
252 END IF
253
254
255
256
257
258
259 safmin =
dlamch(
'SAFE MINIMUM' )
260 safmax = one/safmin
261
262 IF ( ilo .GE. ihi ) THEN
263 RETURN
264 END IF
265
266 IF ( ilschur ) THEN
267 istartm = 1
268 istopm = n
269 ELSE
270 istartm = ilo
271 istopm = ihi
272 END IF
273
274 ns = nshifts
275 npos = max( nblock_desired-ns, 1 )
276
277
278
279
280
281
282
283 CALL zlaset(
'FULL', ns+1, ns+1, czero, cone, qc, ldqc )
284 CALL zlaset(
'FULL', ns, ns, czero, cone, zc, ldzc )
285
286 DO i = 1, ns
287
288 scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) )
289 IF( scale .GE. safmin .AND. scale .LE. safmax ) THEN
290 alpha( i ) = alpha( i )/scale
291 beta( i ) = beta( i )/scale
292 END IF
293
294 temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo )
295 temp3 = beta( i )*a( ilo+1, ilo )
296
297 IF ( abs( temp2 ) .GT. safmax .OR.
298 $ abs( temp3 ) .GT. safmax ) THEN
299 temp2 = cone
300 temp3 = czero
301 END IF
302
303 CALL zlartg( temp2, temp3, c, s, temp )
304 CALL zrot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c,
305 $ s )
306 CALL zrot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c,
307 $ s )
308 CALL zrot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c,
309 $ dconjg( s ) )
310
311
312 DO j = 1, ns-i
313
314 CALL zlaqz1( .true., .true., j, 1, ns, ihi-ilo+1, a( ilo,
315 $ ilo ), lda, b( ilo, ilo ), ldb, ns+1, 1, qc,
316 $ ldqc, ns, 1, zc, ldzc )
317
318 END DO
319
320 END DO
321
322
323
324
325
326 sheight = ns+1
327 swidth = istopm-( ilo+ns )+1
328 IF ( swidth > 0 ) THEN
329 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
330 $ ldqc,
331 $ a( ilo, ilo+ns ), lda, czero, work, sheight )
332 CALL zlacpy(
'ALL', sheight, swidth, work, sheight, a( ilo,
333 $ ilo+ns ), lda )
334 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
335 $ ldqc,
336 $ b( ilo, ilo+ns ), ldb, czero, work, sheight )
337 CALL zlacpy(
'ALL', sheight, swidth, work, sheight, b( ilo,
338 $ ilo+ns ), ldb )
339 END IF
340 IF ( ilq ) THEN
341 CALL zgemm(
'N',
'N', n, sheight, sheight, cone, q( 1,
342 $ ilo ),
343 $ ldq, qc, ldqc, czero, work, n )
344 CALL zlacpy(
'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
345 END IF
346
347
348
349 sheight = ilo-1-istartm+1
350 swidth = ns
351 IF ( sheight > 0 ) THEN
352 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
353 $ a( istartm, ilo ), lda, zc, ldzc, czero, work,
354 $ sheight )
355 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
356 $ a( istartm,
357 $ ilo ), lda )
358 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
359 $ b( istartm, ilo ), ldb, zc, ldzc, czero, work,
360 $ sheight )
361 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
362 $ b( istartm,
363 $ ilo ), ldb )
364 END IF
365 IF ( ilz ) THEN
366 CALL zgemm(
'N',
'N', n, swidth, swidth, cone, z( 1, ilo ),
367 $ ldz, zc, ldzc, czero, work, n )
368 CALL zlacpy(
'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
369 END IF
370
371
372
373
374
375 k = ilo
376 DO WHILE ( k < ihi-ns )
377 np = min( ihi-ns-k, npos )
378
379 nblock = ns+np
380
381 istartb = k+1
382
383 istopb = k+nblock-1
384
385 CALL zlaset(
'FULL', ns+np, ns+np, czero, cone, qc, ldqc )
386 CALL zlaset(
'FULL', ns+np, ns+np, czero, cone, zc, ldzc )
387
388
389 DO i = ns-1, 0, -1
390 DO j = 0, np-1
391
392
393
394 CALL zlaqz1( .true., .true., k+i+j, istartb, istopb,
395 $ ihi,
396 $ a, lda, b, ldb, nblock, k+1, qc, ldqc,
397 $ nblock, k, zc, ldzc )
398 END DO
399 END DO
400
401
402
403
404
405
406 sheight = ns+np
407 swidth = istopm-( k+ns+np )+1
408 IF ( swidth > 0 ) THEN
409 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
410 $ ldqc, a( k+1, k+ns+np ), lda, czero, work,
411 $ sheight )
412 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
413 $ a( k+1,
414 $ k+ns+np ), lda )
415 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
416 $ ldqc, b( k+1, k+ns+np ), ldb, czero, work,
417 $ sheight )
418 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
419 $ b( k+1,
420 $ k+ns+np ), ldb )
421 END IF
422 IF ( ilq ) THEN
423 CALL zgemm(
'N',
'N', n, nblock, nblock, cone, q( 1,
424 $ k+1 ),
425 $ ldq, qc, ldqc, czero, work, n )
426 CALL zlacpy(
'ALL', n, nblock, work, n, q( 1, k+1 ),
427 $ ldq )
428 END IF
429
430
431
432 sheight = k-istartm+1
433 swidth = nblock
434 IF ( sheight > 0 ) THEN
435 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
436 $ a( istartm, k ), lda, zc, ldzc, czero, work,
437 $ sheight )
438 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
439 $ a( istartm, k ), lda )
440 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
441 $ b( istartm, k ), ldb, zc, ldzc, czero, work,
442 $ sheight )
443 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
444 $ b( istartm, k ), ldb )
445 END IF
446 IF ( ilz ) THEN
447 CALL zgemm(
'N',
'N', n, nblock, nblock, cone, z( 1, k ),
448 $ ldz, zc, ldzc, czero, work, n )
449 CALL zlacpy(
'ALL', n, nblock, work, n, z( 1, k ), ldz )
450 END IF
451
452 k = k+np
453
454 END DO
455
456
457
458
459 CALL zlaset(
'FULL', ns, ns, czero, cone, qc, ldqc )
460 CALL zlaset(
'FULL', ns+1, ns+1, czero, cone, zc, ldzc )
461
462
463 istartb = ihi-ns+1
464
465 istopb = ihi
466
467 DO i = 1, ns
468
469 DO ishift = ihi-i, ihi-1
470 CALL zlaqz1( .true., .true., ishift, istartb, istopb,
471 $ ihi,
472 $ a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
473 $ ihi-ns, zc, ldzc )
474 END DO
475
476 END DO
477
478
479
480
481
482 sheight = ns
483 swidth = istopm-( ihi+1 )+1
484 IF ( swidth > 0 ) THEN
485 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
486 $ ldqc,
487 $ a( ihi-ns+1, ihi+1 ), lda, czero, work, sheight )
488 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
489 $ a( ihi-ns+1, ihi+1 ), lda )
490 CALL zgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
491 $ ldqc,
492 $ b( ihi-ns+1, ihi+1 ), ldb, czero, work, sheight )
493 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
494 $ b( ihi-ns+1, ihi+1 ), ldb )
495 END IF
496 IF ( ilq ) THEN
497 CALL zgemm(
'N',
'N', n, ns, ns, cone, q( 1, ihi-ns+1 ),
498 $ ldq,
499 $ qc, ldqc, czero, work, n )
500 CALL zlacpy(
'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
501 END IF
502
503
504
505 sheight = ihi-ns-istartm+1
506 swidth = ns+1
507 IF ( sheight > 0 ) THEN
508 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
509 $ a( istartm, ihi-ns ), lda, zc, ldzc, czero, work,
510 $ sheight )
511 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
512 $ a( istartm,
513 $ ihi-ns ), lda )
514 CALL zgemm(
'N',
'N', sheight, swidth, swidth, cone,
515 $ b( istartm, ihi-ns ), ldb, zc, ldzc, czero, work,
516 $ sheight )
517 CALL zlacpy(
'ALL', sheight, swidth, work, sheight,
518 $ b( istartm,
519 $ ihi-ns ), ldb )
520 END IF
521 IF ( ilz ) THEN
522 CALL zgemm(
'N',
'N', n, ns+1, ns+1, cone, z( 1, ihi-ns ),
523 $ ldz,
524 $ zc, ldzc, czero, work, n )
525 CALL zlacpy(
'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
526 END IF
527
subroutine xerbla(srname, info)
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
subroutine zlaqz1(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
ZLAQZ1
subroutine zlartg(f, g, c, s, r)
ZLARTG generates a plane rotation with real cosine and complex sine.
subroutine zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zrot(n, cx, incx, cy, incy, c, s)
ZROT applies a plane rotation with real cosine and complex sine to a pair of complex vectors.