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 28 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  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 array, returns
  194. *> this value as the first entry of the work array, and no error
  195. *> message related to LWORK is issued by XERBLA.
  196. *> \endverbatim
  197. *>
  198. *> \param[out] RWORK
  199. *> \verbatim
  200. *> RWORK is REAL array, dimension (MAX(1,LRWORK))
  201. *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
  202. *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
  203. *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  204. *> define the matrix in intermediate bidiagonal-block form
  205. *> remaining after nonconvergence. INFO specifies the number
  206. *> of nonzero PHI's.
  207. *> \endverbatim
  208. *>
  209. *> \param[in] LRWORK
  210. *> \verbatim
  211. *> LRWORK is INTEGER
  212. *> The dimension of the array RWORK.
  213. *>
  214. *> If LRWORK = -1, then a workspace query is assumed; the routine
  215. *> only calculates the optimal size of the RWORK array, returns
  216. *> this value as the first entry of the work array, and no error
  217. *> message related to LRWORK is issued by XERBLA.
  218. *> \endverbatim
  219. *
  220. *> \param[out] IWORK
  221. *> \verbatim
  222. *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
  223. *> \endverbatim
  224. *>
  225. *> \param[out] INFO
  226. *> \verbatim
  227. *> INFO is INTEGER
  228. *> = 0: successful exit.
  229. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  230. *> > 0: CBBCSD did not converge. See the description of WORK
  231. *> above for details.
  232. *> \endverbatim
  233. *
  234. *> \par References:
  235. * ================
  236. *>
  237. *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
  238. *> Algorithms, 50(1):33-65, 2009.
  239. *
  240. * Authors:
  241. * ========
  242. *
  243. *> \author Univ. of Tennessee
  244. *> \author Univ. of California Berkeley
  245. *> \author Univ. of Colorado Denver
  246. *> \author NAG Ltd.
  247. *
  248. *> \date June 2016
  249. *
  250. *> \ingroup complexOTHERcomputational
  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 (version 3.7.1) --
  259. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  260. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  261. * June 2016
  262. *
  263. * .. Scalar Arguments ..
  264. CHARACTER JOBU1, JOBU2, JOBV1T
  265. INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
  266. $ M, P, Q
  267. INTEGER LRWORK, LRWORKMIN, LRWORKOPT
  268. * ..
  269. * .. Array Arguments ..
  270. REAL RWORK(*)
  271. REAL THETA(*)
  272. COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
  273. $ X11(LDX11,*), X21(LDX21,*)
  274. INTEGER IWORK(*)
  275. * ..
  276. *
  277. * =====================================================================
  278. *
  279. * .. Parameters ..
  280. COMPLEX ONE, ZERO
  281. PARAMETER ( ONE = (1.0E0,0.0E0), ZERO = (0.0E0,0.0E0) )
  282. * ..
  283. * .. Local Scalars ..
  284. INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
  285. $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
  286. $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
  287. $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
  288. $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
  289. $ LWORKMIN, LWORKOPT, R
  290. LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
  291. * ..
  292. * .. Local Arrays ..
  293. REAL DUM( 1 )
  294. COMPLEX CDUM( 1, 1 )
  295. * ..
  296. * .. External Subroutines ..
  297. EXTERNAL CBBCSD, CCOPY, CLACPY, CLAPMR, CLAPMT, CUNBDB1,
  298. $ CUNBDB2, CUNBDB3, CUNBDB4, CUNGLQ, CUNGQR,
  299. $ XERBLA
  300. * ..
  301. * .. External Functions ..
  302. LOGICAL LSAME
  303. EXTERNAL LSAME
  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
  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) = LWORKOPT
  513. IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
  514. INFO = -19
  515. END IF
  516. END IF
  517. IF( INFO .NE. 0 ) THEN
  518. CALL XERBLA( 'CUNCSD2BY1', -INFO )
  519. RETURN
  520. ELSE IF( LQUERY ) THEN
  521. RETURN
  522. END IF
  523. LORGQR = LWORK-IORGQR+1
  524. LORGLQ = LWORK-IORGLQ+1
  525. *
  526. * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
  527. * in which R = MIN(P,M-P,Q,M-Q)
  528. *
  529. IF( R .EQ. Q ) THEN
  530. *
  531. * Case 1: R = Q
  532. *
  533. * Simultaneously bidiagonalize X11 and X21
  534. *
  535. CALL CUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  536. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  537. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  538. *
  539. * Accumulate Householder reflectors
  540. *
  541. IF( WANTU1 .AND. P .GT. 0 ) THEN
  542. CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  543. CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  544. $ LORGQR, CHILDINFO )
  545. END IF
  546. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  547. CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  548. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  549. $ WORK(IORGQR), LORGQR, CHILDINFO )
  550. END IF
  551. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  552. V1T(1,1) = ONE
  553. DO J = 2, Q
  554. V1T(1,J) = ZERO
  555. V1T(J,1) = ZERO
  556. END DO
  557. CALL CLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
  558. $ LDV1T )
  559. CALL CUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  560. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  561. END IF
  562. *
  563. * Simultaneously diagonalize X11 and X21.
  564. *
  565. CALL CBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  566. $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, CDUM,
  567. $ 1, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  568. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  569. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
  570. $ CHILDINFO )
  571. *
  572. * Permute rows and columns to place zero submatrices in
  573. * preferred positions
  574. *
  575. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  576. DO I = 1, Q
  577. IWORK(I) = M - P - Q + I
  578. END DO
  579. DO I = Q + 1, M - P
  580. IWORK(I) = I - Q
  581. END DO
  582. CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  583. END IF
  584. ELSE IF( R .EQ. P ) THEN
  585. *
  586. * Case 2: R = P
  587. *
  588. * Simultaneously bidiagonalize X11 and X21
  589. *
  590. CALL CUNBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  591. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  592. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  593. *
  594. * Accumulate Householder reflectors
  595. *
  596. IF( WANTU1 .AND. P .GT. 0 ) THEN
  597. U1(1,1) = ONE
  598. DO J = 2, P
  599. U1(1,J) = ZERO
  600. U1(J,1) = ZERO
  601. END DO
  602. CALL CLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
  603. CALL CUNGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
  604. $ WORK(IORGQR), LORGQR, CHILDINFO )
  605. END IF
  606. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  607. CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  608. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  609. $ WORK(IORGQR), LORGQR, CHILDINFO )
  610. END IF
  611. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  612. CALL CLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
  613. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  614. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  615. END IF
  616. *
  617. * Simultaneously diagonalize X11 and X21.
  618. *
  619. CALL CBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  620. $ RWORK(IPHI), V1T, LDV1T, CDUM, 1, U1, LDU1, U2,
  621. $ LDU2, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  622. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  623. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD), LBBCSD,
  624. $ CHILDINFO )
  625. *
  626. * Permute rows and columns to place identity submatrices in
  627. * preferred positions
  628. *
  629. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  630. DO I = 1, Q
  631. IWORK(I) = M - P - Q + I
  632. END DO
  633. DO I = Q + 1, M - P
  634. IWORK(I) = I - Q
  635. END DO
  636. CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  637. END IF
  638. ELSE IF( R .EQ. M-P ) THEN
  639. *
  640. * Case 3: R = M-P
  641. *
  642. * Simultaneously bidiagonalize X11 and X21
  643. *
  644. CALL CUNBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  645. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  646. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  647. *
  648. * Accumulate Householder reflectors
  649. *
  650. IF( WANTU1 .AND. P .GT. 0 ) THEN
  651. CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  652. CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  653. $ LORGQR, CHILDINFO )
  654. END IF
  655. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  656. U2(1,1) = ONE
  657. DO J = 2, M-P
  658. U2(1,J) = ZERO
  659. U2(J,1) = ZERO
  660. END DO
  661. CALL CLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
  662. $ LDU2 )
  663. CALL CUNGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
  664. $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
  665. END IF
  666. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  667. CALL CLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
  668. CALL CUNGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  669. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  670. END IF
  671. *
  672. * Simultaneously diagonalize X11 and X21.
  673. *
  674. CALL CBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  675. $ THETA, RWORK(IPHI), CDUM, 1, V1T, LDV1T, U2, LDU2,
  676. $ U1, LDU1, RWORK(IB11D), RWORK(IB11E),
  677. $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
  678. $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
  679. $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
  680. *
  681. * Permute rows and columns to place identity submatrices in
  682. * preferred positions
  683. *
  684. IF( Q .GT. R ) THEN
  685. DO I = 1, R
  686. IWORK(I) = Q - R + I
  687. END DO
  688. DO I = R + 1, Q
  689. IWORK(I) = I - R
  690. END DO
  691. IF( WANTU1 ) THEN
  692. CALL CLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
  693. END IF
  694. IF( WANTV1T ) THEN
  695. CALL CLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
  696. END IF
  697. END IF
  698. ELSE
  699. *
  700. * Case 4: R = M-Q
  701. *
  702. * Simultaneously bidiagonalize X11 and X21
  703. *
  704. CALL CUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  705. $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  706. $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
  707. $ LORBDB-M, CHILDINFO )
  708. *
  709. * Accumulate Householder reflectors
  710. *
  711. IF( WANTU1 .AND. P .GT. 0 ) THEN
  712. CALL CCOPY( P, WORK(IORBDB), 1, U1, 1 )
  713. DO J = 2, P
  714. U1(1,J) = ZERO
  715. END DO
  716. CALL CLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
  717. $ LDU1 )
  718. CALL CUNGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
  719. $ WORK(IORGQR), LORGQR, CHILDINFO )
  720. END IF
  721. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  722. CALL CCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
  723. DO J = 2, M-P
  724. U2(1,J) = ZERO
  725. END DO
  726. CALL CLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
  727. $ LDU2 )
  728. CALL CUNGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
  729. $ WORK(IORGQR), LORGQR, CHILDINFO )
  730. END IF
  731. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  732. CALL CLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
  733. CALL CLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
  734. $ V1T(M-Q+1,M-Q+1), LDV1T )
  735. CALL CLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
  736. $ V1T(P+1,P+1), LDV1T )
  737. CALL CUNGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
  738. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  739. END IF
  740. *
  741. * Simultaneously diagonalize X11 and X21.
  742. *
  743. CALL CBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  744. $ THETA, RWORK(IPHI), U2, LDU2, U1, LDU1, CDUM, 1,
  745. $ V1T, LDV1T, RWORK(IB11D), RWORK(IB11E),
  746. $ RWORK(IB12D), RWORK(IB12E), RWORK(IB21D),
  747. $ RWORK(IB21E), RWORK(IB22D), RWORK(IB22E),
  748. $ RWORK(IBBCSD), LBBCSD, CHILDINFO )
  749. *
  750. * Permute rows and columns to place identity submatrices in
  751. * preferred positions
  752. *
  753. IF( P .GT. R ) THEN
  754. DO I = 1, R
  755. IWORK(I) = P - R + I
  756. END DO
  757. DO I = R + 1, P
  758. IWORK(I) = I - R
  759. END DO
  760. IF( WANTU1 ) THEN
  761. CALL CLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
  762. END IF
  763. IF( WANTV1T ) THEN
  764. CALL CLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )
  765. END IF
  766. END IF
  767. END IF
  768. *
  769. RETURN
  770. *
  771. * End of CUNCSD2BY1
  772. *
  773. END