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

◆ slaqz4()

subroutine slaqz4 ( 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,
real, dimension( * ), intent(inout)  sr,
real, dimension( * ), intent(inout)  si,
real, dimension( * ), intent(inout)  ss,
real, dimension( lda, * ), intent(inout)  a,
integer, intent(in)  lda,
real, dimension( ldb, * ), intent(inout)  b,
integer, intent(in)  ldb,
real, dimension( ldq, * ), intent(inout)  q,
integer, intent(in)  ldq,
real, dimension( ldz, * ), intent(inout)  z,
integer, intent(in)  ldz,
real, dimension( ldqc, * ), intent(inout)  qc,
integer, intent(in)  ldqc,
real, dimension( ldzc, * ), intent(inout)  zc,
integer, intent(in)  ldzc,
real, dimension( * ), intent(inout)  work,
integer, intent(in)  lwork,
integer, intent(out)  info 
)

SLAQZ4

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

Purpose:
 SLAQZ4 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]SR
          SR is REAL array. SR contains
          the real parts of the shifts to use.
[in]SI
          SI is REAL array. SI contains
          the imaginary parts of the shifts to use.
[in]SS
          SS is REAL array. SS contains
          the scale of the shifts to use.
[in,out]A
          A is REAL 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 REAL 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 REAL array, dimension (LDQ, N)
[in]LDQ
          LDQ is INTEGER
[in,out]Z
          Z is REAL array, dimension (LDZ, N)
[in]LDZ
          LDZ is INTEGER
[in,out]QC
          QC is REAL array, dimension (LDQC, NBLOCK_DESIRED)
[in]LDQC
          LDQC is INTEGER
[in,out]ZC
          ZC is REAL array, dimension (LDZC, NBLOCK_DESIRED)
[in]LDZC
          LDZ is INTEGER
[out]WORK
          WORK is REAL 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 210 of file slaqz4.f.

