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.

cuncsd.f 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. *> \brief \b CUNCSD
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download CUNCSD + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cuncsd.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cuncsd.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cuncsd.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * RECURSIVE SUBROUTINE CUNCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
  22. * SIGNS, M, P, Q, X11, LDX11, X12,
  23. * LDX12, X21, LDX21, X22, LDX22, THETA,
  24. * U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
  25. * LDV2T, WORK, LWORK, RWORK, LRWORK,
  26. * IWORK, INFO )
  27. *
  28. * .. Scalar Arguments ..
  29. * CHARACTER JOBU1, JOBU2, JOBV1T, JOBV2T, SIGNS, TRANS
  30. * INTEGER INFO, LDU1, LDU2, LDV1T, LDV2T, LDX11, LDX12,
  31. * $ LDX21, LDX22, LRWORK, LWORK, M, P, Q
  32. * ..
  33. * .. Array Arguments ..
  34. * INTEGER IWORK( * )
  35. * REAL THETA( * )
  36. * REAL RWORK( * )
  37. * COMPLEX U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
  38. * $ V2T( LDV2T, * ), WORK( * ), X11( LDX11, * ),
  39. * $ X12( LDX12, * ), X21( LDX21, * ), X22( LDX22,
  40. * $ * )
  41. * ..
  42. *
  43. *
  44. *> \par Purpose:
  45. * =============
  46. *>
  47. *> \verbatim
  48. *>
  49. *> CUNCSD computes the CS decomposition of an M-by-M partitioned
  50. *> unitary matrix X:
  51. *>
  52. *> [ I 0 0 | 0 0 0 ]
  53. *> [ 0 C 0 | 0 -S 0 ]
  54. *> [ X11 | X12 ] [ U1 | ] [ 0 0 0 | 0 0 -I ] [ V1 | ]**H
  55. *> X = [-----------] = [---------] [---------------------] [---------] .
  56. *> [ X21 | X22 ] [ | U2 ] [ 0 0 0 | I 0 0 ] [ | V2 ]
  57. *> [ 0 S 0 | 0 C 0 ]
  58. *> [ 0 0 I | 0 0 0 ]
  59. *>
  60. *> X11 is P-by-Q. The unitary matrices U1, U2, V1, and V2 are P-by-P,
  61. *> (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
  62. *> R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
  63. *> which R = MIN(P,M-P,Q,M-Q).
  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] JOBV2T
  91. *> \verbatim
  92. *> JOBV2T is CHARACTER
  93. *> = 'Y': V2T is computed;
  94. *> otherwise: V2T is not computed.
  95. *> \endverbatim
  96. *>
  97. *> \param[in] TRANS
  98. *> \verbatim
  99. *> TRANS is CHARACTER
  100. *> = 'T': X, U1, U2, V1T, and V2T are stored in row-major
  101. *> order;
  102. *> otherwise: X, U1, U2, V1T, and V2T are stored in column-
  103. *> major order.
  104. *> \endverbatim
  105. *>
  106. *> \param[in] SIGNS
  107. *> \verbatim
  108. *> SIGNS is CHARACTER
  109. *> = 'O': The lower-left block is made nonpositive (the
  110. *> "other" convention);
  111. *> otherwise: The upper-right block is made nonpositive (the
  112. *> "default" convention).
  113. *> \endverbatim
  114. *>
  115. *> \param[in] M
  116. *> \verbatim
  117. *> M is INTEGER
  118. *> The number of rows and columns in X.
  119. *> \endverbatim
  120. *>
  121. *> \param[in] P
  122. *> \verbatim
  123. *> P is INTEGER
  124. *> The number of rows in X11 and X12. 0 <= P <= M.
  125. *> \endverbatim
  126. *>
  127. *> \param[in] Q
  128. *> \verbatim
  129. *> Q is INTEGER
  130. *> The number of columns in X11 and X21. 0 <= Q <= M.
  131. *> \endverbatim
  132. *>
  133. *> \param[in,out] X11
  134. *> \verbatim
  135. *> X11 is COMPLEX array, dimension (LDX11,Q)
  136. *> On entry, part of the unitary matrix whose CSD is desired.
  137. *> \endverbatim
  138. *>
  139. *> \param[in] LDX11
  140. *> \verbatim
  141. *> LDX11 is INTEGER
  142. *> The leading dimension of X11. LDX11 >= MAX(1,P).
  143. *> \endverbatim
  144. *>
  145. *> \param[in,out] X12
  146. *> \verbatim
  147. *> X12 is COMPLEX array, dimension (LDX12,M-Q)
  148. *> On entry, part of the unitary matrix whose CSD is desired.
  149. *> \endverbatim
  150. *>
  151. *> \param[in] LDX12
  152. *> \verbatim
  153. *> LDX12 is INTEGER
  154. *> The leading dimension of X12. LDX12 >= MAX(1,P).
  155. *> \endverbatim
  156. *>
  157. *> \param[in,out] X21
  158. *> \verbatim
  159. *> X21 is COMPLEX array, dimension (LDX21,Q)
  160. *> On entry, part of the unitary matrix whose CSD is desired.
  161. *> \endverbatim
  162. *>
  163. *> \param[in] LDX21
  164. *> \verbatim
  165. *> LDX21 is INTEGER
  166. *> The leading dimension of X11. LDX21 >= MAX(1,M-P).
  167. *> \endverbatim
  168. *>
  169. *> \param[in,out] X22
  170. *> \verbatim
  171. *> X22 is COMPLEX array, dimension (LDX22,M-Q)
  172. *> On entry, part of the unitary matrix whose CSD is desired.
  173. *> \endverbatim
  174. *>
  175. *> \param[in] LDX22
  176. *> \verbatim
  177. *> LDX22 is INTEGER
  178. *> The leading dimension of X11. LDX22 >= MAX(1,M-P).
  179. *> \endverbatim
  180. *>
  181. *> \param[out] THETA
  182. *> \verbatim
  183. *> THETA is REAL array, dimension (R), in which R =
  184. *> MIN(P,M-P,Q,M-Q).
  185. *> C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
  186. *> S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
  187. *> \endverbatim
  188. *>
  189. *> \param[out] U1
  190. *> \verbatim
  191. *> U1 is COMPLEX array, dimension (LDU1,P)
  192. *> If JOBU1 = 'Y', U1 contains the P-by-P unitary matrix U1.
  193. *> \endverbatim
  194. *>
  195. *> \param[in] LDU1
  196. *> \verbatim
  197. *> LDU1 is INTEGER
  198. *> The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
  199. *> MAX(1,P).
  200. *> \endverbatim
  201. *>
  202. *> \param[out] U2
  203. *> \verbatim
  204. *> U2 is COMPLEX array, dimension (LDU2,M-P)
  205. *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) unitary
  206. *> matrix U2.
  207. *> \endverbatim
  208. *>
  209. *> \param[in] LDU2
  210. *> \verbatim
  211. *> LDU2 is INTEGER
  212. *> The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
  213. *> MAX(1,M-P).
  214. *> \endverbatim
  215. *>
  216. *> \param[out] V1T
  217. *> \verbatim
  218. *> V1T is COMPLEX array, dimension (LDV1T,Q)
  219. *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix unitary
  220. *> matrix V1**H.
  221. *> \endverbatim
  222. *>
  223. *> \param[in] LDV1T
  224. *> \verbatim
  225. *> LDV1T is INTEGER
  226. *> The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
  227. *> MAX(1,Q).
  228. *> \endverbatim
  229. *>
  230. *> \param[out] V2T
  231. *> \verbatim
  232. *> V2T is COMPLEX array, dimension (LDV2T,M-Q)
  233. *> If JOBV2T = 'Y', V2T contains the (M-Q)-by-(M-Q) unitary
  234. *> matrix V2**H.
  235. *> \endverbatim
  236. *>
  237. *> \param[in] LDV2T
  238. *> \verbatim
  239. *> LDV2T is INTEGER
  240. *> The leading dimension of V2T. If JOBV2T = 'Y', LDV2T >=
  241. *> MAX(1,M-Q).
  242. *> \endverbatim
  243. *>
  244. *> \param[out] WORK
  245. *> \verbatim
  246. *> WORK is COMPLEX array, dimension (MAX(1,LWORK))
  247. *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  248. *> \endverbatim
  249. *>
  250. *> \param[in] LWORK
  251. *> \verbatim
  252. *> LWORK is INTEGER
  253. *> The dimension of the array WORK.
  254. *>
  255. *> If LWORK = -1, then a workspace query is assumed; the routine
  256. *> only calculates the optimal size of the WORK array, returns
  257. *> this value as the first entry of the work array, and no error
  258. *> message related to LWORK is issued by XERBLA.
  259. *> \endverbatim
  260. *>
  261. *> \param[out] RWORK
  262. *> \verbatim
  263. *> RWORK is REAL array, dimension MAX(1,LRWORK)
  264. *> On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
  265. *> If INFO > 0 on exit, RWORK(2:R) contains the values PHI(1),
  266. *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  267. *> define the matrix in intermediate bidiagonal-block form
  268. *> remaining after nonconvergence. INFO specifies the number
  269. *> of nonzero PHI's.
  270. *> \endverbatim
  271. *>
  272. *> \param[in] LRWORK
  273. *> \verbatim
  274. *> LRWORK is INTEGER
  275. *> The dimension of the array RWORK.
  276. *>
  277. *> If LRWORK = -1, then a workspace query is assumed; the routine
  278. *> only calculates the optimal size of the RWORK array, returns
  279. *> this value as the first entry of the work array, and no error
  280. *> message related to LRWORK is issued by XERBLA.
  281. *> \endverbatim
  282. *>
  283. *> \param[out] IWORK
  284. *> \verbatim
  285. *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
  286. *> \endverbatim
  287. *>
  288. *> \param[out] INFO
  289. *> \verbatim
  290. *> INFO is INTEGER
  291. *> = 0: successful exit.
  292. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  293. *> > 0: CBBCSD did not converge. See the description of RWORK
  294. *> above for details.
  295. *> \endverbatim
  296. *
  297. *> \par References:
  298. * ================
  299. *>
  300. *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
  301. *> Algorithms, 50(1):33-65, 2009.
  302. *
  303. * Authors:
  304. * ========
  305. *
  306. *> \author Univ. of Tennessee
  307. *> \author Univ. of California Berkeley
  308. *> \author Univ. of Colorado Denver
  309. *> \author NAG Ltd.
  310. *
  311. *> \ingroup uncsd
  312. *
  313. * =====================================================================
  314. RECURSIVE SUBROUTINE CUNCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
  315. $ SIGNS, M, P, Q, X11, LDX11, X12,
  316. $ LDX12, X21, LDX21, X22, LDX22, THETA,
  317. $ U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
  318. $ LDV2T, WORK, LWORK, RWORK, LRWORK,
  319. $ IWORK, INFO )
  320. *
  321. * -- LAPACK computational routine --
  322. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  323. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  324. *
  325. * .. Scalar Arguments ..
  326. CHARACTER JOBU1, JOBU2, JOBV1T, JOBV2T, SIGNS, TRANS
  327. INTEGER INFO, LDU1, LDU2, LDV1T, LDV2T, LDX11, LDX12,
  328. $ LDX21, LDX22, LRWORK, LWORK, M, P, Q
  329. * ..
  330. * .. Array Arguments ..
  331. INTEGER IWORK( * )
  332. REAL THETA( * )
  333. REAL RWORK( * )
  334. COMPLEX U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
  335. $ V2T( LDV2T, * ), WORK( * ), X11( LDX11, * ),
  336. $ X12( LDX12, * ), X21( LDX21, * ), X22( LDX22,
  337. $ * )
  338. * ..
  339. *
  340. * ===================================================================
  341. *
  342. * .. Parameters ..
  343. COMPLEX ONE, ZERO
  344. PARAMETER ( ONE = (1.0E0,0.0E0),
  345. $ ZERO = (0.0E0,0.0E0) )
  346. * ..
  347. * .. Local Scalars ..
  348. CHARACTER TRANST, SIGNST
  349. INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
  350. $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
  351. $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
  352. $ ITAUQ2, J, LBBCSDWORK, LBBCSDWORKMIN,
  353. $ LBBCSDWORKOPT, LORBDBWORK, LORBDBWORKMIN,
  354. $ LORBDBWORKOPT, LORGLQWORK, LORGLQWORKMIN,
  355. $ LORGLQWORKOPT, LORGQRWORK, LORGQRWORKMIN,
  356. $ LORGQRWORKOPT, LWORKMIN, LWORKOPT, P1, Q1
  357. LOGICAL COLMAJOR, DEFAULTSIGNS, LQUERY, WANTU1, WANTU2,
  358. $ WANTV1T, WANTV2T
  359. INTEGER LRWORKMIN, LRWORKOPT
  360. LOGICAL LRQUERY
  361. * ..
  362. * .. External Subroutines ..
  363. EXTERNAL XERBLA, CBBCSD, CLACPY, CLAPMR, CLAPMT,
  364. $ CUNBDB, CUNGLQ, CUNGQR
  365. * ..
  366. * .. External Functions ..
  367. LOGICAL LSAME
  368. REAL SROUNDUP_LWORK
  369. EXTERNAL LSAME, SROUNDUP_LWORK
  370. * ..
  371. * .. Intrinsic Functions
  372. INTRINSIC INT, MAX, MIN
  373. * ..
  374. * .. Executable Statements ..
  375. *
  376. * Test input arguments
  377. *
  378. INFO = 0
  379. WANTU1 = LSAME( JOBU1, 'Y' )
  380. WANTU2 = LSAME( JOBU2, 'Y' )
  381. WANTV1T = LSAME( JOBV1T, 'Y' )
  382. WANTV2T = LSAME( JOBV2T, 'Y' )
  383. COLMAJOR = .NOT. LSAME( TRANS, 'T' )
  384. DEFAULTSIGNS = .NOT. LSAME( SIGNS, 'O' )
  385. LQUERY = LWORK .EQ. -1
  386. LRQUERY = LRWORK .EQ. -1
  387. IF( M .LT. 0 ) THEN
  388. INFO = -7
  389. ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
  390. INFO = -8
  391. ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
  392. INFO = -9
  393. ELSE IF ( COLMAJOR .AND. LDX11 .LT. MAX( 1, P ) ) THEN
  394. INFO = -11
  395. ELSE IF (.NOT. COLMAJOR .AND. LDX11 .LT. MAX( 1, Q ) ) THEN
  396. INFO = -11
  397. ELSE IF (COLMAJOR .AND. LDX12 .LT. MAX( 1, P ) ) THEN
  398. INFO = -13
  399. ELSE IF (.NOT. COLMAJOR .AND. LDX12 .LT. MAX( 1, M-Q ) ) THEN
  400. INFO = -13
  401. ELSE IF (COLMAJOR .AND. LDX21 .LT. MAX( 1, M-P ) ) THEN
  402. INFO = -15
  403. ELSE IF (.NOT. COLMAJOR .AND. LDX21 .LT. MAX( 1, Q ) ) THEN
  404. INFO = -15
  405. ELSE IF (COLMAJOR .AND. LDX22 .LT. MAX( 1, M-P ) ) THEN
  406. INFO = -17
  407. ELSE IF (.NOT. COLMAJOR .AND. LDX22 .LT. MAX( 1, M-Q ) ) THEN
  408. INFO = -17
  409. ELSE IF( WANTU1 .AND. LDU1 .LT. P ) THEN
  410. INFO = -20
  411. ELSE IF( WANTU2 .AND. LDU2 .LT. M-P ) THEN
  412. INFO = -22
  413. ELSE IF( WANTV1T .AND. LDV1T .LT. Q ) THEN
  414. INFO = -24
  415. ELSE IF( WANTV2T .AND. LDV2T .LT. M-Q ) THEN
  416. INFO = -26
  417. END IF
  418. *
  419. * Work with transpose if convenient
  420. *
  421. IF( INFO .EQ. 0 .AND. MIN( P, M-P ) .LT. MIN( Q, M-Q ) ) THEN
  422. IF( COLMAJOR ) THEN
  423. TRANST = 'T'
  424. ELSE
  425. TRANST = 'N'
  426. END IF
  427. IF( DEFAULTSIGNS ) THEN
  428. SIGNST = 'O'
  429. ELSE
  430. SIGNST = 'D'
  431. END IF
  432. CALL CUNCSD( JOBV1T, JOBV2T, JOBU1, JOBU2, TRANST, SIGNST, M,
  433. $ Q, P, X11, LDX11, X21, LDX21, X12, LDX12, X22,
  434. $ LDX22, THETA, V1T, LDV1T, V2T, LDV2T, U1, LDU1,
  435. $ U2, LDU2, WORK, LWORK, RWORK, LRWORK, IWORK,
  436. $ INFO )
  437. RETURN
  438. END IF
  439. *
  440. * Work with permutation [ 0 I; I 0 ] * X * [ 0 I; I 0 ] if
  441. * convenient
  442. *
  443. IF( INFO .EQ. 0 .AND. M-Q .LT. Q ) THEN
  444. IF( DEFAULTSIGNS ) THEN
  445. SIGNST = 'O'
  446. ELSE
  447. SIGNST = 'D'
  448. END IF
  449. CALL CUNCSD( JOBU2, JOBU1, JOBV2T, JOBV1T, TRANS, SIGNST, M,
  450. $ M-P, M-Q, X22, LDX22, X21, LDX21, X12, LDX12, X11,
  451. $ LDX11, THETA, U2, LDU2, U1, LDU1, V2T, LDV2T, V1T,
  452. $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK, INFO )
  453. RETURN
  454. END IF
  455. *
  456. * Compute workspace
  457. *
  458. IF( INFO .EQ. 0 ) THEN
  459. *
  460. * Real workspace
  461. *
  462. IPHI = 2
  463. IB11D = IPHI + MAX( 1, Q - 1 )
  464. IB11E = IB11D + MAX( 1, Q )
  465. IB12D = IB11E + MAX( 1, Q - 1 )
  466. IB12E = IB12D + MAX( 1, Q )
  467. IB21D = IB12E + MAX( 1, Q - 1 )
  468. IB21E = IB21D + MAX( 1, Q )
  469. IB22D = IB21E + MAX( 1, Q - 1 )
  470. IB22E = IB22D + MAX( 1, Q )
  471. IBBCSD = IB22E + MAX( 1, Q - 1 )
  472. CALL CBBCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS, M, P, Q,
  473. $ THETA, THETA, U1, LDU1, U2, LDU2, V1T, LDV1T,
  474. $ V2T, LDV2T, THETA, THETA, THETA, THETA, THETA,
  475. $ THETA, THETA, THETA, RWORK, -1, CHILDINFO )
  476. LBBCSDWORKOPT = INT( RWORK(1) )
  477. LBBCSDWORKMIN = LBBCSDWORKOPT
  478. LRWORKOPT = IBBCSD + LBBCSDWORKOPT - 1
  479. LRWORKMIN = IBBCSD + LBBCSDWORKMIN - 1
  480. RWORK(1) = LRWORKOPT
  481. *
  482. * Complex workspace
  483. *
  484. ITAUP1 = 2
  485. ITAUP2 = ITAUP1 + MAX( 1, P )
  486. ITAUQ1 = ITAUP2 + MAX( 1, M - P )
  487. ITAUQ2 = ITAUQ1 + MAX( 1, Q )
  488. IORGQR = ITAUQ2 + MAX( 1, M - Q )
  489. CALL CUNGQR( M-Q, M-Q, M-Q, U1, MAX(1,M-Q), U1, WORK, -1,
  490. $ CHILDINFO )
  491. LORGQRWORKOPT = INT( WORK(1) )
  492. LORGQRWORKMIN = MAX( 1, M - Q )
  493. IORGLQ = ITAUQ2 + MAX( 1, M - Q )
  494. CALL CUNGLQ( M-Q, M-Q, M-Q, U1, MAX(1,M-Q), U1, WORK, -1,
  495. $ CHILDINFO )
  496. LORGLQWORKOPT = INT( WORK(1) )
  497. LORGLQWORKMIN = MAX( 1, M - Q )
  498. IORBDB = ITAUQ2 + MAX( 1, M - Q )
  499. CALL CUNBDB( TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12,
  500. $ X21, LDX21, X22, LDX22, THETA, THETA, U1, U2,
  501. $ V1T, V2T, WORK, -1, CHILDINFO )
  502. LORBDBWORKOPT = INT( WORK(1) )
  503. LORBDBWORKMIN = LORBDBWORKOPT
  504. LWORKOPT = MAX( IORGQR + LORGQRWORKOPT, IORGLQ + LORGLQWORKOPT,
  505. $ IORBDB + LORBDBWORKOPT ) - 1
  506. LWORKMIN = MAX( IORGQR + LORGQRWORKMIN, IORGLQ + LORGLQWORKMIN,
  507. $ IORBDB + LORBDBWORKMIN ) - 1
  508. LWORKOPT = MAX(LWORKOPT,LWORKMIN)
  509. WORK(1) = SROUNDUP_LWORK(LWORKOPT)
  510. *
  511. IF( LWORK .LT. LWORKMIN
  512. $ .AND. .NOT. ( LQUERY .OR. LRQUERY ) ) THEN
  513. INFO = -22
  514. ELSE IF( LRWORK .LT. LRWORKMIN
  515. $ .AND. .NOT. ( LQUERY .OR. LRQUERY ) ) THEN
  516. INFO = -24
  517. ELSE
  518. LORGQRWORK = LWORK - IORGQR + 1
  519. LORGLQWORK = LWORK - IORGLQ + 1
  520. LORBDBWORK = LWORK - IORBDB + 1
  521. LBBCSDWORK = LRWORK - IBBCSD + 1
  522. END IF
  523. END IF
  524. *
  525. * Abort if any illegal arguments
  526. *
  527. IF( INFO .NE. 0 ) THEN
  528. CALL XERBLA( 'CUNCSD', -INFO )
  529. RETURN
  530. ELSE IF( LQUERY .OR. LRQUERY ) THEN
  531. RETURN
  532. END IF
  533. *
  534. * Transform to bidiagonal block form
  535. *
  536. CALL CUNBDB( TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12, X21,
  537. $ LDX21, X22, LDX22, THETA, RWORK(IPHI), WORK(ITAUP1),
  538. $ WORK(ITAUP2), WORK(ITAUQ1), WORK(ITAUQ2),
  539. $ WORK(IORBDB), LORBDBWORK, CHILDINFO )
  540. *
  541. * Accumulate Householder reflectors
  542. *
  543. IF( COLMAJOR ) THEN
  544. IF( WANTU1 .AND. P .GT. 0 ) THEN
  545. CALL CLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  546. CALL CUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  547. $ LORGQRWORK, INFO)
  548. END IF
  549. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  550. CALL CLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  551. CALL CUNGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  552. $ WORK(IORGQR), LORGQRWORK, INFO )
  553. END IF
  554. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  555. CALL CLACPY( 'U', Q-1, Q-1, X11(1,2), LDX11, V1T(2,2),
  556. $ LDV1T )
  557. V1T(1, 1) = ONE
  558. DO J = 2, Q
  559. V1T(1,J) = ZERO
  560. V1T(J,1) = ZERO
  561. END DO
  562. CALL CUNGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  563. $ WORK(IORGLQ), LORGLQWORK, INFO )
  564. END IF
  565. IF( WANTV2T .AND. M-Q .GT. 0 ) THEN
  566. CALL CLACPY( 'U', P, M-Q, X12, LDX12, V2T, LDV2T )
  567. IF( M-P .GT. Q ) THEN
  568. CALL CLACPY( 'U', M-P-Q, M-P-Q, X22(Q+1,P+1), LDX22,
  569. $ V2T(P+1,P+1), LDV2T )
  570. END IF
  571. IF( M .GT. Q ) THEN
  572. CALL CUNGLQ( M-Q, M-Q, M-Q, V2T, LDV2T, WORK(ITAUQ2),
  573. $ WORK(IORGLQ), LORGLQWORK, INFO )
  574. END IF
  575. END IF
  576. ELSE
  577. IF( WANTU1 .AND. P .GT. 0 ) THEN
  578. CALL CLACPY( 'U', Q, P, X11, LDX11, U1, LDU1 )
  579. CALL CUNGLQ( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGLQ),
  580. $ LORGLQWORK, INFO)
  581. END IF
  582. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  583. CALL CLACPY( 'U', Q, M-P, X21, LDX21, U2, LDU2 )
  584. CALL CUNGLQ( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  585. $ WORK(IORGLQ), LORGLQWORK, INFO )
  586. END IF
  587. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  588. CALL CLACPY( 'L', Q-1, Q-1, X11(2,1), LDX11, V1T(2,2),
  589. $ LDV1T )
  590. V1T(1, 1) = ONE
  591. DO J = 2, Q
  592. V1T(1,J) = ZERO
  593. V1T(J,1) = ZERO
  594. END DO
  595. CALL CUNGQR( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  596. $ WORK(IORGQR), LORGQRWORK, INFO )
  597. END IF
  598. IF( WANTV2T .AND. M-Q .GT. 0 ) THEN
  599. P1 = MIN( P+1, M )
  600. Q1 = MIN( Q+1, M )
  601. CALL CLACPY( 'L', M-Q, P, X12, LDX12, V2T, LDV2T )
  602. IF ( M .GT. P+Q ) THEN
  603. CALL CLACPY( 'L', M-P-Q, M-P-Q, X22(P1,Q1), LDX22,
  604. $ V2T(P+1,P+1), LDV2T )
  605. END IF
  606. CALL CUNGQR( M-Q, M-Q, M-Q, V2T, LDV2T, WORK(ITAUQ2),
  607. $ WORK(IORGQR), LORGQRWORK, INFO )
  608. END IF
  609. END IF
  610. *
  611. * Compute the CSD of the matrix in bidiagonal-block form
  612. *
  613. CALL CBBCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS, M, P, Q, THETA,
  614. $ RWORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
  615. $ LDV2T, RWORK(IB11D), RWORK(IB11E), RWORK(IB12D),
  616. $ RWORK(IB12E), RWORK(IB21D), RWORK(IB21E),
  617. $ RWORK(IB22D), RWORK(IB22E), RWORK(IBBCSD),
  618. $ LBBCSDWORK, INFO )
  619. *
  620. * Permute rows and columns to place identity submatrices in top-
  621. * left corner of (1,1)-block and/or bottom-right corner of (1,2)-
  622. * block and/or bottom-right corner of (2,1)-block and/or top-left
  623. * corner of (2,2)-block
  624. *
  625. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  626. DO I = 1, Q
  627. IWORK(I) = M - P - Q + I
  628. END DO
  629. DO I = Q + 1, M - P
  630. IWORK(I) = I - Q
  631. END DO
  632. IF( COLMAJOR ) THEN
  633. CALL CLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  634. ELSE
  635. CALL CLAPMR( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  636. END IF
  637. END IF
  638. IF( M .GT. 0 .AND. WANTV2T ) THEN
  639. DO I = 1, P
  640. IWORK(I) = M - P - Q + I
  641. END DO
  642. DO I = P + 1, M - Q
  643. IWORK(I) = I - P
  644. END DO
  645. IF( .NOT. COLMAJOR ) THEN
  646. CALL CLAPMT( .FALSE., M-Q, M-Q, V2T, LDV2T, IWORK )
  647. ELSE
  648. CALL CLAPMR( .FALSE., M-Q, M-Q, V2T, LDV2T, IWORK )
  649. END IF
  650. END IF
  651. *
  652. RETURN
  653. *
  654. * End CUNCSD
  655. *
  656. END