207 IMPLICIT NONE
208
209
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
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
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
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
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
255
256
257
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
278
279
280
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
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
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, 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
343
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
365
366
367
368 k = ilo
369 DO WHILE ( k < ihi-ns )
370 np = min( ihi-ns-k, npos )
371
372 nblock = ns+np
373
374 istartb = k+1
375
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
382 DO i = ns-1, 0, -1
383 DO j = 0, np-1
384
385
386
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
394
395
396
397
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
419
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
445
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
451 istartb = ihi-ns+1
452
453 istopb = ihi
454
455 DO i = 1, ns
456
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
466
467
468
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
488
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)
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.