214 IMPLICIT NONE
215
216* Function arguments
217 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
218 INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
219 $ NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
220
221 REAL, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
222 $ Z( LDZ, * ), QC( LDQC, * ), ZC( LDZC, * ), WORK( * ), SR( * ),
223 $ SI( * ), SS( * )
224
225 INTEGER, INTENT( OUT ) :: INFO
226
227* Parameters
228 REAL :: ZERO, ONE, HALF
229 parameter( zero = 0.0, one = 1.0, half = 0.5 )
230
231* Local scalars
232 INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
233 $ ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
234 REAL :: TEMP, V( 3 ), C1, S1, C2, S2, SWAP
235*
236* External functions
237 EXTERNAL :: xerbla, sgemm, slaqz1, slaqz2, slaset, slartg, srot,
238 $ slacpy
239 REAL, EXTERNAL :: SROUNDUP_LWORK
240
241 info = 0
242 IF ( nblock_desired .LT. nshifts+1 ) THEN
243 info = -8
244 END IF
245 IF ( lwork .EQ.-1 ) THEN
246* workspace query, quick return
247 work( 1 ) = sroundup_lwork(n*nblock_desired)
248 RETURN
249 ELSE IF ( lwork .LT. n*nblock_desired ) THEN
250 info = -25
251 END IF
252
253 IF( info.NE.0 ) THEN
254 CALL xerbla( 'SLAQZ4', -info )
255 RETURN
256 END IF
257
258* Executable statements
259
260 IF ( nshifts .LT. 2 ) THEN
261 RETURN
262 END IF
263
264 IF ( ilo .GE. ihi ) THEN
265 RETURN
266 END IF
267
268 IF ( ilschur ) THEN
269 istartm = 1
270 istopm = n
271 ELSE
272 istartm = ilo
273 istopm = ihi
274 END IF
275
276* Shuffle shifts into pairs of real shifts and pairs
277* of complex conjugate shifts assuming complex
278* conjugate shifts are already adjacent to one
279* another
280
281 DO i = 1, nshifts-2, 2
282 IF( si( i ).NE.-si( i+1 ) ) THEN
283*
284 swap = sr( i )
285 sr( i ) = sr( i+1 )
286 sr( i+1 ) = sr( i+2 )
287 sr( i+2 ) = swap
288
289 swap = si( i )
290 si( i ) = si( i+1 )
291 si( i+1 ) = si( i+2 )
292 si( i+2 ) = swap
293
294 swap = ss( i )
295 ss( i ) = ss( i+1 )
296 ss( i+1 ) = ss( i+2 )
297 ss( i+2 ) = swap
298 END IF
299 END DO
300
301* NSHFTS is supposed to be even, but if it is odd,
302* then simply reduce it by one. The shuffle above
303* ensures that the dropped shift is real and that
304* the remaining shifts are paired.
305
306 ns = nshifts-mod( nshifts, 2 )
307 npos = max( nblock_desired-ns, 1 )
308
309* The following block introduces the shifts and chases
310* them down one by one just enough to make space for
311* the other shifts. The near-the-diagonal block is
312* of size (ns+1) x ns.
313
314 CALL slaset( 'FULL', ns+1, ns+1, zero, one, qc, ldqc )
315 CALL slaset( 'FULL', ns, ns, zero, one, zc, ldzc )
316
317 DO i = 1, ns, 2
318* Introduce the shift
319 CALL slaqz1( a( ilo, ilo ), lda, b( ilo, ilo ), ldb, sr( i ),
320 $ sr( i+1 ), si( i ), ss( i ), ss( i+1 ), v )
321
322 temp = v( 2 )
323 CALL slartg( temp, v( 3 ), c1, s1, v( 2 ) )
324 CALL slartg( v( 1 ), v( 2 ), c2, s2, temp )
325
326 CALL srot( ns, a( ilo+1, ilo ), lda, a( ilo+2, ilo ), lda, c1,
327 $ s1 )
328 CALL srot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda, c2,
329 $ s2 )
330 CALL srot( ns, b( ilo+1, ilo ), ldb, b( ilo+2, ilo ), ldb, c1,
331 $ s1 )
332 CALL srot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb, c2,
333 $ s2 )
334 CALL srot( ns+1, qc( 1, 2 ), 1, qc( 1, 3 ), 1, c1, s1 )
335 CALL srot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c2, s2 )
336
337* Chase the shift down
338 DO j = 1, ns-1-i
339
340 CALL slaqz2( .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* Update the rest of the pencil
349
350* Update A(ilo:ilo+ns,ilo+ns:istopm) and B(ilo:ilo+ns,ilo+ns:istopm)
351* from the left with Qc(1:ns+1,1:ns+1)'
352 sheight = ns+1
353 swidth = istopm-( ilo+ns )+1
354 IF ( swidth > 0 ) THEN
355 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,
356 $ a( ilo, ilo+ns ), lda, zero, work, sheight )
357 CALL slacpy( 'ALL', sheight, swidth, work, sheight, a( ilo,
358 $ ilo+ns ), lda )
359 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,
360 $ b( ilo, ilo+ns ), ldb, zero, work, sheight )
361 CALL slacpy( 'ALL', sheight, swidth, work, sheight, b( ilo,
362 $ ilo+ns ), ldb )
363 END IF
364 IF ( ilq ) THEN
365 CALL sgemm( 'N', 'N', n, sheight, sheight, one, q( 1, ilo ),
366 $ ldq, qc, ldqc, zero, work, n )
367 CALL slacpy( 'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
368 END IF
369
370* Update A(istartm:ilo-1,ilo:ilo+ns-1) and B(istartm:ilo-1,ilo:ilo+ns-1)
371* from the right with Zc(1:ns,1:ns)
372 sheight = ilo-1-istartm+1
373 swidth = ns
374 IF ( sheight > 0 ) THEN
375 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,
376 $ ilo ), lda, zc, ldzc, zero, work, sheight )
377 CALL slacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,
378 $ ilo ), lda )
379 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,
380 $ ilo ), ldb, zc, ldzc, zero, work, sheight )
381 CALL slacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,
382 $ ilo ), ldb )
383 END IF
384 IF ( ilz ) THEN
385 CALL sgemm( 'N', 'N', n, swidth, swidth, one, z( 1, ilo ), ldz,
386 $ zc, ldzc, zero, work, n )
387 CALL slacpy( 'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
388 END IF
389
390* The following block chases the shifts down to the bottom
391* right block. If possible, a shift is moved down npos
392* positions at a time
393
394 k = ilo
395 DO WHILE ( k < ihi-ns )
396 np = min( ihi-ns-k, npos )
397* Size of the near-the-diagonal block
398 nblock = ns+np
399* istartb points to the first row we will be updating
400 istartb = k+1
401* istopb points to the last column we will be updating
402 istopb = k+nblock-1
403
404 CALL slaset( 'FULL', ns+np, ns+np, zero, one, qc, ldqc )
405 CALL slaset( 'FULL', ns+np, ns+np, zero, one, zc, ldzc )
406
407* Near the diagonal shift chase
408 DO i = ns-1, 0, -2
409 DO j = 0, np-1
410* Move down the block with index k+i+j-1, updating
411* the (ns+np x ns+np) block:
412* (k:k+ns+np,k:k+ns+np-1)
413 CALL slaqz2( .true., .true., k+i+j-1, istartb, istopb,
414 $ ihi, a, lda, b, ldb, nblock, k+1, qc, ldqc,
415 $ nblock, k, zc, ldzc )
416 END DO
417 END DO
418
419* Update rest of the pencil
420
421* Update A(k+1:k+ns+np, k+ns+np:istopm) and
422* B(k+1:k+ns+np, k+ns+np:istopm)
423* from the left with Qc(1:ns+np,1:ns+np)'
424 sheight = ns+np
425 swidth = istopm-( k+ns+np )+1
426 IF ( swidth > 0 ) THEN
427 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc,
428 $ ldqc, a( k+1, k+ns+np ), lda, zero, work,
429 $ sheight )
430 CALL slacpy( 'ALL', sheight, swidth, work, sheight, a( k+1,
431 $ k+ns+np ), lda )
432 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc,
433 $ ldqc, b( k+1, k+ns+np ), ldb, zero, work,
434 $ sheight )
435 CALL slacpy( 'ALL', sheight, swidth, work, sheight, b( k+1,
436 $ k+ns+np ), ldb )
437 END IF
438 IF ( ilq ) THEN
439 CALL sgemm( 'N', 'N', n, nblock, nblock, one, q( 1, k+1 ),
440 $ ldq, qc, ldqc, zero, work, n )
441 CALL slacpy( 'ALL', n, nblock, work, n, q( 1, k+1 ), ldq )
442 END IF
443
444* Update A(istartm:k,k:k+ns+npos-1) and B(istartm:k,k:k+ns+npos-1)
445* from the right with Zc(1:ns+np,1:ns+np)
446 sheight = k-istartm+1
447 swidth = nblock
448 IF ( sheight > 0 ) THEN
449 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one,
450 $ a( istartm, k ), lda, zc, ldzc, zero, work,
451 $ sheight )
452 CALL slacpy( 'ALL', sheight, swidth, work, sheight,
453 $ a( istartm, k ), lda )
454 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one,
455 $ b( istartm, k ), ldb, zc, ldzc, zero, work,
456 $ sheight )
457 CALL slacpy( 'ALL', sheight, swidth, work, sheight,
458 $ b( istartm, k ), ldb )
459 END IF
460 IF ( ilz ) THEN
461 CALL sgemm( 'N', 'N', n, nblock, nblock, one, z( 1, k ),
462 $ ldz, zc, ldzc, zero, work, n )
463 CALL slacpy( 'ALL', n, nblock, work, n, z( 1, k ), ldz )
464 END IF
465
466 k = k+np
467
468 END DO
469
470* The following block removes the shifts from the bottom right corner
471* one by one. Updates are initially applied to A(ihi-ns+1:ihi,ihi-ns:ihi).
472
473 CALL slaset( 'FULL', ns, ns, zero, one, qc, ldqc )
474 CALL slaset( 'FULL', ns+1, ns+1, zero, one, zc, ldzc )
475
476* istartb points to the first row we will be updating
477 istartb = ihi-ns+1
478* istopb points to the last column we will be updating
479 istopb = ihi
480
481 DO i = 1, ns, 2
482* Chase the shift down to the bottom right corner
483 DO ishift = ihi-i-1, ihi-2
484 CALL slaqz2( .true., .true., ishift, istartb, istopb, ihi,
485 $ a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
486 $ ihi-ns, zc, ldzc )
487 END DO
488
489 END DO
490
491* Update rest of the pencil
492
493* Update A(ihi-ns+1:ihi, ihi+1:istopm)
494* from the left with Qc(1:ns,1:ns)'
495 sheight = ns
496 swidth = istopm-( ihi+1 )+1
497 IF ( swidth > 0 ) THEN
498 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,
499 $ a( ihi-ns+1, ihi+1 ), lda, zero, work, sheight )
500 CALL slacpy( 'ALL', sheight, swidth, work, sheight,
501 $ a( ihi-ns+1, ihi+1 ), lda )
502 CALL sgemm( 'T', 'N', sheight, swidth, sheight, one, qc, ldqc,
503 $ b( ihi-ns+1, ihi+1 ), ldb, zero, work, sheight )
504 CALL slacpy( 'ALL', sheight, swidth, work, sheight,
505 $ b( ihi-ns+1, ihi+1 ), ldb )
506 END IF
507 IF ( ilq ) THEN
508 CALL sgemm( 'N', 'N', n, ns, ns, one, q( 1, ihi-ns+1 ), ldq,
509 $ qc, ldqc, zero, work, n )
510 CALL slacpy( 'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
511 END IF
512
513* Update A(istartm:ihi-ns,ihi-ns:ihi)
514* from the right with Zc(1:ns+1,1:ns+1)
515 sheight = ihi-ns-istartm+1
516 swidth = ns+1
517 IF ( sheight > 0 ) THEN
518 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one, a( istartm,
519 $ ihi-ns ), lda, zc, ldzc, zero, work, sheight )
520 CALL slacpy( 'ALL', sheight, swidth, work, sheight, a( istartm,
521 $ ihi-ns ), lda )
522 CALL sgemm( 'N', 'N', sheight, swidth, swidth, one, b( istartm,
523 $ ihi-ns ), ldb, zc, ldzc, zero, work, sheight )
524 CALL slacpy( 'ALL', sheight, swidth, work, sheight, b( istartm,
525 $ ihi-ns ), ldb )
526 END IF
527 IF ( ilz ) THEN
528 CALL sgemm( 'N', 'N', n, ns+1, ns+1, one, z( 1, ihi-ns ), ldz, zc,
529 $ ldzc, zero, work, n )
530 CALL slacpy( 'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
531 END IF
532
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:188
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
Definition slacpy.f:103
subroutine slaqz1(a, lda, b, ldb, sr1, sr2, si, beta1, beta2, v)
SLAQZ1
Definition slaqz1.f:127
subroutine slaqz2(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
SLAQZ2
Definition slaqz2.f:173
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
Definition slartg.f90:111
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition slaset.f:110
subroutine srot(n, sx, incx, sy, incy, c, s)
SROT
Definition srot.f:92
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
Here is the call graph for this function:
Here is the caller graph for this function: