211 IMPLICIT NONE
212
213
214 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
215 INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
216 $ NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
217
218 DOUBLE PRECISION, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ),
219 $ Q( LDQ, * ), Z( LDZ, * ), QC( LDQC, * ),
220 $ ZC( LDZC, * ), WORK( * ), SR( * ), SI( * ),
221 $ SS( * )
222
223 INTEGER, INTENT( OUT ) :: INFO
224
225
226 DOUBLE PRECISION :: ZERO, ONE, HALF
227 parameter( zero = 0.0d0, one = 1.0d0, half = 0.5d0 )
228
229
230 INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
231 $ ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
232 DOUBLE PRECISION :: TEMP, V( 3 ), C1, S1, C2, S2, SWAP
233
234
237
238 info = 0
239 IF ( nblock_desired .LT. nshifts+1 ) THEN
240 info = -8
241 END IF
242 IF ( lwork .EQ.-1 ) THEN
243
244 work( 1 ) = n*nblock_desired
245 RETURN
246 ELSE IF ( lwork .LT. n*nblock_desired ) THEN
247 info = -25
248 END IF
249
250 IF( info.NE.0 ) THEN
251 CALL xerbla(
'DLAQZ4', -info )
252 RETURN
253 END IF
254
255
256
257 IF ( nshifts .LT. 2 ) THEN
258 RETURN
259 END IF
260
261 IF ( ilo .GE. ihi ) THEN
262 RETURN
263 END IF
264
265 IF ( ilschur ) THEN
266 istartm = 1
267 istopm = n
268 ELSE
269 istartm = ilo
270 istopm = ihi
271 END IF
272
273
274
275
276
277
278 DO i = 1, nshifts-2, 2
279 IF( si( i ).NE.-si( i+1 ) ) THEN
280
281 swap = sr( i )
282 sr( i ) = sr( i+1 )
283 sr( i+1 ) = sr( i+2 )
284 sr( i+2 ) = swap
285
286 swap = si( i )
287 si( i ) = si( i+1 )
288 si( i+1 ) = si( i+2 )
289 si( i+2 ) = swap
290
291 swap = ss( i )
292 ss( i ) = ss( i+1 )
293 ss( i+1 ) = ss( i+2 )
294 ss( i+2 ) = swap
295 END IF
296 END DO
297
298
299
300
301
302
303 ns = nshifts-mod( nshifts, 2 )
304 npos = max( nblock_desired-ns, 1 )
305
306
307
308
309
310
311 CALL dlaset(
'FULL', ns+1, ns+1, zero, one, qc, ldqc )
312 CALL dlaset(
'FULL', ns, ns, zero, one, zc, ldzc )
313
314 DO i = 1, ns, 2
315
316 CALL dlaqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb,
317 $ sr( i ),
318 $ sr( i+1 ), si( i ), ss( i ), ss( i+1 ), v )
319
320 temp = v( 2 )
321 CALL dlartg( temp, v( 3 ), c1, s1, v( 2 ) )
322 CALL dlartg( v( 1 ), v( 2 ), c2, s2, temp )
323
324 CALL drot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda,
325 $ c1,
326 $ s1 )
327 CALL drot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,
328 $ s2 )
329 CALL drot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb,
330 $ c1,
331 $ s1 )
332 CALL drot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,
333 $ s2 )
334 CALL drot( ns+1, qc( 1, 2 ), 1, qc( 1, 3 ), 1, c1, s1 )
335 CALL drot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c2, s2 )
336
337
338 DO j = 1, ns-1-i
339
340 CALL dlaqz2( .true., .true., j, 1, ns, ihi-ilo+1, a( ilo,
341 $ ilo ), lda, b( ilo, ilo ), ldb, ns+1, 1, qc,
342 $ ldqc, ns, 1, zc, ldzc )
343
344 END DO
345
346 END DO
347
348
349
350
351
352 sheight = ns+1
353 swidth = istopm-( ilo+ns )+1
354 IF ( swidth > 0 ) THEN
355 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
356 $ ldqc,
357 $ a( ilo, ilo+ns ), lda, zero, work, sheight )
358 CALL dlacpy(
'ALL', sheight, swidth, work, sheight, a( ilo,
359 $ ilo+ns ), lda )
360 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
361 $ ldqc,
362 $ b( ilo, ilo+ns ), ldb, zero, work, sheight )
363 CALL dlacpy(
'ALL', sheight, swidth, work, sheight, b( ilo,
364 $ ilo+ns ), ldb )
365 END IF
366 IF ( ilq ) THEN
367 CALL dgemm(
'N',
'N', n, sheight, sheight, one, q( 1, ilo ),
368 $ ldq, qc, ldqc, zero, work, n )
369 CALL dlacpy(
'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
370 END IF
371
372
373
374 sheight = ilo-1-istartm+1
375 swidth = ns
376 IF ( sheight > 0 ) THEN
377 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
378 $ a( istartm,
379 $ ilo ), lda, zc, ldzc, zero, work, sheight )
380 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
381 $ a( istartm,
382 $ ilo ), lda )
383 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
384 $ b( istartm,
385 $ ilo ), ldb, zc, ldzc, zero, work, sheight )
386 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
387 $ b( istartm,
388 $ ilo ), ldb )
389 END IF
390 IF ( ilz ) THEN
391 CALL dgemm(
'N',
'N', n, swidth, swidth, one, z( 1, ilo ),
392 $ ldz,
393 $ zc, ldzc, zero, work, n )
394 CALL dlacpy(
'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
395 END IF
396
397
398
399
400
401 k = ilo
402 DO WHILE ( k < ihi-ns )
403 np = min( ihi-ns-k, npos )
404
405 nblock = ns+np
406
407 istartb = k+1
408
409 istopb = k+nblock-1
410
411 CALL dlaset(
'FULL', ns+np, ns+np, zero, one, qc, ldqc )
412 CALL dlaset(
'FULL', ns+np, ns+np, zero, one, zc, ldzc )
413
414
415 DO i = ns-1, 0, -2
416 DO j = 0, np-1
417
418
419
420 CALL dlaqz2( .true., .true., k+i+j-1, istartb, istopb,
421 $ ihi, a, lda, b, ldb, nblock, k+1, qc, ldqc,
422 $ nblock, k, zc, ldzc )
423 END DO
424 END DO
425
426
427
428
429
430
431 sheight = ns+np
432 swidth = istopm-( k+ns+np )+1
433 IF ( swidth > 0 ) THEN
434 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
435 $ ldqc, a( k+1, k+ns+np ), lda, zero, work,
436 $ sheight )
437 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
438 $ a( k+1,
439 $ k+ns+np ), lda )
440 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
441 $ ldqc, b( k+1, k+ns+np ), ldb, zero, work,
442 $ sheight )
443 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
444 $ b( k+1,
445 $ k+ns+np ), ldb )
446 END IF
447 IF ( ilq ) THEN
448 CALL dgemm(
'N',
'N', n, nblock, nblock, one, q( 1,
449 $ k+1 ),
450 $ ldq, qc, ldqc, zero, work, n )
451 CALL dlacpy(
'ALL', n, nblock, work, n, q( 1, k+1 ),
452 $ ldq )
453 END IF
454
455
456
457 sheight = k-istartm+1
458 swidth = nblock
459 IF ( sheight > 0 ) THEN
460 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
461 $ a( istartm, k ), lda, zc, ldzc, zero, work,
462 $ sheight )
463 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
464 $ a( istartm, k ), lda )
465 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
466 $ b( istartm, k ), ldb, zc, ldzc, zero, work,
467 $ sheight )
468 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
469 $ b( istartm, k ), ldb )
470 END IF
471 IF ( ilz ) THEN
472 CALL dgemm(
'N',
'N', n, nblock, nblock, one, z( 1, k ),
473 $ ldz, zc, ldzc, zero, work, n )
474 CALL dlacpy(
'ALL', n, nblock, work, n, z( 1, k ), ldz )
475 END IF
476
477 k = k+np
478
479 END DO
480
481
482
483
484 CALL dlaset(
'FULL', ns, ns, zero, one, qc, ldqc )
485 CALL dlaset(
'FULL', ns+1, ns+1, zero, one, zc, ldzc )
486
487
488 istartb = ihi-ns+1
489
490 istopb = ihi
491
492 DO i = 1, ns, 2
493
494 DO ishift = ihi-i-1, ihi-2
495 CALL dlaqz2( .true., .true., ishift, istartb, istopb,
496 $ ihi,
497 $ a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
498 $ ihi-ns, zc, ldzc )
499 END DO
500
501 END DO
502
503
504
505
506
507 sheight = ns
508 swidth = istopm-( ihi+1 )+1
509 IF ( swidth > 0 ) THEN
510 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
511 $ ldqc,
512 $ a( ihi-ns+1, ihi+1 ), lda, zero, work, sheight )
513 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
514 $ a( ihi-ns+1, ihi+1 ), lda )
515 CALL dgemm(
'T',
'N', sheight, swidth, sheight, one, qc,
516 $ ldqc,
517 $ b( ihi-ns+1, ihi+1 ), ldb, zero, work, sheight )
518 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
519 $ b( ihi-ns+1, ihi+1 ), ldb )
520 END IF
521 IF ( ilq ) THEN
522 CALL dgemm(
'N',
'N', n, ns, ns, one, q( 1, ihi-ns+1 ), ldq,
523 $ qc, ldqc, zero, work, n )
524 CALL dlacpy(
'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
525 END IF
526
527
528
529 sheight = ihi-ns-istartm+1
530 swidth = ns+1
531 IF ( sheight > 0 ) THEN
532 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
533 $ a( istartm,
534 $ ihi-ns ), lda, zc, ldzc, zero, work, sheight )
535 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
536 $ a( istartm,
537 $ ihi-ns ), lda )
538 CALL dgemm(
'N',
'N', sheight, swidth, swidth, one,
539 $ b( istartm,
540 $ ihi-ns ), ldb, zc, ldzc, zero, work, sheight )
541 CALL dlacpy(
'ALL', sheight, swidth, work, sheight,
542 $ b( istartm,
543 $ ihi-ns ), ldb )
544 END IF
545 IF ( ilz ) THEN
546 CALL dgemm(
'N',
'N', n, ns+1, ns+1, one, z( 1, ihi-ns ),
547 $ ldz,
548 $ zc, ldzc, zero, work, n )
549 CALL dlacpy(
'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
550 END IF
551
subroutine xerbla(srname, info)
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlaqz1(a, lda, b, ldb, sr1, sr2, si, beta1, beta2, v)
DLAQZ1
subroutine dlaqz2(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
DLAQZ2
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT