Annotation of rpl/lapack/lapack/dtrexc.f, revision 1.8
1.8 ! bertrand 1: *> \brief \b DTREXC
! 2: *
! 3: * =========== DOCUMENTATION ===========
! 4: *
! 5: * Online html documentation available at
! 6: * http://www.netlib.org/lapack/explore-html/
! 7: *
! 8: *> \htmlonly
! 9: *> Download DTREXC + dependencies
! 10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtrexc.f">
! 11: *> [TGZ]</a>
! 12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtrexc.f">
! 13: *> [ZIP]</a>
! 14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrexc.f">
! 15: *> [TXT]</a>
! 16: *> \endhtmlonly
! 17: *
! 18: * Definition:
! 19: * ===========
! 20: *
! 21: * SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,
! 22: * INFO )
! 23: *
! 24: * .. Scalar Arguments ..
! 25: * CHARACTER COMPQ
! 26: * INTEGER IFST, ILST, INFO, LDQ, LDT, N
! 27: * ..
! 28: * .. Array Arguments ..
! 29: * DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * )
! 30: * ..
! 31: *
! 32: *
! 33: *> \par Purpose:
! 34: * =============
! 35: *>
! 36: *> \verbatim
! 37: *>
! 38: *> DTREXC reorders the real Schur factorization of a real matrix
! 39: *> A = Q*T*Q**T, so that the diagonal block of T with row index IFST is
! 40: *> moved to row ILST.
! 41: *>
! 42: *> The real Schur form T is reordered by an orthogonal similarity
! 43: *> transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors
! 44: *> is updated by postmultiplying it with Z.
! 45: *>
! 46: *> T must be in Schur canonical form (as returned by DHSEQR), that is,
! 47: *> block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each
! 48: *> 2-by-2 diagonal block has its diagonal elements equal and its
! 49: *> off-diagonal elements of opposite sign.
! 50: *> \endverbatim
! 51: *
! 52: * Arguments:
! 53: * ==========
! 54: *
! 55: *> \param[in] COMPQ
! 56: *> \verbatim
! 57: *> COMPQ is CHARACTER*1
! 58: *> = 'V': update the matrix Q of Schur vectors;
! 59: *> = 'N': do not update Q.
! 60: *> \endverbatim
! 61: *>
! 62: *> \param[in] N
! 63: *> \verbatim
! 64: *> N is INTEGER
! 65: *> The order of the matrix T. N >= 0.
! 66: *> \endverbatim
! 67: *>
! 68: *> \param[in,out] T
! 69: *> \verbatim
! 70: *> T is DOUBLE PRECISION array, dimension (LDT,N)
! 71: *> On entry, the upper quasi-triangular matrix T, in Schur
! 72: *> Schur canonical form.
! 73: *> On exit, the reordered upper quasi-triangular matrix, again
! 74: *> in Schur canonical form.
! 75: *> \endverbatim
! 76: *>
! 77: *> \param[in] LDT
! 78: *> \verbatim
! 79: *> LDT is INTEGER
! 80: *> The leading dimension of the array T. LDT >= max(1,N).
! 81: *> \endverbatim
! 82: *>
! 83: *> \param[in,out] Q
! 84: *> \verbatim
! 85: *> Q is DOUBLE PRECISION array, dimension (LDQ,N)
! 86: *> On entry, if COMPQ = 'V', the matrix Q of Schur vectors.
! 87: *> On exit, if COMPQ = 'V', Q has been postmultiplied by the
! 88: *> orthogonal transformation matrix Z which reorders T.
! 89: *> If COMPQ = 'N', Q is not referenced.
! 90: *> \endverbatim
! 91: *>
! 92: *> \param[in] LDQ
! 93: *> \verbatim
! 94: *> LDQ is INTEGER
! 95: *> The leading dimension of the array Q. LDQ >= max(1,N).
! 96: *> \endverbatim
! 97: *>
! 98: *> \param[in,out] IFST
! 99: *> \verbatim
! 100: *> IFST is INTEGER
! 101: *> \endverbatim
! 102: *>
! 103: *> \param[in,out] ILST
! 104: *> \verbatim
! 105: *> ILST is INTEGER
! 106: *>
! 107: *> Specify the reordering of the diagonal blocks of T.
! 108: *> The block with row index IFST is moved to row ILST, by a
! 109: *> sequence of transpositions between adjacent blocks.
! 110: *> On exit, if IFST pointed on entry to the second row of a
! 111: *> 2-by-2 block, it is changed to point to the first row; ILST
! 112: *> always points to the first row of the block in its final
! 113: *> position (which may differ from its input value by +1 or -1).
! 114: *> 1 <= IFST <= N; 1 <= ILST <= N.
! 115: *> \endverbatim
! 116: *>
! 117: *> \param[out] WORK
! 118: *> \verbatim
! 119: *> WORK is DOUBLE PRECISION array, dimension (N)
! 120: *> \endverbatim
! 121: *>
! 122: *> \param[out] INFO
! 123: *> \verbatim
! 124: *> INFO is INTEGER
! 125: *> = 0: successful exit
! 126: *> < 0: if INFO = -i, the i-th argument had an illegal value
! 127: *> = 1: two adjacent blocks were too close to swap (the problem
! 128: *> is very ill-conditioned); T may have been partially
! 129: *> reordered, and ILST points to the first row of the
! 130: *> current position of the block being moved.
! 131: *> \endverbatim
! 132: *
! 133: * Authors:
! 134: * ========
! 135: *
! 136: *> \author Univ. of Tennessee
! 137: *> \author Univ. of California Berkeley
! 138: *> \author Univ. of Colorado Denver
! 139: *> \author NAG Ltd.
! 140: *
! 141: *> \date November 2011
! 142: *
! 143: *> \ingroup doubleOTHERcomputational
! 144: *
! 145: * =====================================================================
1.1 bertrand 146: SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,
147: $ INFO )
148: *
1.8 ! bertrand 149: * -- LAPACK computational routine (version 3.4.0) --
1.1 bertrand 150: * -- LAPACK is a software package provided by Univ. of Tennessee, --
151: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.8 ! bertrand 152: * November 2011
1.1 bertrand 153: *
154: * .. Scalar Arguments ..
155: CHARACTER COMPQ
156: INTEGER IFST, ILST, INFO, LDQ, LDT, N
157: * ..
158: * .. Array Arguments ..
159: DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * )
160: * ..
161: *
162: * =====================================================================
163: *
164: * .. Parameters ..
165: DOUBLE PRECISION ZERO
166: PARAMETER ( ZERO = 0.0D+0 )
167: * ..
168: * .. Local Scalars ..
169: LOGICAL WANTQ
170: INTEGER HERE, NBF, NBL, NBNEXT
171: * ..
172: * .. External Functions ..
173: LOGICAL LSAME
174: EXTERNAL LSAME
175: * ..
176: * .. External Subroutines ..
177: EXTERNAL DLAEXC, XERBLA
178: * ..
179: * .. Intrinsic Functions ..
180: INTRINSIC MAX
181: * ..
182: * .. Executable Statements ..
183: *
184: * Decode and test the input arguments.
185: *
186: INFO = 0
187: WANTQ = LSAME( COMPQ, 'V' )
188: IF( .NOT.WANTQ .AND. .NOT.LSAME( COMPQ, 'N' ) ) THEN
189: INFO = -1
190: ELSE IF( N.LT.0 ) THEN
191: INFO = -2
192: ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
193: INFO = -4
194: ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.MAX( 1, N ) ) ) THEN
195: INFO = -6
196: ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
197: INFO = -7
198: ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
199: INFO = -8
200: END IF
201: IF( INFO.NE.0 ) THEN
202: CALL XERBLA( 'DTREXC', -INFO )
203: RETURN
204: END IF
205: *
206: * Quick return if possible
207: *
208: IF( N.LE.1 )
209: $ RETURN
210: *
211: * Determine the first row of specified block
212: * and find out it is 1 by 1 or 2 by 2.
213: *
214: IF( IFST.GT.1 ) THEN
215: IF( T( IFST, IFST-1 ).NE.ZERO )
216: $ IFST = IFST - 1
217: END IF
218: NBF = 1
219: IF( IFST.LT.N ) THEN
220: IF( T( IFST+1, IFST ).NE.ZERO )
221: $ NBF = 2
222: END IF
223: *
224: * Determine the first row of the final block
225: * and find out it is 1 by 1 or 2 by 2.
226: *
227: IF( ILST.GT.1 ) THEN
228: IF( T( ILST, ILST-1 ).NE.ZERO )
229: $ ILST = ILST - 1
230: END IF
231: NBL = 1
232: IF( ILST.LT.N ) THEN
233: IF( T( ILST+1, ILST ).NE.ZERO )
234: $ NBL = 2
235: END IF
236: *
237: IF( IFST.EQ.ILST )
238: $ RETURN
239: *
240: IF( IFST.LT.ILST ) THEN
241: *
242: * Update ILST
243: *
244: IF( NBF.EQ.2 .AND. NBL.EQ.1 )
245: $ ILST = ILST - 1
246: IF( NBF.EQ.1 .AND. NBL.EQ.2 )
247: $ ILST = ILST + 1
248: *
249: HERE = IFST
250: *
251: 10 CONTINUE
252: *
253: * Swap block with next one below
254: *
255: IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
256: *
257: * Current block either 1 by 1 or 2 by 2
258: *
259: NBNEXT = 1
260: IF( HERE+NBF+1.LE.N ) THEN
261: IF( T( HERE+NBF+1, HERE+NBF ).NE.ZERO )
262: $ NBNEXT = 2
263: END IF
264: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBF, NBNEXT,
265: $ WORK, INFO )
266: IF( INFO.NE.0 ) THEN
267: ILST = HERE
268: RETURN
269: END IF
270: HERE = HERE + NBNEXT
271: *
272: * Test if 2 by 2 block breaks into two 1 by 1 blocks
273: *
274: IF( NBF.EQ.2 ) THEN
275: IF( T( HERE+1, HERE ).EQ.ZERO )
276: $ NBF = 3
277: END IF
278: *
279: ELSE
280: *
281: * Current block consists of two 1 by 1 blocks each of which
282: * must be swapped individually
283: *
284: NBNEXT = 1
285: IF( HERE+3.LE.N ) THEN
286: IF( T( HERE+3, HERE+2 ).NE.ZERO )
287: $ NBNEXT = 2
288: END IF
289: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, NBNEXT,
290: $ WORK, INFO )
291: IF( INFO.NE.0 ) THEN
292: ILST = HERE
293: RETURN
294: END IF
295: IF( NBNEXT.EQ.1 ) THEN
296: *
297: * Swap two 1 by 1 blocks, no problems possible
298: *
299: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, NBNEXT,
300: $ WORK, INFO )
301: HERE = HERE + 1
302: ELSE
303: *
304: * Recompute NBNEXT in case 2 by 2 split
305: *
306: IF( T( HERE+2, HERE+1 ).EQ.ZERO )
307: $ NBNEXT = 1
308: IF( NBNEXT.EQ.2 ) THEN
309: *
310: * 2 by 2 Block did not split
311: *
312: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1,
313: $ NBNEXT, WORK, INFO )
314: IF( INFO.NE.0 ) THEN
315: ILST = HERE
316: RETURN
317: END IF
318: HERE = HERE + 2
319: ELSE
320: *
321: * 2 by 2 Block did split
322: *
323: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,
324: $ WORK, INFO )
325: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, 1,
326: $ WORK, INFO )
327: HERE = HERE + 2
328: END IF
329: END IF
330: END IF
331: IF( HERE.LT.ILST )
332: $ GO TO 10
333: *
334: ELSE
335: *
336: HERE = IFST
337: 20 CONTINUE
338: *
339: * Swap block with next one above
340: *
341: IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
342: *
343: * Current block either 1 by 1 or 2 by 2
344: *
345: NBNEXT = 1
346: IF( HERE.GE.3 ) THEN
347: IF( T( HERE-1, HERE-2 ).NE.ZERO )
348: $ NBNEXT = 2
349: END IF
350: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,
351: $ NBF, WORK, INFO )
352: IF( INFO.NE.0 ) THEN
353: ILST = HERE
354: RETURN
355: END IF
356: HERE = HERE - NBNEXT
357: *
358: * Test if 2 by 2 block breaks into two 1 by 1 blocks
359: *
360: IF( NBF.EQ.2 ) THEN
361: IF( T( HERE+1, HERE ).EQ.ZERO )
362: $ NBF = 3
363: END IF
364: *
365: ELSE
366: *
367: * Current block consists of two 1 by 1 blocks each of which
368: * must be swapped individually
369: *
370: NBNEXT = 1
371: IF( HERE.GE.3 ) THEN
372: IF( T( HERE-1, HERE-2 ).NE.ZERO )
373: $ NBNEXT = 2
374: END IF
375: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,
376: $ 1, WORK, INFO )
377: IF( INFO.NE.0 ) THEN
378: ILST = HERE
379: RETURN
380: END IF
381: IF( NBNEXT.EQ.1 ) THEN
382: *
383: * Swap two 1 by 1 blocks, no problems possible
384: *
385: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBNEXT, 1,
386: $ WORK, INFO )
387: HERE = HERE - 1
388: ELSE
389: *
390: * Recompute NBNEXT in case 2 by 2 split
391: *
392: IF( T( HERE, HERE-1 ).EQ.ZERO )
393: $ NBNEXT = 1
394: IF( NBNEXT.EQ.2 ) THEN
395: *
396: * 2 by 2 Block did not split
397: *
398: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 2, 1,
399: $ WORK, INFO )
400: IF( INFO.NE.0 ) THEN
401: ILST = HERE
402: RETURN
403: END IF
404: HERE = HERE - 2
405: ELSE
406: *
407: * 2 by 2 Block did split
408: *
409: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,
410: $ WORK, INFO )
411: CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 1, 1,
412: $ WORK, INFO )
413: HERE = HERE - 2
414: END IF
415: END IF
416: END IF
417: IF( HERE.GT.ILST )
418: $ GO TO 20
419: END IF
420: ILST = HERE
421: *
422: RETURN
423: *
424: * End of DTREXC
425: *
426: END
CVSweb interface <joel.bertrand@systella.fr>