1: SUBROUTINE DTGSY2( TRANS, IJOB, M, N, A, LDA, B, LDB, C, LDC, D,
2: $ LDD, E, LDE, F, LDF, SCALE, RDSUM, RDSCAL,
3: $ IWORK, PQ, INFO )
4: *
5: * -- LAPACK auxiliary routine (version 3.2) --
6: * -- LAPACK is a software package provided by Univ. of Tennessee, --
7: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
8: * January 2007
9: *
10: * .. Scalar Arguments ..
11: CHARACTER TRANS
12: INTEGER IJOB, INFO, LDA, LDB, LDC, LDD, LDE, LDF, M, N,
13: $ PQ
14: DOUBLE PRECISION RDSCAL, RDSUM, SCALE
15: * ..
16: * .. Array Arguments ..
17: INTEGER IWORK( * )
18: DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ),
19: $ D( LDD, * ), E( LDE, * ), F( LDF, * )
20: * ..
21: *
22: * Purpose
23: * =======
24: *
25: * DTGSY2 solves the generalized Sylvester equation:
26: *
27: * A * R - L * B = scale * C (1)
28: * D * R - L * E = scale * F,
29: *
30: * using Level 1 and 2 BLAS. where R and L are unknown M-by-N matrices,
31: * (A, D), (B, E) and (C, F) are given matrix pairs of size M-by-M,
32: * N-by-N and M-by-N, respectively, with real entries. (A, D) and (B, E)
33: * must be in generalized Schur canonical form, i.e. A, B are upper
34: * quasi triangular and D, E are upper triangular. The solution (R, L)
35: * overwrites (C, F). 0 <= SCALE <= 1 is an output scaling factor
36: * chosen to avoid overflow.
37: *
38: * In matrix notation solving equation (1) corresponds to solve
39: * Z*x = scale*b, where Z is defined as
40: *
41: * Z = [ kron(In, A) -kron(B', Im) ] (2)
42: * [ kron(In, D) -kron(E', Im) ],
43: *
44: * Ik is the identity matrix of size k and X' is the transpose of X.
45: * kron(X, Y) is the Kronecker product between the matrices X and Y.
46: * In the process of solving (1), we solve a number of such systems
47: * where Dim(In), Dim(In) = 1 or 2.
48: *
49: * If TRANS = 'T', solve the transposed system Z'*y = scale*b for y,
50: * which is equivalent to solve for R and L in
51: *
52: * A' * R + D' * L = scale * C (3)
53: * R * B' + L * E' = scale * -F
54: *
55: * This case is used to compute an estimate of Dif[(A, D), (B, E)] =
56: * sigma_min(Z) using reverse communicaton with DLACON.
57: *
58: * DTGSY2 also (IJOB >= 1) contributes to the computation in DTGSYL
59: * of an upper bound on the separation between to matrix pairs. Then
60: * the input (A, D), (B, E) are sub-pencils of the matrix pair in
61: * DTGSYL. See DTGSYL for details.
62: *
63: * Arguments
64: * =========
65: *
66: * TRANS (input) CHARACTER*1
67: * = 'N', solve the generalized Sylvester equation (1).
68: * = 'T': solve the 'transposed' system (3).
69: *
70: * IJOB (input) INTEGER
71: * Specifies what kind of functionality to be performed.
72: * = 0: solve (1) only.
73: * = 1: A contribution from this subsystem to a Frobenius
74: * norm-based estimate of the separation between two matrix
75: * pairs is computed. (look ahead strategy is used).
76: * = 2: A contribution from this subsystem to a Frobenius
77: * norm-based estimate of the separation between two matrix
78: * pairs is computed. (DGECON on sub-systems is used.)
79: * Not referenced if TRANS = 'T'.
80: *
81: * M (input) INTEGER
82: * On entry, M specifies the order of A and D, and the row
83: * dimension of C, F, R and L.
84: *
85: * N (input) INTEGER
86: * On entry, N specifies the order of B and E, and the column
87: * dimension of C, F, R and L.
88: *
89: * A (input) DOUBLE PRECISION array, dimension (LDA, M)
90: * On entry, A contains an upper quasi triangular matrix.
91: *
92: * LDA (input) INTEGER
93: * The leading dimension of the matrix A. LDA >= max(1, M).
94: *
95: * B (input) DOUBLE PRECISION array, dimension (LDB, N)
96: * On entry, B contains an upper quasi triangular matrix.
97: *
98: * LDB (input) INTEGER
99: * The leading dimension of the matrix B. LDB >= max(1, N).
100: *
101: * C (input/output) DOUBLE PRECISION array, dimension (LDC, N)
102: * On entry, C contains the right-hand-side of the first matrix
103: * equation in (1).
104: * On exit, if IJOB = 0, C has been overwritten by the
105: * solution R.
106: *
107: * LDC (input) INTEGER
108: * The leading dimension of the matrix C. LDC >= max(1, M).
109: *
110: * D (input) DOUBLE PRECISION array, dimension (LDD, M)
111: * On entry, D contains an upper triangular matrix.
112: *
113: * LDD (input) INTEGER
114: * The leading dimension of the matrix D. LDD >= max(1, M).
115: *
116: * E (input) DOUBLE PRECISION array, dimension (LDE, N)
117: * On entry, E contains an upper triangular matrix.
118: *
119: * LDE (input) INTEGER
120: * The leading dimension of the matrix E. LDE >= max(1, N).
121: *
122: * F (input/output) DOUBLE PRECISION array, dimension (LDF, N)
123: * On entry, F contains the right-hand-side of the second matrix
124: * equation in (1).
125: * On exit, if IJOB = 0, F has been overwritten by the
126: * solution L.
127: *
128: * LDF (input) INTEGER
129: * The leading dimension of the matrix F. LDF >= max(1, M).
130: *
131: * SCALE (output) DOUBLE PRECISION
132: * On exit, 0 <= SCALE <= 1. If 0 < SCALE < 1, the solutions
133: * R and L (C and F on entry) will hold the solutions to a
134: * slightly perturbed system but the input matrices A, B, D and
135: * E have not been changed. If SCALE = 0, R and L will hold the
136: * solutions to the homogeneous system with C = F = 0. Normally,
137: * SCALE = 1.
138: *
139: * RDSUM (input/output) DOUBLE PRECISION
140: * On entry, the sum of squares of computed contributions to
141: * the Dif-estimate under computation by DTGSYL, where the
142: * scaling factor RDSCAL (see below) has been factored out.
143: * On exit, the corresponding sum of squares updated with the
144: * contributions from the current sub-system.
145: * If TRANS = 'T' RDSUM is not touched.
146: * NOTE: RDSUM only makes sense when DTGSY2 is called by DTGSYL.
147: *
148: * RDSCAL (input/output) DOUBLE PRECISION
149: * On entry, scaling factor used to prevent overflow in RDSUM.
150: * On exit, RDSCAL is updated w.r.t. the current contributions
151: * in RDSUM.
152: * If TRANS = 'T', RDSCAL is not touched.
153: * NOTE: RDSCAL only makes sense when DTGSY2 is called by
154: * DTGSYL.
155: *
156: * IWORK (workspace) INTEGER array, dimension (M+N+2)
157: *
158: * PQ (output) INTEGER
159: * On exit, the number of subsystems (of size 2-by-2, 4-by-4 and
160: * 8-by-8) solved by this routine.
161: *
162: * INFO (output) INTEGER
163: * On exit, if INFO is set to
164: * =0: Successful exit
165: * <0: If INFO = -i, the i-th argument had an illegal value.
166: * >0: The matrix pairs (A, D) and (B, E) have common or very
167: * close eigenvalues.
168: *
169: * Further Details
170: * ===============
171: *
172: * Based on contributions by
173: * Bo Kagstrom and Peter Poromaa, Department of Computing Science,
174: * Umea University, S-901 87 Umea, Sweden.
175: *
176: * =====================================================================
177: * Replaced various illegal calls to DCOPY by calls to DLASET.
178: * Sven Hammarling, 27/5/02.
179: *
180: * .. Parameters ..
181: INTEGER LDZ
182: PARAMETER ( LDZ = 8 )
183: DOUBLE PRECISION ZERO, ONE
184: PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
185: * ..
186: * .. Local Scalars ..
187: LOGICAL NOTRAN
188: INTEGER I, IE, IERR, II, IS, ISP1, J, JE, JJ, JS, JSP1,
189: $ K, MB, NB, P, Q, ZDIM
190: DOUBLE PRECISION ALPHA, SCALOC
191: * ..
192: * .. Local Arrays ..
193: INTEGER IPIV( LDZ ), JPIV( LDZ )
194: DOUBLE PRECISION RHS( LDZ ), Z( LDZ, LDZ )
195: * ..
196: * .. External Functions ..
197: LOGICAL LSAME
198: EXTERNAL LSAME
199: * ..
200: * .. External Subroutines ..
201: EXTERNAL DAXPY, DCOPY, DGEMM, DGEMV, DGER, DGESC2,
202: $ DGETC2, DLASET, DLATDF, DSCAL, XERBLA
203: * ..
204: * .. Intrinsic Functions ..
205: INTRINSIC MAX
206: * ..
207: * .. Executable Statements ..
208: *
209: * Decode and test input parameters
210: *
211: INFO = 0
212: IERR = 0
213: NOTRAN = LSAME( TRANS, 'N' )
214: IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
215: INFO = -1
216: ELSE IF( NOTRAN ) THEN
217: IF( ( IJOB.LT.0 ) .OR. ( IJOB.GT.2 ) ) THEN
218: INFO = -2
219: END IF
220: END IF
221: IF( INFO.EQ.0 ) THEN
222: IF( M.LE.0 ) THEN
223: INFO = -3
224: ELSE IF( N.LE.0 ) THEN
225: INFO = -4
226: ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
227: INFO = -5
228: ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
229: INFO = -8
230: ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
231: INFO = -10
232: ELSE IF( LDD.LT.MAX( 1, M ) ) THEN
233: INFO = -12
234: ELSE IF( LDE.LT.MAX( 1, N ) ) THEN
235: INFO = -14
236: ELSE IF( LDF.LT.MAX( 1, M ) ) THEN
237: INFO = -16
238: END IF
239: END IF
240: IF( INFO.NE.0 ) THEN
241: CALL XERBLA( 'DTGSY2', -INFO )
242: RETURN
243: END IF
244: *
245: * Determine block structure of A
246: *
247: PQ = 0
248: P = 0
249: I = 1
250: 10 CONTINUE
251: IF( I.GT.M )
252: $ GO TO 20
253: P = P + 1
254: IWORK( P ) = I
255: IF( I.EQ.M )
256: $ GO TO 20
257: IF( A( I+1, I ).NE.ZERO ) THEN
258: I = I + 2
259: ELSE
260: I = I + 1
261: END IF
262: GO TO 10
263: 20 CONTINUE
264: IWORK( P+1 ) = M + 1
265: *
266: * Determine block structure of B
267: *
268: Q = P + 1
269: J = 1
270: 30 CONTINUE
271: IF( J.GT.N )
272: $ GO TO 40
273: Q = Q + 1
274: IWORK( Q ) = J
275: IF( J.EQ.N )
276: $ GO TO 40
277: IF( B( J+1, J ).NE.ZERO ) THEN
278: J = J + 2
279: ELSE
280: J = J + 1
281: END IF
282: GO TO 30
283: 40 CONTINUE
284: IWORK( Q+1 ) = N + 1
285: PQ = P*( Q-P-1 )
286: *
287: IF( NOTRAN ) THEN
288: *
289: * Solve (I, J) - subsystem
290: * A(I, I) * R(I, J) - L(I, J) * B(J, J) = C(I, J)
291: * D(I, I) * R(I, J) - L(I, J) * E(J, J) = F(I, J)
292: * for I = P, P - 1, ..., 1; J = 1, 2, ..., Q
293: *
294: SCALE = ONE
295: SCALOC = ONE
296: DO 120 J = P + 2, Q
297: JS = IWORK( J )
298: JSP1 = JS + 1
299: JE = IWORK( J+1 ) - 1
300: NB = JE - JS + 1
301: DO 110 I = P, 1, -1
302: *
303: IS = IWORK( I )
304: ISP1 = IS + 1
305: IE = IWORK( I+1 ) - 1
306: MB = IE - IS + 1
307: ZDIM = MB*NB*2
308: *
309: IF( ( MB.EQ.1 ) .AND. ( NB.EQ.1 ) ) THEN
310: *
311: * Build a 2-by-2 system Z * x = RHS
312: *
313: Z( 1, 1 ) = A( IS, IS )
314: Z( 2, 1 ) = D( IS, IS )
315: Z( 1, 2 ) = -B( JS, JS )
316: Z( 2, 2 ) = -E( JS, JS )
317: *
318: * Set up right hand side(s)
319: *
320: RHS( 1 ) = C( IS, JS )
321: RHS( 2 ) = F( IS, JS )
322: *
323: * Solve Z * x = RHS
324: *
325: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
326: IF( IERR.GT.0 )
327: $ INFO = IERR
328: *
329: IF( IJOB.EQ.0 ) THEN
330: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV,
331: $ SCALOC )
332: IF( SCALOC.NE.ONE ) THEN
333: DO 50 K = 1, N
334: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
335: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
336: 50 CONTINUE
337: SCALE = SCALE*SCALOC
338: END IF
339: ELSE
340: CALL DLATDF( IJOB, ZDIM, Z, LDZ, RHS, RDSUM,
341: $ RDSCAL, IPIV, JPIV )
342: END IF
343: *
344: * Unpack solution vector(s)
345: *
346: C( IS, JS ) = RHS( 1 )
347: F( IS, JS ) = RHS( 2 )
348: *
349: * Substitute R(I, J) and L(I, J) into remaining
350: * equation.
351: *
352: IF( I.GT.1 ) THEN
353: ALPHA = -RHS( 1 )
354: CALL DAXPY( IS-1, ALPHA, A( 1, IS ), 1, C( 1, JS ),
355: $ 1 )
356: CALL DAXPY( IS-1, ALPHA, D( 1, IS ), 1, F( 1, JS ),
357: $ 1 )
358: END IF
359: IF( J.LT.Q ) THEN
360: CALL DAXPY( N-JE, RHS( 2 ), B( JS, JE+1 ), LDB,
361: $ C( IS, JE+1 ), LDC )
362: CALL DAXPY( N-JE, RHS( 2 ), E( JS, JE+1 ), LDE,
363: $ F( IS, JE+1 ), LDF )
364: END IF
365: *
366: ELSE IF( ( MB.EQ.1 ) .AND. ( NB.EQ.2 ) ) THEN
367: *
368: * Build a 4-by-4 system Z * x = RHS
369: *
370: Z( 1, 1 ) = A( IS, IS )
371: Z( 2, 1 ) = ZERO
372: Z( 3, 1 ) = D( IS, IS )
373: Z( 4, 1 ) = ZERO
374: *
375: Z( 1, 2 ) = ZERO
376: Z( 2, 2 ) = A( IS, IS )
377: Z( 3, 2 ) = ZERO
378: Z( 4, 2 ) = D( IS, IS )
379: *
380: Z( 1, 3 ) = -B( JS, JS )
381: Z( 2, 3 ) = -B( JS, JSP1 )
382: Z( 3, 3 ) = -E( JS, JS )
383: Z( 4, 3 ) = -E( JS, JSP1 )
384: *
385: Z( 1, 4 ) = -B( JSP1, JS )
386: Z( 2, 4 ) = -B( JSP1, JSP1 )
387: Z( 3, 4 ) = ZERO
388: Z( 4, 4 ) = -E( JSP1, JSP1 )
389: *
390: * Set up right hand side(s)
391: *
392: RHS( 1 ) = C( IS, JS )
393: RHS( 2 ) = C( IS, JSP1 )
394: RHS( 3 ) = F( IS, JS )
395: RHS( 4 ) = F( IS, JSP1 )
396: *
397: * Solve Z * x = RHS
398: *
399: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
400: IF( IERR.GT.0 )
401: $ INFO = IERR
402: *
403: IF( IJOB.EQ.0 ) THEN
404: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV,
405: $ SCALOC )
406: IF( SCALOC.NE.ONE ) THEN
407: DO 60 K = 1, N
408: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
409: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
410: 60 CONTINUE
411: SCALE = SCALE*SCALOC
412: END IF
413: ELSE
414: CALL DLATDF( IJOB, ZDIM, Z, LDZ, RHS, RDSUM,
415: $ RDSCAL, IPIV, JPIV )
416: END IF
417: *
418: * Unpack solution vector(s)
419: *
420: C( IS, JS ) = RHS( 1 )
421: C( IS, JSP1 ) = RHS( 2 )
422: F( IS, JS ) = RHS( 3 )
423: F( IS, JSP1 ) = RHS( 4 )
424: *
425: * Substitute R(I, J) and L(I, J) into remaining
426: * equation.
427: *
428: IF( I.GT.1 ) THEN
429: CALL DGER( IS-1, NB, -ONE, A( 1, IS ), 1, RHS( 1 ),
430: $ 1, C( 1, JS ), LDC )
431: CALL DGER( IS-1, NB, -ONE, D( 1, IS ), 1, RHS( 1 ),
432: $ 1, F( 1, JS ), LDF )
433: END IF
434: IF( J.LT.Q ) THEN
435: CALL DAXPY( N-JE, RHS( 3 ), B( JS, JE+1 ), LDB,
436: $ C( IS, JE+1 ), LDC )
437: CALL DAXPY( N-JE, RHS( 3 ), E( JS, JE+1 ), LDE,
438: $ F( IS, JE+1 ), LDF )
439: CALL DAXPY( N-JE, RHS( 4 ), B( JSP1, JE+1 ), LDB,
440: $ C( IS, JE+1 ), LDC )
441: CALL DAXPY( N-JE, RHS( 4 ), E( JSP1, JE+1 ), LDE,
442: $ F( IS, JE+1 ), LDF )
443: END IF
444: *
445: ELSE IF( ( MB.EQ.2 ) .AND. ( NB.EQ.1 ) ) THEN
446: *
447: * Build a 4-by-4 system Z * x = RHS
448: *
449: Z( 1, 1 ) = A( IS, IS )
450: Z( 2, 1 ) = A( ISP1, IS )
451: Z( 3, 1 ) = D( IS, IS )
452: Z( 4, 1 ) = ZERO
453: *
454: Z( 1, 2 ) = A( IS, ISP1 )
455: Z( 2, 2 ) = A( ISP1, ISP1 )
456: Z( 3, 2 ) = D( IS, ISP1 )
457: Z( 4, 2 ) = D( ISP1, ISP1 )
458: *
459: Z( 1, 3 ) = -B( JS, JS )
460: Z( 2, 3 ) = ZERO
461: Z( 3, 3 ) = -E( JS, JS )
462: Z( 4, 3 ) = ZERO
463: *
464: Z( 1, 4 ) = ZERO
465: Z( 2, 4 ) = -B( JS, JS )
466: Z( 3, 4 ) = ZERO
467: Z( 4, 4 ) = -E( JS, JS )
468: *
469: * Set up right hand side(s)
470: *
471: RHS( 1 ) = C( IS, JS )
472: RHS( 2 ) = C( ISP1, JS )
473: RHS( 3 ) = F( IS, JS )
474: RHS( 4 ) = F( ISP1, JS )
475: *
476: * Solve Z * x = RHS
477: *
478: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
479: IF( IERR.GT.0 )
480: $ INFO = IERR
481: IF( IJOB.EQ.0 ) THEN
482: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV,
483: $ SCALOC )
484: IF( SCALOC.NE.ONE ) THEN
485: DO 70 K = 1, N
486: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
487: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
488: 70 CONTINUE
489: SCALE = SCALE*SCALOC
490: END IF
491: ELSE
492: CALL DLATDF( IJOB, ZDIM, Z, LDZ, RHS, RDSUM,
493: $ RDSCAL, IPIV, JPIV )
494: END IF
495: *
496: * Unpack solution vector(s)
497: *
498: C( IS, JS ) = RHS( 1 )
499: C( ISP1, JS ) = RHS( 2 )
500: F( IS, JS ) = RHS( 3 )
501: F( ISP1, JS ) = RHS( 4 )
502: *
503: * Substitute R(I, J) and L(I, J) into remaining
504: * equation.
505: *
506: IF( I.GT.1 ) THEN
507: CALL DGEMV( 'N', IS-1, MB, -ONE, A( 1, IS ), LDA,
508: $ RHS( 1 ), 1, ONE, C( 1, JS ), 1 )
509: CALL DGEMV( 'N', IS-1, MB, -ONE, D( 1, IS ), LDD,
510: $ RHS( 1 ), 1, ONE, F( 1, JS ), 1 )
511: END IF
512: IF( J.LT.Q ) THEN
513: CALL DGER( MB, N-JE, ONE, RHS( 3 ), 1,
514: $ B( JS, JE+1 ), LDB, C( IS, JE+1 ), LDC )
515: CALL DGER( MB, N-JE, ONE, RHS( 3 ), 1,
516: $ E( JS, JE+1 ), LDE, F( IS, JE+1 ), LDF )
517: END IF
518: *
519: ELSE IF( ( MB.EQ.2 ) .AND. ( NB.EQ.2 ) ) THEN
520: *
521: * Build an 8-by-8 system Z * x = RHS
522: *
523: CALL DLASET( 'F', LDZ, LDZ, ZERO, ZERO, Z, LDZ )
524: *
525: Z( 1, 1 ) = A( IS, IS )
526: Z( 2, 1 ) = A( ISP1, IS )
527: Z( 5, 1 ) = D( IS, IS )
528: *
529: Z( 1, 2 ) = A( IS, ISP1 )
530: Z( 2, 2 ) = A( ISP1, ISP1 )
531: Z( 5, 2 ) = D( IS, ISP1 )
532: Z( 6, 2 ) = D( ISP1, ISP1 )
533: *
534: Z( 3, 3 ) = A( IS, IS )
535: Z( 4, 3 ) = A( ISP1, IS )
536: Z( 7, 3 ) = D( IS, IS )
537: *
538: Z( 3, 4 ) = A( IS, ISP1 )
539: Z( 4, 4 ) = A( ISP1, ISP1 )
540: Z( 7, 4 ) = D( IS, ISP1 )
541: Z( 8, 4 ) = D( ISP1, ISP1 )
542: *
543: Z( 1, 5 ) = -B( JS, JS )
544: Z( 3, 5 ) = -B( JS, JSP1 )
545: Z( 5, 5 ) = -E( JS, JS )
546: Z( 7, 5 ) = -E( JS, JSP1 )
547: *
548: Z( 2, 6 ) = -B( JS, JS )
549: Z( 4, 6 ) = -B( JS, JSP1 )
550: Z( 6, 6 ) = -E( JS, JS )
551: Z( 8, 6 ) = -E( JS, JSP1 )
552: *
553: Z( 1, 7 ) = -B( JSP1, JS )
554: Z( 3, 7 ) = -B( JSP1, JSP1 )
555: Z( 7, 7 ) = -E( JSP1, JSP1 )
556: *
557: Z( 2, 8 ) = -B( JSP1, JS )
558: Z( 4, 8 ) = -B( JSP1, JSP1 )
559: Z( 8, 8 ) = -E( JSP1, JSP1 )
560: *
561: * Set up right hand side(s)
562: *
563: K = 1
564: II = MB*NB + 1
565: DO 80 JJ = 0, NB - 1
566: CALL DCOPY( MB, C( IS, JS+JJ ), 1, RHS( K ), 1 )
567: CALL DCOPY( MB, F( IS, JS+JJ ), 1, RHS( II ), 1 )
568: K = K + MB
569: II = II + MB
570: 80 CONTINUE
571: *
572: * Solve Z * x = RHS
573: *
574: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
575: IF( IERR.GT.0 )
576: $ INFO = IERR
577: IF( IJOB.EQ.0 ) THEN
578: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV,
579: $ SCALOC )
580: IF( SCALOC.NE.ONE ) THEN
581: DO 90 K = 1, N
582: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
583: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
584: 90 CONTINUE
585: SCALE = SCALE*SCALOC
586: END IF
587: ELSE
588: CALL DLATDF( IJOB, ZDIM, Z, LDZ, RHS, RDSUM,
589: $ RDSCAL, IPIV, JPIV )
590: END IF
591: *
592: * Unpack solution vector(s)
593: *
594: K = 1
595: II = MB*NB + 1
596: DO 100 JJ = 0, NB - 1
597: CALL DCOPY( MB, RHS( K ), 1, C( IS, JS+JJ ), 1 )
598: CALL DCOPY( MB, RHS( II ), 1, F( IS, JS+JJ ), 1 )
599: K = K + MB
600: II = II + MB
601: 100 CONTINUE
602: *
603: * Substitute R(I, J) and L(I, J) into remaining
604: * equation.
605: *
606: IF( I.GT.1 ) THEN
607: CALL DGEMM( 'N', 'N', IS-1, NB, MB, -ONE,
608: $ A( 1, IS ), LDA, RHS( 1 ), MB, ONE,
609: $ C( 1, JS ), LDC )
610: CALL DGEMM( 'N', 'N', IS-1, NB, MB, -ONE,
611: $ D( 1, IS ), LDD, RHS( 1 ), MB, ONE,
612: $ F( 1, JS ), LDF )
613: END IF
614: IF( J.LT.Q ) THEN
615: K = MB*NB + 1
616: CALL DGEMM( 'N', 'N', MB, N-JE, NB, ONE, RHS( K ),
617: $ MB, B( JS, JE+1 ), LDB, ONE,
618: $ C( IS, JE+1 ), LDC )
619: CALL DGEMM( 'N', 'N', MB, N-JE, NB, ONE, RHS( K ),
620: $ MB, E( JS, JE+1 ), LDE, ONE,
621: $ F( IS, JE+1 ), LDF )
622: END IF
623: *
624: END IF
625: *
626: 110 CONTINUE
627: 120 CONTINUE
628: ELSE
629: *
630: * Solve (I, J) - subsystem
631: * A(I, I)' * R(I, J) + D(I, I)' * L(J, J) = C(I, J)
632: * R(I, I) * B(J, J) + L(I, J) * E(J, J) = -F(I, J)
633: * for I = 1, 2, ..., P, J = Q, Q - 1, ..., 1
634: *
635: SCALE = ONE
636: SCALOC = ONE
637: DO 200 I = 1, P
638: *
639: IS = IWORK( I )
640: ISP1 = IS + 1
641: IE = IWORK ( I+1 ) - 1
642: MB = IE - IS + 1
643: DO 190 J = Q, P + 2, -1
644: *
645: JS = IWORK( J )
646: JSP1 = JS + 1
647: JE = IWORK( J+1 ) - 1
648: NB = JE - JS + 1
649: ZDIM = MB*NB*2
650: IF( ( MB.EQ.1 ) .AND. ( NB.EQ.1 ) ) THEN
651: *
652: * Build a 2-by-2 system Z' * x = RHS
653: *
654: Z( 1, 1 ) = A( IS, IS )
655: Z( 2, 1 ) = -B( JS, JS )
656: Z( 1, 2 ) = D( IS, IS )
657: Z( 2, 2 ) = -E( JS, JS )
658: *
659: * Set up right hand side(s)
660: *
661: RHS( 1 ) = C( IS, JS )
662: RHS( 2 ) = F( IS, JS )
663: *
664: * Solve Z' * x = RHS
665: *
666: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
667: IF( IERR.GT.0 )
668: $ INFO = IERR
669: *
670: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV, SCALOC )
671: IF( SCALOC.NE.ONE ) THEN
672: DO 130 K = 1, N
673: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
674: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
675: 130 CONTINUE
676: SCALE = SCALE*SCALOC
677: END IF
678: *
679: * Unpack solution vector(s)
680: *
681: C( IS, JS ) = RHS( 1 )
682: F( IS, JS ) = RHS( 2 )
683: *
684: * Substitute R(I, J) and L(I, J) into remaining
685: * equation.
686: *
687: IF( J.GT.P+2 ) THEN
688: ALPHA = RHS( 1 )
689: CALL DAXPY( JS-1, ALPHA, B( 1, JS ), 1, F( IS, 1 ),
690: $ LDF )
691: ALPHA = RHS( 2 )
692: CALL DAXPY( JS-1, ALPHA, E( 1, JS ), 1, F( IS, 1 ),
693: $ LDF )
694: END IF
695: IF( I.LT.P ) THEN
696: ALPHA = -RHS( 1 )
697: CALL DAXPY( M-IE, ALPHA, A( IS, IE+1 ), LDA,
698: $ C( IE+1, JS ), 1 )
699: ALPHA = -RHS( 2 )
700: CALL DAXPY( M-IE, ALPHA, D( IS, IE+1 ), LDD,
701: $ C( IE+1, JS ), 1 )
702: END IF
703: *
704: ELSE IF( ( MB.EQ.1 ) .AND. ( NB.EQ.2 ) ) THEN
705: *
706: * Build a 4-by-4 system Z' * x = RHS
707: *
708: Z( 1, 1 ) = A( IS, IS )
709: Z( 2, 1 ) = ZERO
710: Z( 3, 1 ) = -B( JS, JS )
711: Z( 4, 1 ) = -B( JSP1, JS )
712: *
713: Z( 1, 2 ) = ZERO
714: Z( 2, 2 ) = A( IS, IS )
715: Z( 3, 2 ) = -B( JS, JSP1 )
716: Z( 4, 2 ) = -B( JSP1, JSP1 )
717: *
718: Z( 1, 3 ) = D( IS, IS )
719: Z( 2, 3 ) = ZERO
720: Z( 3, 3 ) = -E( JS, JS )
721: Z( 4, 3 ) = ZERO
722: *
723: Z( 1, 4 ) = ZERO
724: Z( 2, 4 ) = D( IS, IS )
725: Z( 3, 4 ) = -E( JS, JSP1 )
726: Z( 4, 4 ) = -E( JSP1, JSP1 )
727: *
728: * Set up right hand side(s)
729: *
730: RHS( 1 ) = C( IS, JS )
731: RHS( 2 ) = C( IS, JSP1 )
732: RHS( 3 ) = F( IS, JS )
733: RHS( 4 ) = F( IS, JSP1 )
734: *
735: * Solve Z' * x = RHS
736: *
737: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
738: IF( IERR.GT.0 )
739: $ INFO = IERR
740: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV, SCALOC )
741: IF( SCALOC.NE.ONE ) THEN
742: DO 140 K = 1, N
743: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
744: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
745: 140 CONTINUE
746: SCALE = SCALE*SCALOC
747: END IF
748: *
749: * Unpack solution vector(s)
750: *
751: C( IS, JS ) = RHS( 1 )
752: C( IS, JSP1 ) = RHS( 2 )
753: F( IS, JS ) = RHS( 3 )
754: F( IS, JSP1 ) = RHS( 4 )
755: *
756: * Substitute R(I, J) and L(I, J) into remaining
757: * equation.
758: *
759: IF( J.GT.P+2 ) THEN
760: CALL DAXPY( JS-1, RHS( 1 ), B( 1, JS ), 1,
761: $ F( IS, 1 ), LDF )
762: CALL DAXPY( JS-1, RHS( 2 ), B( 1, JSP1 ), 1,
763: $ F( IS, 1 ), LDF )
764: CALL DAXPY( JS-1, RHS( 3 ), E( 1, JS ), 1,
765: $ F( IS, 1 ), LDF )
766: CALL DAXPY( JS-1, RHS( 4 ), E( 1, JSP1 ), 1,
767: $ F( IS, 1 ), LDF )
768: END IF
769: IF( I.LT.P ) THEN
770: CALL DGER( M-IE, NB, -ONE, A( IS, IE+1 ), LDA,
771: $ RHS( 1 ), 1, C( IE+1, JS ), LDC )
772: CALL DGER( M-IE, NB, -ONE, D( IS, IE+1 ), LDD,
773: $ RHS( 3 ), 1, C( IE+1, JS ), LDC )
774: END IF
775: *
776: ELSE IF( ( MB.EQ.2 ) .AND. ( NB.EQ.1 ) ) THEN
777: *
778: * Build a 4-by-4 system Z' * x = RHS
779: *
780: Z( 1, 1 ) = A( IS, IS )
781: Z( 2, 1 ) = A( IS, ISP1 )
782: Z( 3, 1 ) = -B( JS, JS )
783: Z( 4, 1 ) = ZERO
784: *
785: Z( 1, 2 ) = A( ISP1, IS )
786: Z( 2, 2 ) = A( ISP1, ISP1 )
787: Z( 3, 2 ) = ZERO
788: Z( 4, 2 ) = -B( JS, JS )
789: *
790: Z( 1, 3 ) = D( IS, IS )
791: Z( 2, 3 ) = D( IS, ISP1 )
792: Z( 3, 3 ) = -E( JS, JS )
793: Z( 4, 3 ) = ZERO
794: *
795: Z( 1, 4 ) = ZERO
796: Z( 2, 4 ) = D( ISP1, ISP1 )
797: Z( 3, 4 ) = ZERO
798: Z( 4, 4 ) = -E( JS, JS )
799: *
800: * Set up right hand side(s)
801: *
802: RHS( 1 ) = C( IS, JS )
803: RHS( 2 ) = C( ISP1, JS )
804: RHS( 3 ) = F( IS, JS )
805: RHS( 4 ) = F( ISP1, JS )
806: *
807: * Solve Z' * x = RHS
808: *
809: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
810: IF( IERR.GT.0 )
811: $ INFO = IERR
812: *
813: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV, SCALOC )
814: IF( SCALOC.NE.ONE ) THEN
815: DO 150 K = 1, N
816: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
817: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
818: 150 CONTINUE
819: SCALE = SCALE*SCALOC
820: END IF
821: *
822: * Unpack solution vector(s)
823: *
824: C( IS, JS ) = RHS( 1 )
825: C( ISP1, JS ) = RHS( 2 )
826: F( IS, JS ) = RHS( 3 )
827: F( ISP1, JS ) = RHS( 4 )
828: *
829: * Substitute R(I, J) and L(I, J) into remaining
830: * equation.
831: *
832: IF( J.GT.P+2 ) THEN
833: CALL DGER( MB, JS-1, ONE, RHS( 1 ), 1, B( 1, JS ),
834: $ 1, F( IS, 1 ), LDF )
835: CALL DGER( MB, JS-1, ONE, RHS( 3 ), 1, E( 1, JS ),
836: $ 1, F( IS, 1 ), LDF )
837: END IF
838: IF( I.LT.P ) THEN
839: CALL DGEMV( 'T', MB, M-IE, -ONE, A( IS, IE+1 ),
840: $ LDA, RHS( 1 ), 1, ONE, C( IE+1, JS ),
841: $ 1 )
842: CALL DGEMV( 'T', MB, M-IE, -ONE, D( IS, IE+1 ),
843: $ LDD, RHS( 3 ), 1, ONE, C( IE+1, JS ),
844: $ 1 )
845: END IF
846: *
847: ELSE IF( ( MB.EQ.2 ) .AND. ( NB.EQ.2 ) ) THEN
848: *
849: * Build an 8-by-8 system Z' * x = RHS
850: *
851: CALL DLASET( 'F', LDZ, LDZ, ZERO, ZERO, Z, LDZ )
852: *
853: Z( 1, 1 ) = A( IS, IS )
854: Z( 2, 1 ) = A( IS, ISP1 )
855: Z( 5, 1 ) = -B( JS, JS )
856: Z( 7, 1 ) = -B( JSP1, JS )
857: *
858: Z( 1, 2 ) = A( ISP1, IS )
859: Z( 2, 2 ) = A( ISP1, ISP1 )
860: Z( 6, 2 ) = -B( JS, JS )
861: Z( 8, 2 ) = -B( JSP1, JS )
862: *
863: Z( 3, 3 ) = A( IS, IS )
864: Z( 4, 3 ) = A( IS, ISP1 )
865: Z( 5, 3 ) = -B( JS, JSP1 )
866: Z( 7, 3 ) = -B( JSP1, JSP1 )
867: *
868: Z( 3, 4 ) = A( ISP1, IS )
869: Z( 4, 4 ) = A( ISP1, ISP1 )
870: Z( 6, 4 ) = -B( JS, JSP1 )
871: Z( 8, 4 ) = -B( JSP1, JSP1 )
872: *
873: Z( 1, 5 ) = D( IS, IS )
874: Z( 2, 5 ) = D( IS, ISP1 )
875: Z( 5, 5 ) = -E( JS, JS )
876: *
877: Z( 2, 6 ) = D( ISP1, ISP1 )
878: Z( 6, 6 ) = -E( JS, JS )
879: *
880: Z( 3, 7 ) = D( IS, IS )
881: Z( 4, 7 ) = D( IS, ISP1 )
882: Z( 5, 7 ) = -E( JS, JSP1 )
883: Z( 7, 7 ) = -E( JSP1, JSP1 )
884: *
885: Z( 4, 8 ) = D( ISP1, ISP1 )
886: Z( 6, 8 ) = -E( JS, JSP1 )
887: Z( 8, 8 ) = -E( JSP1, JSP1 )
888: *
889: * Set up right hand side(s)
890: *
891: K = 1
892: II = MB*NB + 1
893: DO 160 JJ = 0, NB - 1
894: CALL DCOPY( MB, C( IS, JS+JJ ), 1, RHS( K ), 1 )
895: CALL DCOPY( MB, F( IS, JS+JJ ), 1, RHS( II ), 1 )
896: K = K + MB
897: II = II + MB
898: 160 CONTINUE
899: *
900: *
901: * Solve Z' * x = RHS
902: *
903: CALL DGETC2( ZDIM, Z, LDZ, IPIV, JPIV, IERR )
904: IF( IERR.GT.0 )
905: $ INFO = IERR
906: *
907: CALL DGESC2( ZDIM, Z, LDZ, RHS, IPIV, JPIV, SCALOC )
908: IF( SCALOC.NE.ONE ) THEN
909: DO 170 K = 1, N
910: CALL DSCAL( M, SCALOC, C( 1, K ), 1 )
911: CALL DSCAL( M, SCALOC, F( 1, K ), 1 )
912: 170 CONTINUE
913: SCALE = SCALE*SCALOC
914: END IF
915: *
916: * Unpack solution vector(s)
917: *
918: K = 1
919: II = MB*NB + 1
920: DO 180 JJ = 0, NB - 1
921: CALL DCOPY( MB, RHS( K ), 1, C( IS, JS+JJ ), 1 )
922: CALL DCOPY( MB, RHS( II ), 1, F( IS, JS+JJ ), 1 )
923: K = K + MB
924: II = II + MB
925: 180 CONTINUE
926: *
927: * Substitute R(I, J) and L(I, J) into remaining
928: * equation.
929: *
930: IF( J.GT.P+2 ) THEN
931: CALL DGEMM( 'N', 'T', MB, JS-1, NB, ONE,
932: $ C( IS, JS ), LDC, B( 1, JS ), LDB, ONE,
933: $ F( IS, 1 ), LDF )
934: CALL DGEMM( 'N', 'T', MB, JS-1, NB, ONE,
935: $ F( IS, JS ), LDF, E( 1, JS ), LDE, ONE,
936: $ F( IS, 1 ), LDF )
937: END IF
938: IF( I.LT.P ) THEN
939: CALL DGEMM( 'T', 'N', M-IE, NB, MB, -ONE,
940: $ A( IS, IE+1 ), LDA, C( IS, JS ), LDC,
941: $ ONE, C( IE+1, JS ), LDC )
942: CALL DGEMM( 'T', 'N', M-IE, NB, MB, -ONE,
943: $ D( IS, IE+1 ), LDD, F( IS, JS ), LDF,
944: $ ONE, C( IE+1, JS ), LDC )
945: END IF
946: *
947: END IF
948: *
949: 190 CONTINUE
950: 200 CONTINUE
951: *
952: END IF
953: RETURN
954: *
955: * End of DTGSY2
956: *
957: END
CVSweb interface <joel.bertrand@systella.fr>