1
SUBROUTINE SB03MY( TRANA, N, A, LDA, C, LDC, SCALE, INFO )
3
C RELEASE 4.0, WGS COPYRIGHT 1999.
7
C To solve the real Lyapunov matrix equation
9
C op(A)'*X + X*op(A) = scale*C
11
C where op(A) = A or A' (A**T), A is upper quasi-triangular and C is
12
C symmetric (C = C'). (A' denotes the transpose of the matrix A.)
13
C A is N-by-N, the right hand side C and the solution X are N-by-N,
14
C and scale is an output scale factor, set less than or equal to 1
15
C to avoid overflow in X. The solution matrix X is overwritten
18
C A must be in Schur canonical form (as returned by LAPACK routines
19
C DGEES or DHSEQR), that is, block upper triangular with 1-by-1 and
20
C 2-by-2 diagonal blocks; each 2-by-2 diagonal block has its
21
C diagonal elements equal and its off-diagonal elements of opposite
29
C Specifies the form of op(A) to be used, as follows:
30
C = 'N': op(A) = A (No transpose);
31
C = 'T': op(A) = A**T (Transpose);
32
C = 'C': op(A) = A**T (Conjugate transpose = Transpose).
34
C Input/Output Parameters
37
C The order of the matrices A, X, and C. N >= 0.
39
C A (input) DOUBLE PRECISION array, dimension (LDA,N)
40
C The leading N-by-N part of this array must contain the
41
C upper quasi-triangular matrix A, in Schur canonical form.
42
C The part of A below the first sub-diagonal is not
46
C The leading dimension of array A. LDA >= MAX(1,N).
48
C C (input/output) DOUBLE PRECISION array, dimension (LDC,N)
49
C On entry, the leading N-by-N part of this array must
50
C contain the symmetric matrix C.
51
C On exit, if INFO >= 0, the leading N-by-N part of this
52
C array contains the symmetric solution matrix X.
55
C The leading dimension of array C. LDC >= MAX(1,N).
57
C SCALE (output) DOUBLE PRECISION
58
C The scale factor, scale, set less than or equal to 1 to
59
C prevent the solution overflowing.
64
C = 0: successful exit;
65
C < 0: if INFO = -i, the i-th argument had an illegal
67
C = 1: if A and -A have common or very close eigenvalues;
68
C perturbed values were used to solve the equation
69
C (but the matrix A is unchanged).
73
C Bartels-Stewart algorithm is used. A set of equivalent linear
74
C algebraic systems of equations of order at most four are formed
75
C and solved using Gaussian elimination with complete pivoting.
79
C [1] Bartels, R.H. and Stewart, G.W. T
80
C Solution of the matrix equation A X + XB = C.
81
C Comm. A.C.M., 15, pp. 820-826, 1972.
85
C The algorithm requires 0(N ) operations.
89
C Release 3.0: V. Sima, Katholieke Univ. Leuven, Belgium, May 1997.
90
C Supersedes Release 2.0 routine SB03AY by Control Systems Research
91
C Group, Kingston Polytechnic, United Kingdom, October 1982.
92
C Based on DTRLYP by P. Petkov, Tech. University of Sofia, September
97
C V. Sima, Katholieke Univ. Leuven, Belgium, May 1999.
101
C Continuous-time system, Lyapunov equation, matrix algebra, real
104
C ******************************************************************
107
DOUBLE PRECISION ZERO, ONE
108
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
110
C .. Scalar Arguments ..
112
INTEGER INFO, LDA, LDC, N
113
DOUBLE PRECISION SCALE
115
C .. Array Arguments ..
116
DOUBLE PRECISION A( LDA, * ), C( LDC, * )
118
C .. Local Scalars ..
119
LOGICAL NOTRNA, LUPPER
120
INTEGER IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXT,
121
$ MINK1N, MINK2N, MINL1N, MINL2N
122
DOUBLE PRECISION A11, BIGNUM, DA11, DB, EPS, SCALOC, SMIN,
126
DOUBLE PRECISION DUM( 1 ), VEC( 2, 2 ), X( 2, 2 )
128
C .. External Functions ..
130
DOUBLE PRECISION DDOT, DLAMCH, DLANHS
131
EXTERNAL DDOT, DLAMCH, DLANHS, LSAME
133
C .. External Subroutines ..
134
EXTERNAL DLABAD, DLALN2, DLASY2, DSCAL, SB03MW, XERBLA
136
C .. Intrinsic Functions ..
137
INTRINSIC ABS, DBLE, MAX, MIN
139
C .. Executable Statements ..
141
C Decode and Test input parameters.
143
NOTRNA = LSAME( TRANA, 'N' )
147
IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND.
148
$ .NOT.LSAME( TRANA, 'C' ) ) THEN
150
ELSE IF( N.LT.0 ) THEN
152
ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
154
ELSE IF( LDC.LT.MAX( 1, N ) ) THEN
159
CALL XERBLA( 'SB03MY', -INFO )
165
C Quick return if possible.
170
C Set constants to control overflow.
173
SMLNUM = DLAMCH( 'S' )
174
BIGNUM = ONE / SMLNUM
175
CALL DLABAD( SMLNUM, BIGNUM )
176
SMLNUM = SMLNUM*DBLE( N*N ) / EPS
177
BIGNUM = ONE / SMLNUM
179
SMIN = MAX( SMLNUM, EPS*DLANHS( 'Max', N, A, LDA, DUM ) )
183
C Solve A'*X + X*A = scale*C.
185
C The (K,L)th block of X is determined starting from
186
C upper-left corner column by column by
188
C A(K,K)'*X(K,L) + X(K,L)*A(L,L) = C(K,L) - R(K,L),
192
C R(K,L) = SUM [A(I,K)'*X(I,L)] + SUM [X(K,J)*A(J,L)].
195
C Start column loop (index = L).
196
C L1 (L2): column index of the first (last) row of X(K,L).
206
IF( A( L+1, L ).NE.ZERO )
211
C Start row loop (index = K).
212
C K1 (K2): row index of the first (last) row of X(K,L).
222
IF( A( K+1, K ).NE.ZERO )
227
IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
228
VEC( 1, 1 ) = C( K1, L1 ) -
229
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) +
230
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L1 ), 1 ) )
233
A11 = A( K1, K1 ) + A( L1, L1 )
235
IF( DA11.LE.SMIN ) THEN
240
DB = ABS( VEC( 1, 1 ) )
241
IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
242
IF( DB.GT.BIGNUM*DA11 )
245
X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
247
IF( SCALOC.NE.ONE ) THEN
250
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
255
C( K1, L1 ) = X( 1, 1 )
257
C( L1, K1 ) = X( 1, 1 )
260
ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
262
VEC( 1, 1 ) = C( K1, L1 ) -
263
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) +
264
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L1 ), 1 ) )
266
VEC( 2, 1 ) = C( K2, L1 ) -
267
$ ( DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) +
268
$ DDOT( L1-1, C( K2, 1 ), LDC, A( 1, L1 ), 1 ) )
270
CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),
271
$ LDA, ONE, ONE, VEC, 2, -A( L1, L1 ),
272
$ ZERO, X, 2, SCALOC, XNORM, IERR )
276
IF( SCALOC.NE.ONE ) THEN
279
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
284
C( K1, L1 ) = X( 1, 1 )
285
C( K2, L1 ) = X( 2, 1 )
286
C( L1, K1 ) = X( 1, 1 )
287
C( L1, K2 ) = X( 2, 1 )
289
ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
291
VEC( 1, 1 ) = C( K1, L1 ) -
292
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) +
293
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L1 ), 1 ) )
295
VEC( 2, 1 ) = C( K1, L2 ) -
296
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) +
297
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L2 ), 1 ) )
299
CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( L1, L1 ),
300
$ LDA, ONE, ONE, VEC, 2, -A( K1, K1 ),
301
$ ZERO, X, 2, SCALOC, XNORM, IERR )
305
IF( SCALOC.NE.ONE ) THEN
308
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
313
C( K1, L1 ) = X( 1, 1 )
314
C( K1, L2 ) = X( 2, 1 )
315
C( L1, K1 ) = X( 1, 1 )
316
C( L2, K1 ) = X( 2, 1 )
318
ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
320
VEC( 1, 1 ) = C( K1, L1 ) -
321
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) +
322
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L1 ), 1 ) )
324
VEC( 1, 2 ) = C( K1, L2 ) -
325
$ ( DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) +
326
$ DDOT( L1-1, C( K1, 1 ), LDC, A( 1, L2 ), 1 ) )
328
VEC( 2, 1 ) = C( K2, L1 ) -
329
$ ( DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) +
330
$ DDOT( L1-1, C( K2, 1 ), LDC, A( 1, L1 ), 1 ) )
332
VEC( 2, 2 ) = C( K2, L2 ) -
333
$ ( DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 ) +
334
$ DDOT( L1-1, C( K2, 1 ), LDC, A( 1, L2 ), 1 ) )
337
CALL SB03MW( .FALSE., LUPPER, A( K1, K1 ), LDA,
338
$ VEC, 2, SCALOC, X, 2, XNORM, IERR )
340
X( 2, 1 ) = X( 1, 2 )
342
X( 1, 2 ) = X( 2, 1 )
345
CALL DLASY2( .TRUE., .FALSE., 1, 2, 2, A( K1, K1 ),
346
$ LDA, A( L1, L1 ), LDA, VEC, 2, SCALOC,
347
$ X, 2, XNORM, IERR )
352
IF( SCALOC.NE.ONE ) THEN
355
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
360
C( K1, L1 ) = X( 1, 1 )
361
C( K1, L2 ) = X( 1, 2 )
362
C( K2, L1 ) = X( 2, 1 )
363
C( K2, L2 ) = X( 2, 2 )
365
C( L1, K1 ) = X( 1, 1 )
366
C( L2, K1 ) = X( 1, 2 )
367
C( L1, K2 ) = X( 2, 1 )
368
C( L2, K2 ) = X( 2, 2 )
378
C Solve A*X + X*A' = scale*C.
380
C The (K,L)th block of X is determined starting from
381
C bottom-right corner column by column by
383
C A(K,K)*X(K,L) + X(K,L)*A(L,L)' = C(K,L) - R(K,L),
387
C R(K,L) = SUM [A(K,I)*X(I,L)] + SUM [X(K,J)*A(L,J)'].
390
C Start column loop (index = L).
391
C L1 (L2): column index of the first (last) row of X(K,L).
401
IF( A( L, L-1 ).NE.ZERO )
405
MINL1N = MIN( L1+1, N )
406
MINL2N = MIN( L2+1, N )
408
C Start row loop (index = K).
409
C K1 (K2): row index of the first (last) row of X(K,L).
419
IF( A( K, K-1 ).NE.ZERO )
423
MINK1N = MIN( K1+1, N )
424
MINK2N = MIN( K2+1, N )
426
IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
427
VEC( 1, 1 ) = C( K1, L1 ) -
428
$ ( DDOT( N-K1, A( K1, MINK1N ), LDA,
429
$ C( MINK1N, L1 ), 1 ) +
430
$ DDOT( N-L1, C( K1, MINL1N ), LDC,
431
$ A( L1, MINL1N ), LDA ) )
434
A11 = A( K1, K1 ) + A( L1, L1 )
436
IF( DA11.LE.SMIN ) THEN
441
DB = ABS( VEC( 1, 1 ) )
442
IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
443
IF( DB.GT.BIGNUM*DA11 )
446
X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
448
IF( SCALOC.NE.ONE ) THEN
451
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
456
C( K1, L1 ) = X( 1, 1 )
458
C( L1, K1 ) = X( 1, 1 )
461
ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
463
VEC( 1, 1 ) = C( K1, L1 ) -
464
$ ( DDOT( N-K2, A( K1, MINK2N ), LDA,
465
$ C( MINK2N, L1 ), 1 ) +
466
$ DDOT( N-L2, C( K1, MINL2N ), LDC,
467
$ A( L1, MINL2N ), LDA ) )
469
VEC( 2, 1 ) = C( K2, L1 ) -
470
$ ( DDOT( N-K2, A( K2, MINK2N ), LDA,
471
$ C( MINK2N, L1 ), 1 ) +
472
$ DDOT( N-L2, C( K2, MINL2N ), LDC,
473
$ A( L1, MINL2N ), LDA ) )
475
CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),
476
$ LDA, ONE, ONE, VEC, 2, -A( L1, L1 ),
477
$ ZERO, X, 2, SCALOC, XNORM, IERR )
481
IF( SCALOC.NE.ONE ) THEN
484
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
489
C( K1, L1 ) = X( 1, 1 )
490
C( K2, L1 ) = X( 2, 1 )
491
C( L1, K1 ) = X( 1, 1 )
492
C( L1, K2 ) = X( 2, 1 )
494
ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
496
VEC( 1, 1 ) = C( K1, L1 ) -
497
$ ( DDOT( N-K1, A( K1, MINK1N ), LDA,
498
$ C( MINK1N, L1 ), 1 ) +
499
$ DDOT( N-L2, C( K1, MINL2N ), LDC,
500
$ A( L1, MINL2N ), LDA ) )
502
VEC( 2, 1 ) = C( K1, L2 ) -
503
$ ( DDOT( N-K1, A( K1, MINK1N ), LDA,
504
$ C( MINK1N, L2 ), 1 ) +
505
$ DDOT( N-L2, C( K1, MINL2N ), LDC,
506
$ A( L2, MINL2N ), LDA ) )
508
CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( L1, L1 ),
509
$ LDA, ONE, ONE, VEC, 2, -A( K1, K1 ),
510
$ ZERO, X, 2, SCALOC, XNORM, IERR )
514
IF( SCALOC.NE.ONE ) THEN
517
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
522
C( K1, L1 ) = X( 1, 1 )
523
C( K1, L2 ) = X( 2, 1 )
524
C( L1, K1 ) = X( 1, 1 )
525
C( L2, K1 ) = X( 2, 1 )
527
ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
529
VEC( 1, 1 ) = C( K1, L1 ) -
530
$ ( DDOT( N-K2, A( K1, MINK2N ), LDA,
531
$ C( MINK2N, L1 ), 1 ) +
532
$ DDOT( N-L2, C( K1, MINL2N ), LDC,
533
$ A( L1, MINL2N ), LDA ) )
535
VEC( 1, 2 ) = C( K1, L2 ) -
536
$ ( DDOT( N-K2, A( K1, MINK2N ), LDA,
537
$ C( MINK2N, L2 ), 1 ) +
538
$ DDOT( N-L2, C( K1, MINL2N ), LDC,
539
$ A( L2, MINL2N ), LDA ) )
541
VEC( 2, 1 ) = C( K2, L1 ) -
542
$ ( DDOT( N-K2, A( K2, MINK2N ), LDA,
543
$ C( MINK2N, L1 ), 1 ) +
544
$ DDOT( N-L2, C( K2, MINL2N ), LDC,
545
$ A( L1, MINL2N ), LDA ) )
547
VEC( 2, 2 ) = C( K2, L2 ) -
548
$ ( DDOT( N-K2, A( K2, MINK2N ), LDA,
549
$ C( MINK2N, L2 ), 1 ) +
550
$ DDOT( N-L2, C( K2, MINL2N ), LDC,
551
$ A( L2, MINL2N ), LDA ) )
554
CALL SB03MW( .TRUE., LUPPER, A( K1, K1 ), LDA, VEC,
555
$ 2, SCALOC, X, 2, XNORM, IERR )
557
X( 2, 1 ) = X( 1, 2 )
559
X( 1, 2 ) = X( 2, 1 )
562
CALL DLASY2( .FALSE., .TRUE., 1, 2, 2, A( K1, K1 ),
563
$ LDA, A( L1, L1 ), LDA, VEC, 2, SCALOC,
564
$ X, 2, XNORM, IERR )
569
IF( SCALOC.NE.ONE ) THEN
572
CALL DSCAL( N, SCALOC, C( 1, J ), 1 )
577
C( K1, L1 ) = X( 1, 1 )
578
C( K1, L2 ) = X( 1, 2 )
579
C( K2, L1 ) = X( 2, 1 )
580
C( K2, L2 ) = X( 2, 2 )
582
C( L1, K1 ) = X( 1, 1 )
583
C( L2, K1 ) = X( 1, 2 )
584
C( L1, K2 ) = X( 2, 1 )
585
C( L2, K2 ) = X( 2, 2 )
596
C *** Last line of SB03MY ***