1 *> \brief \b ZUNCSD2BY1
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download ZUNCSD2BY1 + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zuncsd2by1.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zuncsd2by1.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zuncsd2by1.f">
21 * SUBROUTINE ZUNCSD2BY1( 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 ..
33 * DOUBLE PRECISION RWORK(*)
34 * DOUBLE PRECISION THETA(*)
35 * COMPLEX*16 U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
36 * $ X11(LDX11,*), X21(LDX21,*)
46 *> ZUNCSD2BY1 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).
70 *> = 'Y': U1 is computed;
71 *> otherwise: U1 is not computed.
77 *> = 'Y': U2 is computed;
78 *> otherwise: U2 is not computed.
83 *> JOBV1T is CHARACTER
84 *> = 'Y': V1T is computed;
85 *> otherwise: V1T is not computed.
91 *> The number of rows in X.
97 *> The number of rows in X11. 0 <= P <= M.
103 *> The number of columns in X11 and X21. 0 <= Q <= M.
106 *> \param[in,out] X11
108 *> X11 is COMPLEX*16 array, dimension (LDX11,Q)
109 *> On entry, part of the unitary matrix whose CSD is desired.
115 *> The leading dimension of X11. LDX11 >= MAX(1,P).
118 *> \param[in,out] X21
120 *> X21 is COMPLEX*16 array, dimension (LDX21,Q)
121 *> On entry, part of the unitary matrix whose CSD is desired.
127 *> The leading dimension of X21. LDX21 >= MAX(1,M-P).
132 *> THETA is DOUBLE PRECISION array, dimension (R), in which R =
134 *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
135 *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
140 *> U1 is COMPLEX*16 array, dimension (P)
141 *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
147 *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
153 *> U2 is COMPLEX*16 array, dimension (M-P)
154 *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
161 *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
167 *> V1T is COMPLEX*16 array, dimension (Q)
168 *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
175 *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
181 *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
182 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
188 *> The dimension of the array WORK.
190 *> If LWORK = -1, then a workspace query is assumed; the routine
191 *> only calculates the optimal size of the WORK array, returns
192 *> this value as the first entry of the work array, and no error
193 *> message related to LWORK is issued by XERBLA.
198 *> RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
199 *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
200 *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
201 *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
202 *> define the matrix in intermediate bidiagonal-block form
203 *> remaining after nonconvergence. INFO specifies the number
210 *> The dimension of the array RWORK.
212 *> If LRWORK = -1, then a workspace query is assumed; the routine
213 *> only calculates the optimal size of the RWORK array, returns
214 *> this value as the first entry of the work array, and no error
215 *> message related to LRWORK is issued by XERBLA.
220 *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
226 *> = 0: successful exit.
227 *> < 0: if INFO = -i, the i-th argument had an illegal value.
228 *> > 0: ZBBCSD did not converge. See the description of WORK
229 *> above for details.
235 *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
236 *> Algorithms, 50(1):33-65, 2009.
241 *> \author Univ. of Tennessee
242 *> \author Univ. of California Berkeley
243 *> \author Univ. of Colorado Denver
248 *> \ingroup complex16OTHERcomputational
250 * =====================================================================
251 SUBROUTINE ZUNCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
252 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
253 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
256 * -- LAPACK computational routine (version 3.6.1) --
257 * -- LAPACK is a software package provided by Univ. of Tennessee, --
258 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
261 * .. Scalar Arguments ..
262 CHARACTER JOBU1, JOBU2, JOBV1T
263 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
265 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
267 * .. Array Arguments ..
268 DOUBLE PRECISION RWORK(*)
269 DOUBLE PRECISION THETA(*)
270 COMPLEX*16 U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
271 $ X11(LDX11,*), X21(LDX21,*)
275 * =====================================================================
279 PARAMETER ( ONE = (1.0D0,0.0D0), ZERO = (0.0D0,0.0D0) )
281 * .. Local Scalars ..
282 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
283 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
284 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
285 $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
286 $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
287 $ LWORKMIN, LWORKOPT, R
288 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
291 DOUBLE PRECISION DUM( 1 )
292 COMPLEX*16 CDUM( 1, 1 )
294 * .. External Subroutines ..
295 EXTERNAL ZBBCSD, ZCOPY, ZLACPY, ZLAPMR, ZLAPMT, ZUNBDB1,
296 $ ZUNBDB2, ZUNBDB3, ZUNBDB4, ZUNGLQ, ZUNGQR,
299 * .. External Functions ..
303 * .. Intrinsic Function ..
304 INTRINSIC INT, MAX, MIN
306 * .. Executable Statements ..
308 * Test input arguments
311 WANTU1 = LSAME( JOBU1, 'Y' )
312 WANTU2 = LSAME( JOBU2, 'Y' )
313 WANTV1T = LSAME( JOBV1T, 'Y' )
314 LQUERY = LWORK .EQ. -1
318 ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
320 ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
322 ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
324 ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
326 ELSE IF( WANTU1 .AND. LDU1 .LT. MAX( 1, P ) ) THEN
328 ELSE IF( WANTU2 .AND. LDU2 .LT. MAX( 1, M - P ) ) THEN
330 ELSE IF( WANTV1T .AND. LDV1T .LT. MAX( 1, Q ) ) THEN
334 R = MIN( P, M-P, Q, M-Q )
339 * |-----------------------------------------|
341 * |-----------------------------------------|
342 * | TAUP1 (MAX(1,P)) |
343 * | TAUP2 (MAX(1,M-P)) |
344 * | TAUQ1 (MAX(1,Q)) |
345 * |-----------------------------------------|
346 * | ZUNBDB WORK | ZUNGQR WORK | ZUNGLQ WORK |
351 * |-----------------------------------------|
353 * |------------------|
355 * |------------------|
356 * | PHI (MAX(1,R-1)) |
357 * |------------------|
367 * |------------------|
369 IF( INFO .EQ. 0 ) THEN
371 IB11D = IPHI + MAX( 1, R-1 )
372 IB11E = IB11D + MAX( 1, R )
373 IB12D = IB11E + MAX( 1, R - 1 )
374 IB12E = IB12D + MAX( 1, R )
375 IB21D = IB12E + MAX( 1, R - 1 )
376 IB21E = IB21D + MAX( 1, R )
377 IB22D = IB21E + MAX( 1, R - 1 )
378 IB22E = IB22D + MAX( 1, R )
379 IBBCSD = IB22E + MAX( 1, R - 1 )
381 ITAUP2 = ITAUP1 + MAX( 1, P )
382 ITAUQ1 = ITAUP2 + MAX( 1, M-P )
383 IORBDB = ITAUQ1 + MAX( 1, Q )
384 IORGQR = ITAUQ1 + MAX( 1, Q )
385 IORGLQ = ITAUQ1 + MAX( 1, Q )
391 CALL ZUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
392 $ CDUM, CDUM, CDUM, WORK, -1, CHILDINFO )
393 LORBDB = INT( WORK(1) )
394 IF( WANTU1 .AND. P .GT. 0 ) THEN
395 CALL ZUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
397 LORGQRMIN = MAX( LORGQRMIN, P )
398 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
400 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
401 CALL ZUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
403 LORGQRMIN = MAX( LORGQRMIN, M-P )
404 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
406 IF( WANTV1T .AND. Q .GT. 0 ) THEN
407 CALL ZUNGLQ( Q-1, Q-1, Q-1, V1T, LDV1T,
408 $ CDUM, WORK(1), -1, CHILDINFO )
409 LORGLQMIN = MAX( LORGLQMIN, Q-1 )
410 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
412 CALL ZBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
413 $ DUM, U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM, 1,
414 $ DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
415 $ RWORK(1), -1, CHILDINFO )
416 LBBCSD = INT( RWORK(1) )
417 ELSE IF( R .EQ. P ) THEN
418 CALL ZUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
419 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
420 LORBDB = INT( WORK(1) )
421 IF( WANTU1 .AND. P .GT. 0 ) THEN
422 CALL ZUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, CDUM, WORK(1),
424 LORGQRMIN = MAX( LORGQRMIN, P-1 )
425 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
427 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
428 CALL ZUNGQR( M-P, M-P, Q, U2, LDU2, CDUM, WORK(1), -1,
430 LORGQRMIN = MAX( LORGQRMIN, M-P )
431 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
433 IF( WANTV1T .AND. Q .GT. 0 ) THEN
434 CALL ZUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
436 LORGLQMIN = MAX( LORGLQMIN, Q )
437 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
439 CALL ZBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
440 $ DUM, V1T, LDV1T, CDUM, 1, U1, LDU1, U2, LDU2,
441 $ DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
442 $ RWORK(1), -1, CHILDINFO )
443 LBBCSD = INT( RWORK(1) )
444 ELSE IF( R .EQ. M-P ) THEN
445 CALL ZUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
446 $ CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO )
447 LORBDB = INT( WORK(1) )
448 IF( WANTU1 .AND. P .GT. 0 ) THEN
449 CALL ZUNGQR( P, P, Q, U1, LDU1, CDUM, WORK(1), -1,
451 LORGQRMIN = MAX( LORGQRMIN, P )
452 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
454 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
455 CALL ZUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, CDUM,
456 $ WORK(1), -1, CHILDINFO )
457 LORGQRMIN = MAX( LORGQRMIN, M-P-1 )
458 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
460 IF( WANTV1T .AND. Q .GT. 0 ) THEN
461 CALL ZUNGLQ( Q, Q, R, V1T, LDV1T, CDUM, WORK(1), -1,
463 LORGLQMIN = MAX( LORGLQMIN, Q )
464 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
466 CALL ZBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
467 $ THETA, DUM, CDUM, 1, V1T, LDV1T, U2, LDU2, U1,
468 $ LDU1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
469 $ RWORK(1), -1, CHILDINFO )
470 LBBCSD = INT( RWORK(1) )
472 CALL ZUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
473 $ CDUM, CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO
475 LORBDB = M + INT( WORK(1) )
476 IF( WANTU1 .AND. P .GT. 0 ) THEN
477 CALL ZUNGQR( P, P, M-Q, U1, LDU1, CDUM, WORK(1), -1,
479 LORGQRMIN = MAX( LORGQRMIN, P )
480 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
482 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
483 CALL ZUNGQR( M-P, M-P, M-Q, U2, LDU2, CDUM, WORK(1), -1,
485 LORGQRMIN = MAX( LORGQRMIN, M-P )
486 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
488 IF( WANTV1T .AND. Q .GT. 0 ) THEN
489 CALL ZUNGLQ( Q, Q, Q, V1T, LDV1T, CDUM, WORK(1), -1,
491 LORGLQMIN = MAX( LORGLQMIN, Q )
492 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
494 CALL ZBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
495 $ THETA, DUM, U2, LDU2, U1, LDU1, CDUM, 1, V1T,
496 $ LDV1T, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
497 $ RWORK(1), -1, CHILDINFO )
498 LBBCSD = INT( RWORK(1) )
500 LRWORKMIN = IBBCSD+LBBCSD-1
501 LRWORKOPT = LRWORKMIN
503 LWORKMIN = MAX( IORBDB+LORBDB-1,
504 $ IORGQR+LORGQRMIN-1,
505 $ IORGLQ+LORGLQMIN-1 )
506 LWORKOPT = MAX( IORBDB+LORBDB-1,
507 $ IORGQR+LORGQROPT-1,
508 $ IORGLQ+LORGLQOPT-1 )
510 IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
514 IF( INFO .NE. 0 ) THEN
515 CALL XERBLA( 'ZUNCSD2BY1', -INFO )
517 ELSE IF( LQUERY ) THEN
520 LORGQR = LWORK-IORGQR+1
521 LORGLQ = LWORK-IORGLQ+1
523 * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
524 * in which R = MIN(P,M-P,Q,M-Q)
530 * Simultaneously bidiagonalize X11 and X21
532 CALL ZUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
533 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
534 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
536 * Accumulate Householder reflectors
538 IF( WANTU1 .AND. P .GT. 0 ) THEN
539 CALL ZLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
540 CALL ZUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
541 $ LORGQR, CHILDINFO )
543 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
544 CALL ZLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
545 CALL ZUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
546 $ WORK(IORGQR), LORGQR, CHILDINFO )
548 IF( WANTV1T .AND. Q .GT. 0 ) THEN
554 CALL ZLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
556 CALL ZUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
557 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
560 * Simultaneously diagonalize X11 and X21.
562 CALL ZBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
563 $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
564 $ 1, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
565 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
566 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
569 * Permute rows and columns to place zero submatrices in
570 * preferred positions
572 IF( Q .GT. 0 .AND. WANTU2 ) THEN
574 IWORK(I) = M - P - Q + I
579 CALL ZLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
581 ELSE IF( R .EQ. P ) THEN
585 * Simultaneously bidiagonalize X11 and X21
587 CALL ZUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
588 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
589 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
591 * Accumulate Householder reflectors
593 IF( WANTU1 .AND. P .GT. 0 ) THEN
599 CALL ZLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
600 CALL ZUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
601 $ WORK(IORGQR), LORGQR, CHILDINFO )
603 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
604 CALL ZLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
605 CALL ZUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
606 $ WORK(IORGQR), LORGQR, CHILDINFO )
608 IF( WANTV1T .AND. Q .GT. 0 ) THEN
609 CALL ZLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
610 CALL ZUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
611 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
614 * Simultaneously diagonalize X11 and X21.
616 CALL ZBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
617 $ RWORK(IPHI), V1T, LDV1T, CDUM, 1, U1, LDU1, U2,
618 $ LDU2, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
619 $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
620 $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
623 * Permute rows and columns to place identity submatrices in
624 * preferred positions
626 IF( Q .GT. 0 .AND. WANTU2 ) THEN
628 IWORK(I) = M - P - Q + I
633 CALL ZLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
635 ELSE IF( R .EQ. M-P ) THEN
639 * Simultaneously bidiagonalize X11 and X21
641 CALL ZUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
642 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
643 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
645 * Accumulate Householder reflectors
647 IF( WANTU1 .AND. P .GT. 0 ) THEN
648 CALL ZLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
649 CALL ZUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
650 $ LORGQR, CHILDINFO )
652 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
658 CALL ZLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
660 CALL ZUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
661 $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
663 IF( WANTV1T .AND. Q .GT. 0 ) THEN
664 CALL ZLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
665 CALL ZUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
666 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
669 * Simultaneously diagonalize X11 and X21.
671 CALL ZBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
672 $ THETA, RWORK(IPHI), CDUM, 1, V1T, LDV1T, U2, LDU2,
673 $ U1, LDU1, RWORK(IB11D), RWORK(IB11E),
674 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
675 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
676 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
678 * Permute rows and columns to place identity submatrices in
679 * preferred positions
689 CALL ZLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
692 CALL ZLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
699 * Simultaneously bidiagonalize X11 and X21
701 CALL ZUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
702 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
703 $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
704 $ LORBDB-M, CHILDINFO )
706 * Accumulate Householder reflectors
708 IF( WANTU1 .AND. P .GT. 0 ) THEN
709 CALL ZCOPY( P, WORK(IORBDB), 1, U1, 1 )
713 CALL ZLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
715 CALL ZUNGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
716 $ WORK(IORGQR), LORGQR, CHILDINFO )
718 IF( WANTU2 .AND. M-P .GT. 0 ) THEN
719 CALL ZCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
723 CALL ZLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
725 CALL ZUNGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
726 $ WORK(IORGQR), LORGQR, CHILDINFO )
728 IF( WANTV1T .AND. Q .GT. 0 ) THEN
729 CALL ZLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
730 CALL ZLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
731 $ V1T(M-Q+1,M-Q+1), LDV1T )
732 CALL ZLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
733 $ V1T(P+1,P+1), LDV1T )
734 CALL ZUNGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
735 $ WORK(IORGLQ), LORGLQ, CHILDINFO )
738 * Simultaneously diagonalize X11 and X21.
740 CALL ZBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
741 $ THETA, RWORK(IPHI), U2, LDU2, U1, LDU1, CDUM, 1,
742 $ V1T, LDV1T, RWORK(IB11D), RWORK(IB11E),
743 $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
744 $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
745 $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
747 * Permute rows and columns to place identity submatrices in
748 * preferred positions
758 CALL ZLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
761 CALL ZLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )