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