Lots of trailing whitespaces in the files of Syd. Cleaning this. No big deal.
[platform/upstream/lapack.git] / SRC / dtgexc.f
1 *> \brief \b DTGEXC
2 *
3 *  =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at
6 *            http://www.netlib.org/lapack/explore-html/
7 *
8 *> \htmlonly
9 *> Download DTGEXC + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtgexc.f">
11 *> [TGZ]</a>
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtgexc.f">
13 *> [ZIP]</a>
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgexc.f">
15 *> [TXT]</a>
16 *> \endhtmlonly
17 *
18 *  Definition:
19 *  ===========
20 *
21 *       SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
22 *                          LDZ, IFST, ILST, WORK, LWORK, INFO )
23 *
24 *       .. Scalar Arguments ..
25 *       LOGICAL            WANTQ, WANTZ
26 *       INTEGER            IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
27 *       ..
28 *       .. Array Arguments ..
29 *       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
30 *      $                   WORK( * ), Z( LDZ, * )
31 *       ..
32 *
33 *
34 *> \par Purpose:
35 *  =============
36 *>
37 *> \verbatim
38 *>
39 *> DTGEXC reorders the generalized real Schur decomposition of a real
40 *> matrix pair (A,B) using an orthogonal equivalence transformation
41 *>
42 *>                (A, B) = Q * (A, B) * Z**T,
43 *>
44 *> so that the diagonal block of (A, B) with row index IFST is moved
45 *> to row ILST.
46 *>
47 *> (A, B) must be in generalized real Schur canonical form (as returned
48 *> by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2
49 *> diagonal blocks. B is upper triangular.
50 *>
51 *> Optionally, the matrices Q and Z of generalized Schur vectors are
52 *> updated.
53 *>
54 *>        Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T
55 *>        Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T
56 *>
57 *> \endverbatim
58 *
59 *  Arguments:
60 *  ==========
61 *
62 *> \param[in] WANTQ
63 *> \verbatim
64 *>          WANTQ is LOGICAL
65 *>          .TRUE. : update the left transformation matrix Q;
66 *>          .FALSE.: do not update Q.
67 *> \endverbatim
68 *>
69 *> \param[in] WANTZ
70 *> \verbatim
71 *>          WANTZ is LOGICAL
72 *>          .TRUE. : update the right transformation matrix Z;
73 *>          .FALSE.: do not update Z.
74 *> \endverbatim
75 *>
76 *> \param[in] N
77 *> \verbatim
78 *>          N is INTEGER
79 *>          The order of the matrices A and B. N >= 0.
80 *> \endverbatim
81 *>
82 *> \param[in,out] A
83 *> \verbatim
84 *>          A is DOUBLE PRECISION array, dimension (LDA,N)
85 *>          On entry, the matrix A in generalized real Schur canonical
86 *>          form.
87 *>          On exit, the updated matrix A, again in generalized
88 *>          real Schur canonical form.
89 *> \endverbatim
90 *>
91 *> \param[in] LDA
92 *> \verbatim
93 *>          LDA is INTEGER
94 *>          The leading dimension of the array A. LDA >= max(1,N).
95 *> \endverbatim
96 *>
97 *> \param[in,out] B
98 *> \verbatim
99 *>          B is DOUBLE PRECISION array, dimension (LDB,N)
100 *>          On entry, the matrix B in generalized real Schur canonical
101 *>          form (A,B).
102 *>          On exit, the updated matrix B, again in generalized
103 *>          real Schur canonical form (A,B).
104 *> \endverbatim
105 *>
106 *> \param[in] LDB
107 *> \verbatim
108 *>          LDB is INTEGER
109 *>          The leading dimension of the array B. LDB >= max(1,N).
110 *> \endverbatim
111 *>
112 *> \param[in,out] Q
113 *> \verbatim
114 *>          Q is DOUBLE PRECISION array, dimension (LDQ,N)
115 *>          On entry, if WANTQ = .TRUE., the orthogonal matrix Q.
116 *>          On exit, the updated matrix Q.
117 *>          If WANTQ = .FALSE., Q is not referenced.
118 *> \endverbatim
119 *>
120 *> \param[in] LDQ
121 *> \verbatim
122 *>          LDQ is INTEGER
123 *>          The leading dimension of the array Q. LDQ >= 1.
124 *>          If WANTQ = .TRUE., LDQ >= N.
125 *> \endverbatim
126 *>
127 *> \param[in,out] Z
128 *> \verbatim
129 *>          Z is DOUBLE PRECISION array, dimension (LDZ,N)
130 *>          On entry, if WANTZ = .TRUE., the orthogonal matrix Z.
131 *>          On exit, the updated matrix Z.
132 *>          If WANTZ = .FALSE., Z is not referenced.
133 *> \endverbatim
134 *>
135 *> \param[in] LDZ
136 *> \verbatim
137 *>          LDZ is INTEGER
138 *>          The leading dimension of the array Z. LDZ >= 1.
139 *>          If WANTZ = .TRUE., LDZ >= N.
140 *> \endverbatim
141 *>
142 *> \param[in,out] IFST
143 *> \verbatim
144 *>          IFST is INTEGER
145 *> \endverbatim
146 *>
147 *> \param[in,out] ILST
148 *> \verbatim
149 *>          ILST is INTEGER
150 *>          Specify the reordering of the diagonal blocks of (A, B).
151 *>          The block with row index IFST is moved to row ILST, by a
152 *>          sequence of swapping between adjacent blocks.
153 *>          On exit, if IFST pointed on entry to the second row of
154 *>          a 2-by-2 block, it is changed to point to the first row;
155 *>          ILST always points to the first row of the block in its
156 *>          final position (which may differ from its input value by
157 *>          +1 or -1). 1 <= IFST, ILST <= N.
158 *> \endverbatim
159 *>
160 *> \param[out] WORK
161 *> \verbatim
162 *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
163 *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
164 *> \endverbatim
165 *>
166 *> \param[in] LWORK
167 *> \verbatim
168 *>          LWORK is INTEGER
169 *>          The dimension of the array WORK.
170 *>          LWORK >= 1 when N <= 1, otherwise LWORK >= 4*N + 16.
171 *>
172 *>          If LWORK = -1, then a workspace query is assumed; the routine
173 *>          only calculates the optimal size of the WORK array, returns
174 *>          this value as the first entry of the WORK array, and no error
175 *>          message related to LWORK is issued by XERBLA.
176 *> \endverbatim
177 *>
178 *> \param[out] INFO
179 *> \verbatim
180 *>          INFO is INTEGER
181 *>           =0:  successful exit.
182 *>           <0:  if INFO = -i, the i-th argument had an illegal value.
183 *>           =1:  The transformed matrix pair (A, B) would be too far
184 *>                from generalized Schur form; the problem is ill-
185 *>                conditioned. (A, B) may have been partially reordered,
186 *>                and ILST points to the first row of the current
187 *>                position of the block being moved.
188 *> \endverbatim
189 *
190 *  Authors:
191 *  ========
192 *
193 *> \author Univ. of Tennessee
194 *> \author Univ. of California Berkeley
195 *> \author Univ. of Colorado Denver
196 *> \author NAG Ltd.
197 *
198 *> \date November 2011
199 *
200 *> \ingroup doubleGEcomputational
201 *
202 *> \par Contributors:
203 *  ==================
204 *>
205 *>     Bo Kagstrom and Peter Poromaa, Department of Computing Science,
206 *>     Umea University, S-901 87 Umea, Sweden.
207 *
208 *> \par References:
209 *  ================
210 *>
211 *> \verbatim
212 *>
213 *>  [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the
214 *>      Generalized Real Schur Form of a Regular Matrix Pair (A, B), in
215 *>      M.S. Moonen et al (eds), Linear Algebra for Large Scale and
216 *>      Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.
217 *> \endverbatim
218 *>
219 *  =====================================================================
220       SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
221      $                   LDZ, IFST, ILST, WORK, LWORK, INFO )
222 *
223 *  -- LAPACK computational routine (version 3.4.0) --
224 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
225 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
226 *     November 2011
227 *
228 *     .. Scalar Arguments ..
229       LOGICAL            WANTQ, WANTZ
230       INTEGER            IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
231 *     ..
232 *     .. Array Arguments ..
233       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
234      $                   WORK( * ), Z( LDZ, * )
235 *     ..
236 *
237 *  =====================================================================
238 *
239 *     .. Parameters ..
240       DOUBLE PRECISION   ZERO
241       PARAMETER          ( ZERO = 0.0D+0 )
242 *     ..
243 *     .. Local Scalars ..
244       LOGICAL            LQUERY
245       INTEGER            HERE, LWMIN, NBF, NBL, NBNEXT
246 *     ..
247 *     .. External Subroutines ..
248       EXTERNAL           DTGEX2, XERBLA
249 *     ..
250 *     .. Intrinsic Functions ..
251       INTRINSIC          MAX
252 *     ..
253 *     .. Executable Statements ..
254 *
255 *     Decode and test input arguments.
256 *
257       INFO = 0
258       LQUERY = ( LWORK.EQ.-1 )
259       IF( N.LT.0 ) THEN
260          INFO = -3
261       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
262          INFO = -5
263       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
264          INFO = -7
265       ELSE IF( LDQ.LT.1 .OR. WANTQ .AND. ( LDQ.LT.MAX( 1, N ) ) ) THEN
266          INFO = -9
267       ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. ( LDZ.LT.MAX( 1, N ) ) ) THEN
268          INFO = -11
269       ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
270          INFO = -12
271       ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
272          INFO = -13
273       END IF
274 *
275       IF( INFO.EQ.0 ) THEN
276          IF( N.LE.1 ) THEN
277             LWMIN = 1
278          ELSE
279             LWMIN = 4*N + 16
280          END IF
281          WORK(1) = LWMIN
282 *
283          IF (LWORK.LT.LWMIN .AND. .NOT.LQUERY) THEN
284             INFO = -15
285          END IF
286       END IF
287 *
288       IF( INFO.NE.0 ) THEN
289          CALL XERBLA( 'DTGEXC', -INFO )
290          RETURN
291       ELSE IF( LQUERY ) THEN
292          RETURN
293       END IF
294 *
295 *     Quick return if possible
296 *
297       IF( N.LE.1 )
298      $   RETURN
299 *
300 *     Determine the first row of the specified block and find out
301 *     if it is 1-by-1 or 2-by-2.
302 *
303       IF( IFST.GT.1 ) THEN
304          IF( A( IFST, IFST-1 ).NE.ZERO )
305      $      IFST = IFST - 1
306       END IF
307       NBF = 1
308       IF( IFST.LT.N ) THEN
309          IF( A( IFST+1, IFST ).NE.ZERO )
310      $      NBF = 2
311       END IF
312 *
313 *     Determine the first row of the final block
314 *     and find out if it is 1-by-1 or 2-by-2.
315 *
316       IF( ILST.GT.1 ) THEN
317          IF( A( ILST, ILST-1 ).NE.ZERO )
318      $      ILST = ILST - 1
319       END IF
320       NBL = 1
321       IF( ILST.LT.N ) THEN
322          IF( A( ILST+1, ILST ).NE.ZERO )
323      $      NBL = 2
324       END IF
325       IF( IFST.EQ.ILST )
326      $   RETURN
327 *
328       IF( IFST.LT.ILST ) THEN
329 *
330 *        Update ILST.
331 *
332          IF( NBF.EQ.2 .AND. NBL.EQ.1 )
333      $      ILST = ILST - 1
334          IF( NBF.EQ.1 .AND. NBL.EQ.2 )
335      $      ILST = ILST + 1
336 *
337          HERE = IFST
338 *
339    10    CONTINUE
340 *
341 *        Swap with next one below.
342 *
343          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
344 *
345 *           Current block either 1-by-1 or 2-by-2.
346 *
347             NBNEXT = 1
348             IF( HERE+NBF+1.LE.N ) THEN
349                IF( A( HERE+NBF+1, HERE+NBF ).NE.ZERO )
350      $            NBNEXT = 2
351             END IF
352             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
353      $                   LDZ, HERE, NBF, NBNEXT, WORK, LWORK, INFO )
354             IF( INFO.NE.0 ) THEN
355                ILST = HERE
356                RETURN
357             END IF
358             HERE = HERE + NBNEXT
359 *
360 *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
361 *
362             IF( NBF.EQ.2 ) THEN
363                IF( A( HERE+1, HERE ).EQ.ZERO )
364      $            NBF = 3
365             END IF
366 *
367          ELSE
368 *
369 *           Current block consists of two 1-by-1 blocks, each of which
370 *           must be swapped individually.
371 *
372             NBNEXT = 1
373             IF( HERE+3.LE.N ) THEN
374                IF( A( HERE+3, HERE+2 ).NE.ZERO )
375      $            NBNEXT = 2
376             END IF
377             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
378      $                   LDZ, HERE+1, 1, NBNEXT, WORK, LWORK, INFO )
379             IF( INFO.NE.0 ) THEN
380                ILST = HERE
381                RETURN
382             END IF
383             IF( NBNEXT.EQ.1 ) THEN
384 *
385 *              Swap two 1-by-1 blocks.
386 *
387                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
388      $                      LDZ, HERE, 1, 1, WORK, LWORK, INFO )
389                IF( INFO.NE.0 ) THEN
390                   ILST = HERE
391                   RETURN
392                END IF
393                HERE = HERE + 1
394 *
395             ELSE
396 *
397 *              Recompute NBNEXT in case of 2-by-2 split.
398 *
399                IF( A( HERE+2, HERE+1 ).EQ.ZERO )
400      $            NBNEXT = 1
401                IF( NBNEXT.EQ.2 ) THEN
402 *
403 *                 2-by-2 block did not split.
404 *
405                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
406      $                         Z, LDZ, HERE, 1, NBNEXT, WORK, LWORK,
407      $                         INFO )
408                   IF( INFO.NE.0 ) THEN
409                      ILST = HERE
410                      RETURN
411                   END IF
412                   HERE = HERE + 2
413                ELSE
414 *
415 *                 2-by-2 block did split.
416 *
417                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
418      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
419                   IF( INFO.NE.0 ) THEN
420                      ILST = HERE
421                      RETURN
422                   END IF
423                   HERE = HERE + 1
424                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
425      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
426                   IF( INFO.NE.0 ) THEN
427                      ILST = HERE
428                      RETURN
429                   END IF
430                   HERE = HERE + 1
431                END IF
432 *
433             END IF
434          END IF
435          IF( HERE.LT.ILST )
436      $      GO TO 10
437       ELSE
438          HERE = IFST
439 *
440    20    CONTINUE
441 *
442 *        Swap with next one below.
443 *
444          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
445 *
446 *           Current block either 1-by-1 or 2-by-2.
447 *
448             NBNEXT = 1
449             IF( HERE.GE.3 ) THEN
450                IF( A( HERE-1, HERE-2 ).NE.ZERO )
451      $            NBNEXT = 2
452             END IF
453             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
454      $                   LDZ, HERE-NBNEXT, NBNEXT, NBF, WORK, LWORK,
455      $                   INFO )
456             IF( INFO.NE.0 ) THEN
457                ILST = HERE
458                RETURN
459             END IF
460             HERE = HERE - NBNEXT
461 *
462 *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
463 *
464             IF( NBF.EQ.2 ) THEN
465                IF( A( HERE+1, HERE ).EQ.ZERO )
466      $            NBF = 3
467             END IF
468 *
469          ELSE
470 *
471 *           Current block consists of two 1-by-1 blocks, each of which
472 *           must be swapped individually.
473 *
474             NBNEXT = 1
475             IF( HERE.GE.3 ) THEN
476                IF( A( HERE-1, HERE-2 ).NE.ZERO )
477      $            NBNEXT = 2
478             END IF
479             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
480      $                   LDZ, HERE-NBNEXT, NBNEXT, 1, WORK, LWORK,
481      $                   INFO )
482             IF( INFO.NE.0 ) THEN
483                ILST = HERE
484                RETURN
485             END IF
486             IF( NBNEXT.EQ.1 ) THEN
487 *
488 *              Swap two 1-by-1 blocks.
489 *
490                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
491      $                      LDZ, HERE, NBNEXT, 1, WORK, LWORK, INFO )
492                IF( INFO.NE.0 ) THEN
493                   ILST = HERE
494                   RETURN
495                END IF
496                HERE = HERE - 1
497             ELSE
498 *
499 *             Recompute NBNEXT in case of 2-by-2 split.
500 *
501                IF( A( HERE, HERE-1 ).EQ.ZERO )
502      $            NBNEXT = 1
503                IF( NBNEXT.EQ.2 ) THEN
504 *
505 *                 2-by-2 block did not split.
506 *
507                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
508      $                         Z, LDZ, HERE-1, 2, 1, WORK, LWORK, INFO )
509                   IF( INFO.NE.0 ) THEN
510                      ILST = HERE
511                      RETURN
512                   END IF
513                   HERE = HERE - 2
514                ELSE
515 *
516 *                 2-by-2 block did split.
517 *
518                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
519      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
520                   IF( INFO.NE.0 ) THEN
521                      ILST = HERE
522                      RETURN
523                   END IF
524                   HERE = HERE - 1
525                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
526      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
527                   IF( INFO.NE.0 ) THEN
528                      ILST = HERE
529                      RETURN
530                   END IF
531                   HERE = HERE - 1
532                END IF
533             END IF
534          END IF
535          IF( HERE.GT.ILST )
536      $      GO TO 20
537       END IF
538       ILST = HERE
539       WORK( 1 ) = LWMIN
540       RETURN
541 *
542 *     End of DTGEXC
543 *
544       END