1 *> \brief \b STGEX2 swaps adjacent diagonal blocks in an upper (quasi) triangular matrix pair by an orthogonal equivalence transformation.
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download STGEX2 + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/stgex2.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/stgex2.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgex2.f">
21 * SUBROUTINE STGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
22 * LDZ, J1, N1, N2, WORK, LWORK, INFO )
24 * .. Scalar Arguments ..
25 * LOGICAL WANTQ, WANTZ
26 * INTEGER INFO, J1, LDA, LDB, LDQ, LDZ, LWORK, N, N1, N2
28 * .. Array Arguments ..
29 * REAL A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
30 * $ WORK( * ), Z( LDZ, * )
39 *> STGEX2 swaps adjacent diagonal blocks (A11, B11) and (A22, B22)
40 *> of size 1-by-1 or 2-by-2 in an upper (quasi) triangular matrix pair
41 *> (A, B) by an orthogonal equivalence transformation.
43 *> (A, B) must be in generalized real Schur canonical form (as returned
44 *> by SGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2
45 *> diagonal blocks. B is upper triangular.
47 *> Optionally, the matrices Q and Z of generalized Schur vectors are
50 *> Q(in) * A(in) * Z(in)**T = Q(out) * A(out) * Z(out)**T
51 *> Q(in) * B(in) * Z(in)**T = Q(out) * B(out) * Z(out)**T
61 *> .TRUE. : update the left transformation matrix Q;
62 *> .FALSE.: do not update Q.
68 *> .TRUE. : update the right transformation matrix Z;
69 *> .FALSE.: do not update Z.
75 *> The order of the matrices A and B. N >= 0.
80 *> A is REAL arrays, dimensions (LDA,N)
81 *> On entry, the matrix A in the pair (A, B).
82 *> On exit, the updated matrix A.
88 *> The leading dimension of the array A. LDA >= max(1,N).
93 *> B is REAL arrays, dimensions (LDB,N)
94 *> On entry, the matrix B in the pair (A, B).
95 *> On exit, the updated matrix B.
101 *> The leading dimension of the array B. LDB >= max(1,N).
106 *> Q is REAL array, dimension (LDZ,N)
107 *> On entry, if WANTQ = .TRUE., the orthogonal matrix Q.
108 *> On exit, the updated matrix Q.
109 *> Not referenced if WANTQ = .FALSE..
115 *> The leading dimension of the array Q. LDQ >= 1.
116 *> If WANTQ = .TRUE., LDQ >= N.
121 *> Z is REAL array, dimension (LDZ,N)
122 *> On entry, if WANTZ =.TRUE., the orthogonal matrix Z.
123 *> On exit, the updated matrix Z.
124 *> Not referenced if WANTZ = .FALSE..
130 *> The leading dimension of the array Z. LDZ >= 1.
131 *> If WANTZ = .TRUE., LDZ >= N.
137 *> The index to the first block (A11, B11). 1 <= J1 <= N.
143 *> The order of the first block (A11, B11). N1 = 0, 1 or 2.
149 *> The order of the second block (A22, B22). N2 = 0, 1 or 2.
154 *> WORK is REAL array, dimension (MAX(1,LWORK)).
160 *> The dimension of the array WORK.
161 *> LWORK >= MAX( N*(N2+N1), (N2+N1)*(N2+N1)*2 )
167 *> =0: Successful exit
168 *> >0: If INFO = 1, the transformed matrix (A, B) would be
169 *> too far from generalized Schur form; the blocks are
170 *> not swapped and (A, B) and (Q, Z) are unchanged.
171 *> The problem of swapping is too ill-conditioned.
172 *> <0: If INFO = -16: LWORK is too small. Appropriate value
173 *> for LWORK is returned in WORK(1).
179 *> \author Univ. of Tennessee
180 *> \author Univ. of California Berkeley
181 *> \author Univ. of Colorado Denver
184 *> \date November 2015
186 *> \ingroup realGEauxiliary
188 *> \par Further Details:
189 * =====================
191 *> In the current code both weak and strong stability tests are
192 *> performed. The user can omit the strong stability test by changing
193 *> the internal logical parameter WANDS to .FALSE.. See ref. [2] for
196 *> \par Contributors:
199 *> Bo Kagstrom and Peter Poromaa, Department of Computing Science,
200 *> Umea University, S-901 87 Umea, Sweden.
207 *> [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the
208 *> Generalized Real Schur Form of a Regular Matrix Pair (A, B), in
209 *> M.S. Moonen et al (eds), Linear Algebra for Large Scale and
210 *> Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.
212 *> [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified
213 *> Eigenvalues of a Regular Matrix Pair (A, B) and Condition
214 *> Estimation: Theory, Algorithms and Software,
215 *> Report UMINF - 94.04, Department of Computing Science, Umea
216 *> University, S-901 87 Umea, Sweden, 1994. Also as LAPACK Working
217 *> Note 87. To appear in Numerical Algorithms, 1996.
220 * =====================================================================
221 SUBROUTINE STGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
222 $ LDZ, J1, N1, N2, WORK, LWORK, INFO )
224 * -- LAPACK auxiliary routine (version 3.6.0) --
225 * -- LAPACK is a software package provided by Univ. of Tennessee, --
226 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
229 * .. Scalar Arguments ..
231 INTEGER INFO, J1, LDA, LDB, LDQ, LDZ, LWORK, N, N1, N2
233 * .. Array Arguments ..
234 REAL A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
235 $ WORK( * ), Z( LDZ, * )
238 * =====================================================================
239 * Replaced various illegal calls to SCOPY by calls to SLASET, or by DO
240 * loops. Sven Hammarling, 1/5/02.
244 PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 )
246 PARAMETER ( TWENTY = 2.0E+01 )
248 PARAMETER ( LDST = 4 )
250 PARAMETER ( WANDS = .TRUE. )
252 * .. Local Scalars ..
254 INTEGER I, IDUM, LINFO, M
255 REAL BQRA21, BRQA21, DDUM, DNORM, DSCALE, DSUM, EPS,
256 $ F, G, SA, SB, SCALE, SMLNUM, SS, THRESH, WS
259 INTEGER IWORK( LDST )
260 REAL AI( 2 ), AR( 2 ), BE( 2 ), IR( LDST, LDST ),
261 $ IRCOP( LDST, LDST ), LI( LDST, LDST ),
262 $ LICOP( LDST, LDST ), S( LDST, LDST ),
263 $ SCPY( LDST, LDST ), T( LDST, LDST ),
264 $ TAUL( LDST ), TAUR( LDST ), TCPY( LDST, LDST )
266 * .. External Functions ..
270 * .. External Subroutines ..
271 EXTERNAL SGEMM, SGEQR2, SGERQ2, SLACPY, SLAGV2, SLARTG,
272 $ SLASET, SLASSQ, SORG2R, SORGR2, SORM2R, SORMR2,
273 $ SROT, SSCAL, STGSY2
275 * .. Intrinsic Functions ..
276 INTRINSIC ABS, MAX, SQRT
278 * .. Executable Statements ..
282 * Quick return if possible
284 IF( N.LE.1 .OR. N1.LE.0 .OR. N2.LE.0 )
286 IF( N1.GT.N .OR. ( J1+N1 ).GT.N )
289 IF( LWORK.LT.MAX( N*M, M*M*2 ) ) THEN
291 WORK( 1 ) = MAX( N*M, M*M*2 )
298 * Make a local copy of selected block
300 CALL SLASET( 'Full', LDST, LDST, ZERO, ZERO, LI, LDST )
301 CALL SLASET( 'Full', LDST, LDST, ZERO, ZERO, IR, LDST )
302 CALL SLACPY( 'Full', M, M, A( J1, J1 ), LDA, S, LDST )
303 CALL SLACPY( 'Full', M, M, B( J1, J1 ), LDB, T, LDST )
305 * Compute threshold for testing acceptance of swapping.
308 SMLNUM = SLAMCH( 'S' ) / EPS
311 CALL SLACPY( 'Full', M, M, S, LDST, WORK, M )
312 CALL SLASSQ( M*M, WORK, 1, DSCALE, DSUM )
313 CALL SLACPY( 'Full', M, M, T, LDST, WORK, M )
314 CALL SLASSQ( M*M, WORK, 1, DSCALE, DSUM )
315 DNORM = DSCALE*SQRT( DSUM )
317 * THRES has been changed from
318 * THRESH = MAX( TEN*EPS*SA, SMLNUM )
320 * THRESH = MAX( TWENTY*EPS*SA, SMLNUM )
322 * "Bug" reported by Ondra Kamenik, confirmed by Julie Langou, fixed by
323 * Jim Demmel and Guillaume Revy. See forum post 1783.
325 THRESH = MAX( TWENTY*EPS*DNORM, SMLNUM )
329 * CASE 1: Swap 1-by-1 and 1-by-1 blocks.
331 * Compute orthogonal QL and RQ that swap 1-by-1 and 1-by-1 blocks
332 * using Givens rotations and perform the swap tentatively.
334 F = S( 2, 2 )*T( 1, 1 ) - T( 2, 2 )*S( 1, 1 )
335 G = S( 2, 2 )*T( 1, 2 ) - T( 2, 2 )*S( 1, 2 )
336 SB = ABS( T( 2, 2 ) )
337 SA = ABS( S( 2, 2 ) )
338 CALL SLARTG( F, G, IR( 1, 2 ), IR( 1, 1 ), DDUM )
339 IR( 2, 1 ) = -IR( 1, 2 )
340 IR( 2, 2 ) = IR( 1, 1 )
341 CALL SROT( 2, S( 1, 1 ), 1, S( 1, 2 ), 1, IR( 1, 1 ),
343 CALL SROT( 2, T( 1, 1 ), 1, T( 1, 2 ), 1, IR( 1, 1 ),
346 CALL SLARTG( S( 1, 1 ), S( 2, 1 ), LI( 1, 1 ), LI( 2, 1 ),
349 CALL SLARTG( T( 1, 1 ), T( 2, 1 ), LI( 1, 1 ), LI( 2, 1 ),
352 CALL SROT( 2, S( 1, 1 ), LDST, S( 2, 1 ), LDST, LI( 1, 1 ),
354 CALL SROT( 2, T( 1, 1 ), LDST, T( 2, 1 ), LDST, LI( 1, 1 ),
356 LI( 2, 2 ) = LI( 1, 1 )
357 LI( 1, 2 ) = -LI( 2, 1 )
359 * Weak stability test:
360 * |S21| + |T21| <= O(EPS * F-norm((S, T)))
362 WS = ABS( S( 2, 1 ) ) + ABS( T( 2, 1 ) )
369 * Strong stability test:
370 * F-norm((A-QL**T*S*QR, B-QL**T*T*QR)) <= O(EPS*F-norm((A, B)))
372 CALL SLACPY( 'Full', M, M, A( J1, J1 ), LDA, WORK( M*M+1 ),
374 CALL SGEMM( 'N', 'N', M, M, M, ONE, LI, LDST, S, LDST, ZERO,
376 CALL SGEMM( 'N', 'T', M, M, M, -ONE, WORK, M, IR, LDST, ONE,
380 CALL SLASSQ( M*M, WORK( M*M+1 ), 1, DSCALE, DSUM )
382 CALL SLACPY( 'Full', M, M, B( J1, J1 ), LDB, WORK( M*M+1 ),
384 CALL SGEMM( 'N', 'N', M, M, M, ONE, LI, LDST, T, LDST, ZERO,
386 CALL SGEMM( 'N', 'T', M, M, M, -ONE, WORK, M, IR, LDST, ONE,
388 CALL SLASSQ( M*M, WORK( M*M+1 ), 1, DSCALE, DSUM )
389 SS = DSCALE*SQRT( DSUM )
390 STRONG = SS.LE.THRESH
395 * Update (A(J1:J1+M-1, M+J1:N), B(J1:J1+M-1, M+J1:N)) and
396 * (A(1:J1-1, J1:J1+M), B(1:J1-1, J1:J1+M)).
398 CALL SROT( J1+1, A( 1, J1 ), 1, A( 1, J1+1 ), 1, IR( 1, 1 ),
400 CALL SROT( J1+1, B( 1, J1 ), 1, B( 1, J1+1 ), 1, IR( 1, 1 ),
402 CALL SROT( N-J1+1, A( J1, J1 ), LDA, A( J1+1, J1 ), LDA,
403 $ LI( 1, 1 ), LI( 2, 1 ) )
404 CALL SROT( N-J1+1, B( J1, J1 ), LDB, B( J1+1, J1 ), LDB,
405 $ LI( 1, 1 ), LI( 2, 1 ) )
407 * Set N1-by-N2 (2,1) - blocks to ZERO.
412 * Accumulate transformations into Q and Z if requested.
415 $ CALL SROT( N, Z( 1, J1 ), 1, Z( 1, J1+1 ), 1, IR( 1, 1 ),
418 $ CALL SROT( N, Q( 1, J1 ), 1, Q( 1, J1+1 ), 1, LI( 1, 1 ),
421 * Exit with INFO = 0 if swap was successfully performed.
427 * CASE 2: Swap 1-by-1 and 2-by-2 blocks, or 2-by-2
430 * Solve the generalized Sylvester equation
431 * S11 * R - L * S22 = SCALE * S12
432 * T11 * R - L * T22 = SCALE * T12
433 * for R and L. Solutions in LI and IR.
435 CALL SLACPY( 'Full', N1, N2, T( 1, N1+1 ), LDST, LI, LDST )
436 CALL SLACPY( 'Full', N1, N2, S( 1, N1+1 ), LDST,
437 $ IR( N2+1, N1+1 ), LDST )
438 CALL STGSY2( 'N', 0, N1, N2, S, LDST, S( N1+1, N1+1 ), LDST,
439 $ IR( N2+1, N1+1 ), LDST, T, LDST, T( N1+1, N1+1 ),
440 $ LDST, LI, LDST, SCALE, DSUM, DSCALE, IWORK, IDUM,
443 * Compute orthogonal matrix QL:
445 * QL**T * LI = [ TL ]
449 * [ SCALE * identity(N2) ]
452 CALL SSCAL( N1, -ONE, LI( 1, I ), 1 )
453 LI( N1+I, I ) = SCALE
455 CALL SGEQR2( M, N2, LI, LDST, TAUL, WORK, LINFO )
458 CALL SORG2R( M, M, N2, LI, LDST, TAUL, WORK, LINFO )
462 * Compute orthogonal matrix RQ:
464 * IR * RQ**T = [ 0 TR],
466 * where IR = [ SCALE * identity(N1), R ]
469 IR( N2+I, I ) = SCALE
471 CALL SGERQ2( N1, M, IR( N2+1, 1 ), LDST, TAUR, WORK, LINFO )
474 CALL SORGR2( M, M, N1, IR, LDST, TAUR, WORK, LINFO )
478 * Perform the swapping tentatively:
480 CALL SGEMM( 'T', 'N', M, M, M, ONE, LI, LDST, S, LDST, ZERO,
482 CALL SGEMM( 'N', 'T', M, M, M, ONE, WORK, M, IR, LDST, ZERO, S,
484 CALL SGEMM( 'T', 'N', M, M, M, ONE, LI, LDST, T, LDST, ZERO,
486 CALL SGEMM( 'N', 'T', M, M, M, ONE, WORK, M, IR, LDST, ZERO, T,
488 CALL SLACPY( 'F', M, M, S, LDST, SCPY, LDST )
489 CALL SLACPY( 'F', M, M, T, LDST, TCPY, LDST )
490 CALL SLACPY( 'F', M, M, IR, LDST, IRCOP, LDST )
491 CALL SLACPY( 'F', M, M, LI, LDST, LICOP, LDST )
493 * Triangularize the B-part by an RQ factorization.
494 * Apply transformation (from left) to A-part, giving S.
496 CALL SGERQ2( M, M, T, LDST, TAUR, WORK, LINFO )
499 CALL SORMR2( 'R', 'T', M, M, M, T, LDST, TAUR, S, LDST, WORK,
503 CALL SORMR2( 'L', 'N', M, M, M, T, LDST, TAUR, IR, LDST, WORK,
508 * Compute F-norm(S21) in BRQA21. (T21 is 0.)
513 CALL SLASSQ( N1, S( N2+1, I ), 1, DSCALE, DSUM )
515 BRQA21 = DSCALE*SQRT( DSUM )
517 * Triangularize the B-part by a QR factorization.
518 * Apply transformation (from right) to A-part, giving S.
520 CALL SGEQR2( M, M, TCPY, LDST, TAUL, WORK, LINFO )
523 CALL SORM2R( 'L', 'T', M, M, M, TCPY, LDST, TAUL, SCPY, LDST,
525 CALL SORM2R( 'R', 'N', M, M, M, TCPY, LDST, TAUL, LICOP, LDST,
530 * Compute F-norm(S21) in BQRA21. (T21 is 0.)
535 CALL SLASSQ( N1, SCPY( N2+1, I ), 1, DSCALE, DSUM )
537 BQRA21 = DSCALE*SQRT( DSUM )
539 * Decide which method to use.
540 * Weak stability test:
541 * F-norm(S21) <= O(EPS * F-norm((S, T)))
543 IF( BQRA21.LE.BRQA21 .AND. BQRA21.LE.THRESH ) THEN
544 CALL SLACPY( 'F', M, M, SCPY, LDST, S, LDST )
545 CALL SLACPY( 'F', M, M, TCPY, LDST, T, LDST )
546 CALL SLACPY( 'F', M, M, IRCOP, LDST, IR, LDST )
547 CALL SLACPY( 'F', M, M, LICOP, LDST, LI, LDST )
548 ELSE IF( BRQA21.GE.THRESH ) THEN
552 * Set lower triangle of B-part to zero
554 CALL SLASET( 'Lower', M-1, M-1, ZERO, ZERO, T(2,1), LDST )
558 * Strong stability test:
559 * F-norm((A-QL*S*QR**T, B-QL*T*QR**T)) <= O(EPS*F-norm((A,B)))
561 CALL SLACPY( 'Full', M, M, A( J1, J1 ), LDA, WORK( M*M+1 ),
563 CALL SGEMM( 'N', 'N', M, M, M, ONE, LI, LDST, S, LDST, ZERO,
565 CALL SGEMM( 'N', 'N', M, M, M, -ONE, WORK, M, IR, LDST, ONE,
569 CALL SLASSQ( M*M, WORK( M*M+1 ), 1, DSCALE, DSUM )
571 CALL SLACPY( 'Full', M, M, B( J1, J1 ), LDB, WORK( M*M+1 ),
573 CALL SGEMM( 'N', 'N', M, M, M, ONE, LI, LDST, T, LDST, ZERO,
575 CALL SGEMM( 'N', 'N', M, M, M, -ONE, WORK, M, IR, LDST, ONE,
577 CALL SLASSQ( M*M, WORK( M*M+1 ), 1, DSCALE, DSUM )
578 SS = DSCALE*SQRT( DSUM )
579 STRONG = ( SS.LE.THRESH )
585 * If the swap is accepted ("weakly" and "strongly"), apply the
586 * transformations and set N1-by-N2 (2,1)-block to zero.
588 CALL SLASET( 'Full', N1, N2, ZERO, ZERO, S(N2+1,1), LDST )
590 * copy back M-by-M diagonal block starting at index J1 of (A, B)
592 CALL SLACPY( 'F', M, M, S, LDST, A( J1, J1 ), LDA )
593 CALL SLACPY( 'F', M, M, T, LDST, B( J1, J1 ), LDB )
594 CALL SLASET( 'Full', LDST, LDST, ZERO, ZERO, T, LDST )
596 * Standardize existing 2-by-2 blocks.
598 CALL SLASET( 'Full', M, M, ZERO, ZERO, WORK, M )
601 IDUM = LWORK - M*M - 2
603 CALL SLAGV2( A( J1, J1 ), LDA, B( J1, J1 ), LDB, AR, AI, BE,
604 $ WORK( 1 ), WORK( 2 ), T( 1, 1 ), T( 2, 1 ) )
605 WORK( M+1 ) = -WORK( 2 )
606 WORK( M+2 ) = WORK( 1 )
607 T( N2, N2 ) = T( 1, 1 )
608 T( 1, 2 ) = -T( 2, 1 )
614 CALL SLAGV2( A( J1+N2, J1+N2 ), LDA, B( J1+N2, J1+N2 ), LDB,
615 $ TAUR, TAUL, WORK( M*M+1 ), WORK( N2*M+N2+1 ),
616 $ WORK( N2*M+N2+2 ), T( N2+1, N2+1 ),
618 WORK( M*M ) = WORK( N2*M+N2+1 )
619 WORK( M*M-1 ) = -WORK( N2*M+N2+2 )
620 T( M, M ) = T( N2+1, N2+1 )
621 T( M-1, M ) = -T( M, M-1 )
623 CALL SGEMM( 'T', 'N', N2, N1, N2, ONE, WORK, M, A( J1, J1+N2 ),
624 $ LDA, ZERO, WORK( M*M+1 ), N2 )
625 CALL SLACPY( 'Full', N2, N1, WORK( M*M+1 ), N2, A( J1, J1+N2 ),
627 CALL SGEMM( 'T', 'N', N2, N1, N2, ONE, WORK, M, B( J1, J1+N2 ),
628 $ LDB, ZERO, WORK( M*M+1 ), N2 )
629 CALL SLACPY( 'Full', N2, N1, WORK( M*M+1 ), N2, B( J1, J1+N2 ),
631 CALL SGEMM( 'N', 'N', M, M, M, ONE, LI, LDST, WORK, M, ZERO,
633 CALL SLACPY( 'Full', M, M, WORK( M*M+1 ), M, LI, LDST )
634 CALL SGEMM( 'N', 'N', N2, N1, N1, ONE, A( J1, J1+N2 ), LDA,
635 $ T( N2+1, N2+1 ), LDST, ZERO, WORK, N2 )
636 CALL SLACPY( 'Full', N2, N1, WORK, N2, A( J1, J1+N2 ), LDA )
637 CALL SGEMM( 'N', 'N', N2, N1, N1, ONE, B( J1, J1+N2 ), LDB,
638 $ T( N2+1, N2+1 ), LDST, ZERO, WORK, N2 )
639 CALL SLACPY( 'Full', N2, N1, WORK, N2, B( J1, J1+N2 ), LDB )
640 CALL SGEMM( 'T', 'N', M, M, M, ONE, IR, LDST, T, LDST, ZERO,
642 CALL SLACPY( 'Full', M, M, WORK, M, IR, LDST )
644 * Accumulate transformations into Q and Z if requested.
647 CALL SGEMM( 'N', 'N', N, M, M, ONE, Q( 1, J1 ), LDQ, LI,
648 $ LDST, ZERO, WORK, N )
649 CALL SLACPY( 'Full', N, M, WORK, N, Q( 1, J1 ), LDQ )
654 CALL SGEMM( 'N', 'N', N, M, M, ONE, Z( 1, J1 ), LDZ, IR,
655 $ LDST, ZERO, WORK, N )
656 CALL SLACPY( 'Full', N, M, WORK, N, Z( 1, J1 ), LDZ )
660 * Update (A(J1:J1+M-1, M+J1:N), B(J1:J1+M-1, M+J1:N)) and
661 * (A(1:J1-1, J1:J1+M), B(1:J1-1, J1:J1+M)).
665 CALL SGEMM( 'T', 'N', M, N-I+1, M, ONE, LI, LDST,
666 $ A( J1, I ), LDA, ZERO, WORK, M )
667 CALL SLACPY( 'Full', M, N-I+1, WORK, M, A( J1, I ), LDA )
668 CALL SGEMM( 'T', 'N', M, N-I+1, M, ONE, LI, LDST,
669 $ B( J1, I ), LDB, ZERO, WORK, M )
670 CALL SLACPY( 'Full', M, N-I+1, WORK, M, B( J1, I ), LDB )
674 CALL SGEMM( 'N', 'N', I, M, M, ONE, A( 1, J1 ), LDA, IR,
675 $ LDST, ZERO, WORK, I )
676 CALL SLACPY( 'Full', I, M, WORK, I, A( 1, J1 ), LDA )
677 CALL SGEMM( 'N', 'N', I, M, M, ONE, B( 1, J1 ), LDB, IR,
678 $ LDST, ZERO, WORK, I )
679 CALL SLACPY( 'Full', I, M, WORK, I, B( 1, J1 ), LDB )
682 * Exit with INFO = 0 if swap was successfully performed.
688 * Exit with INFO = 1 if swap was rejected.