LAPACK 3.12.0
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ claqz3()

subroutine claqz3 ( logical, intent(in)  ilschur,
logical, intent(in)  ilq,
logical, intent(in)  ilz,
integer, intent(in)  n,
integer, intent(in)  ilo,
integer, intent(in)  ihi,
integer, intent(in)  nshifts,
integer, intent(in)  nblock_desired,
complex, dimension( * ), intent(inout)  alpha,
complex, dimension( * ), intent(inout)  beta,
complex, dimension( lda, * ), intent(inout)  a,
integer, intent(in)  lda,
complex, dimension( ldb, * ), intent(inout)  b,
integer, intent(in)  ldb,
complex, dimension( ldq, * ), intent(inout)  q,
integer, intent(in)  ldq,
complex, dimension( ldz, * ), intent(inout)  z,
integer, intent(in)  ldz,
complex, dimension( ldqc, * ), intent(inout)  qc,
integer, intent(in)  ldqc,
complex, dimension( ldzc, * ), intent(inout)  zc,
integer, intent(in)  ldzc,
complex, dimension( * ), intent(inout)  work,
integer, intent(in)  lwork,
integer, intent(out)  info 
)

CLAQZ3

Download CLAQZ3 + dependencies [TGZ] [ZIP] [TXT]

Purpose:
 CLAQZ3 Executes a single multishift QZ sweep
Parameters
[in]ILSCHUR
          ILSCHUR is LOGICAL
              Determines whether or not to update the full Schur form
[in]ILQ
          ILQ is LOGICAL
              Determines whether or not to update the matrix Q
[in]ILZ
          ILZ is LOGICAL
              Determines whether or not to update the matrix Z
[in]N
          N is INTEGER
          The order of the matrices A, B, Q, and Z.  N >= 0.
[in]ILO
          ILO is INTEGER
[in]IHI
          IHI is INTEGER
[in]NSHIFTS
          NSHIFTS is INTEGER
          The desired number of shifts to use
[in]NBLOCK_DESIRED
          NBLOCK_DESIRED is INTEGER
          The desired size of the computational windows
[in]ALPHA
          ALPHA is COMPLEX array. SR contains
          the alpha parts of the shifts to use.
[in]BETA
          BETA is COMPLEX array. SS contains
          the scale of the shifts to use.
[in,out]A
          A is COMPLEX array, dimension (LDA, N)
[in]LDA
          LDA is INTEGER
          The leading dimension of the array A.  LDA >= max( 1, N ).
[in,out]B
          B is COMPLEX array, dimension (LDB, N)
[in]LDB
          LDB is INTEGER
          The leading dimension of the array B.  LDB >= max( 1, N ).
[in,out]Q
          Q is COMPLEX array, dimension (LDQ, N)
[in]LDQ
          LDQ is INTEGER
[in,out]Z
          Z is COMPLEX array, dimension (LDZ, N)
[in]LDZ
          LDZ is INTEGER
[in,out]QC
          QC is COMPLEX array, dimension (LDQC, NBLOCK_DESIRED)
[in]LDQC
          LDQC is INTEGER
[in,out]ZC
          ZC is COMPLEX array, dimension (LDZC, NBLOCK_DESIRED)
[in]LDZC
          LDZ is INTEGER
[out]WORK
          WORK is COMPLEX array, dimension (MAX(1,LWORK))
          On exit, if INFO >= 0, WORK(1) returns the optimal LWORK.
[in]LWORK
          LWORK is INTEGER
          The dimension of the array WORK.  LWORK >= max(1,N).

          If LWORK = -1, then a workspace query is assumed; the routine
          only calculates the optimal size of the WORK array, returns
          this value as the first entry of the WORK array, and no error
          message related to LWORK is issued by XERBLA.
[out]INFO
          INFO is INTEGER
          = 0: successful exit
          < 0: if INFO = -i, the i-th argument had an illegal value
Author
Thijs Steel, KU Leuven
Date
May 2020

Definition at line 203 of file claqz3.f.

