205 IMPLICIT NONE
206
207
208 LOGICAL, INTENT( IN ) :: ILSCHUR, ILQ, ILZ
209 INTEGER, INTENT( IN ) :: N, ILO, IHI, LDA, LDB, LDQ, LDZ, LWORK,
210 $ NSHIFTS, NBLOCK_DESIRED, LDQC, LDZC
211
212 COMPLEX, INTENT( INOUT ) :: A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
213 $ Z( LDZ, * ), QC( LDQC, * ), ZC( LDZC, * ), WORK( * ),
214 $ ALPHA( * ), BETA( * )
215
216 INTEGER, INTENT( OUT ) :: INFO
217
218
219 COMPLEX CZERO, CONE
220 parameter( czero = ( 0.0, 0.0 ), cone = ( 1.0, 0.0 ) )
221 REAL :: ZERO, ONE, HALF
222 parameter( zero = 0.0, one = 1.0, half = 0.5 )
223
224
225 INTEGER :: I, J, NS, ISTARTM, ISTOPM, SHEIGHT, SWIDTH, K, NP,
226 $ ISTARTB, ISTOPB, ISHIFT, NBLOCK, NPOS
227 REAL :: SAFMIN, SAFMAX, C, SCALE
228 COMPLEX :: TEMP, TEMP2, TEMP3, S
229
230
233 REAL, EXTERNAL :: SLAMCH
234
235 info = 0
236 IF ( nblock_desired .LT. nshifts+1 ) THEN
237 info = -8
238 END IF
239 IF ( lwork .EQ.-1 ) THEN
240
241 work( 1 ) = cmplx( n*nblock_desired )
242 RETURN
243 ELSE IF ( lwork .LT. n*nblock_desired ) THEN
244 info = -25
245 END IF
246
247 IF( info.NE.0 ) THEN
248 CALL xerbla(
'CLAQZ3', -info )
249 RETURN
250 END IF
251
252
253
254
255
256
257 safmin =
slamch(
'SAFE MINIMUM' )
258 safmax = one/safmin
259
260 IF ( ilo .GE. ihi ) THEN
261 RETURN
262 END IF
263
264 IF ( ilschur ) THEN
265 istartm = 1
266 istopm = n
267 ELSE
268 istartm = ilo
269 istopm = ihi
270 END IF
271
272 ns = nshifts
273 npos = max( nblock_desired-ns, 1 )
274
275
276
277
278
279
280
281 CALL claset(
'FULL', ns+1, ns+1, czero, cone, qc, ldqc )
282 CALL claset(
'FULL', ns, ns, czero, cone, zc, ldzc )
283
284 DO i = 1, ns
285
286 scale = sqrt( abs( alpha( i ) ) ) * sqrt( abs( beta( i ) ) )
287 IF( scale .GE. safmin .AND. scale .LE. safmax ) THEN
288 alpha( i ) = alpha( i )/scale
289 beta( i ) = beta( i )/scale
290 END IF
291
292 temp2 = beta( i )*a( ilo, ilo )-alpha( i )*b( ilo, ilo )
293 temp3 = beta( i )*a( ilo+1, ilo )
294
295 IF ( abs( temp2 ) .GT. safmax .OR.
296 $ abs( temp3 ) .GT. safmax ) THEN
297 temp2 = cone
298 temp3 = czero
299 END IF
300
301 CALL clartg( temp2, temp3, c, s, temp )
302 CALL crot( ns, a( ilo, ilo ), lda, a( ilo+1, ilo ), lda,
303 $ c, s )
304 CALL crot( ns, b( ilo, ilo ), ldb, b( ilo+1, ilo ), ldb,
305 $ c, s )
306 CALL crot( ns+1, qc( 1, 1 ), 1, qc( 1, 2 ), 1, c,
307 $ conjg( s ) )
308
309
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
321
322
323
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,
328 $ ldqc,
329 $ a( ilo, ilo+ns ), lda, czero, work, sheight )
330 CALL clacpy(
'ALL', sheight, swidth, work, sheight, a( ilo,
331 $ ilo+ns ), lda )
332 CALL cgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
333 $ ldqc,
334 $ b( ilo, ilo+ns ), ldb, czero, work, sheight )
335 CALL clacpy(
'ALL', sheight, swidth, work, sheight, b( ilo,
336 $ ilo+ns ), ldb )
337 END IF
338 IF ( ilq ) THEN
339 CALL cgemm(
'N',
'N', n, sheight, sheight, cone, q( 1, ilo ),
340 $ ldq, qc, ldqc, czero, work, n )
341 CALL clacpy(
'ALL', n, sheight, work, n, q( 1, ilo ), ldq )
342 END IF
343
344
345
346 sheight = ilo-1-istartm+1
347 swidth = ns
348 IF ( sheight > 0 ) THEN
349 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
350 $ a( istartm, ilo ), lda, zc, ldzc, czero, work,
351 $ sheight )
352 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
353 $ a( istartm,
354 $ ilo ), lda )
355 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
356 $ b( istartm, ilo ), ldb, zc, ldzc, czero, work,
357 $ sheight )
358 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
359 $ b( istartm,
360 $ ilo ), ldb )
361 END IF
362 IF ( ilz ) THEN
363 CALL cgemm(
'N',
'N', n, swidth, swidth, cone, z( 1, ilo ),
364 $ ldz, zc, ldzc, czero, work, n )
365 CALL clacpy(
'ALL', n, swidth, work, n, z( 1, ilo ), ldz )
366 END IF
367
368
369
370
371
372 k = ilo
373 DO WHILE ( k < ihi-ns )
374 np = min( ihi-ns-k, npos )
375
376 nblock = ns+np
377
378 istartb = k+1
379
380 istopb = k+nblock-1
381
382 CALL claset(
'FULL', ns+np, ns+np, czero, cone, qc, ldqc )
383 CALL claset(
'FULL', ns+np, ns+np, czero, cone, zc, ldzc )
384
385
386 DO i = ns-1, 0, -1
387 DO j = 0, np-1
388
389
390
391 CALL claqz1( .true., .true., k+i+j, istartb, istopb,
392 $ ihi,
393 $ a, lda, b, ldb, nblock, k+1, qc, ldqc,
394 $ nblock, k, zc, ldzc )
395 END DO
396 END DO
397
398
399
400
401
402
403 sheight = ns+np
404 swidth = istopm-( k+ns+np )+1
405 IF ( swidth > 0 ) THEN
406 CALL cgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
407 $ ldqc, a( k+1, k+ns+np ), lda, czero, work,
408 $ sheight )
409 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
410 $ a( k+1,
411 $ k+ns+np ), lda )
412 CALL cgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
413 $ ldqc, b( k+1, k+ns+np ), ldb, czero, work,
414 $ sheight )
415 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
416 $ b( k+1,
417 $ k+ns+np ), ldb )
418 END IF
419 IF ( ilq ) THEN
420 CALL cgemm(
'N',
'N', n, nblock, nblock, cone, q( 1,
421 $ k+1 ),
422 $ ldq, qc, ldqc, czero, work, n )
423 CALL clacpy(
'ALL', n, nblock, work, n, q( 1, k+1 ),
424 $ ldq )
425 END IF
426
427
428
429 sheight = k-istartm+1
430 swidth = nblock
431 IF ( sheight > 0 ) THEN
432 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
433 $ a( istartm, k ), lda, zc, ldzc, czero, work,
434 $ sheight )
435 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
436 $ a( istartm, k ), lda )
437 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
438 $ b( istartm, k ), ldb, zc, ldzc, czero, work,
439 $ sheight )
440 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
441 $ b( istartm, k ), ldb )
442 END IF
443 IF ( ilz ) THEN
444 CALL cgemm(
'N',
'N', n, nblock, nblock, cone, z( 1, k ),
445 $ ldz, zc, ldzc, czero, work, n )
446 CALL clacpy(
'ALL', n, nblock, work, n, z( 1, k ), ldz )
447 END IF
448
449 k = k+np
450
451 END DO
452
453
454
455
456 CALL claset(
'FULL', ns, ns, czero, cone, qc, ldqc )
457 CALL claset(
'FULL', ns+1, ns+1, czero, cone, zc, ldzc )
458
459
460 istartb = ihi-ns+1
461
462 istopb = ihi
463
464 DO i = 1, ns
465
466 DO ishift = ihi-i, ihi-1
467 CALL claqz1( .true., .true., ishift, istartb, istopb,
468 $ ihi,
469 $ a, lda, b, ldb, ns, ihi-ns+1, qc, ldqc, ns+1,
470 $ ihi-ns, zc, ldzc )
471 END DO
472
473 END DO
474
475
476
477
478
479 sheight = ns
480 swidth = istopm-( ihi+1 )+1
481 IF ( swidth > 0 ) THEN
482 CALL cgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
483 $ ldqc,
484 $ a( ihi-ns+1, ihi+1 ), lda, czero, work, sheight )
485 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
486 $ a( ihi-ns+1, ihi+1 ), lda )
487 CALL cgemm(
'C',
'N', sheight, swidth, sheight, cone, qc,
488 $ ldqc,
489 $ b( ihi-ns+1, ihi+1 ), ldb, czero, work, sheight )
490 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
491 $ b( ihi-ns+1, ihi+1 ), ldb )
492 END IF
493 IF ( ilq ) THEN
494 CALL cgemm(
'N',
'N', n, ns, ns, cone, q( 1, ihi-ns+1 ),
495 $ ldq,
496 $ qc, ldqc, czero, work, n )
497 CALL clacpy(
'ALL', n, ns, work, n, q( 1, ihi-ns+1 ), ldq )
498 END IF
499
500
501
502 sheight = ihi-ns-istartm+1
503 swidth = ns+1
504 IF ( sheight > 0 ) THEN
505 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
506 $ a( istartm, ihi-ns ), lda, zc, ldzc, czero, work,
507 $ sheight )
508 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
509 $ a( istartm,
510 $ ihi-ns ), lda )
511 CALL cgemm(
'N',
'N', sheight, swidth, swidth, cone,
512 $ b( istartm, ihi-ns ), ldb, zc, ldzc, czero, work,
513 $ sheight )
514 CALL clacpy(
'ALL', sheight, swidth, work, sheight,
515 $ b( istartm,
516 $ ihi-ns ), ldb )
517 END IF
518 IF ( ilz ) THEN
519 CALL cgemm(
'N',
'N', n, ns+1, ns+1, cone, z( 1, ihi-ns ),
520 $ ldz,
521 $ zc, ldzc, czero, work, n )
522 CALL clacpy(
'ALL', n, ns+1, work, n, z( 1, ihi-ns ), ldz )
523 END IF
524
subroutine xerbla(srname, info)
subroutine cgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
CGEMM
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
real function slamch(cmach)
SLAMCH
subroutine claqz1(ilq, ilz, k, istartm, istopm, ihi, a, lda, b, ldb, nq, qstart, q, ldq, nz, zstart, z, ldz)
CLAQZ1
subroutine clartg(f, g, c, s, r)
CLARTG generates a plane rotation with real cosine and complex sine.
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.
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.