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