219
220
221
222
223
224
225 LOGICAL WANTQ, WANTZ
226 INTEGER INFO, J1, LDA, LDB, LDQ, LDZ, LWORK, N, N1, N2
227
228
229 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
230 $ WORK( * ), Z( LDZ, * )
231
232
233
234
235
236
237
238 DOUBLE PRECISION ZERO, ONE
239 parameter( zero = 0.0d+0, one = 1.0d+0 )
240 DOUBLE PRECISION TWENTY
241 parameter( twenty = 2.0d+01 )
242 INTEGER LDST
243 parameter( ldst = 4 )
244 LOGICAL WANDS
245 parameter( wands = .true. )
246
247
248 LOGICAL STRONG, WEAK
249 INTEGER I, IDUM, LINFO, M
250 DOUBLE PRECISION BQRA21, BRQA21, DDUM, DNORMA, DNORMB, DSCALE,
251 $ DSUM, EPS, F, G, SA, SB, SCALE, SMLNUM,
252 $ THRESHA, THRESHB
253
254
255 INTEGER IWORK( LDST + 2 )
256 DOUBLE PRECISION AI( 2 ), AR( 2 ), BE( 2 ), IR( LDST, LDST ),
257 $ IRCOP( LDST, LDST ), LI( LDST, LDST ),
258 $ LICOP( LDST, LDST ), S( LDST, LDST ),
259 $ SCPY( LDST, LDST ), T( LDST, LDST ),
260 $ TAUL( LDST ), TAUR( LDST ), TCPY( LDST, LDST )
261
262
263 DOUBLE PRECISION DLAMCH
265
266
271
272
273 INTRINSIC abs, max, sqrt
274
275
276
277 info = 0
278
279
280
281 IF( n.LE.1 .OR. n1.LE.0 .OR. n2.LE.0 )
282 $ RETURN
283 IF( n1.GT.n .OR. ( j1+n1 ).GT.n )
284 $ RETURN
285 m = n1 + n2
286 IF( lwork.LT.max( 1, n*m, m*m*2 ) ) THEN
287 info = -16
288 work( 1 ) = max( 1, n*m, m*m*2 )
289 RETURN
290 END IF
291
292 weak = .false.
293 strong = .false.
294
295
296
297 CALL dlaset(
'Full', ldst, ldst, zero, zero, li, ldst )
298 CALL dlaset(
'Full', ldst, ldst, zero, zero, ir, ldst )
299 CALL dlacpy(
'Full', m, m, a( j1, j1 ), lda, s, ldst )
300 CALL dlacpy(
'Full', m, m, b( j1, j1 ), ldb, t, ldst )
301
302
303
305 smlnum =
dlamch(
'S' ) / eps
306 dscale = zero
307 dsum = one
308 CALL dlacpy(
'Full', m, m, s, ldst, work, m )
309 CALL dlassq( m*m, work, 1, dscale, dsum )
310 dnorma = dscale*sqrt( dsum )
311 dscale = zero
312 dsum = one
313 CALL dlacpy(
'Full', m, m, t, ldst, work, m )
314 CALL dlassq( m*m, work, 1, dscale, dsum )
315 dnormb = dscale*sqrt( dsum )
316
317
318
319
320
321
322
323
324
325 thresha = max( twenty*eps*dnorma, smlnum )
326 threshb = max( twenty*eps*dnormb, smlnum )
327
328 IF( m.EQ.2 ) THEN
329
330
331
332
333
334
335 f = s( 2, 2 )*t( 1, 1 ) - t( 2, 2 )*s( 1, 1 )
336 g = s( 2, 2 )*t( 1, 2 ) - t( 2, 2 )*s( 1, 2 )
337 sa = abs( s( 2, 2 ) ) * abs( t( 1, 1 ) )
338 sb = abs( s( 1, 1 ) ) * abs( t( 2, 2 ) )
339 CALL dlartg( f, g, ir( 1, 2 ), ir( 1, 1 ), ddum )
340 ir( 2, 1 ) = -ir( 1, 2 )
341 ir( 2, 2 ) = ir( 1, 1 )
342 CALL drot( 2, s( 1, 1 ), 1, s( 1, 2 ), 1, ir( 1, 1 ),
343 $ ir( 2, 1 ) )
344 CALL drot( 2, t( 1, 1 ), 1, t( 1, 2 ), 1, ir( 1, 1 ),
345 $ ir( 2, 1 ) )
346 IF( sa.GE.sb ) THEN
347 CALL dlartg( s( 1, 1 ), s( 2, 1 ), li( 1, 1 ), li( 2,
348 $ 1 ),
349 $ ddum )
350 ELSE
351 CALL dlartg( t( 1, 1 ), t( 2, 1 ), li( 1, 1 ), li( 2,
352 $ 1 ),
353 $ ddum )
354 END IF
355 CALL drot( 2, s( 1, 1 ), ldst, s( 2, 1 ), ldst, li( 1, 1 ),
356 $ li( 2, 1 ) )
357 CALL drot( 2, t( 1, 1 ), ldst, t( 2, 1 ), ldst, li( 1, 1 ),
358 $ li( 2, 1 ) )
359 li( 2, 2 ) = li( 1, 1 )
360 li( 1, 2 ) = -li( 2, 1 )
361
362
363
364
365 weak = abs( s( 2, 1 ) ) .LE. thresha .AND.
366 $ abs( t( 2, 1 ) ) .LE. threshb
367 IF( .NOT.weak )
368 $ GO TO 70
369
370 IF( wands ) THEN
371
372
373
374
375
376
377 CALL dlacpy(
'Full', m, m, a( j1, j1 ), lda,
378 $ work( m*m+1 ),
379 $ m )
380 CALL dgemm(
'N',
'N', m, m, m, one, li, ldst, s, ldst,
381 $ zero,
382 $ work, m )
383 CALL dgemm(
'N',
'T', m, m, m, -one, work, m, ir, ldst,
384 $ one,
385 $ work( m*m+1 ), m )
386 dscale = zero
387 dsum = one
388 CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
389 sa = dscale*sqrt( dsum )
390
391 CALL dlacpy(
'Full', m, m, b( j1, j1 ), ldb,
392 $ work( m*m+1 ),
393 $ m )
394 CALL dgemm(
'N',
'N', m, m, m, one, li, ldst, t, ldst,
395 $ zero,
396 $ work, m )
397 CALL dgemm(
'N',
'T', m, m, m, -one, work, m, ir, ldst,
398 $ one,
399 $ work( m*m+1 ), m )
400 dscale = zero
401 dsum = one
402 CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
403 sb = dscale*sqrt( dsum )
404 strong = sa.LE.thresha .AND. sb.LE.threshb
405 IF( .NOT.strong )
406 $ GO TO 70
407 END IF
408
409
410
411
412 CALL drot( j1+1, a( 1, j1 ), 1, a( 1, j1+1 ), 1, ir( 1, 1 ),
413 $ ir( 2, 1 ) )
414 CALL drot( j1+1, b( 1, j1 ), 1, b( 1, j1+1 ), 1, ir( 1, 1 ),
415 $ ir( 2, 1 ) )
416 CALL drot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda,
417 $ li( 1, 1 ), li( 2, 1 ) )
418 CALL drot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb,
419 $ li( 1, 1 ), li( 2, 1 ) )
420
421
422
423 a( j1+1, j1 ) = zero
424 b( j1+1, j1 ) = zero
425
426
427
428 IF( wantz )
429 $
CALL drot( n, z( 1, j1 ), 1, z( 1, j1+1 ), 1, ir( 1, 1 ),
430 $ ir( 2, 1 ) )
431 IF( wantq )
432 $
CALL drot( n, q( 1, j1 ), 1, q( 1, j1+1 ), 1, li( 1, 1 ),
433 $ li( 2, 1 ) )
434
435
436
437 RETURN
438
439 ELSE
440
441
442
443
444
445
446
447
448
449 CALL dlacpy(
'Full', n1, n2, t( 1, n1+1 ), ldst, li, ldst )
450 CALL dlacpy(
'Full', n1, n2, s( 1, n1+1 ), ldst,
451 $ ir( n2+1, n1+1 ), ldst )
452 CALL dtgsy2(
'N', 0, n1, n2, s, ldst, s( n1+1, n1+1 ), ldst,
453 $ ir( n2+1, n1+1 ), ldst, t, ldst, t( n1+1, n1+1 ),
454 $ ldst, li, ldst, scale, dsum, dscale, iwork, idum,
455 $ linfo )
456 IF( linfo.NE.0 )
457 $ GO TO 70
458
459
460
461
462
463
464
465
466
467 DO 10 i = 1, n2
468 CALL dscal( n1, -one, li( 1, i ), 1 )
469 li( n1+i, i ) = scale
470 10 CONTINUE
471 CALL dgeqr2( m, n2, li, ldst, taul, work, linfo )
472 IF( linfo.NE.0 )
473 $ GO TO 70
474 CALL dorg2r( m, m, n2, li, ldst, taul, work, linfo )
475 IF( linfo.NE.0 )
476 $ GO TO 70
477
478
479
480
481
482
483
484 DO 20 i = 1, n1
485 ir( n2+i, i ) = scale
486 20 CONTINUE
487 CALL dgerq2( n1, m, ir( n2+1, 1 ), ldst, taur, work, linfo )
488 IF( linfo.NE.0 )
489 $ GO TO 70
490 CALL dorgr2( m, m, n1, ir, ldst, taur, work, linfo )
491 IF( linfo.NE.0 )
492 $ GO TO 70
493
494
495
496 CALL dgemm(
'T',
'N', m, m, m, one, li, ldst, s, ldst, zero,
497 $ work, m )
498 CALL dgemm(
'N',
'T', m, m, m, one, work, m, ir, ldst, zero,
499 $ s,
500 $ ldst )
501 CALL dgemm(
'T',
'N', m, m, m, one, li, ldst, t, ldst, zero,
502 $ work, m )
503 CALL dgemm(
'N',
'T', m, m, m, one, work, m, ir, ldst, zero,
504 $ t,
505 $ ldst )
506 CALL dlacpy(
'F', m, m, s, ldst, scpy, ldst )
507 CALL dlacpy(
'F', m, m, t, ldst, tcpy, ldst )
508 CALL dlacpy(
'F', m, m, ir, ldst, ircop, ldst )
509 CALL dlacpy(
'F', m, m, li, ldst, licop, ldst )
510
511
512
513
514 CALL dgerq2( m, m, t, ldst, taur, work, linfo )
515 IF( linfo.NE.0 )
516 $ GO TO 70
517 CALL dormr2(
'R',
'T', m, m, m, t, ldst, taur, s, ldst,
518 $ work,
519 $ linfo )
520 IF( linfo.NE.0 )
521 $ GO TO 70
522 CALL dormr2(
'L',
'N', m, m, m, t, ldst, taur, ir, ldst,
523 $ work,
524 $ linfo )
525 IF( linfo.NE.0 )
526 $ GO TO 70
527
528
529
530 dscale = zero
531 dsum = one
532 DO 30 i = 1, n2
533 CALL dlassq( n1, s( n2+1, i ), 1, dscale, dsum )
534 30 CONTINUE
535 brqa21 = dscale*sqrt( dsum )
536
537
538
539
540 CALL dgeqr2( m, m, tcpy, ldst, taul, work, linfo )
541 IF( linfo.NE.0 )
542 $ GO TO 70
543 CALL dorm2r(
'L',
'T', m, m, m, tcpy, ldst, taul, scpy,
544 $ ldst,
545 $ work, info )
546 CALL dorm2r(
'R',
'N', m, m, m, tcpy, ldst, taul, licop,
547 $ ldst,
548 $ work, info )
549 IF( linfo.NE.0 )
550 $ GO TO 70
551
552
553
554 dscale = zero
555 dsum = one
556 DO 40 i = 1, n2
557 CALL dlassq( n1, scpy( n2+1, i ), 1, dscale, dsum )
558 40 CONTINUE
559 bqra21 = dscale*sqrt( dsum )
560
561
562
563
564
565 IF( bqra21.LE.brqa21 .AND. bqra21.LE.thresha ) THEN
566 CALL dlacpy(
'F', m, m, scpy, ldst, s, ldst )
567 CALL dlacpy(
'F', m, m, tcpy, ldst, t, ldst )
568 CALL dlacpy(
'F', m, m, ircop, ldst, ir, ldst )
569 CALL dlacpy(
'F', m, m, licop, ldst, li, ldst )
570 ELSE IF( brqa21.GE.thresha ) THEN
571 GO TO 70
572 END IF
573
574
575
576 CALL dlaset(
'Lower', m-1, m-1, zero, zero, t(2,1), ldst )
577
578 IF( wands ) THEN
579
580
581
582
583
584
585 CALL dlacpy(
'Full', m, m, a( j1, j1 ), lda,
586 $ work( m*m+1 ),
587 $ m )
588 CALL dgemm(
'N',
'N', m, m, m, one, li, ldst, s, ldst,
589 $ zero,
590 $ work, m )
591 CALL dgemm(
'N',
'N', m, m, m, -one, work, m, ir, ldst,
592 $ one,
593 $ work( m*m+1 ), m )
594 dscale = zero
595 dsum = one
596 CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
597 sa = dscale*sqrt( dsum )
598
599 CALL dlacpy(
'Full', m, m, b( j1, j1 ), ldb,
600 $ work( m*m+1 ),
601 $ m )
602 CALL dgemm(
'N',
'N', m, m, m, one, li, ldst, t, ldst,
603 $ zero,
604 $ work, m )
605 CALL dgemm(
'N',
'N', m, m, m, -one, work, m, ir, ldst,
606 $ one,
607 $ work( m*m+1 ), m )
608 dscale = zero
609 dsum = one
610 CALL dlassq( m*m, work( m*m+1 ), 1, dscale, dsum )
611 sb = dscale*sqrt( dsum )
612 strong = sa.LE.thresha .AND. sb.LE.threshb
613 IF( .NOT.strong )
614 $ GO TO 70
615
616 END IF
617
618
619
620
621 CALL dlaset(
'Full', n1, n2, zero, zero, s(n2+1,1), ldst )
622
623
624
625 CALL dlacpy(
'F', m, m, s, ldst, a( j1, j1 ), lda )
626 CALL dlacpy(
'F', m, m, t, ldst, b( j1, j1 ), ldb )
627 CALL dlaset(
'Full', ldst, ldst, zero, zero, t, ldst )
628
629
630
631 CALL dlaset(
'Full', m, m, zero, zero, work, m )
632 work( 1 ) = one
633 t( 1, 1 ) = one
634 idum = lwork - m*m - 2
635 IF( n2.GT.1 ) THEN
636 CALL dlagv2( a( j1, j1 ), lda, b( j1, j1 ), ldb, ar, ai,
637 $ be,
638 $ work( 1 ), work( 2 ), t( 1, 1 ), t( 2, 1 ) )
639 work( m+1 ) = -work( 2 )
640 work( m+2 ) = work( 1 )
641 t( n2, n2 ) = t( 1, 1 )
642 t( 1, 2 ) = -t( 2, 1 )
643 END IF
644 work( m*m ) = one
645 t( m, m ) = one
646
647 IF( n1.GT.1 ) THEN
648 CALL dlagv2( a( j1+n2, j1+n2 ), lda, b( j1+n2, j1+n2 ),
649 $ ldb,
650 $ taur, taul, work( m*m+1 ), work( n2*m+n2+1 ),
651 $ work( n2*m+n2+2 ), t( n2+1, n2+1 ),
652 $ t( m, m-1 ) )
653 work( m*m ) = work( n2*m+n2+1 )
654 work( m*m-1 ) = -work( n2*m+n2+2 )
655 t( m, m ) = t( n2+1, n2+1 )
656 t( m-1, m ) = -t( m, m-1 )
657 END IF
658 CALL dgemm(
'T',
'N', n2, n1, n2, one, work, m, a( j1,
659 $ j1+n2 ),
660 $ lda, zero, work( m*m+1 ), n2 )
661 CALL dlacpy(
'Full', n2, n1, work( m*m+1 ), n2, a( j1,
662 $ j1+n2 ),
663 $ lda )
664 CALL dgemm(
'T',
'N', n2, n1, n2, one, work, m, b( j1,
665 $ j1+n2 ),
666 $ ldb, zero, work( m*m+1 ), n2 )
667 CALL dlacpy(
'Full', n2, n1, work( m*m+1 ), n2, b( j1,
668 $ j1+n2 ),
669 $ ldb )
670 CALL dgemm(
'N',
'N', m, m, m, one, li, ldst, work, m, zero,
671 $ work( m*m+1 ), m )
672 CALL dlacpy(
'Full', m, m, work( m*m+1 ), m, li, ldst )
673 CALL dgemm(
'N',
'N', n2, n1, n1, one, a( j1, j1+n2 ), lda,
674 $ t( n2+1, n2+1 ), ldst, zero, work, n2 )
675 CALL dlacpy(
'Full', n2, n1, work, n2, a( j1, j1+n2 ), lda )
676 CALL dgemm(
'N',
'N', n2, n1, n1, one, b( j1, j1+n2 ), ldb,
677 $ t( n2+1, n2+1 ), ldst, zero, work, n2 )
678 CALL dlacpy(
'Full', n2, n1, work, n2, b( j1, j1+n2 ), ldb )
679 CALL dgemm(
'T',
'N', m, m, m, one, ir, ldst, t, ldst, zero,
680 $ work, m )
681 CALL dlacpy(
'Full', m, m, work, m, ir, ldst )
682
683
684
685 IF( wantq ) THEN
686 CALL dgemm(
'N',
'N', n, m, m, one, q( 1, j1 ), ldq, li,
687 $ ldst, zero, work, n )
688 CALL dlacpy(
'Full', n, m, work, n, q( 1, j1 ), ldq )
689
690 END IF
691
692 IF( wantz ) THEN
693 CALL dgemm(
'N',
'N', n, m, m, one, z( 1, j1 ), ldz, ir,
694 $ ldst, zero, work, n )
695 CALL dlacpy(
'Full', n, m, work, n, z( 1, j1 ), ldz )
696
697 END IF
698
699
700
701
702 i = j1 + m
703 IF( i.LE.n ) THEN
704 CALL dgemm(
'T',
'N', m, n-i+1, m, one, li, ldst,
705 $ a( j1, i ), lda, zero, work, m )
706 CALL dlacpy(
'Full', m, n-i+1, work, m, a( j1, i ), lda )
707 CALL dgemm(
'T',
'N', m, n-i+1, m, one, li, ldst,
708 $ b( j1, i ), ldb, zero, work, m )
709 CALL dlacpy(
'Full', m, n-i+1, work, m, b( j1, i ), ldb )
710 END IF
711 i = j1 - 1
712 IF( i.GT.0 ) THEN
713 CALL dgemm(
'N',
'N', i, m, m, one, a( 1, j1 ), lda, ir,
714 $ ldst, zero, work, i )
715 CALL dlacpy(
'Full', i, m, work, i, a( 1, j1 ), lda )
716 CALL dgemm(
'N',
'N', i, m, m, one, b( 1, j1 ), ldb, ir,
717 $ ldst, zero, work, i )
718 CALL dlacpy(
'Full', i, m, work, i, b( 1, j1 ), ldb )
719 END IF
720
721
722
723 RETURN
724
725 END IF
726
727
728
729 70 CONTINUE
730
731 info = 1
732 RETURN
733
734
735
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgeqr2(m, n, a, lda, tau, work, info)
DGEQR2 computes the QR factorization of a general rectangular matrix using an unblocked algorithm.
subroutine dgerq2(m, n, a, lda, tau, work, info)
DGERQ2 computes the RQ factorization of a general rectangular matrix using an unblocked algorithm.
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlagv2(a, lda, b, ldb, alphar, alphai, beta, csl, snl, csr, snr)
DLAGV2 computes the Generalized Schur factorization of a real 2-by-2 matrix pencil (A,...
double precision function dlamch(cmach)
DLAMCH
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine dlassq(n, x, incx, scale, sumsq)
DLASSQ updates a sum of squares represented in scaled form.
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT
subroutine dscal(n, da, dx, incx)
DSCAL
subroutine dtgsy2(trans, ijob, m, n, a, lda, b, ldb, c, ldc, d, ldd, e, lde, f, ldf, scale, rdsum, rdscal, iwork, pq, info)
DTGSY2 solves the generalized Sylvester equation (unblocked algorithm).
subroutine dorg2r(m, n, k, a, lda, tau, work, info)
DORG2R generates all or part of the orthogonal matrix Q from a QR factorization determined by sgeqrf ...
subroutine dorgr2(m, n, k, a, lda, tau, work, info)
DORGR2 generates all or part of the orthogonal matrix Q from an RQ factorization determined by sgerqf...
subroutine dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work, info)
DORM2R multiplies a general matrix by the orthogonal matrix from a QR factorization determined by sge...
subroutine dormr2(side, trans, m, n, k, a, lda, tau, c, ldc, work, info)
DORMR2 multiplies a general matrix by the orthogonal matrix from a RQ factorization determined by sge...