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). I1 is a K1-by-K1 identity matrix and I2 is a
62 *> K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0).
72 *> = 'Y': U1 is computed;
73 *> otherwise: U1 is not computed.
79 *> = 'Y': U2 is computed;
80 *> otherwise: U2 is not computed.
85 *> JOBV1T is CHARACTER
86 *> = 'Y': V1T is computed;
87 *> otherwise: V1T is not computed.
93 *> The number of rows in X.
99 *> The number of rows in X11. 0 <= P <= M.
105 *> The number of columns in X11 and X21. 0 <= Q <= M.
108 *> \param[in,out] X11
110 *> X11 is COMPLEX array, dimension (LDX11,Q)
111 *> On entry, part of the unitary matrix whose CSD is desired.
117 *> The leading dimension of X11. LDX11 >= MAX(1,P).
120 *> \param[in,out] X21
122 *> X21 is COMPLEX array, dimension (LDX21,Q)
123 *> On entry, part of the unitary matrix whose CSD is desired.
129 *> The leading dimension of X21. LDX21 >= MAX(1,M-P).
134 *> THETA is REAL array, dimension (R), in which R =
136 *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
137 *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
142 *> U1 is COMPLEX array, dimension (P)
143 *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
149 *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
155 *> U2 is COMPLEX array, dimension (M-P)
156 *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
163 *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
169 *> V1T is COMPLEX array, dimension (Q)
170 *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
177 *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
183 *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
184 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
190 *> The dimension of the array WORK.
192 *> If LWORK = -1, then a workspace query is assumed; the routine
193 *> only calculates the optimal size of the WORK array, returns
194 *> this value as the first entry of the work array, and no error
195 *> message related to LWORK is issued by XERBLA.
200 *> RWORK is REAL array, dimension (MAX(1,LRWORK))
201 *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
202 *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
203 *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
204 *> define the matrix in intermediate bidiagonal-block form
205 *> remaining after nonconvergence. INFO specifies the number
212 *> The dimension of the array RWORK.
214 *> If LRWORK = -1, then a workspace query is assumed; the routine
215 *> only calculates the optimal size of the RWORK array, returns
216 *> this value as the first entry of the work array, and no error
217 *> message related to LRWORK is issued by XERBLA.
222 *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
228 *> = 0: successful exit.
229 *> < 0: if INFO = -i, the i-th argument had an illegal value.
230 *> > 0: CBBCSD did not converge. See the description of WORK
231 *> above for details.
237 *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
238 *> Algorithms, 50(1):33-65, 2009.
243 *> \author Univ. of Tennessee
244 *> \author Univ. of California Berkeley
245 *> \author Univ. of Colorado Denver
250 *> \ingroup complexOTHERcomputational
252 * =====================================================================
253 SUBROUTINE CUNCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
254 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
255 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
258 * -- LAPACK computational routine (version 3.6.1) --
259 * -- LAPACK is a software package provided by Univ. of Tennessee, --
260 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
263 * .. Scalar Arguments ..
264 CHARACTER JOBU1, JOBU2, JOBV1T
265 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
267 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
269 * .. Array Arguments ..
272 COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
273 $ X11(LDX11,*), X21(LDX21,*)
277 * =====================================================================
281 PARAMETER ( ONE = (1.0E0,0.0E0), ZERO = (0.0E0,0.0E0) )
283 * .. Local Scalars ..
284 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
285 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
286 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
287 $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
288 $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
289 $ LWORKMIN, LWORKOPT, R
290 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
296 * .. External Subroutines ..
297 EXTERNAL CBBCSD, CCOPY, CLACPY, CLAPMR, CLAPMT, CUNBDB1,
298 $ CUNBDB2, CUNBDB3, CUNBDB4, CUNGLQ, CUNGQR,
301 * .. External Functions ..
305 * .. Intrinsic Function ..
306 INTRINSIC INT, MAX, MIN
308 * .. Executable Statements ..
310 * Test input arguments
313 WANTU1 = LSAME( JOBU1, 'Y' )
314 WANTU2 = LSAME( JOBU2, 'Y' )
315 WANTV1T = LSAME( JOBV1T, 'Y' )
316 LQUERY = LWORK .EQ. -1
320 ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
322 ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
324 ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
326 ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
328 ELSE IF( WANTU1 .AND. LDU1 .LT. MAX( 1, P ) ) THEN
330 ELSE IF( WANTU2 .AND. LDU2 .LT. MAX( 1, M - P ) ) THEN
332 ELSE IF( WANTV1T .AND. LDV1T .LT. MAX( 1, Q ) ) THEN
336 R = MIN( P, M-P, Q, M-Q )
341 * |-----------------------------------------|
343 * |-----------------------------------------|
344 * | TAUP1 (MAX(1,P)) |
345 * | TAUP2 (MAX(1,M-P)) |
346 * | TAUQ1 (MAX(1,Q)) |
347 * |-----------------------------------------|
348 * | CUNBDB WORK | CUNGQR WORK | CUNGLQ WORK |
353 * |-----------------------------------------|
355 * |------------------|
357 * |------------------|
358 * | PHI (MAX(1,R-1)) |
359 * |------------------|
369 * |------------------|
371 IF( INFO .EQ. 0 ) THEN
373 IB11D = IPHI + MAX( 1, R-1 )
374 IB11E = IB11D + MAX( 1, R )
375 IB12D = IB11E + MAX( 1, R - 1 )
376 IB12E = IB12D + MAX( 1, R )
377 IB21D = IB12E + MAX( 1, R - 1 )
378 IB21E = IB21D + MAX( 1, R )
379 IB22D = IB21E + MAX( 1, R - 1 )
380 IB22E = IB22D + MAX( 1, R )
381 IBBCSD = IB22E + MAX( 1, R - 1 )
383 ITAUP2 = ITAUP1 + MAX( 1, P )
384 ITAUQ1 = ITAUP2 + MAX( 1, M-P )
385 IORBDB = ITAUQ1 + MAX( 1, Q )
386 IORGQR = ITAUQ1 + MAX( 1, Q )
387 IORGLQ = ITAUQ1 + MAX( 1, Q )
393 CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
394 $ DUM, CDUM, CDUM, CDUM, WORK, -1,
396 LORBDB = INT( WORK(1) )
397 IF( WANTU1 .AND. P .GT. 0 ) THEN
398 CALL CUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
400 LORGQRMIN = MAX( LORGQRMIN, P )
401 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
403 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
404 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
406 LORGQRMIN = MAX( LORGQRMIN, M-P )
407 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
409 IF( WANTV1T .AND. Q .GT. 0 ) THEN
410 CALL CUNGLQ( Q-1, Q-1, Q-1, V1T, LDV1T,
411 $ CDUM, WORK(1), -1, CHILDINFO )
412 LORGLQMIN = MAX( LORGLQMIN, Q-1 )
413 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
415 CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
416 $ DUM(1), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
417 $ 1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
418 $ RWORK(1), -1, CHILDINFO )
419 LBBCSD = INT( RWORK(1) )
420 ELSE IF( R .EQ. P ) THEN
421 CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
422 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
423 LORBDB = INT( WORK(1) )
424 IF( WANTU1 .AND. P .GT. 0 ) THEN
425 CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, CDUM, WORK(1),
427 LORGQRMIN = MAX( LORGQRMIN, P-1 )
428 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
430 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
431 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
433 LORGQRMIN = MAX( LORGQRMIN, M-P )
434 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
436 IF( WANTV1T .AND. Q .GT. 0 ) THEN
437 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
439 LORGLQMIN = MAX( LORGLQMIN, Q )
440 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
442 CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
443 $ DUM, V1T, LDV1T, CDUM, 1, U1, LDU1, U2, LDU2,
444 $ DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
445 $ RWORK(1), -1, CHILDINFO )
446 LBBCSD = INT( RWORK(1) )
447 ELSE IF( R .EQ. M-P ) THEN
448 CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
449 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
450 LORBDB = INT( WORK(1) )
451 IF( WANTU1 .AND. P .GT. 0 ) THEN
452 CALL CUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
454 LORGQRMIN = MAX( LORGQRMIN, P )
455 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
457 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
458 CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, CDUM,
459 $ WORK(1), -1, CHILDINFO )
460 LORGQRMIN = MAX( LORGQRMIN, M-P-1 )
461 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
463 IF( WANTV1T .AND. Q .GT. 0 ) THEN
464 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
466 LORGLQMIN = MAX( LORGLQMIN, Q )
467 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
469 CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
470 $ THETA, DUM, CDUM, 1, V1T, LDV1T, U2, LDU2, U1,
471 $ LDU1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
472 $ RWORK(1), -1, CHILDINFO )
473 LBBCSD = INT( RWORK(1) )
475 CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
476 $ CDUM, CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO
478 LORBDB = M + INT( WORK(1) )
479 IF( WANTU1 .AND. P .GT. 0 ) THEN
480 CALL CUNGQR( P, P, M-Q, U1, LDU1, CDUM, WORK(1), -1,
482 LORGQRMIN = MAX( LORGQRMIN, P )
483 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
485 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
486 CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, CDUM, WORK(1), -1,
488 LORGQRMIN = MAX( LORGQRMIN, M-P )
489 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
491 IF( WANTV1T .AND. Q .GT. 0 ) THEN
492 CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, CDUM, WORK(1), -1,
494 LORGLQMIN = MAX( LORGLQMIN, Q )
495 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
497 CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
498 $ THETA, DUM, U2, LDU2, U1, LDU1, CDUM, 1, V1T,
499 $ LDV1T, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
500 $ RWORK(1), -1, CHILDINFO )
501 LBBCSD = INT( RWORK(1) )
503 LRWORKMIN = IBBCSD+LBBCSD-1
504 LRWORKOPT = LRWORKMIN
506 LWORKMIN = MAX( IORBDB+LORBDB-1,
507 $ IORGQR+LORGQRMIN-1,
508 $ IORGLQ+LORGLQMIN-1 )
509 LWORKOPT = MAX( IORBDB+LORBDB-1,
510 $ IORGQR+LORGQROPT-1,
511 $ IORGLQ+LORGLQOPT-1 )
513 IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
517 IF( INFO .NE. 0 ) THEN
518 CALL XERBLA( 'CUNCSD2BY1', -INFO )
520 ELSE IF( LQUERY ) THEN
523 LORGQR = LWORK-IORGQR+1
524 LORGLQ = LWORK-IORGLQ+1
526 * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
527 * in which R = MIN(P,M-P,Q,M-Q)
533 * Simultaneously bidiagonalize X11 and X21
535 CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
536 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
537 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
539 * Accumulate Householder reflectors
541 IF( WANTU1 .AND. P .GT. 0 ) THEN
542 CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
543 CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
544 $ LORGQR, CHILDINFO )
546 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
547 CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
548 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
549 $ WORK(IORGQR), LORGQR, CHILDINFO )
551 IF( WANTV1T .AND. Q .GT. 0 ) THEN
557 CALL CLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
559 CALL CUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
560 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
563 * Simultaneously diagonalize X11 and X21.
565 CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
566 $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
567 $ 1, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
568 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
569 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
572 * Permute rows and columns to place zero submatrices in
573 * preferred positions
575 IF( Q .GT. 0 .AND. WANTU2 ) THEN
577 IWORK(I) = M - P - Q + I
582 CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
584 ELSE IF( R .EQ. P ) THEN
588 * Simultaneously bidiagonalize X11 and X21
590 CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
591 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
592 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
594 * Accumulate Householder reflectors
596 IF( WANTU1 .AND. P .GT. 0 ) THEN
602 CALL CLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
603 CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
604 $ WORK(IORGQR), LORGQR, CHILDINFO )
606 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
607 CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
608 CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
609 $ WORK(IORGQR), LORGQR, CHILDINFO )
611 IF( WANTV1T .AND. Q .GT. 0 ) THEN
612 CALL CLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
613 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
614 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
617 * Simultaneously diagonalize X11 and X21.
619 CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
620 $ RWORK(IPHI), V1T, LDV1T, CDUM, 1, U1, LDU1, U2,
621 $ LDU2, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
622 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
623 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
626 * Permute rows and columns to place identity submatrices in
627 * preferred positions
629 IF( Q .GT. 0 .AND. WANTU2 ) THEN
631 IWORK(I) = M - P - Q + I
636 CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
638 ELSE IF( R .EQ. M-P ) THEN
642 * Simultaneously bidiagonalize X11 and X21
644 CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
645 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
646 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
648 * Accumulate Householder reflectors
650 IF( WANTU1 .AND. P .GT. 0 ) THEN
651 CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
652 CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
653 $ LORGQR, CHILDINFO )
655 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
661 CALL CLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
663 CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
664 $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
666 IF( WANTV1T .AND. Q .GT. 0 ) THEN
667 CALL CLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
668 CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
669 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
672 * Simultaneously diagonalize X11 and X21.
674 CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
675 $ THETA, RWORK(IPHI), CDUM, 1, V1T, LDV1T, U2, LDU2,
676 $ U1, LDU1, RWORK(IB11D), RWORK(IB11E),
677 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
678 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
679 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
681 * Permute rows and columns to place identity submatrices in
682 * preferred positions
692 CALL CLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
695 CALL CLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
702 * Simultaneously bidiagonalize X11 and X21
704 CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
705 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
706 $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
707 $ LORBDB-M, CHILDINFO )
709 * Accumulate Householder reflectors
711 IF( WANTU1 .AND. P .GT. 0 ) THEN
712 CALL CCOPY( P, WORK(IORBDB), 1, U1, 1 )
716 CALL CLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
718 CALL CUNGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
719 $ WORK(IORGQR), LORGQR, CHILDINFO )
721 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
722 CALL CCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
726 CALL CLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
728 CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
729 $ WORK(IORGQR), LORGQR, CHILDINFO )
731 IF( WANTV1T .AND. Q .GT. 0 ) THEN
732 CALL CLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
733 CALL CLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
734 $ V1T(M-Q+1,M-Q+1), LDV1T )
735 CALL CLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
736 $ V1T(P+1,P+1), LDV1T )
737 CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
738 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
741 * Simultaneously diagonalize X11 and X21.
743 CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
744 $ THETA, RWORK(IPHI), U2, LDU2, U1, LDU1, CDUM, 1,
745 $ V1T, LDV1T, RWORK(IB11D), RWORK(IB11E),
746 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
747 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
748 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
750 * Permute rows and columns to place identity submatrices in
751 * preferred positions
761 CALL CLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
764 CALL CLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )