db479cdc4ab7b1a435d2501487d5074eff5d4466
[platform/upstream/lapack.git] / SRC / slaexc.f
1 *> \brief \b SLAEXC swaps adjacent diagonal blocks of a real upper quasi-triangular matrix in Schur canonical form, by an orthogonal similarity transformation.
2 *
3 *  =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at 
6 *            http://www.netlib.org/lapack/explore-html/ 
7 *
8 *> \htmlonly
9 *> Download SLAEXC + dependencies 
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slaexc.f"> 
11 *> [TGZ]</a> 
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slaexc.f"> 
13 *> [ZIP]</a> 
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slaexc.f"> 
15 *> [TXT]</a>
16 *> \endhtmlonly 
17 *
18 *  Definition:
19 *  ===========
20 *
21 *       SUBROUTINE SLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK,
22 *                          INFO )
23
24 *       .. Scalar Arguments ..
25 *       LOGICAL            WANTQ
26 *       INTEGER            INFO, J1, LDQ, LDT, N, N1, N2
27 *       ..
28 *       .. Array Arguments ..
29 *       REAL               Q( LDQ, * ), T( LDT, * ), WORK( * )
30 *       ..
31 *  
32 *
33 *> \par Purpose:
34 *  =============
35 *>
36 *> \verbatim
37 *>
38 *> SLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in
39 *> an upper quasi-triangular matrix T by an orthogonal similarity
40 *> transformation.
41 *>
42 *> T must be in Schur canonical form, that is, block upper triangular
43 *> with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block
44 *> has its diagonal elemnts equal and its off-diagonal elements of
45 *> opposite sign.
46 *> \endverbatim
47 *
48 *  Arguments:
49 *  ==========
50 *
51 *> \param[in] WANTQ
52 *> \verbatim
53 *>          WANTQ is LOGICAL
54 *>          = .TRUE. : accumulate the transformation in the matrix Q;
55 *>          = .FALSE.: do not accumulate the transformation.
56 *> \endverbatim
57 *>
58 *> \param[in] N
59 *> \verbatim
60 *>          N is INTEGER
61 *>          The order of the matrix T. N >= 0.
62 *> \endverbatim
63 *>
64 *> \param[in,out] T
65 *> \verbatim
66 *>          T is REAL array, dimension (LDT,N)
67 *>          On entry, the upper quasi-triangular matrix T, in Schur
68 *>          canonical form.
69 *>          On exit, the updated matrix T, again in Schur canonical form.
70 *> \endverbatim
71 *>
72 *> \param[in] LDT
73 *> \verbatim
74 *>          LDT is INTEGER
75 *>          The leading dimension of the array T. LDT >= max(1,N).
76 *> \endverbatim
77 *>
78 *> \param[in,out] Q
79 *> \verbatim
80 *>          Q is REAL array, dimension (LDQ,N)
81 *>          On entry, if WANTQ is .TRUE., the orthogonal matrix Q.
82 *>          On exit, if WANTQ is .TRUE., the updated matrix Q.
83 *>          If WANTQ is .FALSE., Q is not referenced.
84 *> \endverbatim
85 *>
86 *> \param[in] LDQ
87 *> \verbatim
88 *>          LDQ is INTEGER
89 *>          The leading dimension of the array Q.
90 *>          LDQ >= 1; and if WANTQ is .TRUE., LDQ >= N.
91 *> \endverbatim
92 *>
93 *> \param[in] J1
94 *> \verbatim
95 *>          J1 is INTEGER
96 *>          The index of the first row of the first block T11.
97 *> \endverbatim
98 *>
99 *> \param[in] N1
100 *> \verbatim
101 *>          N1 is INTEGER
102 *>          The order of the first block T11. N1 = 0, 1 or 2.
103 *> \endverbatim
104 *>
105 *> \param[in] N2
106 *> \verbatim
107 *>          N2 is INTEGER
108 *>          The order of the second block T22. N2 = 0, 1 or 2.
109 *> \endverbatim
110 *>
111 *> \param[out] WORK
112 *> \verbatim
113 *>          WORK is REAL array, dimension (N)
114 *> \endverbatim
115 *>
116 *> \param[out] INFO
117 *> \verbatim
118 *>          INFO is INTEGER
119 *>          = 0: successful exit
120 *>          = 1: the transformed matrix T would be too far from Schur
121 *>               form; the blocks are not swapped and T and Q are
122 *>               unchanged.
123 *> \endverbatim
124 *
125 *  Authors:
126 *  ========
127 *
128 *> \author Univ. of Tennessee 
129 *> \author Univ. of California Berkeley 
130 *> \author Univ. of Colorado Denver 
131 *> \author NAG Ltd. 
132 *
133 *> \date September 2012
134 *
135 *> \ingroup realOTHERauxiliary
136 *
137 *  =====================================================================
138       SUBROUTINE SLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK,
139      $                   INFO )
140 *
141 *  -- LAPACK auxiliary routine (version 3.4.2) --
142 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
143 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
144 *     September 2012
145 *
146 *     .. Scalar Arguments ..
147       LOGICAL            WANTQ
148       INTEGER            INFO, J1, LDQ, LDT, N, N1, N2
149 *     ..
150 *     .. Array Arguments ..
151       REAL               Q( LDQ, * ), T( LDT, * ), WORK( * )
152 *     ..
153 *
154 *  =====================================================================
155 *
156 *     .. Parameters ..
157       REAL               ZERO, ONE
158       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
159       REAL               TEN
160       PARAMETER          ( TEN = 1.0E+1 )
161       INTEGER            LDD, LDX
162       PARAMETER          ( LDD = 4, LDX = 2 )
163 *     ..
164 *     .. Local Scalars ..
165       INTEGER            IERR, J2, J3, J4, K, ND
166       REAL               CS, DNORM, EPS, SCALE, SMLNUM, SN, T11, T22,
167      $                   T33, TAU, TAU1, TAU2, TEMP, THRESH, WI1, WI2,
168      $                   WR1, WR2, XNORM
169 *     ..
170 *     .. Local Arrays ..
171       REAL               D( LDD, 4 ), U( 3 ), U1( 3 ), U2( 3 ),
172      $                   X( LDX, 2 )
173 *     ..
174 *     .. External Functions ..
175       REAL               SLAMCH, SLANGE
176       EXTERNAL           SLAMCH, SLANGE
177 *     ..
178 *     .. External Subroutines ..
179       EXTERNAL           SLACPY, SLANV2, SLARFG, SLARFX, SLARTG, SLASY2,
180      $                   SROT
181 *     ..
182 *     .. Intrinsic Functions ..
183       INTRINSIC          ABS, MAX
184 *     ..
185 *     .. Executable Statements ..
186 *
187       INFO = 0
188 *
189 *     Quick return if possible
190 *
191       IF( N.EQ.0 .OR. N1.EQ.0 .OR. N2.EQ.0 )
192      $   RETURN
193       IF( J1+N1.GT.N )
194      $   RETURN
195 *
196       J2 = J1 + 1
197       J3 = J1 + 2
198       J4 = J1 + 3
199 *
200       IF( N1.EQ.1 .AND. N2.EQ.1 ) THEN
201 *
202 *        Swap two 1-by-1 blocks.
203 *
204          T11 = T( J1, J1 )
205          T22 = T( J2, J2 )
206 *
207 *        Determine the transformation to perform the interchange.
208 *
209          CALL SLARTG( T( J1, J2 ), T22-T11, CS, SN, TEMP )
210 *
211 *        Apply transformation to the matrix T.
212 *
213          IF( J3.LE.N )
214      $      CALL SROT( N-J1-1, T( J1, J3 ), LDT, T( J2, J3 ), LDT, CS,
215      $                 SN )
216          CALL SROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )
217 *
218          T( J1, J1 ) = T22
219          T( J2, J2 ) = T11
220 *
221          IF( WANTQ ) THEN
222 *
223 *           Accumulate transformation in the matrix Q.
224 *
225             CALL SROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )
226          END IF
227 *
228       ELSE
229 *
230 *        Swapping involves at least one 2-by-2 block.
231 *
232 *        Copy the diagonal block of order N1+N2 to the local array D
233 *        and compute its norm.
234 *
235          ND = N1 + N2
236          CALL SLACPY( 'Full', ND, ND, T( J1, J1 ), LDT, D, LDD )
237          DNORM = SLANGE( 'Max', ND, ND, D, LDD, WORK )
238 *
239 *        Compute machine-dependent threshold for test for accepting
240 *        swap.
241 *
242          EPS = SLAMCH( 'P' )
243          SMLNUM = SLAMCH( 'S' ) / EPS
244          THRESH = MAX( TEN*EPS*DNORM, SMLNUM )
245 *
246 *        Solve T11*X - X*T22 = scale*T12 for X.
247 *
248          CALL SLASY2( .FALSE., .FALSE., -1, N1, N2, D, LDD,
249      $                D( N1+1, N1+1 ), LDD, D( 1, N1+1 ), LDD, SCALE, X,
250      $                LDX, XNORM, IERR )
251 *
252 *        Swap the adjacent diagonal blocks.
253 *
254          K = N1 + N1 + N2 - 3
255          GO TO ( 10, 20, 30 )K
256 *
257    10    CONTINUE
258 *
259 *        N1 = 1, N2 = 2: generate elementary reflector H so that:
260 *
261 *        ( scale, X11, X12 ) H = ( 0, 0, * )
262 *
263          U( 1 ) = SCALE
264          U( 2 ) = X( 1, 1 )
265          U( 3 ) = X( 1, 2 )
266          CALL SLARFG( 3, U( 3 ), U, 1, TAU )
267          U( 3 ) = ONE
268          T11 = T( J1, J1 )
269 *
270 *        Perform swap provisionally on diagonal block in D.
271 *
272          CALL SLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )
273          CALL SLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )
274 *
275 *        Test whether to reject swap.
276 *
277          IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 3,
278      $       3 )-T11 ) ).GT.THRESH )GO TO 50
279 *
280 *        Accept swap: apply transformation to the entire matrix T.
281 *
282          CALL SLARFX( 'L', 3, N-J1+1, U, TAU, T( J1, J1 ), LDT, WORK )
283          CALL SLARFX( 'R', J2, 3, U, TAU, T( 1, J1 ), LDT, WORK )
284 *
285          T( J3, J1 ) = ZERO
286          T( J3, J2 ) = ZERO
287          T( J3, J3 ) = T11
288 *
289          IF( WANTQ ) THEN
290 *
291 *           Accumulate transformation in the matrix Q.
292 *
293             CALL SLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )
294          END IF
295          GO TO 40
296 *
297    20    CONTINUE
298 *
299 *        N1 = 2, N2 = 1: generate elementary reflector H so that:
300 *
301 *        H (  -X11 ) = ( * )
302 *          (  -X21 ) = ( 0 )
303 *          ( scale ) = ( 0 )
304 *
305          U( 1 ) = -X( 1, 1 )
306          U( 2 ) = -X( 2, 1 )
307          U( 3 ) = SCALE
308          CALL SLARFG( 3, U( 1 ), U( 2 ), 1, TAU )
309          U( 1 ) = ONE
310          T33 = T( J3, J3 )
311 *
312 *        Perform swap provisionally on diagonal block in D.
313 *
314          CALL SLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK )
315          CALL SLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK )
316 *
317 *        Test whether to reject swap.
318 *
319          IF( MAX( ABS( D( 2, 1 ) ), ABS( D( 3, 1 ) ), ABS( D( 1,
320      $       1 )-T33 ) ).GT.THRESH )GO TO 50
321 *
322 *        Accept swap: apply transformation to the entire matrix T.
323 *
324          CALL SLARFX( 'R', J3, 3, U, TAU, T( 1, J1 ), LDT, WORK )
325          CALL SLARFX( 'L', 3, N-J1, U, TAU, T( J1, J2 ), LDT, WORK )
326 *
327          T( J1, J1 ) = T33
328          T( J2, J1 ) = ZERO
329          T( J3, J1 ) = ZERO
330 *
331          IF( WANTQ ) THEN
332 *
333 *           Accumulate transformation in the matrix Q.
334 *
335             CALL SLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK )
336          END IF
337          GO TO 40
338 *
339    30    CONTINUE
340 *
341 *        N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so
342 *        that:
343 *
344 *        H(2) H(1) (  -X11  -X12 ) = (  *  * )
345 *                  (  -X21  -X22 )   (  0  * )
346 *                  ( scale    0  )   (  0  0 )
347 *                  (    0  scale )   (  0  0 )
348 *
349          U1( 1 ) = -X( 1, 1 )
350          U1( 2 ) = -X( 2, 1 )
351          U1( 3 ) = SCALE
352          CALL SLARFG( 3, U1( 1 ), U1( 2 ), 1, TAU1 )
353          U1( 1 ) = ONE
354 *
355          TEMP = -TAU1*( X( 1, 2 )+U1( 2 )*X( 2, 2 ) )
356          U2( 1 ) = -TEMP*U1( 2 ) - X( 2, 2 )
357          U2( 2 ) = -TEMP*U1( 3 )
358          U2( 3 ) = SCALE
359          CALL SLARFG( 3, U2( 1 ), U2( 2 ), 1, TAU2 )
360          U2( 1 ) = ONE
361 *
362 *        Perform swap provisionally on diagonal block in D.
363 *
364          CALL SLARFX( 'L', 3, 4, U1, TAU1, D, LDD, WORK )
365          CALL SLARFX( 'R', 4, 3, U1, TAU1, D, LDD, WORK )
366          CALL SLARFX( 'L', 3, 4, U2, TAU2, D( 2, 1 ), LDD, WORK )
367          CALL SLARFX( 'R', 4, 3, U2, TAU2, D( 1, 2 ), LDD, WORK )
368 *
369 *        Test whether to reject swap.
370 *
371          IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 4, 1 ) ),
372      $       ABS( D( 4, 2 ) ) ).GT.THRESH )GO TO 50
373 *
374 *        Accept swap: apply transformation to the entire matrix T.
375 *
376          CALL SLARFX( 'L', 3, N-J1+1, U1, TAU1, T( J1, J1 ), LDT, WORK )
377          CALL SLARFX( 'R', J4, 3, U1, TAU1, T( 1, J1 ), LDT, WORK )
378          CALL SLARFX( 'L', 3, N-J1+1, U2, TAU2, T( J2, J1 ), LDT, WORK )
379          CALL SLARFX( 'R', J4, 3, U2, TAU2, T( 1, J2 ), LDT, WORK )
380 *
381          T( J3, J1 ) = ZERO
382          T( J3, J2 ) = ZERO
383          T( J4, J1 ) = ZERO
384          T( J4, J2 ) = ZERO
385 *
386          IF( WANTQ ) THEN
387 *
388 *           Accumulate transformation in the matrix Q.
389 *
390             CALL SLARFX( 'R', N, 3, U1, TAU1, Q( 1, J1 ), LDQ, WORK )
391             CALL SLARFX( 'R', N, 3, U2, TAU2, Q( 1, J2 ), LDQ, WORK )
392          END IF
393 *
394    40    CONTINUE
395 *
396          IF( N2.EQ.2 ) THEN
397 *
398 *           Standardize new 2-by-2 block T11
399 *
400             CALL SLANV2( T( J1, J1 ), T( J1, J2 ), T( J2, J1 ),
401      $                   T( J2, J2 ), WR1, WI1, WR2, WI2, CS, SN )
402             CALL SROT( N-J1-1, T( J1, J1+2 ), LDT, T( J2, J1+2 ), LDT,
403      $                 CS, SN )
404             CALL SROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN )
405             IF( WANTQ )
406      $         CALL SROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN )
407          END IF
408 *
409          IF( N1.EQ.2 ) THEN
410 *
411 *           Standardize new 2-by-2 block T22
412 *
413             J3 = J1 + N2
414             J4 = J3 + 1
415             CALL SLANV2( T( J3, J3 ), T( J3, J4 ), T( J4, J3 ),
416      $                   T( J4, J4 ), WR1, WI1, WR2, WI2, CS, SN )
417             IF( J3+2.LE.N )
418      $         CALL SROT( N-J3-1, T( J3, J3+2 ), LDT, T( J4, J3+2 ),
419      $                    LDT, CS, SN )
420             CALL SROT( J3-1, T( 1, J3 ), 1, T( 1, J4 ), 1, CS, SN )
421             IF( WANTQ )
422      $         CALL SROT( N, Q( 1, J3 ), 1, Q( 1, J4 ), 1, CS, SN )
423          END IF
424 *
425       END IF
426       RETURN
427 *
428 *     Exit with INFO = 1 if swap was rejected.
429 *
430    50 INFO = 1
431       RETURN
432 *
433 *     End of SLAEXC
434 *
435       END