207 IMPLICIT NONE
208
209* Function arguments
210 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
211 INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
212 $ NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
213
214 COMPLEX, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
215 $ Z( LDZ, * ), QC( LDQC, * ), ZC( LDZC, * ), WORK( * ),
216 $ ALPHA( * ), BETA( * )
217
218 INTEGER, INTENT( OUT ) :: INFO
219
220* Parameters
221 COMPLEX CZERO, CONE
222 parameter( czero = ( 0.0, 0.0 ), cone = ( 1.0, 0.0 ) )
223 REAL :: ZERO, ONE, HALF
224 parameter( zero = 0.0, one = 1.0, half = 0.5 )
225
226* Local scalars
227 INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
228 $ ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
229 REAL :: SAFMIN, SAFMAX, C, SCALE
230 COMPLEX :: TEMP, TEMP2, TEMP3, S
231
232* External Functions
233 EXTERNAL :: xerbla, claset, clartg, crot, claqz1, cgemm, clacpy
234 REAL, EXTERNAL :: SLAMCH
235
236 info = 0
237 IF ( nblock_desired .LT. nshifts+1 ) THEN
238 info = -8
239 END IF
240 IF ( lwork .EQ.-1 ) THEN
241* workspace query, quick return
242 work( 1 ) = n*nblock_desired
243 RETURN
244 ELSE IF ( lwork .LT. n*nblock_desired ) THEN
245 info = -25
246 END IF
247
248 IF( info.NE.0 ) THEN
249 CALL xerbla( 'CLAQZ3', -info )
250 RETURN
251 END IF
252
253*
254* Executable statements
255*
256
257* Get machine constants
258 safmin = slamch( 'SAFE MINIMUM' )
259 safmax = one/safmin
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 ns = nshifts
274 npos = max( nblock_desired-ns, 1 )
275
276
277* The following block introduces the shifts and chases
278* them down one by one just enough to make space for
279* the other shifts. The near-the-diagonal block is
280* of size (ns+1) x ns.
281
282 CALL claset( 'FULL', ns+1, ns+1, czero, cone, qc, ldqc )
283 CALL claset( 'FULL', ns, ns, czero, cone, zc, ldzc )
284
285 DO i = 1, ns
286* Introduce the shift
287 scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) )
288 IF( scale .GE. safmin .AND. scale .LE. safmax ) THEN
289 alpha( i ) = alpha( i )/scale
290 beta( i ) = beta( i )/scale
291 END IF
292
293 temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo )
294 temp3 = beta( i )*a( ilo+1, ilo )
295
296 IF ( abs( temp2 ) .GT. safmax .OR.
297 $ abs( temp3 ) .GT. safmax ) THEN
298 temp2 = cone
299 temp3 = czero
300 END IF
301
302 CALL clartg( temp2, temp3, c, s, temp )
303 CALL crot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c,
304 $ s )
305 CALL crot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c,
306 $ s )
307 CALL crot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c, conjg( s ) )
308
309* Chase the shift down
310 DO j = 1, ns-i
311
312 CALL claqz1( .true., .true., j, 1, ns, ihi-ilo+1, a( ilo,
313 $ ilo ), lda, b( ilo, ilo ), ldb, ns+1, 1, qc,
314 $ ldqc, ns, 1, zc, ldzc )
315
316 END DO
317
318 END DO
319
320* Update the rest of the pencil
321
322* Update A(ilo:ilo+ns,ilo+ns:istopm) and B(ilo:ilo+ns,ilo+ns:istopm)
323* from the left with Qc(1:ns+1,1:ns+1)'
324 sheight = ns+1
325 swidth = istopm-( ilo+ns )+1
326 IF ( swidth > 0 ) THEN
327 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,
328 $ a( ilo, ilo+ns ), lda, czero, work, sheight )
329 CALL clacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,
330 $ ilo+ns ), lda )
331 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,
332 $ b( ilo, ilo+ns ), ldb, czero, work, sheight )
333 CALL clacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,
334 $ ilo+ns ), ldb )
335 END IF
336 IF ( ilq ) THEN
337 CALL cgemm( 'N', 'N', n, sheight, sheight, cone, q( 1, ilo ),
338 $ ldq, qc, ldqc, czero, work, n )
339 CALL clacpy( 'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
340 END IF
341
342* Update A(istartm:ilo-1,ilo:ilo+ns-1) and B(istartm:ilo-1,ilo:ilo+ns-1)
343* from the right with Zc(1:ns,1:ns)
344 sheight = ilo-1-istartm+1
345 swidth = ns
346 IF ( sheight > 0 ) THEN
347 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
348 $ a( istartm, ilo ), lda, zc, ldzc, czero, work,
349 $ sheight )
350 CALL clacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,
351 $ ilo ), lda )
352 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
353 $ b( istartm, ilo ), ldb, zc, ldzc, czero, work,
354 $ sheight )
355 CALL clacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,
356 $ ilo ), ldb )
357 END IF
358 IF ( ilz ) THEN
359 CALL cgemm( 'N', 'N', n, swidth, swidth, cone, z( 1, ilo ),
360 $ ldz, zc, ldzc, czero, work, n )
361 CALL clacpy( 'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
362 END IF
363
364* The following block chases the shifts down to the bottom
365* right block. If possible, a shift is moved down npos
366* positions at a time
367
368 k = ilo
369 DO WHILE ( k < ihi-ns )
370 np = min( ihi-ns-k, npos )
371* Size of the near-the-diagonal block
372 nblock = ns+np
373* istartb points to the first row we will be updating
374 istartb = k+1
375* istopb points to the last column we will be updating
376 istopb = k+nblock-1
377
378 CALL claset( 'FULL', ns+np, ns+np, czero, cone, qc, ldqc )
379 CALL claset( 'FULL', ns+np, ns+np, czero, cone, zc, ldzc )
380
381* Near the diagonal shift chase
382 DO i = ns-1, 0, -1
383 DO j = 0, np-1
384* Move down the block with index k+i+j, updating
385* the (ns+np x ns+np) block:
386* (k:k+ns+np,k:k+ns+np-1)
387 CALL claqz1( .true., .true., k+i+j, istartb, istopb, ihi,
388 $ a, lda, b, ldb, nblock, k+1, qc, ldqc,
389 $ nblock, k, zc, ldzc )
390 END DO
391 END DO
392
393* Update rest of the pencil
394
395* Update A(k+1:k+ns+np, k+ns+np:istopm) and
396* B(k+1:k+ns+np, k+ns+np:istopm)
397* from the left with Qc(1:ns+np,1:ns+np)'
398 sheight = ns+np
399 swidth = istopm-( k+ns+np )+1
400 IF ( swidth > 0 ) THEN
401 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,
402 $ ldqc, a( k+1, k+ns+np ), lda, czero, work,
403 $ sheight )
404 CALL clacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,
405 $ k+ns+np ), lda )
406 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc,
407 $ ldqc, b( k+1, k+ns+np ), ldb, czero, work,
408 $ sheight )
409 CALL clacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,
410 $ k+ns+np ), ldb )
411 END IF
412 IF ( ilq ) THEN
413 CALL cgemm( 'N', 'N', n, nblock, nblock, cone, q( 1, k+1 ),
414 $ ldq, qc, ldqc, czero, work, n )
415 CALL clacpy( 'ALL', n, nblock, work, n, q( 1, k+1 ), ldq )
416 END IF
417
418* Update A(istartm:k,k:k+ns+npos-1) and B(istartm:k,k:k+ns+npos-1)
419* from the right with Zc(1:ns+np,1:ns+np)
420 sheight = k-istartm+1
421 swidth = nblock
422 IF ( sheight > 0 ) THEN
423 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
424 $ a( istartm, k ), lda, zc, ldzc, czero, work,
425 $ sheight )
426 CALL clacpy( 'ALL', sheight, swidth, work, sheight,
427 $ a( istartm, k ), lda )
428 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
429 $ b( istartm, k ), ldb, zc, ldzc, czero, work,
430 $ sheight )
431 CALL clacpy( 'ALL', sheight, swidth, work, sheight,
432 $ b( istartm, k ), ldb )
433 END IF
434 IF ( ilz ) THEN
435 CALL cgemm( 'N', 'N', n, nblock, nblock, cone, z( 1, k ),
436 $ ldz, zc, ldzc, czero, work, n )
437 CALL clacpy( 'ALL', n, nblock, work, n, z( 1, k ), ldz )
438 END IF
439
440 k = k+np
441
442 END DO
443
444* The following block removes the shifts from the bottom right corner
445* one by one. Updates are initially applied to A(ihi-ns+1:ihi,ihi-ns:ihi).
446
447 CALL claset( 'FULL', ns, ns, czero, cone, qc, ldqc )
448 CALL claset( 'FULL', ns+1, ns+1, czero, cone, zc, ldzc )
449
450* istartb points to the first row we will be updating
451 istartb = ihi-ns+1
452* istopb points to the last column we will be updating
453 istopb = ihi
454
455 DO i = 1, ns
456* Chase the shift down to the bottom right corner
457 DO ishift = ihi-i, ihi-1
458 CALL claqz1( .true., .true., ishift, istartb, istopb, ihi,
459 $ a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
460 $ ihi-ns, zc, ldzc )
461 END DO
462
463 END DO
464
465* Update rest of the pencil
466
467* Update A(ihi-ns+1:ihi, ihi+1:istopm)
468* from the left with Qc(1:ns,1:ns)'
469 sheight = ns
470 swidth = istopm-( ihi+1 )+1
471 IF ( swidth > 0 ) THEN
472 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,
473 $ a( ihi-ns+1, ihi+1 ), lda, czero, work, sheight )
474 CALL clacpy( 'ALL', sheight, swidth, work, sheight,
475 $ a( ihi-ns+1, ihi+1 ), lda )
476 CALL cgemm( 'C', 'N', sheight, swidth, sheight, cone, qc, ldqc,
477 $ b( ihi-ns+1, ihi+1 ), ldb, czero, work, sheight )
478 CALL clacpy( 'ALL', sheight, swidth, work, sheight,
479 $ b( ihi-ns+1, ihi+1 ), ldb )
480 END IF
481 IF ( ilq ) THEN
482 CALL cgemm( 'N', 'N', n, ns, ns, cone, q( 1, ihi-ns+1 ), ldq,
483 $ qc, ldqc, czero, work, n )
484 CALL clacpy( 'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
485 END IF
486
487* Update A(istartm:ihi-ns,ihi-ns:ihi)
488* from the right with Zc(1:ns+1,1:ns+1)
489 sheight = ihi-ns-istartm+1
490 swidth = ns+1
491 IF ( sheight > 0 ) THEN
492 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
493 $ a( istartm, ihi-ns ), lda, zc, ldzc, czero, work,
494 $ sheight )
495 CALL clacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,
496 $ ihi-ns ), lda )
497 CALL cgemm( 'N', 'N', sheight, swidth, swidth, cone,
498 $ b( istartm, ihi-ns ), ldb, zc, ldzc, czero, work,
499 $ sheight )
500 CALL clacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,
501 $ ihi-ns ), ldb )
502 END IF
503 IF ( ilz ) THEN
504 CALL cgemm( 'N', 'N', n, ns+1, ns+1, cone, z( 1, ihi-ns ), ldz,
505 $ zc, ldzc, czero, work, n )
506 CALL clacpy( 'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
507 END IF
508
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
Definition cgemm.f:188
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
Definition clacpy.f:103
real function slamch(cmach)
SLAMCH
Definition slamch.f:68
subroutine claqz1(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
CLAQZ1
Definition claqz1.f:173
subroutine clartg(f, g, c, s, r)
CLARTG generates a plane rotation with real cosine and complex sine.
Definition clartg.f90:116
subroutine claset(uplo, m, n, alpha, beta, a, lda)
CLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition claset.f:106
subroutine crot(n, cx, incx, cy, incy, c, s)
CROT applies a plane rotation with real cosine and complex sine to a pair of complex vectors.
Definition crot.f:103
Here is the call graph for this function:
Here is the caller graph for this function: