1 *> \brief \b CUNCSD2BY1
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download CUNCSD2BY1 + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cuncsd2by1.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cuncsd2by1.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cuncsd2by1.f">
21 * SUBROUTINE CUNCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
22 * X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
23 * LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
26 * .. Scalar Arguments ..
27 * CHARACTER JOBU1, JOBU2, JOBV1T
28 * INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
30 * INTEGER LRWORK, LRWORKMIN, LRWORKOPT
32 * .. Array Arguments ..
35 * COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
36 * $ X11(LDX11,*), X21(LDX21,*)
46 *> CUNCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with
47 *> orthonormal columns that has been partitioned into a 2-by-1 block
52 *> [ X11 ] [ U1 | ] [ 0 0 0 ]
53 *> X = [-----] = [---------] [----------] V1**T .
54 *> [ X21 ] [ | U2 ] [ 0 0 0 ]
58 *> X11 is P-by-Q. The unitary matrices U1, U2, and V1 are P-by-P,
59 *> (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R
60 *> nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which
61 *> R = MIN(P,M-P,Q,M-Q).
71 *> = 'Y': U1 is computed;
72 *> otherwise: U1 is not computed.
78 *> = 'Y': U2 is computed;
79 *> otherwise: U2 is not computed.
84 *> JOBV1T is CHARACTER
85 *> = 'Y': V1T is computed;
86 *> otherwise: V1T is not computed.
92 *> The number of rows in X.
98 *> The number of rows in X11. 0 <= P <= M.
104 *> The number of columns in X11 and X21. 0 <= Q <= M.
107 *> \param[in,out] X11
109 *> X11 is COMPLEX array, dimension (LDX11,Q)
110 *> On entry, part of the unitary matrix whose CSD is desired.
116 *> The leading dimension of X11. LDX11 >= MAX(1,P).
119 *> \param[in,out] X21
121 *> X21 is COMPLEX array, dimension (LDX21,Q)
122 *> On entry, part of the unitary matrix whose CSD is desired.
128 *> The leading dimension of X21. LDX21 >= MAX(1,M-P).
133 *> THETA is REAL array, dimension (R), in which R =
135 *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
136 *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
141 *> U1 is COMPLEX array, dimension (P)
142 *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
148 *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
154 *> U2 is COMPLEX array, dimension (M-P)
155 *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
162 *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
168 *> V1T is COMPLEX array, dimension (Q)
169 *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
176 *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
182 *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
183 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
189 *> The dimension of the array WORK.
191 *> If LWORK = -1, then a workspace query is assumed; the routine
192 *> only calculates the optimal size of the WORK array, returns
193 *> this value as the first entry of the work array, and no error
194 *> message related to LWORK is issued by XERBLA.
199 *> RWORK is REAL array, dimension (MAX(1,LRWORK))
200 *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
201 *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
202 *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
203 *> define the matrix in intermediate bidiagonal-block form
204 *> remaining after nonconvergence. INFO specifies the number
211 *> The dimension of the array RWORK.
213 *> If LRWORK = -1, then a workspace query is assumed; the routine
214 *> only calculates the optimal size of the RWORK array, returns
215 *> this value as the first entry of the work array, and no error
216 *> message related to LRWORK is issued by XERBLA.
221 *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
227 *> = 0: successful exit.
228 *> < 0: if INFO = -i, the i-th argument had an illegal value.
229 *> > 0: CBBCSD did not converge. See the description of WORK
230 *> above for details.
236 *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
237 *> Algorithms, 50(1):33-65, 2009.
242 *> \author Univ. of Tennessee
243 *> \author Univ. of California Berkeley
244 *> \author Univ. of Colorado Denver
249 *> \ingroup complexOTHERcomputational
251 * =====================================================================
252 SUBROUTINE CUNCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
253 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
254 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
257 * -- LAPACK computational routine (version 3.6.1) --
258 * -- LAPACK is a software package provided by Univ. of Tennessee, --
259 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
262 * .. Scalar Arguments ..
263 CHARACTER JOBU1, JOBU2, JOBV1T
264 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
266 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
268 * .. Array Arguments ..
271 COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
272 $ X11(LDX11,*), X21(LDX21,*)
276 * =====================================================================
280 PARAMETER ( ONE = (1.0E0,0.0E0), ZERO = (0.0E0,0.0E0) )
282 * .. Local Scalars ..
283 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
284 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
285 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
286 $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
287 $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
288 $ LWORKMIN, LWORKOPT, R
289 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
295 * .. External Subroutines ..
296 EXTERNAL CBBCSD, CCOPY, CLACPY, CLAPMR, CLAPMT, CUNBDB1,
297 $ CUNBDB2, CUNBDB3, CUNBDB4, CUNGLQ, CUNGQR,
300 * .. External Functions ..
304 * .. Intrinsic Function ..
305 INTRINSIC INT, MAX, MIN
307 * .. Executable Statements ..
309 * Test input arguments
312 WANTU1 = LSAME( JOBU1, 'Y' )
313 WANTU2 = LSAME( JOBU2, 'Y' )
314 WANTV1T = LSAME( JOBV1T, 'Y' )
315 LQUERY = LWORK .EQ. -1
319 ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
321 ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
323 ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
325 ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
327 ELSE IF( WANTU1 .AND. LDU1 .LT. MAX( 1, P ) ) THEN
329 ELSE IF( WANTU2 .AND. LDU2 .LT. MAX( 1, M - P ) ) THEN
331 ELSE IF( WANTV1T .AND. LDV1T .LT. MAX( 1, Q ) ) THEN
335 R = MIN( P, M-P, Q, M-Q )
340 * |-----------------------------------------|
342 * |-----------------------------------------|
343 * | TAUP1 (MAX(1,P)) |
344 * | TAUP2 (MAX(1,M-P)) |
345 * | TAUQ1 (MAX(1,Q)) |
346 * |-----------------------------------------|
347 * | CUNBDB WORK | CUNGQR WORK | CUNGLQ WORK |
352 * |-----------------------------------------|
354 * |------------------|
356 * |------------------|
357 * | PHI (MAX(1,R-1)) |
358 * |------------------|
368 * |------------------|
370 IF( INFO .EQ. 0 ) THEN
372 IB11D = IPHI + MAX( 1, R-1 )
373 IB11E = IB11D + MAX( 1, R )
374 IB12D = IB11E + MAX( 1, R - 1 )
375 IB12E = IB12D + MAX( 1, R )
376 IB21D = IB12E + MAX( 1, R - 1 )
377 IB21E = IB21D + MAX( 1, R )
378 IB22D = IB21E + MAX( 1, R - 1 )
379 IB22E = IB22D + MAX( 1, R )
380 IBBCSD = IB22E + MAX( 1, R - 1 )
382 ITAUP2 = ITAUP1 + MAX( 1, P )
383 ITAUQ1 = ITAUP2 + MAX( 1, M-P )
384 IORBDB = ITAUQ1 + MAX( 1, Q )
385 IORGQR = ITAUQ1 + MAX( 1, Q )
386 IORGLQ = ITAUQ1 + MAX( 1, Q )
392 CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
393 $ DUM, CDUM, CDUM, CDUM, WORK, -1,
395 LORBDB = INT( WORK(1) )
396 IF( WANTU1 .AND. P .GT. 0 ) THEN
397 CALL CUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
399 LORGQRMIN = MAX( LORGQRMIN, P )
400 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
402 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
403 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
405 LORGQRMIN = MAX( LORGQRMIN, M-P )
406 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
408 IF( WANTV1T .AND. Q .GT. 0 ) THEN
409 CALL CUNGLQ( Q-1, Q-1, Q-1, V1T, LDV1T,
410 $ CDUM, WORK(1), -1, CHILDINFO )
411 LORGLQMIN = MAX( LORGLQMIN, Q-1 )
412 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
414 CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
415 $ DUM(1), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
416 $ 1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
417 $ RWORK(1), -1, CHILDINFO )
418 LBBCSD = INT( RWORK(1) )
419 ELSE IF( R .EQ. P ) THEN
420 CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
421 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
422 LORBDB = INT( WORK(1) )
423 IF( WANTU1 .AND. P .GT. 0 ) THEN
424 CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, CDUM, WORK(1),
426 LORGQRMIN = MAX( LORGQRMIN, P-1 )
427 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
429 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
430 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
432 LORGQRMIN = MAX( LORGQRMIN, M-P )
433 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
435 IF( WANTV1T .AND. Q .GT. 0 ) THEN
436 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
438 LORGLQMIN = MAX( LORGLQMIN, Q )
439 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
441 CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
442 $ DUM, V1T, LDV1T, CDUM, 1, U1, LDU1, U2, LDU2,
443 $ DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
444 $ RWORK(1), -1, CHILDINFO )
445 LBBCSD = INT( RWORK(1) )
446 ELSE IF( R .EQ. M-P ) THEN
447 CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
448 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
449 LORBDB = INT( WORK(1) )
450 IF( WANTU1 .AND. P .GT. 0 ) THEN
451 CALL CUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
453 LORGQRMIN = MAX( LORGQRMIN, P )
454 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
456 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
457 CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, CDUM,
458 $ WORK(1), -1, CHILDINFO )
459 LORGQRMIN = MAX( LORGQRMIN, M-P-1 )
460 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
462 IF( WANTV1T .AND. Q .GT. 0 ) THEN
463 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
465 LORGLQMIN = MAX( LORGLQMIN, Q )
466 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
468 CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
469 $ THETA, DUM, CDUM, 1, V1T, LDV1T, U2, LDU2, U1,
470 $ LDU1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
471 $ RWORK(1), -1, CHILDINFO )
472 LBBCSD = INT( RWORK(1) )
474 CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
475 $ CDUM, CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO
477 LORBDB = M + INT( WORK(1) )
478 IF( WANTU1 .AND. P .GT. 0 ) THEN
479 CALL CUNGQR( P, P, M-Q, U1, LDU1, CDUM, WORK(1), -1,
481 LORGQRMIN = MAX( LORGQRMIN, P )
482 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
484 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
485 CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, CDUM, WORK(1), -1,
487 LORGQRMIN = MAX( LORGQRMIN, M-P )
488 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
490 IF( WANTV1T .AND. Q .GT. 0 ) THEN
491 CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, CDUM, WORK(1), -1,
493 LORGLQMIN = MAX( LORGLQMIN, Q )
494 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
496 CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
497 $ THETA, DUM, U2, LDU2, U1, LDU1, CDUM, 1, V1T,
498 $ LDV1T, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
499 $ RWORK(1), -1, CHILDINFO )
500 LBBCSD = INT( RWORK(1) )
502 LRWORKMIN = IBBCSD+LBBCSD-1
503 LRWORKOPT = LRWORKMIN
505 LWORKMIN = MAX( IORBDB+LORBDB-1,
506 $ IORGQR+LORGQRMIN-1,
507 $ IORGLQ+LORGLQMIN-1 )
508 LWORKOPT = MAX( IORBDB+LORBDB-1,
509 $ IORGQR+LORGQROPT-1,
510 $ IORGLQ+LORGLQOPT-1 )
512 IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
516 IF( INFO .NE. 0 ) THEN
517 CALL XERBLA( 'CUNCSD2BY1', -INFO )
519 ELSE IF( LQUERY ) THEN
522 LORGQR = LWORK-IORGQR+1
523 LORGLQ = LWORK-IORGLQ+1
525 * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
526 * in which R = MIN(P,M-P,Q,M-Q)
532 * Simultaneously bidiagonalize X11 and X21
534 CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
535 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
536 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
538 * Accumulate Householder reflectors
540 IF( WANTU1 .AND. P .GT. 0 ) THEN
541 CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
542 CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
543 $ LORGQR, CHILDINFO )
545 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
546 CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
547 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
548 $ WORK(IORGQR), LORGQR, CHILDINFO )
550 IF( WANTV1T .AND. Q .GT. 0 ) THEN
556 CALL CLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
558 CALL CUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
559 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
562 * Simultaneously diagonalize X11 and X21.
564 CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
565 $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
566 $ 1, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
567 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
568 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
571 * Permute rows and columns to place zero submatrices in
572 * preferred positions
574 IF( Q .GT. 0 .AND. WANTU2 ) THEN
576 IWORK(I) = M - P - Q + I
581 CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
583 ELSE IF( R .EQ. P ) THEN
587 * Simultaneously bidiagonalize X11 and X21
589 CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
590 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
591 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
593 * Accumulate Householder reflectors
595 IF( WANTU1 .AND. P .GT. 0 ) THEN
601 CALL CLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
602 CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
603 $ WORK(IORGQR), LORGQR, CHILDINFO )
605 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
606 CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
607 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
608 $ WORK(IORGQR), LORGQR, CHILDINFO )
610 IF( WANTV1T .AND. Q .GT. 0 ) THEN
611 CALL CLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
612 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
613 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
616 * Simultaneously diagonalize X11 and X21.
618 CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
619 $ RWORK(IPHI), V1T, LDV1T, CDUM, 1, U1, LDU1, U2,
620 $ LDU2, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
621 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
622 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
625 * Permute rows and columns to place identity submatrices in
626 * preferred positions
628 IF( Q .GT. 0 .AND. WANTU2 ) THEN
630 IWORK(I) = M - P - Q + I
635 CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
637 ELSE IF( R .EQ. M-P ) THEN
641 * Simultaneously bidiagonalize X11 and X21
643 CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
644 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
645 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
647 * Accumulate Householder reflectors
649 IF( WANTU1 .AND. P .GT. 0 ) THEN
650 CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
651 CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
652 $ LORGQR, CHILDINFO )
654 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
660 CALL CLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
662 CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
663 $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
665 IF( WANTV1T .AND. Q .GT. 0 ) THEN
666 CALL CLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
667 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
668 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
671 * Simultaneously diagonalize X11 and X21.
673 CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
674 $ THETA, RWORK(IPHI), CDUM, 1, V1T, LDV1T, U2, LDU2,
675 $ U1, LDU1, RWORK(IB11D), RWORK(IB11E),
676 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
677 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
678 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
680 * Permute rows and columns to place identity submatrices in
681 * preferred positions
691 CALL CLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
694 CALL CLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
701 * Simultaneously bidiagonalize X11 and X21
703 CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
704 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
705 $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
706 $ LORBDB-M, CHILDINFO )
708 * Accumulate Householder reflectors
710 IF( WANTU1 .AND. P .GT. 0 ) THEN
711 CALL CCOPY( P, WORK(IORBDB), 1, U1, 1 )
715 CALL CLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
717 CALL CUNGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
718 $ WORK(IORGQR), LORGQR, CHILDINFO )
720 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
721 CALL CCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
725 CALL CLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
727 CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
728 $ WORK(IORGQR), LORGQR, CHILDINFO )
730 IF( WANTV1T .AND. Q .GT. 0 ) THEN
731 CALL CLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
732 CALL CLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
733 $ V1T(M-Q+1,M-Q+1), LDV1T )
734 CALL CLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
735 $ V1T(P+1,P+1), LDV1T )
736 CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
737 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
740 * Simultaneously diagonalize X11 and X21.
742 CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
743 $ THETA, RWORK(IPHI), U2, LDU2, U1, LDU1, CDUM, 1,
744 $ V1T, LDV1T, RWORK(IB11D), RWORK(IB11E),
745 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
746 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
747 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
749 * Permute rows and columns to place identity submatrices in
750 * preferred positions
760 CALL CLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
763 CALL CLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )