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.

dorcsd.f 21 kB

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