LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zuncsd.f
Go to the documentation of this file.
1*> \brief \b ZUNCSD
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZUNCSD + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zuncsd.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zuncsd.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zuncsd.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* RECURSIVE SUBROUTINE ZUNCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
20* SIGNS, M, P, Q, X11, LDX11, X12,
21* LDX12, X21, LDX21, X22, LDX22, THETA,
22* U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
23* LDV2T, WORK, LWORK, RWORK, LRWORK,
24* IWORK, INFO )
25*
26* .. Scalar Arguments ..
27* CHARACTER JOBU1, JOBU2, JOBV1T, JOBV2T, SIGNS, TRANS
28* INTEGER INFO, LDU1, LDU2, LDV1T, LDV2T, LDX11, LDX12,
29* $ LDX21, LDX22, LRWORK, LWORK, M, P, Q
30* ..
31* .. Array Arguments ..
32* INTEGER IWORK( * )
33* DOUBLE PRECISION THETA( * )
34* DOUBLE PRECISION RWORK( * )
35* COMPLEX*16 U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
36* $ V2T( LDV2T, * ), WORK( * ), X11( LDX11, * ),
37* $ X12( LDX12, * ), X21( LDX21, * ), X22( LDX22,
38* $ * )
39* ..
40*
41*
42*> \par Purpose:
43* =============
44*>
45*> \verbatim
46*>
47*> ZUNCSD computes the CS decomposition of an M-by-M partitioned
48*> unitary matrix X:
49*>
50*> [ I 0 0 | 0 0 0 ]
51*> [ 0 C 0 | 0 -S 0 ]
52*> [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H
53*> X = [-----------] = [---------] [---------------------] [---------] .
54*> [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ]
55*> [ 0 S 0 | 0 C 0 ]
56*> [ 0 0 I | 0 0 0 ]
57*>
58*> X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P,
59*> (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
60*> R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
61*> which R = MIN(P,M-P,Q,M-Q).
62*> \endverbatim
63*
64* Arguments:
65* ==========
66*
67*> \param[in] JOBU1
68*> \verbatim
69*> JOBU1 is CHARACTER
70*> = 'Y': U1 is computed;
71*> otherwise: U1 is not computed.
72*> \endverbatim
73*>
74*> \param[in] JOBU2
75*> \verbatim
76*> JOBU2 is CHARACTER
77*> = 'Y': U2 is computed;
78*> otherwise: U2 is not computed.
79*> \endverbatim
80*>
81*> \param[in] JOBV1T
82*> \verbatim
83*> JOBV1T is CHARACTER
84*> = 'Y': V1T is computed;
85*> otherwise: V1T is not computed.
86*> \endverbatim
87*>
88*> \param[in] JOBV2T
89*> \verbatim
90*> JOBV2T is CHARACTER
91*> = 'Y': V2T is computed;
92*> otherwise: V2T is not computed.
93*> \endverbatim
94*>
95*> \param[in] TRANS
96*> \verbatim
97*> TRANS is CHARACTER
98*> = 'T': X, U1, U2, V1T, and V2T are stored in row-major
99*> order;
100*> otherwise: X, U1, U2, V1T, and V2T are stored in column-
101*> major order.
102*> \endverbatim
103*>
104*> \param[in] SIGNS
105*> \verbatim
106*> SIGNS is CHARACTER
107*> = 'O': The lower-left block is made nonpositive (the
108*> "other" convention);
109*> otherwise: The upper-right block is made nonpositive (the
110*> "default" convention).
111*> \endverbatim
112*>
113*> \param[in] M
114*> \verbatim
115*> M is INTEGER
116*> The number of rows and columns in X.
117*> \endverbatim
118*>
119*> \param[in] P
120*> \verbatim
121*> P is INTEGER
122*> The number of rows in X11 and X12. 0 <= P <= M.
123*> \endverbatim
124*>
125*> \param[in] Q
126*> \verbatim
127*> Q is INTEGER
128*> The number of columns in X11 and X21. 0 <= Q <= M.
129*> \endverbatim
130*>
131*> \param[in,out] X11
132*> \verbatim
133*> X11 is COMPLEX*16 array, dimension (LDX11,Q)
134*> On entry, part of the unitary matrix whose CSD is desired.
135*> \endverbatim
136*>
137*> \param[in] LDX11
138*> \verbatim
139*> LDX11 is INTEGER
140*> The leading dimension of X11. LDX11 >= MAX(1,P).
141*> \endverbatim
142*>
143*> \param[in,out] X12
144*> \verbatim
145*> X12 is COMPLEX*16 array, dimension (LDX12,M-Q)
146*> On entry, part of the unitary matrix whose CSD is desired.
147*> \endverbatim
148*>
149*> \param[in] LDX12
150*> \verbatim
151*> LDX12 is INTEGER
152*> The leading dimension of X12. LDX12 >= MAX(1,P).
153*> \endverbatim
154*>
155*> \param[in,out] X21
156*> \verbatim
157*> X21 is COMPLEX*16 array, dimension (LDX21,Q)
158*> On entry, part of the unitary matrix whose CSD is desired.
159*> \endverbatim
160*>
161*> \param[in] LDX21
162*> \verbatim
163*> LDX21 is INTEGER
164*> The leading dimension of X11. LDX21 >= MAX(1,M-P).
165*> \endverbatim
166*>
167*> \param[in,out] X22
168*> \verbatim
169*> X22 is COMPLEX*16 array, dimension (LDX22,M-Q)
170*> On entry, part of the unitary matrix whose CSD is desired.
171*> \endverbatim
172*>
173*> \param[in] LDX22
174*> \verbatim
175*> LDX22 is INTEGER
176*> The leading dimension of X11. LDX22 >= MAX(1,M-P).
177*> \endverbatim
178*>
179*> \param[out] THETA
180*> \verbatim
181*> THETA is DOUBLE PRECISION array, dimension (R), in which R =
182*> MIN(P,M-P,Q,M-Q).
183*> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
184*> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
185*> \endverbatim
186*>
187*> \param[out] U1
188*> \verbatim
189*> U1 is COMPLEX*16 array, dimension (LDU1,P)
190*> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
191*> \endverbatim
192*>
193*> \param[in] LDU1
194*> \verbatim
195*> LDU1 is INTEGER
196*> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
197*> MAX(1,P).
198*> \endverbatim
199*>
200*> \param[out] U2
201*> \verbatim
202*> U2 is COMPLEX*16 array, dimension (LDU2,M-P)
203*> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
204*> matrix U2.
205*> \endverbatim
206*>
207*> \param[in] LDU2
208*> \verbatim
209*> LDU2 is INTEGER
210*> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
211*> MAX(1,M-P).
212*> \endverbatim
213*>
214*> \param[out] V1T
215*> \verbatim
216*> V1T is COMPLEX*16 array, dimension (LDV1T,Q)
217*> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
218*> matrix V1**H.
219*> \endverbatim
220*>
221*> \param[in] LDV1T
222*> \verbatim
223*> LDV1T is INTEGER
224*> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
225*> MAX(1,Q).
226*> \endverbatim
227*>
228*> \param[out] V2T
229*> \verbatim
230*> V2T is COMPLEX*16 array, dimension (LDV2T,M-Q)
231*> If JOBV2T = 'Y', V2T contains the (M-Q)-by-(M-Q) unitary
232*> matrix V2**H.
233*> \endverbatim
234*>
235*> \param[in] LDV2T
236*> \verbatim
237*> LDV2T is INTEGER
238*> The leading dimension of V2T. If JOBV2T = 'Y', LDV2T >=
239*> MAX(1,M-Q).
240*> \endverbatim
241*>
242*> \param[out] WORK
243*> \verbatim
244*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
245*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
246*> \endverbatim
247*>
248*> \param[in] LWORK
249*> \verbatim
250*> LWORK is INTEGER
251*> The dimension of the array WORK.
252*>
253*> If LWORK = -1, then a workspace query is assumed; the routine
254*> only calculates the optimal size of the WORK array, returns
255*> this value as the first entry of the work array, and no error
256*> message related to LWORK is issued by XERBLA.
257*> \endverbatim
258*>
259*> \param[out] RWORK
260*> \verbatim
261*> RWORK is DOUBLE PRECISION array, dimension MAX(1,LRWORK)
262*> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
263*> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
264*> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
265*> define the matrix in intermediate bidiagonal-block form
266*> remaining after nonconvergence. INFO specifies the number
267*> of nonzero PHI's.
268*> \endverbatim
269*>
270*> \param[in] LRWORK
271*> \verbatim
272*> LRWORK is INTEGER
273*> The dimension of the array RWORK.
274*>
275*> If LRWORK = -1, then a workspace query is assumed; the routine
276*> only calculates the optimal size of the RWORK array, returns
277*> this value as the first entry of the work array, and no error
278*> message related to LRWORK is issued by XERBLA.
279*> \endverbatim
280*>
281*> \param[out] IWORK
282*> \verbatim
283*> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
284*> \endverbatim
285*>
286*> \param[out] INFO
287*> \verbatim
288*> INFO is INTEGER
289*> = 0: successful exit.
290*> < 0: if INFO = -i, the i-th argument had an illegal value.
291*> > 0: ZBBCSD did not converge. See the description of RWORK
292*> above for details.
293*> \endverbatim
294*
295*> \par References:
296* ================
297*>
298*> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
299*> Algorithms, 50(1):33-65, 2009.
300*
301* Authors:
302* ========
303*
304*> \author Univ. of Tennessee
305*> \author Univ. of California Berkeley
306*> \author Univ. of Colorado Denver
307*> \author NAG Ltd.
308*
309*> \ingroup uncsd
310*
311* =====================================================================
312 RECURSIVE SUBROUTINE zuncsd( JOBU1, JOBU2, JOBV1T, JOBV2T,
313 $ TRANS,
314 $ SIGNS, M, P, Q, X11, LDX11, X12,
315 $ LDX12, X21, LDX21, X22, LDX22, THETA,
316 $ U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
317 $ LDV2T, WORK, LWORK, RWORK, LRWORK,
318 $ IWORK, INFO )
319*
320* -- LAPACK computational routine --
321* -- LAPACK is a software package provided by Univ. of Tennessee, --
322* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
323*
324* .. Scalar Arguments ..
325 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
326 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12,
327 $ ldx21, ldx22, lrwork, lwork, m, p, q
328* ..
329* .. Array Arguments ..
330 INTEGER iwork( * )
331 DOUBLE PRECISION theta( * )
332 DOUBLE PRECISION rwork( * )
333 COMPLEX*16 u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
334 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
335 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
336 $ * )
337* ..
338*
339* ===================================================================
340*
341* .. Parameters ..
342 COMPLEX*16 one, zero
343 PARAMETER ( one = (1.0d0,0.0d0),
344 $ zero = (0.0d0,0.0d0) )
345* ..
346* .. Local Scalars ..
347 CHARACTER transt, signst
348 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
349 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
350 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
351 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
352 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
353 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
354 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
355 $ lorgqrworkopt, lworkmin, lworkopt, p1, q1
356 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
357 $ wantv1t, wantv2t
358 INTEGER lrworkmin, lrworkopt
359 LOGICAL lrquery
360* ..
361* .. External Subroutines ..
362 EXTERNAL xerbla, zbbcsd, zlacpy, zlapmr,
363 $ zlapmt,
365* ..
366* .. External Functions ..
367 LOGICAL lsame
368 EXTERNAL lsame
369* ..
370* .. Intrinsic Functions
371 INTRINSIC int, max, min
372* ..
373* .. Executable Statements ..
374*
375* Test input arguments
376*
377 info = 0
378 wantu1 = lsame( jobu1, 'Y' )
379 wantu2 = lsame( jobu2, 'Y' )
380 wantv1t = lsame( jobv1t, 'Y' )
381 wantv2t = lsame( jobv2t, 'Y' )
382 colmajor = .NOT. lsame( trans, 'T' )
383 defaultsigns = .NOT. lsame( signs, 'O' )
384 lquery = lwork .EQ. -1
385 lrquery = lrwork .EQ. -1
386 IF( m .LT. 0 ) THEN
387 info = -7
388 ELSE IF( p .LT. 0 .OR. p .GT. m ) THEN
389 info = -8
390 ELSE IF( q .LT. 0 .OR. q .GT. m ) THEN
391 info = -9
392 ELSE IF ( colmajor .AND. ldx11 .LT. max( 1, p ) ) THEN
393 info = -11
394 ELSE IF (.NOT. colmajor .AND. ldx11 .LT. max( 1, q ) ) THEN
395 info = -11
396 ELSE IF (colmajor .AND. ldx12 .LT. max( 1, p ) ) THEN
397 info = -13
398 ELSE IF (.NOT. colmajor .AND. ldx12 .LT. max( 1, m-q ) ) THEN
399 info = -13
400 ELSE IF (colmajor .AND. ldx21 .LT. max( 1, m-p ) ) THEN
401 info = -15
402 ELSE IF (.NOT. colmajor .AND. ldx21 .LT. max( 1, q ) ) THEN
403 info = -15
404 ELSE IF (colmajor .AND. ldx22 .LT. max( 1, m-p ) ) THEN
405 info = -17
406 ELSE IF (.NOT. colmajor .AND. ldx22 .LT. max( 1, m-q ) ) THEN
407 info = -17
408 ELSE IF( wantu1 .AND. ldu1 .LT. p ) THEN
409 info = -20
410 ELSE IF( wantu2 .AND. ldu2 .LT. m-p ) THEN
411 info = -22
412 ELSE IF( wantv1t .AND. ldv1t .LT. q ) THEN
413 info = -24
414 ELSE IF( wantv2t .AND. ldv2t .LT. m-q ) THEN
415 info = -26
416 END IF
417*
418* Work with transpose if convenient
419*
420 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) ) THEN
421 IF( colmajor ) THEN
422 transt = 'T'
423 ELSE
424 transt = 'N'
425 END IF
426 IF( defaultsigns ) THEN
427 signst = 'O'
428 ELSE
429 signst = 'D'
430 END IF
431 CALL zuncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst,
432 $ m,
433 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
434 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
435 $ u2, ldu2, work, lwork, rwork, lrwork, iwork,
436 $ info )
437 RETURN
438 END IF
439*
440* Work with permutation [ 0 I; I 0 ] * X * [ 0 I; I 0 ] if
441* convenient
442*
443 IF( info .EQ. 0 .AND. m-q .LT. q ) THEN
444 IF( defaultsigns ) THEN
445 signst = 'O'
446 ELSE
447 signst = 'D'
448 END IF
449 CALL zuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
450 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
451 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
452 $ ldv1t, work, lwork, rwork, lrwork, iwork, info )
453 RETURN
454 END IF
455*
456* Compute workspace
457*
458 IF( info .EQ. 0 ) THEN
459*
460* Real workspace
461*
462 iphi = 2
463 ib11d = iphi + max( 1, q - 1 )
464 ib11e = ib11d + max( 1, q )
465 ib12d = ib11e + max( 1, q - 1 )
466 ib12e = ib12d + max( 1, q )
467 ib21d = ib12e + max( 1, q - 1 )
468 ib21e = ib21d + max( 1, q )
469 ib22d = ib21e + max( 1, q - 1 )
470 ib22e = ib22d + max( 1, q )
471 ibbcsd = ib22e + max( 1, q - 1 )
472 CALL zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
473 $ theta, theta, u1, ldu1, u2, ldu2, v1t, ldv1t,
474 $ v2t, ldv2t, theta, theta, theta, theta, theta,
475 $ theta, theta, theta, rwork, -1, childinfo )
476 lbbcsdworkopt = int( rwork(1) )
477 lbbcsdworkmin = lbbcsdworkopt
478 lrworkopt = ibbcsd + lbbcsdworkopt - 1
479 lrworkmin = ibbcsd + lbbcsdworkmin - 1
480 rwork(1) = lrworkopt
481*
482* Complex workspace
483*
484 itaup1 = 2
485 itaup2 = itaup1 + max( 1, p )
486 itauq1 = itaup2 + max( 1, m - p )
487 itauq2 = itauq1 + max( 1, q )
488 iorgqr = itauq2 + max( 1, m - q )
489 CALL zungqr( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
490 $ childinfo )
491 lorgqrworkopt = int( work(1) )
492 lorgqrworkmin = max( 1, m - q )
493 iorglq = itauq2 + max( 1, m - q )
494 CALL zunglq( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
495 $ childinfo )
496 lorglqworkopt = int( work(1) )
497 lorglqworkmin = max( 1, m - q )
498 iorbdb = itauq2 + max( 1, m - q )
499 CALL zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
500 $ x21, ldx21, x22, ldx22, theta, theta, u1, u2,
501 $ v1t, v2t, work, -1, childinfo )
502 lorbdbworkopt = int( work(1) )
503 lorbdbworkmin = lorbdbworkopt
504 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
505 $ iorbdb + lorbdbworkopt ) - 1
506 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
507 $ iorbdb + lorbdbworkmin ) - 1
508 work(1) = max(lworkopt,lworkmin)
509*
510 IF( lwork .LT. lworkmin
511 $ .AND. .NOT. ( lquery .OR. lrquery ) ) THEN
512 info = -22
513 ELSE IF( lrwork .LT. lrworkmin
514 $ .AND. .NOT. ( lquery .OR. lrquery ) ) THEN
515 info = -24
516 ELSE
517 lorgqrwork = lwork - iorgqr + 1
518 lorglqwork = lwork - iorglq + 1
519 lorbdbwork = lwork - iorbdb + 1
520 lbbcsdwork = lrwork - ibbcsd + 1
521 END IF
522 END IF
523*
524* Abort if any illegal arguments
525*
526 IF( info .NE. 0 ) THEN
527 CALL xerbla( 'ZUNCSD', -info )
528 RETURN
529 ELSE IF( lquery .OR. lrquery ) THEN
530 RETURN
531 END IF
532*
533* Transform to bidiagonal block form
534*
535 CALL zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
536 $ x21,
537 $ ldx21, x22, ldx22, theta, rwork(iphi), work(itaup1),
538 $ work(itaup2), work(itauq1), work(itauq2),
539 $ work(iorbdb), lorbdbwork, childinfo )
540*
541* Accumulate Householder reflectors
542*
543 IF( colmajor ) THEN
544 IF( wantu1 .AND. p .GT. 0 ) THEN
545 CALL zlacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
546 CALL zungqr( p, p, q, u1, ldu1, work(itaup1),
547 $ work(iorgqr),
548 $ lorgqrwork, info)
549 END IF
550 IF( wantu2 .AND. m-p .GT. 0 ) THEN
551 CALL zlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
552 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
553 $ work(iorgqr), lorgqrwork, info )
554 END IF
555 IF( wantv1t .AND. q .GT. 0 ) THEN
556 CALL zlacpy( 'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
557 $ ldv1t )
558 v1t(1, 1) = one
559 DO j = 2, q
560 v1t(1,j) = zero
561 v1t(j,1) = zero
562 END DO
563 CALL zunglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
564 $ work(itauq1),
565 $ work(iorglq), lorglqwork, info )
566 END IF
567 IF( wantv2t .AND. m-q .GT. 0 ) THEN
568 CALL zlacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t )
569 IF( m-p .GT. q) THEN
570 CALL zlacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
571 $ v2t(p+1,p+1), ldv2t )
572 END IF
573 IF( m .GT. q ) THEN
574 CALL zunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
575 $ work(iorglq), lorglqwork, info )
576 END IF
577 END IF
578 ELSE
579 IF( wantu1 .AND. p .GT. 0 ) THEN
580 CALL zlacpy( 'U', q, p, x11, ldx11, u1, ldu1 )
581 CALL zunglq( p, p, q, u1, ldu1, work(itaup1),
582 $ work(iorglq),
583 $ lorglqwork, info)
584 END IF
585 IF( wantu2 .AND. m-p .GT. 0 ) THEN
586 CALL zlacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 )
587 CALL zunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
588 $ work(iorglq), lorglqwork, info )
589 END IF
590 IF( wantv1t .AND. q .GT. 0 ) THEN
591 CALL zlacpy( 'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
592 $ ldv1t )
593 v1t(1, 1) = one
594 DO j = 2, q
595 v1t(1,j) = zero
596 v1t(j,1) = zero
597 END DO
598 CALL zungqr( q-1, q-1, q-1, v1t(2,2), ldv1t,
599 $ work(itauq1),
600 $ work(iorgqr), lorgqrwork, info )
601 END IF
602 IF( wantv2t .AND. m-q .GT. 0 ) THEN
603 p1 = min( p+1, m )
604 q1 = min( q+1, m )
605 CALL zlacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t )
606 IF( m .GT. p+q ) THEN
607 CALL zlacpy( 'L', m-p-q, m-p-q, x22(p1,q1), ldx22,
608 $ v2t(p+1,p+1), ldv2t )
609 END IF
610 CALL zungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
611 $ work(iorgqr), lorgqrwork, info )
612 END IF
613 END IF
614*
615* Compute the CSD of the matrix in bidiagonal-block form
616*
617 CALL zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
618 $ theta,
619 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
620 $ ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),
621 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
622 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
623 $ lbbcsdwork, info )
624*
625* Permute rows and columns to place identity submatrices in top-
626* left corner of (1,1)-block and/or bottom-right corner of (1,2)-
627* block and/or bottom-right corner of (2,1)-block and/or top-left
628* corner of (2,2)-block
629*
630 IF( q .GT. 0 .AND. wantu2 ) THEN
631 DO i = 1, q
632 iwork(i) = m - p - q + i
633 END DO
634 DO i = q + 1, m - p
635 iwork(i) = i - q
636 END DO
637 IF( colmajor ) THEN
638 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
639 ELSE
640 CALL zlapmr( .false., m-p, m-p, u2, ldu2, iwork )
641 END IF
642 END IF
643 IF( m .GT. 0 .AND. wantv2t ) THEN
644 DO i = 1, p
645 iwork(i) = m - p - q + i
646 END DO
647 DO i = p + 1, m - q
648 iwork(i) = i - p
649 END DO
650 IF( .NOT. colmajor ) THEN
651 CALL zlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
652 ELSE
653 CALL zlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
654 END IF
655 END IF
656*
657 RETURN
658*
659* End ZUNCSD
660*
661 END
662
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zbbcsd(jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta, phi, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, b11d, b11e, b12d, b12e, b21d, b21e, b22d, b22e, rwork, lrwork, info)
ZBBCSD
Definition zbbcsd.f:331
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
Definition zlacpy.f:101
subroutine zlapmr(forwrd, m, n, x, ldx, k)
ZLAPMR rearranges rows of a matrix as specified by a permutation vector.
Definition zlapmr.f:102
subroutine zlapmt(forwrd, m, n, x, ldx, k)
ZLAPMT performs a forward or backward permutation of the columns of a matrix.
Definition zlapmt.f:102
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine zunbdb(trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, phi, taup1, taup2, tauq1, tauq2, work, lwork, info)
ZUNBDB
Definition zunbdb.f:286
recursive subroutine zuncsd(jobu1, jobu2, jobv1t, jobv2t, trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, work, lwork, rwork, lrwork, iwork, info)
ZUNCSD
Definition zuncsd.f:319
subroutine zunglq(m, n, k, a, lda, tau, work, lwork, info)
ZUNGLQ
Definition zunglq.f:125
subroutine zungqr(m, n, k, a, lda, tau, work, lwork, info)
ZUNGQR
Definition zungqr.f:126