LAPACK  3.6.1
LAPACK: Linear Algebra PACKage
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 *> [ I 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 I ]
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).
62 *>
63 *> \endverbatim
64 *
65 * Arguments:
66 * ==========
67 *
68 *> \param[in] JOBU1
69 *> \verbatim
70 *> JOBU1 is CHARACTER
71 *> = 'Y': U1 is computed;
72 *> otherwise: U1 is not computed.
73 *> \endverbatim
74 *>
75 *> \param[in] JOBU2
76 *> \verbatim
77 *> JOBU2 is CHARACTER
78 *> = 'Y': U2 is computed;
79 *> otherwise: U2 is not computed.
80 *> \endverbatim
81 *>
82 *> \param[in] JOBV1T
83 *> \verbatim
84 *> JOBV1T is CHARACTER
85 *> = 'Y': V1T is computed;
86 *> otherwise: V1T is not computed.
87 *> \endverbatim
88 *>
89 *> \param[in] M
90 *> \verbatim
91 *> M is INTEGER
92 *> The number of rows in X.
93 *> \endverbatim
94 *>
95 *> \param[in] P
96 *> \verbatim
97 *> P is INTEGER
98 *> The number of rows in X11. 0 <= P <= M.
99 *> \endverbatim
100 *>
101 *> \param[in] Q
102 *> \verbatim
103 *> Q is INTEGER
104 *> The number of columns in X11 and X21. 0 <= Q <= M.
105 *> \endverbatim
106 *>
107 *> \param[in,out] X11
108 *> \verbatim
109 *> X11 is COMPLEX array, dimension (LDX11,Q)
110 *> On entry, part of the unitary matrix whose CSD is desired.
111 *> \endverbatim
112 *>
113 *> \param[in] LDX11
114 *> \verbatim
115 *> LDX11 is INTEGER
116 *> The leading dimension of X11. LDX11 >= MAX(1,P).
117 *> \endverbatim
118 *>
119 *> \param[in,out] X21
120 *> \verbatim
121 *> X21 is COMPLEX array, dimension (LDX21,Q)
122 *> On entry, part of the unitary matrix whose CSD is desired.
123 *> \endverbatim
124 *>
125 *> \param[in] LDX21
126 *> \verbatim
127 *> LDX21 is INTEGER
128 *> The leading dimension of X21. LDX21 >= MAX(1,M-P).
129 *> \endverbatim
130 *>
131 *> \param[out] THETA
132 *> \verbatim
133 *> THETA is REAL array, dimension (R), in which R =
134 *> MIN(P,M-P,Q,M-Q).
135 *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
136 *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
137 *> \endverbatim
138 *>
139 *> \param[out] U1
140 *> \verbatim
141 *> U1 is COMPLEX array, dimension (P)
142 *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
143 *> \endverbatim
144 *>
145 *> \param[in] LDU1
146 *> \verbatim
147 *> LDU1 is INTEGER
148 *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
149 *> MAX(1,P).
150 *> \endverbatim
151 *>
152 *> \param[out] U2
153 *> \verbatim
154 *> U2 is COMPLEX array, dimension (M-P)
155 *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
156 *> matrix U2.
157 *> \endverbatim
158 *>
159 *> \param[in] LDU2
160 *> \verbatim
161 *> LDU2 is INTEGER
162 *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
163 *> MAX(1,M-P).
164 *> \endverbatim
165 *>
166 *> \param[out] V1T
167 *> \verbatim
168 *> V1T is COMPLEX array, dimension (Q)
169 *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
170 *> matrix V1**T.
171 *> \endverbatim
172 *>
173 *> \param[in] LDV1T
174 *> \verbatim
175 *> LDV1T is INTEGER
176 *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
177 *> MAX(1,Q).
178 *> \endverbatim
179 *>
180 *> \param[out] WORK
181 *> \verbatim
182 *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
183 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
184 *> \endverbatim
185 *>
186 *> \param[in] LWORK
187 *> \verbatim
188 *> LWORK is INTEGER
189 *> The dimension of the array WORK.
190 *>
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.
195 *> \endverbatim
196 *>
197 *> \param[out] RWORK
198 *> \verbatim
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
205 *> of nonzero PHI's.
206 *> \endverbatim
207 *>
208 *> \param[in] LRWORK
209 *> \verbatim
210 *> LRWORK is INTEGER
211 *> The dimension of the array RWORK.
212 *>
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.
217 *> \endverbatim
218 *
219 *> \param[out] IWORK
220 *> \verbatim
221 *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
222 *> \endverbatim
223 *>
224 *> \param[out] INFO
225 *> \verbatim
226 *> INFO is INTEGER
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.
231 *> \endverbatim
232 *
233 *> \par References:
234 * ================
235 *>
236 *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
237 *> Algorithms, 50(1):33-65, 2009.
238 *
239 * Authors:
240 * ========
241 *
242 *> \author Univ. of Tennessee
243 *> \author Univ. of California Berkeley
244 *> \author Univ. of Colorado Denver
245 *> \author NAG Ltd.
246 *
247 *> \date June 2016
248 *
249 *> \ingroup complexOTHERcomputational
250 *
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,
255  $ info )
256 *
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..--
260 * June 2016
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  EXTERNAL lsame
303 * ..
304 * .. Intrinsic Function ..
305  INTRINSIC int, max, min
306 * ..
307 * .. Executable Statements ..
308 *
309 * Test input arguments
310 *
311  info = 0
312  wantu1 = lsame( jobu1, 'Y' )
313  wantu2 = lsame( jobu2, 'Y' )
314  wantv1t = lsame( jobv1t, 'Y' )
315  lquery = lwork .EQ. -1
316 *
317  IF( m .LT. 0 ) THEN
318  info = -4
319  ELSE IF( p .LT. 0 .OR. p .GT. m ) THEN
320  info = -5
321  ELSE IF( q .LT. 0 .OR. q .GT. m ) THEN
322  info = -6
323  ELSE IF( ldx11 .LT. max( 1, p ) ) THEN
324  info = -8
325  ELSE IF( ldx21 .LT. max( 1, m-p ) ) THEN
326  info = -10
327  ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) ) THEN
328  info = -13
329  ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) ) THEN
330  info = -15
331  ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) ) THEN
332  info = -17
333  END IF
334 *
335  r = min( p, m-p, q, m-q )
336 *
337 * Compute workspace
338 *
339 * WORK layout:
340 * |-----------------------------------------|
341 * | LWORKOPT (1) |
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 |
348 * | | | |
349 * | | | |
350 * | | | |
351 * | | | |
352 * |-----------------------------------------|
353 * RWORK layout:
354 * |------------------|
355 * | LRWORKOPT (1) |
356 * |------------------|
357 * | PHI (MAX(1,R-1)) |
358 * |------------------|
359 * | B11D (R) |
360 * | B11E (R-1) |
361 * | B12D (R) |
362 * | B12E (R-1) |
363 * | B21D (R) |
364 * | B21E (R-1) |
365 * | B22D (R) |
366 * | B22E (R-1) |
367 * | CBBCSD RWORK |
368 * |------------------|
369 *
370  IF( info .EQ. 0 ) THEN
371  iphi = 2
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 )
381  itaup1 = 2
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 )
387  lorgqrmin = 1
388  lorgqropt = 1
389  lorglqmin = 1
390  lorglqopt = 1
391  IF( r .EQ. q ) THEN
392  CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
393  $ dum, cdum, cdum, cdum, work, -1,
394  $ childinfo )
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,
398  $ childinfo )
399  lorgqrmin = max( lorgqrmin, p )
400  lorgqropt = max( lorgqropt, int( work(1) ) )
401  ENDIF
402  IF( wantu2 .AND. m-p .GT. 0 ) THEN
403  CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
404  $ childinfo )
405  lorgqrmin = max( lorgqrmin, m-p )
406  lorgqropt = max( lorgqropt, int( work(1) ) )
407  END IF
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) ) )
413  END IF
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),
425  $ -1, childinfo )
426  lorgqrmin = max( lorgqrmin, p-1 )
427  lorgqropt = max( lorgqropt, int( work(1) ) )
428  END IF
429  IF( wantu2 .AND. m-p .GT. 0 ) THEN
430  CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
431  $ childinfo )
432  lorgqrmin = max( lorgqrmin, m-p )
433  lorgqropt = max( lorgqropt, int( work(1) ) )
434  END IF
435  IF( wantv1t .AND. q .GT. 0 ) THEN
436  CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
437  $ childinfo )
438  lorglqmin = max( lorglqmin, q )
439  lorglqopt = max( lorglqopt, int( work(1) ) )
440  END IF
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,
452  $ childinfo )
453  lorgqrmin = max( lorgqrmin, p )
454  lorgqropt = max( lorgqropt, int( work(1) ) )
455  END IF
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) ) )
461  END IF
462  IF( wantv1t .AND. q .GT. 0 ) THEN
463  CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
464  $ childinfo )
465  lorglqmin = max( lorglqmin, q )
466  lorglqopt = max( lorglqopt, int( work(1) ) )
467  END IF
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) )
473  ELSE
474  CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
475  $ cdum, cdum, cdum, cdum, work(1), -1, childinfo
476  $ )
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,
480  $ childinfo )
481  lorgqrmin = max( lorgqrmin, p )
482  lorgqropt = max( lorgqropt, int( work(1) ) )
483  END IF
484  IF( wantu2 .AND. m-p .GT. 0 ) THEN
485  CALL cungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1), -1,
486  $ childinfo )
487  lorgqrmin = max( lorgqrmin, m-p )
488  lorgqropt = max( lorgqropt, int( work(1) ) )
489  END IF
490  IF( wantv1t .AND. q .GT. 0 ) THEN
491  CALL cunglq( q, q, q, v1t, ldv1t, cdum, work(1), -1,
492  $ childinfo )
493  lorglqmin = max( lorglqmin, q )
494  lorglqopt = max( lorglqopt, int( work(1) ) )
495  END IF
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) )
501  END IF
502  lrworkmin = ibbcsd+lbbcsd-1
503  lrworkopt = lrworkmin
504  rwork(1) = lrworkopt
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 )
511  work(1) = lworkopt
512  IF( lwork .LT. lworkmin .AND. .NOT.lquery ) THEN
513  info = -19
514  END IF
515  END IF
516  IF( info .NE. 0 ) THEN
517  CALL xerbla( 'CUNCSD2BY1', -info )
518  RETURN
519  ELSE IF( lquery ) THEN
520  RETURN
521  END IF
522  lorgqr = lwork-iorgqr+1
523  lorglq = lwork-iorglq+1
524 *
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)
527 *
528  IF( r .EQ. q ) THEN
529 *
530 * Case 1: R = Q
531 *
532 * Simultaneously bidiagonalize X11 and X21
533 *
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 )
537 *
538 * Accumulate Householder reflectors
539 *
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 )
544  END IF
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 )
549  END IF
550  IF( wantv1t .AND. q .GT. 0 ) THEN
551  v1t(1,1) = one
552  DO j = 2, q
553  v1t(1,j) = zero
554  v1t(j,1) = zero
555  END DO
556  CALL clacpy( 'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
557  $ ldv1t )
558  CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
559  $ work(iorglq), lorglq, childinfo )
560  END IF
561 *
562 * Simultaneously diagonalize X11 and X21.
563 *
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,
569  $ childinfo )
570 *
571 * Permute rows and columns to place zero submatrices in
572 * preferred positions
573 *
574  IF( q .GT. 0 .AND. wantu2 ) THEN
575  DO i = 1, q
576  iwork(i) = m - p - q + i
577  END DO
578  DO i = q + 1, m - p
579  iwork(i) = i - q
580  END DO
581  CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
582  END IF
583  ELSE IF( r .EQ. p ) THEN
584 *
585 * Case 2: R = P
586 *
587 * Simultaneously bidiagonalize X11 and X21
588 *
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 )
592 *
593 * Accumulate Householder reflectors
594 *
595  IF( wantu1 .AND. p .GT. 0 ) THEN
596  u1(1,1) = one
597  DO j = 2, p
598  u1(1,j) = zero
599  u1(j,1) = zero
600  END DO
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 )
604  END IF
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 )
609  END IF
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 )
614  END IF
615 *
616 * Simultaneously diagonalize X11 and X21.
617 *
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,
623  $ childinfo )
624 *
625 * Permute rows and columns to place identity submatrices in
626 * preferred positions
627 *
628  IF( q .GT. 0 .AND. wantu2 ) THEN
629  DO i = 1, q
630  iwork(i) = m - p - q + i
631  END DO
632  DO i = q + 1, m - p
633  iwork(i) = i - q
634  END DO
635  CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
636  END IF
637  ELSE IF( r .EQ. m-p ) THEN
638 *
639 * Case 3: R = M-P
640 *
641 * Simultaneously bidiagonalize X11 and X21
642 *
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 )
646 *
647 * Accumulate Householder reflectors
648 *
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 )
653  END IF
654  IF( wantu2 .AND. m-p .GT. 0 ) THEN
655  u2(1,1) = one
656  DO j = 2, m-p
657  u2(1,j) = zero
658  u2(j,1) = zero
659  END DO
660  CALL clacpy( 'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
661  $ ldu2 )
662  CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
663  $ work(itaup2), work(iorgqr), lorgqr, childinfo )
664  END IF
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 )
669  END IF
670 *
671 * Simultaneously diagonalize X11 and X21.
672 *
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 )
679 *
680 * Permute rows and columns to place identity submatrices in
681 * preferred positions
682 *
683  IF( q .GT. r ) THEN
684  DO i = 1, r
685  iwork(i) = q - r + i
686  END DO
687  DO i = r + 1, q
688  iwork(i) = i - r
689  END DO
690  IF( wantu1 ) THEN
691  CALL clapmt( .false., p, q, u1, ldu1, iwork )
692  END IF
693  IF( wantv1t ) THEN
694  CALL clapmr( .false., q, q, v1t, ldv1t, iwork )
695  END IF
696  END IF
697  ELSE
698 *
699 * Case 4: R = M-Q
700 *
701 * Simultaneously bidiagonalize X11 and X21
702 *
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 )
707 *
708 * Accumulate Householder reflectors
709 *
710  IF( wantu1 .AND. p .GT. 0 ) THEN
711  CALL ccopy( p, work(iorbdb), 1, u1, 1 )
712  DO j = 2, p
713  u1(1,j) = zero
714  END DO
715  CALL clacpy( 'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
716  $ ldu1 )
717  CALL cungqr( p, p, m-q, u1, ldu1, work(itaup1),
718  $ work(iorgqr), lorgqr, childinfo )
719  END IF
720  IF( wantu2 .AND. m-p .GT. 0 ) THEN
721  CALL ccopy( m-p, work(iorbdb+p), 1, u2, 1 )
722  DO j = 2, m-p
723  u2(1,j) = zero
724  END DO
725  CALL clacpy( 'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
726  $ ldu2 )
727  CALL cungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
728  $ work(iorgqr), lorgqr, childinfo )
729  END IF
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 )
738  END IF
739 *
740 * Simultaneously diagonalize X11 and X21.
741 *
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 )
748 *
749 * Permute rows and columns to place identity submatrices in
750 * preferred positions
751 *
752  IF( p .GT. r ) THEN
753  DO i = 1, r
754  iwork(i) = p - r + i
755  END DO
756  DO i = r + 1, p
757  iwork(i) = i - r
758  END DO
759  IF( wantu1 ) THEN
760  CALL clapmt( .false., p, p, u1, ldu1, iwork )
761  END IF
762  IF( wantv1t ) THEN
763  CALL clapmr( .false., p, q, v1t, ldv1t, iwork )
764  END IF
765  END IF
766  END IF
767 *
768  RETURN
769 *
770 * End of CUNCSD2BY1
771 *
772  END
773 
subroutine cunbdb4(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, PHANTOM, WORK, LWORK, INFO)
CUNBDB4
Definition: cunbdb4.f:215
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:334
subroutine xerbla(SRNAME, INFO)
XERBLA
Definition: xerbla.f:62
subroutine cunbdb1(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
CUNBDB1
Definition: cunbdb1.f:204
subroutine cunglq(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
CUNGLQ
Definition: cunglq.f:129
subroutine cunbdb2(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
CUNBDB2
Definition: cunbdb2.f:204
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:256
subroutine clapmr(FORWRD, M, N, X, LDX, K)
CLAPMR rearranges rows of a matrix as specified by a permutation vector.
Definition: clapmr.f:106
subroutine clacpy(UPLO, M, N, A, LDA, B, LDB)
CLACPY copies all or part of one two-dimensional array to another.
Definition: clacpy.f:105
subroutine ccopy(N, CX, INCX, CY, INCY)
CCOPY
Definition: ccopy.f:52
subroutine cunbdb3(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
CUNBDB3
Definition: cunbdb3.f:204
subroutine cungqr(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
CUNGQR
Definition: cungqr.f:130
subroutine clapmt(FORWRD, M, N, X, LDX, K)
CLAPMT performs a forward or backward permutation of the columns of a matrix.
Definition: clapmt.f:106