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