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.

zuncsd2by1.f 26 kB

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