LAPACK 3.12.0
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
cuncsd2by1.f
Go to the documentation of this file.
1*> \brief \b CUNCSD2BY1
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CUNCSD2BY1 + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cuncsd2by1.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cuncsd2by1.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cuncsd2by1.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18* Definition:
19* ===========
20*
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,
24* INFO )
25*
26* .. Scalar Arguments ..
27* CHARACTER JOBU1, JOBU2, JOBV1T
28* INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
29* $ M, P, Q
30* INTEGER LRWORK, LRWORKMIN, LRWORKOPT
31* ..
32* .. Array Arguments ..
33* REAL RWORK(*)
34* REAL THETA(*)
35* COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
36* $ X11(LDX11,*), X21(LDX21,*)
37* INTEGER IWORK(*)
38* ..
39*
40*
41*> \par Purpose:
42* =============
43*>
44*>\verbatim
45*>
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
48*> structure:
49*>
50*> [ I1 0 0 ]
51*> [ 0 C 0 ]
52*> [ X11 ] [ U1 | ] [ 0 0 0 ]
53*> X = [-----] = [---------] [----------] V1**T .
54*> [ X21 ] [ | U2 ] [ 0 0 0 ]
55*> [ 0 S 0 ]
56*> [ 0 0 I2]
57*>
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).
63*>
64*> \endverbatim
65*
66* Arguments:
67* ==========
68*
69*> \param[in] JOBU1
70*> \verbatim
71*> JOBU1 is CHARACTER
72*> = 'Y': U1 is computed;
73*> otherwise: U1 is not computed.
74*> \endverbatim
75*>
76*> \param[in] JOBU2
77*> \verbatim
78*> JOBU2 is CHARACTER
79*> = 'Y': U2 is computed;
80*> otherwise: U2 is not computed.
81*> \endverbatim
82*>
83*> \param[in] JOBV1T
84*> \verbatim
85*> JOBV1T is CHARACTER
86*> = 'Y': V1T is computed;
87*> otherwise: V1T is not computed.
88*> \endverbatim
89*>
90*> \param[in] M
91*> \verbatim
92*> M is INTEGER
93*> The number of rows in X.
94*> \endverbatim
95*>
96*> \param[in] P
97*> \verbatim
98*> P is INTEGER
99*> The number of rows in X11. 0 <= P <= M.
100*> \endverbatim
101*>
102*> \param[in] Q
103*> \verbatim
104*> Q is INTEGER
105*> The number of columns in X11 and X21. 0 <= Q <= M.
106*> \endverbatim
107*>
108*> \param[in,out] X11
109*> \verbatim
110*> X11 is COMPLEX array, dimension (LDX11,Q)
111*> On entry, part of the unitary matrix whose CSD is desired.
112*> \endverbatim
113*>
114*> \param[in] LDX11
115*> \verbatim
116*> LDX11 is INTEGER
117*> The leading dimension of X11. LDX11 >= MAX(1,P).
118*> \endverbatim
119*>
120*> \param[in,out] X21
121*> \verbatim
122*> X21 is COMPLEX array, dimension (LDX21,Q)
123*> On entry, part of the unitary matrix whose CSD is desired.
124*> \endverbatim
125*>
126*> \param[in] LDX21
127*> \verbatim
128*> LDX21 is INTEGER
129*> The leading dimension of X21. LDX21 >= MAX(1,M-P).
130*> \endverbatim
131*>
132*> \param[out] THETA
133*> \verbatim
134*> THETA is REAL array, dimension (R), in which R =
135*> MIN(P,M-P,Q,M-Q).
136*> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
137*> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
138*> \endverbatim
139*>
140*> \param[out] U1
141*> \verbatim
142*> U1 is COMPLEX array, dimension (P)
143*> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
144*> \endverbatim
145*>
146*> \param[in] LDU1
147*> \verbatim
148*> LDU1 is INTEGER
149*> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
150*> MAX(1,P).
151*> \endverbatim
152*>
153*> \param[out] U2
154*> \verbatim
155*> U2 is COMPLEX array, dimension (M-P)
156*> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
157*> matrix U2.
158*> \endverbatim
159*>
160*> \param[in] LDU2
161*> \verbatim
162*> LDU2 is INTEGER
163*> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
164*> MAX(1,M-P).
165*> \endverbatim
166*>
167*> \param[out] V1T
168*> \verbatim
169*> V1T is COMPLEX array, dimension (Q)
170*> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
171*> matrix V1**T.
172*> \endverbatim
173*>
174*> \param[in] LDV1T
175*> \verbatim
176*> LDV1T is INTEGER
177*> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
178*> MAX(1,Q).
179*> \endverbatim
180*>
181*> \param[out] WORK
182*> \verbatim
183*> WORK is COMPLEX array, dimension (MAX(1,LWORK))
184*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
185*> \endverbatim
186*>
187*> \param[in] LWORK
188*> \verbatim
189*> LWORK is INTEGER
190*> The dimension of the array WORK.
191*>
192*> If LWORK = -1, then a workspace query is assumed; the routine
193*> only calculates the optimal size of the WORK and RWORK
194*> arrays, returns this value as the first entry of the WORK
195*> and RWORK array, respectively, and no error message related
196*> to LWORK or LRWORK is issued by XERBLA.
197*> \endverbatim
198*>
199*> \param[out] RWORK
200*> \verbatim
201*> RWORK is REAL array, dimension (MAX(1,LRWORK))
202*> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
203*> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
204*> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
205*> define the matrix in intermediate bidiagonal-block form
206*> remaining after nonconvergence. INFO specifies the number
207*> of nonzero PHI's.
208*> \endverbatim
209*>
210*> \param[in] LRWORK
211*> \verbatim
212*> LRWORK is INTEGER
213*> The dimension of the array RWORK.
214*>
215*> If LRWORK=-1, then a workspace query is assumed; the routine
216*> only calculates the optimal size of the WORK and RWORK
217*> arrays, returns this value as the first entry of the WORK
218*> and RWORK array, respectively, and no error message related
219*> to LWORK or LRWORK is issued by XERBLA.
220*> \endverbatim
221*>
222*> \param[out] IWORK
223*> \verbatim
224*> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
225*> \endverbatim
226*>
227*> \param[out] INFO
228*> \verbatim
229*> INFO is INTEGER
230*> = 0: successful exit.
231*> < 0: if INFO = -i, the i-th argument had an illegal value.
232*> > 0: CBBCSD did not converge. See the description of WORK
233*> above for details.
234*> \endverbatim
235*
236*> \par References:
237* ================
238*>
239*> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
240*> Algorithms, 50(1):33-65, 2009.
241*
242* Authors:
243* ========
244*
245*> \author Univ. of Tennessee
246*> \author Univ. of California Berkeley
247*> \author Univ. of Colorado Denver
248*> \author NAG Ltd.
249*
250*> \ingroup uncsd2by1
251*
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,
256 $ INFO )
257*
258* -- LAPACK computational routine --
259* -- LAPACK is a software package provided by Univ. of Tennessee, --
260* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
261*
262* .. Scalar Arguments ..
263 CHARACTER JOBU1, JOBU2, JOBV1T
264 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
265 $ M, P, Q
266 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
267* ..
268* .. Array Arguments ..
269 REAL RWORK(*)
270 REAL THETA(*)
271 COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
272 $ x11(ldx11,*), x21(ldx21,*)
273 INTEGER IWORK(*)
274* ..
275*
276* =====================================================================
277*
278* .. Parameters ..
279 COMPLEX ONE, ZERO
280 PARAMETER ( ONE = (1.0e0,0.0e0), zero = (0.0e0,0.0e0) )
281* ..
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
290* ..
291* .. Local Arrays ..
292 REAL DUM( 1 )
293 COMPLEX CDUM( 1, 1 )
294* ..
295* .. External Subroutines ..
296 EXTERNAL cbbcsd, ccopy, clacpy, clapmr, clapmt, cunbdb1,
298 $ xerbla
299* ..
300* .. External Functions ..
301 LOGICAL LSAME
302 REAL SROUNDUP_LWORK
303 EXTERNAL LSAME, SROUNDUP_LWORK
304* ..
305* .. Intrinsic Function ..
306 INTRINSIC int, max, min
307* ..
308* .. Executable Statements ..
309*
310* Test input arguments
311*
312 info = 0
313 wantu1 = lsame( jobu1, 'Y' )
314 wantu2 = lsame( jobu2, 'Y' )
315 wantv1t = lsame( jobv1t, 'Y' )
316 lquery = ( lwork.EQ.-1 ) .OR. ( lrwork.EQ.-1 )
317*
318 IF( m .LT. 0 ) THEN
319 info = -4
320 ELSE IF( p .LT. 0 .OR. p .GT. m ) THEN
321 info = -5
322 ELSE IF( q .LT. 0 .OR. q .GT. m ) THEN
323 info = -6
324 ELSE IF( ldx11 .LT. max( 1, p ) ) THEN
325 info = -8
326 ELSE IF( ldx21 .LT. max( 1, m-p ) ) THEN
327 info = -10
328 ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) ) THEN
329 info = -13
330 ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) ) THEN
331 info = -15
332 ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) ) THEN
333 info = -17
334 END IF
335*
336 r = min( p, m-p, q, m-q )
337*
338* Compute workspace
339*
340* WORK layout:
341* |-----------------------------------------|
342* | LWORKOPT (1) |
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 |
349* | | | |
350* | | | |
351* | | | |
352* | | | |
353* |-----------------------------------------|
354* RWORK layout:
355* |------------------|
356* | LRWORKOPT (1) |
357* |------------------|
358* | PHI (MAX(1,R-1)) |
359* |------------------|
360* | B11D (R) |
361* | B11E (R-1) |
362* | B12D (R) |
363* | B12E (R-1) |
364* | B21D (R) |
365* | B21E (R-1) |
366* | B22D (R) |
367* | B22E (R-1) |
368* | CBBCSD RWORK |
369* |------------------|
370*
371 IF( info .EQ. 0 ) THEN
372 iphi = 2
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 )
382 itaup1 = 2
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 )
388 lorgqrmin = 1
389 lorgqropt = 1
390 lorglqmin = 1
391 lorglqopt = 1
392 IF( r .EQ. q ) THEN
393 CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
394 $ dum, cdum, cdum, cdum, work, -1,
395 $ childinfo )
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,
399 $ childinfo )
400 lorgqrmin = max( lorgqrmin, p )
401 lorgqropt = max( lorgqropt, int( work(1) ) )
402 ENDIF
403 IF( wantu2 .AND. m-p .GT. 0 ) THEN
404 CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
405 $ childinfo )
406 lorgqrmin = max( lorgqrmin, m-p )
407 lorgqropt = max( lorgqropt, int( work(1) ) )
408 END IF
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) ) )
414 END IF
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),
426 $ -1, childinfo )
427 lorgqrmin = max( lorgqrmin, p-1 )
428 lorgqropt = max( lorgqropt, int( work(1) ) )
429 END IF
430 IF( wantu2 .AND. m-p .GT. 0 ) THEN
431 CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
432 $ childinfo )
433 lorgqrmin = max( lorgqrmin, m-p )
434 lorgqropt = max( lorgqropt, int( work(1) ) )
435 END IF
436 IF( wantv1t .AND. q .GT. 0 ) THEN
437 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
438 $ childinfo )
439 lorglqmin = max( lorglqmin, q )
440 lorglqopt = max( lorglqopt, int( work(1) ) )
441 END IF
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,
453 $ childinfo )
454 lorgqrmin = max( lorgqrmin, p )
455 lorgqropt = max( lorgqropt, int( work(1) ) )
456 END IF
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) ) )
462 END IF
463 IF( wantv1t .AND. q .GT. 0 ) THEN
464 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
465 $ childinfo )
466 lorglqmin = max( lorglqmin, q )
467 lorglqopt = max( lorglqopt, int( work(1) ) )
468 END IF
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) )
474 ELSE
475 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
476 $ cdum, cdum, cdum, cdum, work(1), -1, childinfo
477 $ )
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,
481 $ childinfo )
482 lorgqrmin = max( lorgqrmin, p )
483 lorgqropt = max( lorgqropt, int( work(1) ) )
484 END IF
485 IF( wantu2 .AND. m-p .GT. 0 ) THEN
486 CALL cungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1), -1,
487 $ childinfo )
488 lorgqrmin = max( lorgqrmin, m-p )
489 lorgqropt = max( lorgqropt, int( work(1) ) )
490 END IF
491 IF( wantv1t .AND. q .GT. 0 ) THEN
492 CALL cunglq( q, q, q, v1t, ldv1t, cdum, work(1), -1,
493 $ childinfo )
494 lorglqmin = max( lorglqmin, q )
495 lorglqopt = max( lorglqopt, int( work(1) ) )
496 END IF
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) )
502 END IF
503 lrworkmin = ibbcsd+lbbcsd-1
504 lrworkopt = lrworkmin
505 rwork(1) = lrworkopt
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 )
512 work(1) = sroundup_lwork(lworkopt)
513 IF( lwork .LT. lworkmin .AND. .NOT.lquery ) THEN
514 info = -19
515 END IF
516 IF( lrwork .LT. lrworkmin .AND. .NOT.lquery ) THEN
517 info = -21
518 END IF
519 END IF
520 IF( info .NE. 0 ) THEN
521 CALL xerbla( 'CUNCSD2BY1', -info )
522 RETURN
523 ELSE IF( lquery ) THEN
524 RETURN
525 END IF
526 lorgqr = lwork-iorgqr+1
527 lorglq = lwork-iorglq+1
528*
529* Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
530* in which R = MIN(P,M-P,Q,M-Q)
531*
532 IF( r .EQ. q ) THEN
533*
534* Case 1: R = Q
535*
536* Simultaneously bidiagonalize X11 and X21
537*
538 CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
539 $ rwork(iphi), work(itaup1), work(itaup2),
540 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
541*
542* Accumulate Householder reflectors
543*
544 IF( wantu1 .AND. p .GT. 0 ) THEN
545 CALL clacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
546 CALL cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
547 $ lorgqr, childinfo )
548 END IF
549 IF( wantu2 .AND. m-p .GT. 0 ) THEN
550 CALL clacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
551 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
552 $ work(iorgqr), lorgqr, childinfo )
553 END IF
554 IF( wantv1t .AND. q .GT. 0 ) THEN
555 v1t(1,1) = one
556 DO j = 2, q
557 v1t(1,j) = zero
558 v1t(j,1) = zero
559 END DO
560 CALL clacpy( 'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
561 $ ldv1t )
562 CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
563 $ work(iorglq), lorglq, childinfo )
564 END IF
565*
566* Simultaneously diagonalize X11 and X21.
567*
568 CALL cbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,
569 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
570 $ 1, rwork(ib11d), rwork(ib11e), rwork(ib12d),
571 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
572 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
573 $ lrwork-ibbcsd+1, childinfo )
574*
575* Permute rows and columns to place zero submatrices in
576* preferred positions
577*
578 IF( q .GT. 0 .AND. wantu2 ) THEN
579 DO i = 1, q
580 iwork(i) = m - p - q + i
581 END DO
582 DO i = q + 1, m - p
583 iwork(i) = i - q
584 END DO
585 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
586 END IF
587 ELSE IF( r .EQ. p ) THEN
588*
589* Case 2: R = P
590*
591* Simultaneously bidiagonalize X11 and X21
592*
593 CALL cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
594 $ rwork(iphi), work(itaup1), work(itaup2),
595 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
596*
597* Accumulate Householder reflectors
598*
599 IF( wantu1 .AND. p .GT. 0 ) THEN
600 u1(1,1) = one
601 DO j = 2, p
602 u1(1,j) = zero
603 u1(j,1) = zero
604 END DO
605 CALL clacpy( 'L', p-1, p-1, x11(2,1), ldx11, u1(2,2), ldu1 )
606 CALL cungqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
607 $ work(iorgqr), lorgqr, childinfo )
608 END IF
609 IF( wantu2 .AND. m-p .GT. 0 ) THEN
610 CALL clacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
611 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
612 $ work(iorgqr), lorgqr, childinfo )
613 END IF
614 IF( wantv1t .AND. q .GT. 0 ) THEN
615 CALL clacpy( 'U', p, q, x11, ldx11, v1t, ldv1t )
616 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
617 $ work(iorglq), lorglq, childinfo )
618 END IF
619*
620* Simultaneously diagonalize X11 and X21.
621*
622 CALL cbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,
623 $ rwork(iphi), v1t, ldv1t, cdum, 1, u1, ldu1, u2,
624 $ ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),
625 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
626 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd), lbbcsd,
627 $ childinfo )
628*
629* Permute rows and columns to place identity submatrices in
630* preferred positions
631*
632 IF( q .GT. 0 .AND. wantu2 ) THEN
633 DO i = 1, q
634 iwork(i) = m - p - q + i
635 END DO
636 DO i = q + 1, m - p
637 iwork(i) = i - q
638 END DO
639 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
640 END IF
641 ELSE IF( r .EQ. m-p ) THEN
642*
643* Case 3: R = M-P
644*
645* Simultaneously bidiagonalize X11 and X21
646*
647 CALL cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
648 $ rwork(iphi), work(itaup1), work(itaup2),
649 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
650*
651* Accumulate Householder reflectors
652*
653 IF( wantu1 .AND. p .GT. 0 ) THEN
654 CALL clacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
655 CALL cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
656 $ lorgqr, childinfo )
657 END IF
658 IF( wantu2 .AND. m-p .GT. 0 ) THEN
659 u2(1,1) = one
660 DO j = 2, m-p
661 u2(1,j) = zero
662 u2(j,1) = zero
663 END DO
664 CALL clacpy( 'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
665 $ ldu2 )
666 CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
667 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
668 END IF
669 IF( wantv1t .AND. q .GT. 0 ) THEN
670 CALL clacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t )
671 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
672 $ work(iorglq), lorglq, childinfo )
673 END IF
674*
675* Simultaneously diagonalize X11 and X21.
676*
677 CALL cbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,
678 $ theta, rwork(iphi), cdum, 1, v1t, ldv1t, u2, ldu2,
679 $ u1, ldu1, rwork(ib11d), rwork(ib11e),
680 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
681 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
682 $ rwork(ibbcsd), lbbcsd, childinfo )
683*
684* Permute rows and columns to place identity submatrices in
685* preferred positions
686*
687 IF( q .GT. r ) THEN
688 DO i = 1, r
689 iwork(i) = q - r + i
690 END DO
691 DO i = r + 1, q
692 iwork(i) = i - r
693 END DO
694 IF( wantu1 ) THEN
695 CALL clapmt( .false., p, q, u1, ldu1, iwork )
696 END IF
697 IF( wantv1t ) THEN
698 CALL clapmr( .false., q, q, v1t, ldv1t, iwork )
699 END IF
700 END IF
701 ELSE
702*
703* Case 4: R = M-Q
704*
705* Simultaneously bidiagonalize X11 and X21
706*
707 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
708 $ rwork(iphi), work(itaup1), work(itaup2),
709 $ work(itauq1), work(iorbdb), work(iorbdb+m),
710 $ lorbdb-m, childinfo )
711*
712* Accumulate Householder reflectors
713*
714
715 IF( wantu2 .AND. m-p .GT. 0 ) THEN
716 CALL ccopy( m-p, work(iorbdb+p), 1, u2, 1 )
717 END IF
718 IF( wantu1 .AND. p .GT. 0 ) THEN
719 CALL ccopy( p, work(iorbdb), 1, u1, 1 )
720 DO j = 2, p
721 u1(1,j) = zero
722 END DO
723 CALL clacpy( 'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
724 $ ldu1 )
725 CALL cungqr( p, p, m-q, u1, ldu1, work(itaup1),
726 $ work(iorgqr), lorgqr, childinfo )
727 END IF
728 IF( wantu2 .AND. m-p .GT. 0 ) THEN
729 DO j = 2, m-p
730 u2(1,j) = zero
731 END DO
732 CALL clacpy( 'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
733 $ ldu2 )
734 CALL cungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
735 $ work(iorgqr), lorgqr, childinfo )
736 END IF
737 IF( wantv1t .AND. q .GT. 0 ) THEN
738 CALL clacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t )
739 CALL clacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,
740 $ v1t(m-q+1,m-q+1), ldv1t )
741 CALL clacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
742 $ v1t(p+1,p+1), ldv1t )
743 CALL cunglq( q, q, q, v1t, ldv1t, work(itauq1),
744 $ work(iorglq), lorglq, childinfo )
745 END IF
746*
747* Simultaneously diagonalize X11 and X21.
748*
749 CALL cbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,
750 $ theta, rwork(iphi), u2, ldu2, u1, ldu1, cdum, 1,
751 $ v1t, ldv1t, rwork(ib11d), rwork(ib11e),
752 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
753 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
754 $ rwork(ibbcsd), lbbcsd, childinfo )
755*
756* Permute rows and columns to place identity submatrices in
757* preferred positions
758*
759 IF( p .GT. r ) THEN
760 DO i = 1, r
761 iwork(i) = p - r + i
762 END DO
763 DO i = r + 1, p
764 iwork(i) = i - r
765 END DO
766 IF( wantu1 ) THEN
767 CALL clapmt( .false., p, p, u1, ldu1, iwork )
768 END IF
769 IF( wantv1t ) THEN
770 CALL clapmr( .false., p, q, v1t, ldv1t, iwork )
771 END IF
772 END IF
773 END IF
774*
775 RETURN
776*
777* End of CUNCSD2BY1
778*
779 END
780
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine cbbcsd(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)
CBBCSD
Definition cbbcsd.f:332
subroutine ccopy(n, cx, incx, cy, incy)
CCOPY
Definition ccopy.f:81
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
Definition clacpy.f:103
subroutine clapmr(forwrd, m, n, x, ldx, k)
CLAPMR rearranges rows of a matrix as specified by a permutation vector.
Definition clapmr.f:104
subroutine clapmt(forwrd, m, n, x, ldx, k)
CLAPMT performs a forward or backward permutation of the columns of a matrix.
Definition clapmt.f:104
subroutine cunbdb1(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB1
Definition cunbdb1.f:202
subroutine cunbdb2(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB2
Definition cunbdb2.f:202
subroutine cunbdb3(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB3
Definition cunbdb3.f:202
subroutine cunbdb4(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, phantom, work, lwork, info)
CUNBDB4
Definition cunbdb4.f:213
subroutine cuncsd2by1(jobu1, jobu2, jobv1t, m, p, q, x11, ldx11, x21, ldx21, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, work, lwork, rwork, lrwork, iwork, info)
CUNCSD2BY1
Definition cuncsd2by1.f:257
subroutine cunglq(m, n, k, a, lda, tau, work, lwork, info)
CUNGLQ
Definition cunglq.f:127
subroutine cungqr(m, n, k, a, lda, tau, work, lwork, info)
CUNGQR
Definition cungqr.f:128