214 IMPLICIT NONE
215
216
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
228 REAL :: ZERO, ONE, HALF
229 parameter( zero = 0.0, one = 1.0, half = 0.5 )
230
231
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
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
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
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
277
278
279
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
302
303
304
305
306 ns = nshifts-mod( nshifts, 2 )
307 npos = max( nblock_desired-ns, 1 )
308
309
310
311
312
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
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
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
349
350
351
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
371
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
391
392
393
394 k = ilo
395 DO WHILE ( k < ihi-ns )
396 np = min( ihi-ns-k, npos )
397
398 nblock = ns+np
399
400 istartb = k+1
401
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
408 DO i = ns-1, 0, -2
409 DO j = 0, np-1
410
411
412
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
420
421
422
423
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
445
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
471
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
477 istartb = ihi-ns+1
478
479 istopb = ihi
480
481 DO i = 1, ns, 2
482
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
492
493
494
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
514
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)
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
subroutine slaqz1(a, lda, b, ldb, sr1, sr2, si, beta1, beta2, v)
SLAQZ1
subroutine slaqz2(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
SLAQZ2
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
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.
subroutine srot(n, sx, incx, sy, incy, c, s)
SROT
real function sroundup_lwork(lwork)
SROUNDUP_LWORK