You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cuncsd2by1.f 27 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  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, 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. *>
  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 and columns in X.
  93. *> \endverbatim
  94. *>
  95. *> \param[in] P
  96. *> \verbatim
  97. *> P is INTEGER
  98. *> The number of rows in X11 and X12. 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
  111. *> 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
  124. *> desired.
  125. *> \endverbatim
  126. *>
  127. *> \param[in] LDX21
  128. *> \verbatim
  129. *> LDX21 is INTEGER
  130. *> The leading dimension of X21. LDX21 >= MAX(1,M-P).
  131. *> \endverbatim
  132. *>
  133. *> \param[out] THETA
  134. *> \verbatim
  135. *> THETA is COMPLEX array, dimension (R), in which R =
  136. *> MIN(P,M-P,Q,M-Q).
  137. *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
  138. *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
  139. *> \endverbatim
  140. *>
  141. *> \param[out] U1
  142. *> \verbatim
  143. *> U1 is COMPLEX array, dimension (P)
  144. *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
  145. *> \endverbatim
  146. *>
  147. *> \param[in] LDU1
  148. *> \verbatim
  149. *> LDU1 is INTEGER
  150. *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
  151. *> MAX(1,P).
  152. *> \endverbatim
  153. *>
  154. *> \param[out] U2
  155. *> \verbatim
  156. *> U2 is COMPLEX array, dimension (M-P)
  157. *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
  158. *> matrix U2.
  159. *> \endverbatim
  160. *>
  161. *> \param[in] LDU2
  162. *> \verbatim
  163. *> LDU2 is INTEGER
  164. *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
  165. *> MAX(1,M-P).
  166. *> \endverbatim
  167. *>
  168. *> \param[out] V1T
  169. *> \verbatim
  170. *> V1T is COMPLEX array, dimension (Q)
  171. *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
  172. *> matrix V1**T.
  173. *> \endverbatim
  174. *>
  175. *> \param[in] LDV1T
  176. *> \verbatim
  177. *> LDV1T is INTEGER
  178. *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
  179. *> MAX(1,Q).
  180. *> \endverbatim
  181. *>
  182. *> \param[out] WORK
  183. *> \verbatim
  184. *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
  185. *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  186. *> If INFO > 0 on exit, WORK(2:R) contains the values PHI(1),
  187. *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  188. *> define the matrix in intermediate bidiagonal-block form
  189. *> remaining after nonconvergence. INFO specifies the number
  190. *> of nonzero PHI's.
  191. *> \endverbatim
  192. *>
  193. *> \param[in] LWORK
  194. *> \verbatim
  195. *> LWORK is INTEGER
  196. *> The dimension of the array WORK.
  197. *> \endverbatim
  198. *> \verbatim
  199. *> If LWORK = -1, then a workspace query is assumed; the routine
  200. *> only calculates the optimal size of the WORK array, returns
  201. *> this value as the first entry of the work array, and no error
  202. *> message related to LWORK is issued by XERBLA.
  203. *> \endverbatim
  204. *>
  205. *> \param[out] RWORK
  206. *> \verbatim
  207. *> RWORK is REAL array, dimension (MAX(1,LRWORK))
  208. *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
  209. *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
  210. *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  211. *> define the matrix in intermediate bidiagonal-block form
  212. *> remaining after nonconvergence. INFO specifies the number
  213. *> of nonzero PHI's.
  214. *> \endverbatim
  215. *>
  216. *> \param[in] LRWORK
  217. *> \verbatim
  218. *> LRWORK is INTEGER
  219. *> The dimension of the array RWORK.
  220. *>
  221. *> If LRWORK = -1, then a workspace query is assumed; the routine
  222. *> only calculates the optimal size of the RWORK array, returns
  223. *> this value as the first entry of the work array, and no error
  224. *> message related to LRWORK is issued by XERBLA.
  225. *> \param[out] IWORK
  226. *> \verbatim
  227. *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
  228. *> \endverbatim
  229. *> \endverbatim
  230. *>
  231. *> \param[out] INFO
  232. *> \verbatim
  233. *> INFO is INTEGER
  234. *> = 0: successful exit.
  235. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  236. *> > 0: CBBCSD did not converge. See the description of WORK
  237. *> above for details.
  238. *> \endverbatim
  239. *
  240. *> \par References:
  241. *> ================
  242. *>
  243. *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
  244. *> Algorithms, 50(1):33-65, 2009.
  245. *>
  246. *
  247. * Authors:
  248. * ========
  249. *
  250. *> \author Univ. of Tennessee
  251. *> \author Univ. of California Berkeley
  252. *> \author Univ. of Colorado Denver
  253. *> \author NAG Ltd.
  254. *
  255. *> \date July 2012
  256. *
  257. *> \ingroup complexOTHERcomputational
  258. *
  259. * =====================================================================
  260. SUBROUTINE CUNCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
  261. $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
  262. $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
  263. $ INFO )
  264. *
  265. * -- LAPACK computational routine (version 3.5.0) --
  266. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  267. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  268. * July 2012
  269. *
  270. * .. Scalar Arguments ..
  271. CHARACTER JOBU1, JOBU2, JOBV1T
  272. INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
  273. $ M, P, Q
  274. INTEGER LRWORK, LRWORKMIN, LRWORKOPT
  275. * ..
  276. * .. Array Arguments ..
  277. REAL RWORK(*)
  278. REAL THETA(*)
  279. COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
  280. $ X11(LDX11,*), X21(LDX21,*)
  281. INTEGER IWORK(*)
  282. * ..
  283. *
  284. * =====================================================================
  285. *
  286. * .. Parameters ..
  287. COMPLEX ONE, ZERO
  288. PARAMETER ( ONE = (1.0E0,0.0E0), ZERO = (0.0E0,0.0E0) )
  289. * ..
  290. * .. Local Scalars ..
  291. INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
  292. $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
  293. $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
  294. $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
  295. $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
  296. $ LWORKMIN, LWORKOPT, R
  297. LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
  298. * ..
  299. * .. External Subroutines ..
  300. EXTERNAL CBBCSD, CCOPY, CLACPY, CLAPMR, CLAPMT, CUNBDB1,
  301. $ CUNBDB2, CUNBDB3, CUNBDB4, CUNGLQ, CUNGQR,
  302. $ XERBLA
  303. * ..
  304. * .. External Functions ..
  305. LOGICAL LSAME
  306. EXTERNAL LSAME
  307. * ..
  308. * .. Intrinsic Function ..
  309. INTRINSIC INT, MAX, MIN
  310. * ..
  311. * .. Executable Statements ..
  312. *
  313. * Test input arguments
  314. *
  315. INFO = 0
  316. WANTU1 = LSAME( JOBU1, 'Y' )
  317. WANTU2 = LSAME( JOBU2, 'Y' )
  318. WANTV1T = LSAME( JOBV1T, 'Y' )
  319. LQUERY = LWORK .EQ. -1
  320. *
  321. IF( M .LT. 0 ) THEN
  322. INFO = -4
  323. ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
  324. INFO = -5
  325. ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
  326. INFO = -6
  327. ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
  328. INFO = -8
  329. ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
  330. INFO = -10
  331. ELSE IF( WANTU1 .AND. LDU1 .LT. P ) THEN
  332. INFO = -13
  333. ELSE IF( WANTU2 .AND. LDU2 .LT. M - P ) THEN
  334. INFO = -15
  335. ELSE IF( WANTV1T .AND. LDV1T .LT. Q ) THEN
  336. INFO = -17
  337. END IF
  338. *
  339. R = MIN( P, M-P, Q, M-Q )
  340. *
  341. * Compute workspace
  342. *
  343. * WORK layout:
  344. * |-----------------------------------------|
  345. * | LWORKOPT (1) |
  346. * |-----------------------------------------|
  347. * | TAUP1 (MAX(1,P)) |
  348. * | TAUP2 (MAX(1,M-P)) |
  349. * | TAUQ1 (MAX(1,Q)) |
  350. * |-----------------------------------------|
  351. * | CUNBDB WORK | CUNGQR WORK | CUNGLQ WORK |
  352. * | | | |
  353. * | | | |
  354. * | | | |
  355. * | | | |
  356. * |-----------------------------------------|
  357. * RWORK layout:
  358. * |------------------|
  359. * | LRWORKOPT (1) |
  360. * |------------------|
  361. * | PHI (MAX(1,R-1)) |
  362. * |------------------|
  363. * | B11D (R) |
  364. * | B11E (R-1) |
  365. * | B12D (R) |
  366. * | B12E (R-1) |
  367. * | B21D (R) |
  368. * | B21E (R-1) |
  369. * | B22D (R) |
  370. * | B22E (R-1) |
  371. * | CBBCSD RWORK |
  372. * |------------------|
  373. *
  374. IF( INFO .EQ. 0 ) THEN
  375. IPHI = 2
  376. IB11D = IPHI + MAX( 1, R-1 )
  377. IB11E = IB11D + MAX( 1, R )
  378. IB12D = IB11E + MAX( 1, R - 1 )
  379. IB12E = IB12D + MAX( 1, R )
  380. IB21D = IB12E + MAX( 1, R - 1 )
  381. IB21E = IB21D + MAX( 1, R )
  382. IB22D = IB21E + MAX( 1, R - 1 )
  383. IB22E = IB22D + MAX( 1, R )
  384. IBBCSD = IB22E + MAX( 1, R - 1 )
  385. ITAUP1 = 2
  386. ITAUP2 = ITAUP1 + MAX( 1, P )
  387. ITAUQ1 = ITAUP2 + MAX( 1, M-P )
  388. IORBDB = ITAUQ1 + MAX( 1, Q )
  389. IORGQR = ITAUQ1 + MAX( 1, Q )
  390. IORGLQ = ITAUQ1 + MAX( 1, Q )
  391. IF( R .EQ. Q ) THEN
  392. CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  393. $ 0, 0, WORK, -1, CHILDINFO )
  394. LORBDB = INT( WORK(1) )
  395. IF( P .GE. M-P ) THEN
  396. CALL CUNGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  397. $ CHILDINFO )
  398. LORGQRMIN = MAX( 1, P )
  399. LORGQROPT = INT( WORK(1) )
  400. ELSE
  401. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  402. $ CHILDINFO )
  403. LORGQRMIN = MAX( 1, M-P )
  404. LORGQROPT = INT( WORK(1) )
  405. END IF
  406. CALL CUNGLQ( MAX(0,Q-1), MAX(0,Q-1), MAX(0,Q-1), V1T, LDV1T,
  407. $ 0, WORK(1), -1, CHILDINFO )
  408. LORGLQMIN = MAX( 1, Q-1 )
  409. LORGLQOPT = INT( WORK(1) )
  410. CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  411. $ 0, U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1, 0, 0,
  412. $ 0, 0, 0, 0, 0, 0, RWORK(1), -1, CHILDINFO )
  413. LBBCSD = INT( RWORK(1) )
  414. ELSE IF( R .EQ. P ) THEN
  415. CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  416. $ 0, 0, WORK(1), -1, CHILDINFO )
  417. LORBDB = INT( WORK(1) )
  418. IF( P-1 .GE. M-P ) THEN
  419. CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, 0, WORK(1),
  420. $ -1, CHILDINFO )
  421. LORGQRMIN = MAX( 1, P-1 )
  422. LORGQROPT = INT( WORK(1) )
  423. ELSE
  424. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  425. $ CHILDINFO )
  426. LORGQRMIN = MAX( 1, M-P )
  427. LORGQROPT = INT( WORK(1) )
  428. END IF
  429. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  430. $ CHILDINFO )
  431. LORGLQMIN = MAX( 1, Q )
  432. LORGLQOPT = INT( WORK(1) )
  433. CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  434. $ 0, V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2, 0, 0,
  435. $ 0, 0, 0, 0, 0, 0, RWORK(1), -1, CHILDINFO )
  436. LBBCSD = INT( RWORK(1) )
  437. ELSE IF( R .EQ. M-P ) THEN
  438. CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  439. $ 0, 0, WORK(1), -1, CHILDINFO )
  440. LORBDB = INT( WORK(1) )
  441. IF( P .GE. M-P-1 ) THEN
  442. CALL CUNGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  443. $ CHILDINFO )
  444. LORGQRMIN = MAX( 1, P )
  445. LORGQROPT = INT( WORK(1) )
  446. ELSE
  447. CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, 0,
  448. $ WORK(1), -1, CHILDINFO )
  449. LORGQRMIN = MAX( 1, M-P-1 )
  450. LORGQROPT = INT( WORK(1) )
  451. END IF
  452. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  453. $ CHILDINFO )
  454. LORGLQMIN = MAX( 1, Q )
  455. LORGLQOPT = INT( WORK(1) )
  456. CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  457. $ THETA, 0, 0, 1, V1T, LDV1T, U2, LDU2, U1, LDU1,
  458. $ 0, 0, 0, 0, 0, 0, 0, 0, RWORK(1), -1,
  459. $ CHILDINFO )
  460. LBBCSD = INT( RWORK(1) )
  461. ELSE
  462. CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  463. $ 0, 0, 0, WORK(1), -1, CHILDINFO )
  464. LORBDB = M + INT( WORK(1) )
  465. IF( P .GE. M-P ) THEN
  466. CALL CUNGQR( P, P, M-Q, U1, LDU1, 0, WORK(1), -1,
  467. $ CHILDINFO )
  468. LORGQRMIN = MAX( 1, P )
  469. LORGQROPT = INT( WORK(1) )
  470. ELSE
  471. CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, 0, WORK(1), -1,
  472. $ CHILDINFO )
  473. LORGQRMIN = MAX( 1, M-P )
  474. LORGQROPT = INT( WORK(1) )
  475. END IF
  476. CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, 0, WORK(1), -1,
  477. $ CHILDINFO )
  478. LORGLQMIN = MAX( 1, Q )
  479. LORGLQOPT = INT( WORK(1) )
  480. CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  481. $ THETA, 0, U2, LDU2, U1, LDU1, 0, 1, V1T, LDV1T,
  482. $ 0, 0, 0, 0, 0, 0, 0, 0, RWORK(1), -1,
  483. $ CHILDINFO )
  484. LBBCSD = INT( RWORK(1) )
  485. END IF
  486. LRWORKMIN = IBBCSD+LBBCSD-1
  487. LRWORKOPT = LRWORKMIN
  488. RWORK(1) = LRWORKOPT
  489. LWORKMIN = MAX( IORBDB+LORBDB-1,
  490. $ IORGQR+LORGQRMIN-1,
  491. $ IORGLQ+LORGLQMIN-1 )
  492. LWORKOPT = MAX( IORBDB+LORBDB-1,
  493. $ IORGQR+LORGQROPT-1,
  494. $ IORGLQ+LORGLQOPT-1 )
  495. WORK(1) = LWORKOPT
  496. IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
  497. INFO = -19
  498. END IF
  499. END IF
  500. IF( INFO .NE. 0 ) THEN
  501. CALL XERBLA( 'CUNCSD2BY1', -INFO )
  502. RETURN
  503. ELSE IF( LQUERY ) THEN
  504. RETURN
  505. END IF
  506. LORGQR = LWORK-IORGQR+1
  507. LORGLQ = LWORK-IORGLQ+1
  508. *
  509. * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
  510. * in which R = MIN(P,M-P,Q,M-Q)
  511. *
  512. IF( R .EQ. Q ) THEN
  513. *
  514. * Case 1: R = Q
  515. *
  516. * Simultaneously bidiagonalize X11 and X21
  517. *
  518. CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  519. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  520. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  521. *
  522. * Accumulate Householder reflectors
  523. *
  524. IF( WANTU1 .AND. P .GT. 0 ) THEN
  525. CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  526. CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  527. $ LORGQR, CHILDINFO )
  528. END IF
  529. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  530. CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  531. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  532. $ WORK(IORGQR), LORGQR, CHILDINFO )
  533. END IF
  534. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  535. V1T(1,1) = ONE
  536. DO J = 2, Q
  537. V1T(1,J) = ZERO
  538. V1T(J,1) = ZERO
  539. END DO
  540. CALL CLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
  541. $ LDV1T )
  542. CALL CUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  543. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  544. END IF
  545. *
  546. * Simultaneously diagonalize X11 and X21.
  547. *
  548. CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  549. $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1,
  550. $ RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  551. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  552. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
  553. $ CHILDINFO )
  554. *
  555. * Permute rows and columns to place zero submatrices in
  556. * preferred positions
  557. *
  558. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  559. DO I = 1, Q
  560. IWORK(I) = M - P - Q + I
  561. END DO
  562. DO I = Q + 1, M - P
  563. IWORK(I) = I - Q
  564. END DO
  565. CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  566. END IF
  567. ELSE IF( R .EQ. P ) THEN
  568. *
  569. * Case 2: R = P
  570. *
  571. * Simultaneously bidiagonalize X11 and X21
  572. *
  573. CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  574. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  575. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  576. *
  577. * Accumulate Householder reflectors
  578. *
  579. IF( WANTU1 .AND. P .GT. 0 ) THEN
  580. U1(1,1) = ONE
  581. DO J = 2, P
  582. U1(1,J) = ZERO
  583. U1(J,1) = ZERO
  584. END DO
  585. CALL CLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
  586. CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
  587. $ WORK(IORGQR), LORGQR, CHILDINFO )
  588. END IF
  589. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  590. CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  591. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  592. $ WORK(IORGQR), LORGQR, CHILDINFO )
  593. END IF
  594. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  595. CALL CLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
  596. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  597. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  598. END IF
  599. *
  600. * Simultaneously diagonalize X11 and X21.
  601. *
  602. CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  603. $ RWORK(IPHI), V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2,
  604. $ RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  605. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  606. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
  607. $ CHILDINFO )
  608. *
  609. * Permute rows and columns to place identity submatrices in
  610. * preferred positions
  611. *
  612. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  613. DO I = 1, Q
  614. IWORK(I) = M - P - Q + I
  615. END DO
  616. DO I = Q + 1, M - P
  617. IWORK(I) = I - Q
  618. END DO
  619. CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  620. END IF
  621. ELSE IF( R .EQ. M-P ) THEN
  622. *
  623. * Case 3: R = M-P
  624. *
  625. * Simultaneously bidiagonalize X11 and X21
  626. *
  627. CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  628. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  629. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  630. *
  631. * Accumulate Householder reflectors
  632. *
  633. IF( WANTU1 .AND. P .GT. 0 ) THEN
  634. CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  635. CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  636. $ LORGQR, CHILDINFO )
  637. END IF
  638. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  639. U2(1,1) = ONE
  640. DO J = 2, M-P
  641. U2(1,J) = ZERO
  642. U2(J,1) = ZERO
  643. END DO
  644. CALL CLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
  645. $ LDU2 )
  646. CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
  647. $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
  648. END IF
  649. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  650. CALL CLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
  651. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  652. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  653. END IF
  654. *
  655. * Simultaneously diagonalize X11 and X21.
  656. *
  657. CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  658. $ THETA, RWORK(IPHI), 0, 1, V1T, LDV1T, U2, LDU2,
  659. $ U1, LDU1, RWORK(IB11D), RWORK(IB11E),
  660. $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
  661. $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
  662. $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
  663. *
  664. * Permute rows and columns to place identity submatrices in
  665. * preferred positions
  666. *
  667. IF( Q .GT. R ) THEN
  668. DO I = 1, R
  669. IWORK(I) = Q - R + I
  670. END DO
  671. DO I = R + 1, Q
  672. IWORK(I) = I - R
  673. END DO
  674. IF( WANTU1 ) THEN
  675. CALL CLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
  676. END IF
  677. IF( WANTV1T ) THEN
  678. CALL CLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
  679. END IF
  680. END IF
  681. ELSE
  682. *
  683. * Case 4: R = M-Q
  684. *
  685. * Simultaneously bidiagonalize X11 and X21
  686. *
  687. CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  688. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  689. $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
  690. $ LORBDB-M, CHILDINFO )
  691. *
  692. * Accumulate Householder reflectors
  693. *
  694. IF( WANTU1 .AND. P .GT. 0 ) THEN
  695. CALL CCOPY( P, WORK(IORBDB), 1, U1, 1 )
  696. DO J = 2, P
  697. U1(1,J) = ZERO
  698. END DO
  699. CALL CLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
  700. $ LDU1 )
  701. CALL CUNGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
  702. $ WORK(IORGQR), LORGQR, CHILDINFO )
  703. END IF
  704. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  705. CALL CCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
  706. DO J = 2, M-P
  707. U2(1,J) = ZERO
  708. END DO
  709. CALL CLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
  710. $ LDU2 )
  711. CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
  712. $ WORK(IORGQR), LORGQR, CHILDINFO )
  713. END IF
  714. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  715. CALL CLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
  716. CALL CLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
  717. $ V1T(M-Q+1,M-Q+1), LDV1T )
  718. CALL CLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
  719. $ V1T(P+1,P+1), LDV1T )
  720. CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
  721. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  722. END IF
  723. *
  724. * Simultaneously diagonalize X11 and X21.
  725. *
  726. CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  727. $ THETA, RWORK(IPHI), U2, LDU2, U1, LDU1, 0, 1, V1T,
  728. $ LDV1T, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  729. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  730. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
  731. $ CHILDINFO )
  732. *
  733. * Permute rows and columns to place identity submatrices in
  734. * preferred positions
  735. *
  736. IF( P .GT. R ) THEN
  737. DO I = 1, R
  738. IWORK(I) = P - R + I
  739. END DO
  740. DO I = R + 1, P
  741. IWORK(I) = I - R
  742. END DO
  743. IF( WANTU1 ) THEN
  744. CALL CLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
  745. END IF
  746. IF( WANTV1T ) THEN
  747. CALL CLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )
  748. END IF
  749. END IF
  750. END IF
  751. *
  752. RETURN
  753. *
  754. * End of CUNCSD2BY1
  755. *
  756. END