Annotation of rpl/lapack/lapack/dtrsyl.f, revision 1.7
1.1 bertrand 1: SUBROUTINE DTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C,
2: $ LDC, SCALE, INFO )
3: *
4: * -- LAPACK routine (version 3.2) --
5: * -- LAPACK is a software package provided by Univ. of Tennessee, --
6: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
7: * November 2006
8: *
9: * .. Scalar Arguments ..
10: CHARACTER TRANA, TRANB
11: INTEGER INFO, ISGN, LDA, LDB, LDC, M, N
12: DOUBLE PRECISION SCALE
13: * ..
14: * .. Array Arguments ..
15: DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * )
16: * ..
17: *
18: * Purpose
19: * =======
20: *
21: * DTRSYL solves the real Sylvester matrix equation:
22: *
23: * op(A)*X + X*op(B) = scale*C or
24: * op(A)*X - X*op(B) = scale*C,
25: *
26: * where op(A) = A or A**T, and A and B are both upper quasi-
27: * triangular. A is M-by-M and B is N-by-N; the right hand side C and
28: * the solution X are M-by-N; and scale is an output scale factor, set
29: * <= 1 to avoid overflow in X.
30: *
31: * A and B must be in Schur canonical form (as returned by DHSEQR), that
32: * is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks;
33: * each 2-by-2 diagonal block has its diagonal elements equal and its
34: * off-diagonal elements of opposite sign.
35: *
36: * Arguments
37: * =========
38: *
39: * TRANA (input) CHARACTER*1
40: * Specifies the option op(A):
41: * = 'N': op(A) = A (No transpose)
42: * = 'T': op(A) = A**T (Transpose)
43: * = 'C': op(A) = A**H (Conjugate transpose = Transpose)
44: *
45: * TRANB (input) CHARACTER*1
46: * Specifies the option op(B):
47: * = 'N': op(B) = B (No transpose)
48: * = 'T': op(B) = B**T (Transpose)
49: * = 'C': op(B) = B**H (Conjugate transpose = Transpose)
50: *
51: * ISGN (input) INTEGER
52: * Specifies the sign in the equation:
53: * = +1: solve op(A)*X + X*op(B) = scale*C
54: * = -1: solve op(A)*X - X*op(B) = scale*C
55: *
56: * M (input) INTEGER
57: * The order of the matrix A, and the number of rows in the
58: * matrices X and C. M >= 0.
59: *
60: * N (input) INTEGER
61: * The order of the matrix B, and the number of columns in the
62: * matrices X and C. N >= 0.
63: *
64: * A (input) DOUBLE PRECISION array, dimension (LDA,M)
65: * The upper quasi-triangular matrix A, in Schur canonical form.
66: *
67: * LDA (input) INTEGER
68: * The leading dimension of the array A. LDA >= max(1,M).
69: *
70: * B (input) DOUBLE PRECISION array, dimension (LDB,N)
71: * The upper quasi-triangular matrix B, in Schur canonical form.
72: *
73: * LDB (input) INTEGER
74: * The leading dimension of the array B. LDB >= max(1,N).
75: *
76: * C (input/output) DOUBLE PRECISION array, dimension (LDC,N)
77: * On entry, the M-by-N right hand side matrix C.
78: * On exit, C is overwritten by the solution matrix X.
79: *
80: * LDC (input) INTEGER
81: * The leading dimension of the array C. LDC >= max(1,M)
82: *
83: * SCALE (output) DOUBLE PRECISION
84: * The scale factor, scale, set <= 1 to avoid overflow in X.
85: *
86: * INFO (output) INTEGER
87: * = 0: successful exit
88: * < 0: if INFO = -i, the i-th argument had an illegal value
89: * = 1: A and B have common or very close eigenvalues; perturbed
90: * values were used to solve the equation (but the matrices
91: * A and B are unchanged).
92: *
93: * =====================================================================
94: *
95: * .. Parameters ..
96: DOUBLE PRECISION ZERO, ONE
97: PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
98: * ..
99: * .. Local Scalars ..
100: LOGICAL NOTRNA, NOTRNB
101: INTEGER IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXT
102: DOUBLE PRECISION A11, BIGNUM, DA11, DB, EPS, SCALOC, SGN, SMIN,
103: $ SMLNUM, SUML, SUMR, XNORM
104: * ..
105: * .. Local Arrays ..
106: DOUBLE PRECISION DUM( 1 ), VEC( 2, 2 ), X( 2, 2 )
107: * ..
108: * .. External Functions ..
109: LOGICAL LSAME
110: DOUBLE PRECISION DDOT, DLAMCH, DLANGE
111: EXTERNAL LSAME, DDOT, DLAMCH, DLANGE
112: * ..
113: * .. External Subroutines ..
114: EXTERNAL DLABAD, DLALN2, DLASY2, DSCAL, XERBLA
115: * ..
116: * .. Intrinsic Functions ..
117: INTRINSIC ABS, DBLE, MAX, MIN
118: * ..
119: * .. Executable Statements ..
120: *
121: * Decode and Test input parameters
122: *
123: NOTRNA = LSAME( TRANA, 'N' )
124: NOTRNB = LSAME( TRANB, 'N' )
125: *
126: INFO = 0
127: IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND. .NOT.
128: $ LSAME( TRANA, 'C' ) ) THEN
129: INFO = -1
130: ELSE IF( .NOT.NOTRNB .AND. .NOT.LSAME( TRANB, 'T' ) .AND. .NOT.
131: $ LSAME( TRANB, 'C' ) ) THEN
132: INFO = -2
133: ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THEN
134: INFO = -3
135: ELSE IF( M.LT.0 ) THEN
136: INFO = -4
137: ELSE IF( N.LT.0 ) THEN
138: INFO = -5
139: ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
140: INFO = -7
141: ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
142: INFO = -9
143: ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
144: INFO = -11
145: END IF
146: IF( INFO.NE.0 ) THEN
147: CALL XERBLA( 'DTRSYL', -INFO )
148: RETURN
149: END IF
150: *
151: * Quick return if possible
152: *
153: SCALE = ONE
154: IF( M.EQ.0 .OR. N.EQ.0 )
155: $ RETURN
156: *
157: * Set constants to control overflow
158: *
159: EPS = DLAMCH( 'P' )
160: SMLNUM = DLAMCH( 'S' )
161: BIGNUM = ONE / SMLNUM
162: CALL DLABAD( SMLNUM, BIGNUM )
163: SMLNUM = SMLNUM*DBLE( M*N ) / EPS
164: BIGNUM = ONE / SMLNUM
165: *
166: SMIN = MAX( SMLNUM, EPS*DLANGE( 'M', M, M, A, LDA, DUM ),
167: $ EPS*DLANGE( 'M', N, N, B, LDB, DUM ) )
168: *
169: SGN = ISGN
170: *
171: IF( NOTRNA .AND. NOTRNB ) THEN
172: *
173: * Solve A*X + ISGN*X*B = scale*C.
174: *
175: * The (K,L)th block of X is determined starting from
176: * bottom-left corner column by column by
177: *
178: * A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
179: *
180: * Where
181: * M L-1
182: * R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].
183: * I=K+1 J=1
184: *
185: * Start column loop (index = L)
186: * L1 (L2) : column index of the first (first) row of X(K,L).
187: *
188: LNEXT = 1
189: DO 60 L = 1, N
190: IF( L.LT.LNEXT )
191: $ GO TO 60
192: IF( L.EQ.N ) THEN
193: L1 = L
194: L2 = L
195: ELSE
196: IF( B( L+1, L ).NE.ZERO ) THEN
197: L1 = L
198: L2 = L + 1
199: LNEXT = L + 2
200: ELSE
201: L1 = L
202: L2 = L
203: LNEXT = L + 1
204: END IF
205: END IF
206: *
207: * Start row loop (index = K)
208: * K1 (K2): row index of the first (last) row of X(K,L).
209: *
210: KNEXT = M
211: DO 50 K = M, 1, -1
212: IF( K.GT.KNEXT )
213: $ GO TO 50
214: IF( K.EQ.1 ) THEN
215: K1 = K
216: K2 = K
217: ELSE
218: IF( A( K, K-1 ).NE.ZERO ) THEN
219: K1 = K - 1
220: K2 = K
221: KNEXT = K - 2
222: ELSE
223: K1 = K
224: K2 = K
225: KNEXT = K - 1
226: END IF
227: END IF
228: *
229: IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
230: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
231: $ C( MIN( K1+1, M ), L1 ), 1 )
232: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
233: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
234: SCALOC = ONE
235: *
236: A11 = A( K1, K1 ) + SGN*B( L1, L1 )
237: DA11 = ABS( A11 )
238: IF( DA11.LE.SMIN ) THEN
239: A11 = SMIN
240: DA11 = SMIN
241: INFO = 1
242: END IF
243: DB = ABS( VEC( 1, 1 ) )
244: IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
245: IF( DB.GT.BIGNUM*DA11 )
246: $ SCALOC = ONE / DB
247: END IF
248: X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
249: *
250: IF( SCALOC.NE.ONE ) THEN
251: DO 10 J = 1, N
252: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
253: 10 CONTINUE
254: SCALE = SCALE*SCALOC
255: END IF
256: C( K1, L1 ) = X( 1, 1 )
257: *
258: ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
259: *
260: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
261: $ C( MIN( K2+1, M ), L1 ), 1 )
262: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
263: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
264: *
265: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
266: $ C( MIN( K2+1, M ), L1 ), 1 )
267: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
268: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
269: *
270: CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),
271: $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
272: $ ZERO, X, 2, SCALOC, XNORM, IERR )
273: IF( IERR.NE.0 )
274: $ INFO = 1
275: *
276: IF( SCALOC.NE.ONE ) THEN
277: DO 20 J = 1, N
278: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
279: 20 CONTINUE
280: SCALE = SCALE*SCALOC
281: END IF
282: C( K1, L1 ) = X( 1, 1 )
283: C( K2, L1 ) = X( 2, 1 )
284: *
285: ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
286: *
287: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
288: $ C( MIN( K1+1, M ), L1 ), 1 )
289: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
290: VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
291: *
292: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
293: $ C( MIN( K1+1, M ), L2 ), 1 )
294: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
295: VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
296: *
297: CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),
298: $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
299: $ ZERO, X, 2, SCALOC, XNORM, IERR )
300: IF( IERR.NE.0 )
301: $ INFO = 1
302: *
303: IF( SCALOC.NE.ONE ) THEN
304: DO 30 J = 1, N
305: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
306: 30 CONTINUE
307: SCALE = SCALE*SCALOC
308: END IF
309: C( K1, L1 ) = X( 1, 1 )
310: C( K1, L2 ) = X( 2, 1 )
311: *
312: ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
313: *
314: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
315: $ C( MIN( K2+1, M ), L1 ), 1 )
316: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
317: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
318: *
319: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
320: $ C( MIN( K2+1, M ), L2 ), 1 )
321: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
322: VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
323: *
324: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
325: $ C( MIN( K2+1, M ), L1 ), 1 )
326: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
327: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
328: *
329: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
330: $ C( MIN( K2+1, M ), L2 ), 1 )
331: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )
332: VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
333: *
334: CALL DLASY2( .FALSE., .FALSE., ISGN, 2, 2,
335: $ A( K1, K1 ), LDA, B( L1, L1 ), LDB, VEC,
336: $ 2, SCALOC, X, 2, XNORM, IERR )
337: IF( IERR.NE.0 )
338: $ INFO = 1
339: *
340: IF( SCALOC.NE.ONE ) THEN
341: DO 40 J = 1, N
342: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
343: 40 CONTINUE
344: SCALE = SCALE*SCALOC
345: END IF
346: C( K1, L1 ) = X( 1, 1 )
347: C( K1, L2 ) = X( 1, 2 )
348: C( K2, L1 ) = X( 2, 1 )
349: C( K2, L2 ) = X( 2, 2 )
350: END IF
351: *
352: 50 CONTINUE
353: *
354: 60 CONTINUE
355: *
356: ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN
357: *
358: * Solve A' *X + ISGN*X*B = scale*C.
359: *
360: * The (K,L)th block of X is determined starting from
361: * upper-left corner column by column by
362: *
363: * A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
364: *
365: * Where
366: * K-1 L-1
367: * R(K,L) = SUM [A(I,K)'*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]
368: * I=1 J=1
369: *
370: * Start column loop (index = L)
371: * L1 (L2): column index of the first (last) row of X(K,L)
372: *
373: LNEXT = 1
374: DO 120 L = 1, N
375: IF( L.LT.LNEXT )
376: $ GO TO 120
377: IF( L.EQ.N ) THEN
378: L1 = L
379: L2 = L
380: ELSE
381: IF( B( L+1, L ).NE.ZERO ) THEN
382: L1 = L
383: L2 = L + 1
384: LNEXT = L + 2
385: ELSE
386: L1 = L
387: L2 = L
388: LNEXT = L + 1
389: END IF
390: END IF
391: *
392: * Start row loop (index = K)
393: * K1 (K2): row index of the first (last) row of X(K,L)
394: *
395: KNEXT = 1
396: DO 110 K = 1, M
397: IF( K.LT.KNEXT )
398: $ GO TO 110
399: IF( K.EQ.M ) THEN
400: K1 = K
401: K2 = K
402: ELSE
403: IF( A( K+1, K ).NE.ZERO ) THEN
404: K1 = K
405: K2 = K + 1
406: KNEXT = K + 2
407: ELSE
408: K1 = K
409: K2 = K
410: KNEXT = K + 1
411: END IF
412: END IF
413: *
414: IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
415: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
416: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
417: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
418: SCALOC = ONE
419: *
420: A11 = A( K1, K1 ) + SGN*B( L1, L1 )
421: DA11 = ABS( A11 )
422: IF( DA11.LE.SMIN ) THEN
423: A11 = SMIN
424: DA11 = SMIN
425: INFO = 1
426: END IF
427: DB = ABS( VEC( 1, 1 ) )
428: IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
429: IF( DB.GT.BIGNUM*DA11 )
430: $ SCALOC = ONE / DB
431: END IF
432: X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
433: *
434: IF( SCALOC.NE.ONE ) THEN
435: DO 70 J = 1, N
436: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
437: 70 CONTINUE
438: SCALE = SCALE*SCALOC
439: END IF
440: C( K1, L1 ) = X( 1, 1 )
441: *
442: ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
443: *
444: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
445: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
446: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
447: *
448: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
449: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
450: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
451: *
452: CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),
453: $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
454: $ ZERO, X, 2, SCALOC, XNORM, IERR )
455: IF( IERR.NE.0 )
456: $ INFO = 1
457: *
458: IF( SCALOC.NE.ONE ) THEN
459: DO 80 J = 1, N
460: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
461: 80 CONTINUE
462: SCALE = SCALE*SCALOC
463: END IF
464: C( K1, L1 ) = X( 1, 1 )
465: C( K2, L1 ) = X( 2, 1 )
466: *
467: ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
468: *
469: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
470: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
471: VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
472: *
473: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
474: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
475: VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
476: *
477: CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),
478: $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
479: $ ZERO, X, 2, SCALOC, XNORM, IERR )
480: IF( IERR.NE.0 )
481: $ INFO = 1
482: *
483: IF( SCALOC.NE.ONE ) THEN
484: DO 90 J = 1, N
485: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
486: 90 CONTINUE
487: SCALE = SCALE*SCALOC
488: END IF
489: C( K1, L1 ) = X( 1, 1 )
490: C( K1, L2 ) = X( 2, 1 )
491: *
492: ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
493: *
494: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
495: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
496: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
497: *
498: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
499: SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
500: VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
501: *
502: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
503: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
504: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
505: *
506: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )
507: SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )
508: VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
509: *
510: CALL DLASY2( .TRUE., .FALSE., ISGN, 2, 2, A( K1, K1 ),
511: $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
512: $ 2, XNORM, IERR )
513: IF( IERR.NE.0 )
514: $ INFO = 1
515: *
516: IF( SCALOC.NE.ONE ) THEN
517: DO 100 J = 1, N
518: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
519: 100 CONTINUE
520: SCALE = SCALE*SCALOC
521: END IF
522: C( K1, L1 ) = X( 1, 1 )
523: C( K1, L2 ) = X( 1, 2 )
524: C( K2, L1 ) = X( 2, 1 )
525: C( K2, L2 ) = X( 2, 2 )
526: END IF
527: *
528: 110 CONTINUE
529: 120 CONTINUE
530: *
531: ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN
532: *
533: * Solve A'*X + ISGN*X*B' = scale*C.
534: *
535: * The (K,L)th block of X is determined starting from
536: * top-right corner column by column by
537: *
538: * A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)
539: *
540: * Where
541: * K-1 N
542: * R(K,L) = SUM [A(I,K)'*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].
543: * I=1 J=L+1
544: *
545: * Start column loop (index = L)
546: * L1 (L2): column index of the first (last) row of X(K,L)
547: *
548: LNEXT = N
549: DO 180 L = N, 1, -1
550: IF( L.GT.LNEXT )
551: $ GO TO 180
552: IF( L.EQ.1 ) THEN
553: L1 = L
554: L2 = L
555: ELSE
556: IF( B( L, L-1 ).NE.ZERO ) THEN
557: L1 = L - 1
558: L2 = L
559: LNEXT = L - 2
560: ELSE
561: L1 = L
562: L2 = L
563: LNEXT = L - 1
564: END IF
565: END IF
566: *
567: * Start row loop (index = K)
568: * K1 (K2): row index of the first (last) row of X(K,L)
569: *
570: KNEXT = 1
571: DO 170 K = 1, M
572: IF( K.LT.KNEXT )
573: $ GO TO 170
574: IF( K.EQ.M ) THEN
575: K1 = K
576: K2 = K
577: ELSE
578: IF( A( K+1, K ).NE.ZERO ) THEN
579: K1 = K
580: K2 = K + 1
581: KNEXT = K + 2
582: ELSE
583: K1 = K
584: K2 = K
585: KNEXT = K + 1
586: END IF
587: END IF
588: *
589: IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
590: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
591: SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,
592: $ B( L1, MIN( L1+1, N ) ), LDB )
593: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
594: SCALOC = ONE
595: *
596: A11 = A( K1, K1 ) + SGN*B( L1, L1 )
597: DA11 = ABS( A11 )
598: IF( DA11.LE.SMIN ) THEN
599: A11 = SMIN
600: DA11 = SMIN
601: INFO = 1
602: END IF
603: DB = ABS( VEC( 1, 1 ) )
604: IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
605: IF( DB.GT.BIGNUM*DA11 )
606: $ SCALOC = ONE / DB
607: END IF
608: X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
609: *
610: IF( SCALOC.NE.ONE ) THEN
611: DO 130 J = 1, N
612: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
613: 130 CONTINUE
614: SCALE = SCALE*SCALOC
615: END IF
616: C( K1, L1 ) = X( 1, 1 )
617: *
618: ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
619: *
620: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
621: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
622: $ B( L1, MIN( L2+1, N ) ), LDB )
623: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
624: *
625: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
626: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
627: $ B( L1, MIN( L2+1, N ) ), LDB )
628: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
629: *
630: CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),
631: $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
632: $ ZERO, X, 2, SCALOC, XNORM, IERR )
633: IF( IERR.NE.0 )
634: $ INFO = 1
635: *
636: IF( SCALOC.NE.ONE ) THEN
637: DO 140 J = 1, N
638: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
639: 140 CONTINUE
640: SCALE = SCALE*SCALOC
641: END IF
642: C( K1, L1 ) = X( 1, 1 )
643: C( K2, L1 ) = X( 2, 1 )
644: *
645: ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
646: *
647: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
648: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
649: $ B( L1, MIN( L2+1, N ) ), LDB )
650: VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
651: *
652: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
653: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
654: $ B( L2, MIN( L2+1, N ) ), LDB )
655: VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
656: *
657: CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),
658: $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
659: $ ZERO, X, 2, SCALOC, XNORM, IERR )
660: IF( IERR.NE.0 )
661: $ INFO = 1
662: *
663: IF( SCALOC.NE.ONE ) THEN
664: DO 150 J = 1, N
665: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
666: 150 CONTINUE
667: SCALE = SCALE*SCALOC
668: END IF
669: C( K1, L1 ) = X( 1, 1 )
670: C( K1, L2 ) = X( 2, 1 )
671: *
672: ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
673: *
674: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
675: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
676: $ B( L1, MIN( L2+1, N ) ), LDB )
677: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
678: *
679: SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
680: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
681: $ B( L2, MIN( L2+1, N ) ), LDB )
682: VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
683: *
684: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
685: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
686: $ B( L1, MIN( L2+1, N ) ), LDB )
687: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
688: *
689: SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )
690: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
691: $ B( L2, MIN( L2+1, N ) ), LDB )
692: VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
693: *
694: CALL DLASY2( .TRUE., .TRUE., ISGN, 2, 2, A( K1, K1 ),
695: $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
696: $ 2, XNORM, IERR )
697: IF( IERR.NE.0 )
698: $ INFO = 1
699: *
700: IF( SCALOC.NE.ONE ) THEN
701: DO 160 J = 1, N
702: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
703: 160 CONTINUE
704: SCALE = SCALE*SCALOC
705: END IF
706: C( K1, L1 ) = X( 1, 1 )
707: C( K1, L2 ) = X( 1, 2 )
708: C( K2, L1 ) = X( 2, 1 )
709: C( K2, L2 ) = X( 2, 2 )
710: END IF
711: *
712: 170 CONTINUE
713: 180 CONTINUE
714: *
715: ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN
716: *
717: * Solve A*X + ISGN*X*B' = scale*C.
718: *
719: * The (K,L)th block of X is determined starting from
720: * bottom-right corner column by column by
721: *
722: * A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)
723: *
724: * Where
725: * M N
726: * R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].
727: * I=K+1 J=L+1
728: *
729: * Start column loop (index = L)
730: * L1 (L2): column index of the first (last) row of X(K,L)
731: *
732: LNEXT = N
733: DO 240 L = N, 1, -1
734: IF( L.GT.LNEXT )
735: $ GO TO 240
736: IF( L.EQ.1 ) THEN
737: L1 = L
738: L2 = L
739: ELSE
740: IF( B( L, L-1 ).NE.ZERO ) THEN
741: L1 = L - 1
742: L2 = L
743: LNEXT = L - 2
744: ELSE
745: L1 = L
746: L2 = L
747: LNEXT = L - 1
748: END IF
749: END IF
750: *
751: * Start row loop (index = K)
752: * K1 (K2): row index of the first (last) row of X(K,L)
753: *
754: KNEXT = M
755: DO 230 K = M, 1, -1
756: IF( K.GT.KNEXT )
757: $ GO TO 230
758: IF( K.EQ.1 ) THEN
759: K1 = K
760: K2 = K
761: ELSE
762: IF( A( K, K-1 ).NE.ZERO ) THEN
763: K1 = K - 1
764: K2 = K
765: KNEXT = K - 2
766: ELSE
767: K1 = K
768: K2 = K
769: KNEXT = K - 1
770: END IF
771: END IF
772: *
773: IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
774: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
775: $ C( MIN( K1+1, M ), L1 ), 1 )
776: SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,
777: $ B( L1, MIN( L1+1, N ) ), LDB )
778: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
779: SCALOC = ONE
780: *
781: A11 = A( K1, K1 ) + SGN*B( L1, L1 )
782: DA11 = ABS( A11 )
783: IF( DA11.LE.SMIN ) THEN
784: A11 = SMIN
785: DA11 = SMIN
786: INFO = 1
787: END IF
788: DB = ABS( VEC( 1, 1 ) )
789: IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
790: IF( DB.GT.BIGNUM*DA11 )
791: $ SCALOC = ONE / DB
792: END IF
793: X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
794: *
795: IF( SCALOC.NE.ONE ) THEN
796: DO 190 J = 1, N
797: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
798: 190 CONTINUE
799: SCALE = SCALE*SCALOC
800: END IF
801: C( K1, L1 ) = X( 1, 1 )
802: *
803: ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
804: *
805: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
806: $ C( MIN( K2+1, M ), L1 ), 1 )
807: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
808: $ B( L1, MIN( L2+1, N ) ), LDB )
809: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
810: *
811: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
812: $ C( MIN( K2+1, M ), L1 ), 1 )
813: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
814: $ B( L1, MIN( L2+1, N ) ), LDB )
815: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
816: *
817: CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),
818: $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
819: $ ZERO, X, 2, SCALOC, XNORM, IERR )
820: IF( IERR.NE.0 )
821: $ INFO = 1
822: *
823: IF( SCALOC.NE.ONE ) THEN
824: DO 200 J = 1, N
825: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
826: 200 CONTINUE
827: SCALE = SCALE*SCALOC
828: END IF
829: C( K1, L1 ) = X( 1, 1 )
830: C( K2, L1 ) = X( 2, 1 )
831: *
832: ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
833: *
834: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
835: $ C( MIN( K1+1, M ), L1 ), 1 )
836: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
837: $ B( L1, MIN( L2+1, N ) ), LDB )
838: VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
839: *
840: SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
841: $ C( MIN( K1+1, M ), L2 ), 1 )
842: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
843: $ B( L2, MIN( L2+1, N ) ), LDB )
844: VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
845: *
846: CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),
847: $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
848: $ ZERO, X, 2, SCALOC, XNORM, IERR )
849: IF( IERR.NE.0 )
850: $ INFO = 1
851: *
852: IF( SCALOC.NE.ONE ) THEN
853: DO 210 J = 1, N
854: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
855: 210 CONTINUE
856: SCALE = SCALE*SCALOC
857: END IF
858: C( K1, L1 ) = X( 1, 1 )
859: C( K1, L2 ) = X( 2, 1 )
860: *
861: ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
862: *
863: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
864: $ C( MIN( K2+1, M ), L1 ), 1 )
865: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
866: $ B( L1, MIN( L2+1, N ) ), LDB )
867: VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
868: *
869: SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
870: $ C( MIN( K2+1, M ), L2 ), 1 )
871: SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
872: $ B( L2, MIN( L2+1, N ) ), LDB )
873: VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
874: *
875: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
876: $ C( MIN( K2+1, M ), L1 ), 1 )
877: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
878: $ B( L1, MIN( L2+1, N ) ), LDB )
879: VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
880: *
881: SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
882: $ C( MIN( K2+1, M ), L2 ), 1 )
883: SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
884: $ B( L2, MIN( L2+1, N ) ), LDB )
885: VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
886: *
887: CALL DLASY2( .FALSE., .TRUE., ISGN, 2, 2, A( K1, K1 ),
888: $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
889: $ 2, XNORM, IERR )
890: IF( IERR.NE.0 )
891: $ INFO = 1
892: *
893: IF( SCALOC.NE.ONE ) THEN
894: DO 220 J = 1, N
895: CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
896: 220 CONTINUE
897: SCALE = SCALE*SCALOC
898: END IF
899: C( K1, L1 ) = X( 1, 1 )
900: C( K1, L2 ) = X( 1, 2 )
901: C( K2, L1 ) = X( 2, 1 )
902: C( K2, L2 ) = X( 2, 2 )
903: END IF
904: *
905: 230 CONTINUE
906: 240 CONTINUE
907: *
908: END IF
909: *
910: RETURN
911: *
912: * End of DTRSYL
913: *
914: END
CVSweb interface <joel.bertrand@systella.fr>