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.

dorcsd2by1.f 26 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. *> \brief \b DORCSD2BY1
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download DORCSD2BY1 + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dorcsd2by1.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dorcsd2by1.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorcsd2by1.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE DORCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
  22. * X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
  23. * LDV1T, WORK, LWORK, IWORK, INFO )
  24. *
  25. * .. Scalar Arguments ..
  26. * CHARACTER JOBU1, JOBU2, JOBV1T
  27. * INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
  28. * $ M, P, Q
  29. * ..
  30. * .. Array Arguments ..
  31. * DOUBLE PRECISION THETA(*)
  32. * DOUBLE PRECISION U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
  33. * $ X11(LDX11,*), X21(LDX21,*)
  34. * INTEGER IWORK(*)
  35. * ..
  36. *
  37. *
  38. *> \par Purpose:
  39. *> =============
  40. *>
  41. *>\verbatim
  42. *> Purpose:
  43. *> ========
  44. *>
  45. *> DORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with
  46. *> orthonormal columns that has been partitioned into a 2-by-1 block
  47. *> structure:
  48. *>
  49. *> [ I 0 0 ]
  50. *> [ 0 C 0 ]
  51. *> [ X11 ] [ U1 | ] [ 0 0 0 ]
  52. *> X = [-----] = [---------] [----------] V1**T .
  53. *> [ X21 ] [ | U2 ] [ 0 0 0 ]
  54. *> [ 0 S 0 ]
  55. *> [ 0 0 I ]
  56. *>
  57. *> X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P,
  58. *> (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
  59. *> R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
  60. *> which R = MIN(P,M-P,Q,M-Q).
  61. *>
  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 and columns in X.
  92. *> \endverbatim
  93. *>
  94. *> \param[in] P
  95. *> \verbatim
  96. *> P is INTEGER
  97. *> The number of rows in X11 and X12. 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 DOUBLE PRECISION array, dimension (LDX11,Q)
  109. *> On entry, part of the orthogonal matrix whose CSD is
  110. *> desired.
  111. *> \endverbatim
  112. *>
  113. *> \param[in] LDX11
  114. *> \verbatim
  115. *> LDX11 is INTEGER
  116. *> The leading dimension of X11. LDX11 >= MAX(1,P).
  117. *> \endverbatim
  118. *>
  119. *> \param[in,out] X21
  120. *> \verbatim
  121. *> X21 is DOUBLE PRECISION array, dimension (LDX21,Q)
  122. *> On entry, part of the orthogonal matrix whose CSD is
  123. *> 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 DOUBLE PRECISION 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 DOUBLE PRECISION array, dimension (P)
  143. *> If JOBU1 = 'Y', U1 contains the P-by-P orthogonal 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 DOUBLE PRECISION array, dimension (M-P)
  156. *> If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) orthogonal
  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 DOUBLE PRECISION array, dimension (Q)
  170. *> If JOBV1T = 'Y', V1T contains the Q-by-Q matrix orthogonal
  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 DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  184. *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  185. *> If INFO > 0 on exit, WORK(2:R) contains the values PHI(1),
  186. *> ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  187. *> define the matrix in intermediate bidiagonal-block form
  188. *> remaining after nonconvergence. INFO specifies the number
  189. *> of nonzero PHI's.
  190. *> \endverbatim
  191. *>
  192. *> \param[in] LWORK
  193. *> \verbatim
  194. *> LWORK is INTEGER
  195. *> The dimension of the array WORK.
  196. *> \endverbatim
  197. *>
  198. *> If LWORK = -1, then a workspace query is assumed; the routine
  199. *> only calculates the optimal size of the WORK array, returns
  200. *> this value as the first entry of the work array, and no error
  201. *> message related to LWORK is issued by XERBLA.
  202. *> \param[out] IWORK
  203. *> \verbatim
  204. *> IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
  205. *> \endverbatim
  206. *>
  207. *> \param[out] INFO
  208. *> \verbatim
  209. *> INFO is INTEGER
  210. *> = 0: successful exit.
  211. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  212. *> > 0: DBBCSD did not converge. See the description of WORK
  213. *> above for details.
  214. *> \endverbatim
  215. *
  216. * Authors:
  217. * ========
  218. *
  219. *> \author Univ. of Tennessee
  220. *> \author Univ. of California Berkeley
  221. *> \author Univ. of Colorado Denver
  222. *> \author NAG Ltd.
  223. *
  224. *> \date July 2012
  225. *
  226. *> \ingroup doubleOTHERcomputational
  227. *
  228. *> \par References:
  229. * ================
  230. *>
  231. *> [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
  232. *> Algorithms, 50(1):33-65, 2009.
  233. *> \endverbatim
  234. *>
  235. * =====================================================================
  236. SUBROUTINE DORCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
  237. $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
  238. $ LDV1T, WORK, LWORK, IWORK, INFO )
  239. *
  240. * -- LAPACK computational routine (3.5.0) --
  241. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  242. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  243. * July 2012
  244. *
  245. * .. Scalar Arguments ..
  246. CHARACTER JOBU1, JOBU2, JOBV1T
  247. INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
  248. $ M, P, Q
  249. * ..
  250. * .. Array Arguments ..
  251. DOUBLE PRECISION THETA(*)
  252. DOUBLE PRECISION U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
  253. $ X11(LDX11,*), X21(LDX21,*)
  254. INTEGER IWORK(*)
  255. * ..
  256. *
  257. * =====================================================================
  258. *
  259. * .. Parameters ..
  260. DOUBLE PRECISION ONE, ZERO
  261. PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0 )
  262. * ..
  263. * .. Local Scalars ..
  264. INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
  265. $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
  266. $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
  267. $ J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
  268. $ LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
  269. $ LWORKMIN, LWORKOPT, R
  270. LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
  271. * ..
  272. * .. External Subroutines ..
  273. EXTERNAL DBBCSD, DCOPY, DLACPY, DLAPMR, DLAPMT, DORBDB1,
  274. $ DORBDB2, DORBDB3, DORBDB4, DORGLQ, DORGQR,
  275. $ XERBLA
  276. * ..
  277. * .. External Functions ..
  278. LOGICAL LSAME
  279. EXTERNAL LSAME
  280. * ..
  281. * .. Intrinsic Function ..
  282. INTRINSIC INT, MAX, MIN
  283. * ..
  284. * .. Executable Statements ..
  285. *
  286. * Test input arguments
  287. *
  288. INFO = 0
  289. WANTU1 = LSAME( JOBU1, 'Y' )
  290. WANTU2 = LSAME( JOBU2, 'Y' )
  291. WANTV1T = LSAME( JOBV1T, 'Y' )
  292. LQUERY = LWORK .EQ. -1
  293. *
  294. IF( M .LT. 0 ) THEN
  295. INFO = -4
  296. ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
  297. INFO = -5
  298. ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
  299. INFO = -6
  300. ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
  301. INFO = -8
  302. ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
  303. INFO = -10
  304. ELSE IF( WANTU1 .AND. LDU1 .LT. P ) THEN
  305. INFO = -13
  306. ELSE IF( WANTU2 .AND. LDU2 .LT. M - P ) THEN
  307. INFO = -15
  308. ELSE IF( WANTV1T .AND. LDV1T .LT. Q ) THEN
  309. INFO = -17
  310. END IF
  311. *
  312. R = MIN( P, M-P, Q, M-Q )
  313. *
  314. * Compute workspace
  315. *
  316. * WORK layout:
  317. * |-------------------------------------------------------|
  318. * | LWORKOPT (1) |
  319. * |-------------------------------------------------------|
  320. * | PHI (MAX(1,R-1)) |
  321. * |-------------------------------------------------------|
  322. * | TAUP1 (MAX(1,P)) | B11D (R) |
  323. * | TAUP2 (MAX(1,M-P)) | B11E (R-1) |
  324. * | TAUQ1 (MAX(1,Q)) | B12D (R) |
  325. * |-----------------------------------------| B12E (R-1) |
  326. * | DORBDB WORK | DORGQR WORK | DORGLQ WORK | B21D (R) |
  327. * | | | | B21E (R-1) |
  328. * | | | | B22D (R) |
  329. * | | | | B22E (R-1) |
  330. * | | | | DBBCSD WORK |
  331. * |-------------------------------------------------------|
  332. *
  333. IF( INFO .EQ. 0 ) THEN
  334. IPHI = 2
  335. IB11D = IPHI + MAX( 1, R-1 )
  336. IB11E = IB11D + MAX( 1, R )
  337. IB12D = IB11E + MAX( 1, R - 1 )
  338. IB12E = IB12D + MAX( 1, R )
  339. IB21D = IB12E + MAX( 1, R - 1 )
  340. IB21E = IB21D + MAX( 1, R )
  341. IB22D = IB21E + MAX( 1, R - 1 )
  342. IB22E = IB22D + MAX( 1, R )
  343. IBBCSD = IB22E + MAX( 1, R - 1 )
  344. ITAUP1 = IPHI + MAX( 1, R-1 )
  345. ITAUP2 = ITAUP1 + MAX( 1, P )
  346. ITAUQ1 = ITAUP2 + MAX( 1, M-P )
  347. IORBDB = ITAUQ1 + MAX( 1, Q )
  348. IORGQR = ITAUQ1 + MAX( 1, Q )
  349. IORGLQ = ITAUQ1 + MAX( 1, Q )
  350. IF( R .EQ. Q ) THEN
  351. CALL DORBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  352. $ 0, 0, WORK, -1, CHILDINFO )
  353. LORBDB = INT( WORK(1) )
  354. IF( P .GE. M-P ) THEN
  355. CALL DORGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  356. $ CHILDINFO )
  357. LORGQRMIN = MAX( 1, P )
  358. LORGQROPT = INT( WORK(1) )
  359. ELSE
  360. CALL DORGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  361. $ CHILDINFO )
  362. LORGQRMIN = MAX( 1, M-P )
  363. LORGQROPT = INT( WORK(1) )
  364. END IF
  365. CALL DORGLQ( MAX(0,Q-1), MAX(0,Q-1), MAX(0,Q-1), V1T, LDV1T,
  366. $ 0, WORK(1), -1, CHILDINFO )
  367. LORGLQMIN = MAX( 1, Q-1 )
  368. LORGLQOPT = INT( WORK(1) )
  369. CALL DBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  370. $ 0, U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1, 0, 0,
  371. $ 0, 0, 0, 0, 0, 0, WORK(1), -1, CHILDINFO )
  372. LBBCSD = INT( WORK(1) )
  373. ELSE IF( R .EQ. P ) THEN
  374. CALL DORBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  375. $ 0, 0, WORK(1), -1, CHILDINFO )
  376. LORBDB = INT( WORK(1) )
  377. IF( P-1 .GE. M-P ) THEN
  378. CALL DORGQR( P-1, P-1, P-1, U1(2,2), LDU1, 0, WORK(1),
  379. $ -1, CHILDINFO )
  380. LORGQRMIN = MAX( 1, P-1 )
  381. LORGQROPT = INT( WORK(1) )
  382. ELSE
  383. CALL DORGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  384. $ CHILDINFO )
  385. LORGQRMIN = MAX( 1, M-P )
  386. LORGQROPT = INT( WORK(1) )
  387. END IF
  388. CALL DORGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  389. $ CHILDINFO )
  390. LORGLQMIN = MAX( 1, Q )
  391. LORGLQOPT = INT( WORK(1) )
  392. CALL DBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  393. $ 0, V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2, 0, 0,
  394. $ 0, 0, 0, 0, 0, 0, WORK(1), -1, CHILDINFO )
  395. LBBCSD = INT( WORK(1) )
  396. ELSE IF( R .EQ. M-P ) THEN
  397. CALL DORBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  398. $ 0, 0, WORK(1), -1, CHILDINFO )
  399. LORBDB = INT( WORK(1) )
  400. IF( P .GE. M-P-1 ) THEN
  401. CALL DORGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  402. $ CHILDINFO )
  403. LORGQRMIN = MAX( 1, P )
  404. LORGQROPT = INT( WORK(1) )
  405. ELSE
  406. CALL DORGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, 0,
  407. $ WORK(1), -1, CHILDINFO )
  408. LORGQRMIN = MAX( 1, M-P-1 )
  409. LORGQROPT = INT( WORK(1) )
  410. END IF
  411. CALL DORGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  412. $ CHILDINFO )
  413. LORGLQMIN = MAX( 1, Q )
  414. LORGLQOPT = INT( WORK(1) )
  415. CALL DBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  416. $ THETA, 0, 0, 1, V1T, LDV1T, U2, LDU2, U1, LDU1,
  417. $ 0, 0, 0, 0, 0, 0, 0, 0, WORK(1), -1,
  418. $ CHILDINFO )
  419. LBBCSD = INT( WORK(1) )
  420. ELSE
  421. CALL DORBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  422. $ 0, 0, 0, WORK(1), -1, CHILDINFO )
  423. LORBDB = M + INT( WORK(1) )
  424. IF( P .GE. M-P ) THEN
  425. CALL DORGQR( P, P, M-Q, U1, LDU1, 0, WORK(1), -1,
  426. $ CHILDINFO )
  427. LORGQRMIN = MAX( 1, P )
  428. LORGQROPT = INT( WORK(1) )
  429. ELSE
  430. CALL DORGQR( M-P, M-P, M-Q, U2, LDU2, 0, WORK(1), -1,
  431. $ CHILDINFO )
  432. LORGQRMIN = MAX( 1, M-P )
  433. LORGQROPT = INT( WORK(1) )
  434. END IF
  435. CALL DORGLQ( Q, Q, Q, V1T, LDV1T, 0, WORK(1), -1,
  436. $ CHILDINFO )
  437. LORGLQMIN = MAX( 1, Q )
  438. LORGLQOPT = INT( WORK(1) )
  439. CALL DBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  440. $ THETA, 0, U2, LDU2, U1, LDU1, 0, 1, V1T, LDV1T,
  441. $ 0, 0, 0, 0, 0, 0, 0, 0, WORK(1), -1,
  442. $ CHILDINFO )
  443. LBBCSD = INT( WORK(1) )
  444. END IF
  445. LWORKMIN = MAX( IORBDB+LORBDB-1,
  446. $ IORGQR+LORGQRMIN-1,
  447. $ IORGLQ+LORGLQMIN-1,
  448. $ IBBCSD+LBBCSD-1 )
  449. LWORKOPT = MAX( IORBDB+LORBDB-1,
  450. $ IORGQR+LORGQROPT-1,
  451. $ IORGLQ+LORGLQOPT-1,
  452. $ IBBCSD+LBBCSD-1 )
  453. WORK(1) = LWORKOPT
  454. IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
  455. INFO = -19
  456. END IF
  457. END IF
  458. IF( INFO .NE. 0 ) THEN
  459. CALL XERBLA( 'DORCSD2BY1', -INFO )
  460. RETURN
  461. ELSE IF( LQUERY ) THEN
  462. RETURN
  463. END IF
  464. LORGQR = LWORK-IORGQR+1
  465. LORGLQ = LWORK-IORGLQ+1
  466. *
  467. * Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
  468. * in which R = MIN(P,M-P,Q,M-Q)
  469. *
  470. IF( R .EQ. Q ) THEN
  471. *
  472. * Case 1: R = Q
  473. *
  474. * Simultaneously bidiagonalize X11 and X21
  475. *
  476. CALL DORBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  477. $ WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  478. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  479. *
  480. * Accumulate Householder reflectors
  481. *
  482. IF( WANTU1 .AND. P .GT. 0 ) THEN
  483. CALL DLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  484. CALL DORGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  485. $ LORGQR, CHILDINFO )
  486. END IF
  487. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  488. CALL DLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  489. CALL DORGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  490. $ WORK(IORGQR), LORGQR, CHILDINFO )
  491. END IF
  492. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  493. V1T(1,1) = ONE
  494. DO J = 2, Q
  495. V1T(1,J) = ZERO
  496. V1T(J,1) = ZERO
  497. END DO
  498. CALL DLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
  499. $ LDV1T )
  500. CALL DORGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  501. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  502. END IF
  503. *
  504. * Simultaneously diagonalize X11 and X21.
  505. *
  506. CALL DBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  507. $ WORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1,
  508. $ WORK(IB11D), WORK(IB11E), WORK(IB12D),
  509. $ WORK(IB12E), WORK(IB21D), WORK(IB21E),
  510. $ WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  511. $ CHILDINFO )
  512. *
  513. * Permute rows and columns to place zero submatrices in
  514. * preferred positions
  515. *
  516. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  517. DO I = 1, Q
  518. IWORK(I) = M - P - Q + I
  519. END DO
  520. DO I = Q + 1, M - P
  521. IWORK(I) = I - Q
  522. END DO
  523. CALL DLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  524. END IF
  525. ELSE IF( R .EQ. P ) THEN
  526. *
  527. * Case 2: R = P
  528. *
  529. * Simultaneously bidiagonalize X11 and X21
  530. *
  531. CALL DORBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  532. $ WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  533. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  534. *
  535. * Accumulate Householder reflectors
  536. *
  537. IF( WANTU1 .AND. P .GT. 0 ) THEN
  538. U1(1,1) = ONE
  539. DO J = 2, P
  540. U1(1,J) = ZERO
  541. U1(J,1) = ZERO
  542. END DO
  543. CALL DLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
  544. CALL DORGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
  545. $ WORK(IORGQR), LORGQR, CHILDINFO )
  546. END IF
  547. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  548. CALL DLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  549. CALL DORGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  550. $ WORK(IORGQR), LORGQR, CHILDINFO )
  551. END IF
  552. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  553. CALL DLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
  554. CALL DORGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  555. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  556. END IF
  557. *
  558. * Simultaneously diagonalize X11 and X21.
  559. *
  560. CALL DBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  561. $ WORK(IPHI), V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2,
  562. $ WORK(IB11D), WORK(IB11E), WORK(IB12D),
  563. $ WORK(IB12E), WORK(IB21D), WORK(IB21E),
  564. $ WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  565. $ CHILDINFO )
  566. *
  567. * Permute rows and columns to place identity submatrices in
  568. * preferred positions
  569. *
  570. IF( Q .GT. 0 .AND. WANTU2 ) THEN
  571. DO I = 1, Q
  572. IWORK(I) = M - P - Q + I
  573. END DO
  574. DO I = Q + 1, M - P
  575. IWORK(I) = I - Q
  576. END DO
  577. CALL DLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  578. END IF
  579. ELSE IF( R .EQ. M-P ) THEN
  580. *
  581. * Case 3: R = M-P
  582. *
  583. * Simultaneously bidiagonalize X11 and X21
  584. *
  585. CALL DORBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  586. $ WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  587. $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  588. *
  589. * Accumulate Householder reflectors
  590. *
  591. IF( WANTU1 .AND. P .GT. 0 ) THEN
  592. CALL DLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  593. CALL DORGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  594. $ LORGQR, CHILDINFO )
  595. END IF
  596. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  597. U2(1,1) = ONE
  598. DO J = 2, M-P
  599. U2(1,J) = ZERO
  600. U2(J,1) = ZERO
  601. END DO
  602. CALL DLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
  603. $ LDU2 )
  604. CALL DORGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
  605. $ WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
  606. END IF
  607. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  608. CALL DLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
  609. CALL DORGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  610. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  611. END IF
  612. *
  613. * Simultaneously diagonalize X11 and X21.
  614. *
  615. CALL DBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  616. $ THETA, WORK(IPHI), 0, 1, V1T, LDV1T, U2, LDU2, U1,
  617. $ LDU1, WORK(IB11D), WORK(IB11E), WORK(IB12D),
  618. $ WORK(IB12E), WORK(IB21D), WORK(IB21E),
  619. $ WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  620. $ CHILDINFO )
  621. *
  622. * Permute rows and columns to place identity submatrices in
  623. * preferred positions
  624. *
  625. IF( Q .GT. R ) THEN
  626. DO I = 1, R
  627. IWORK(I) = Q - R + I
  628. END DO
  629. DO I = R + 1, Q
  630. IWORK(I) = I - R
  631. END DO
  632. IF( WANTU1 ) THEN
  633. CALL DLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
  634. END IF
  635. IF( WANTV1T ) THEN
  636. CALL DLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
  637. END IF
  638. END IF
  639. ELSE
  640. *
  641. * Case 4: R = M-Q
  642. *
  643. * Simultaneously bidiagonalize X11 and X21
  644. *
  645. CALL DORBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  646. $ WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  647. $ WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
  648. $ LORBDB-M, CHILDINFO )
  649. *
  650. * Accumulate Householder reflectors
  651. *
  652. IF( WANTU1 .AND. P .GT. 0 ) THEN
  653. CALL DCOPY( P, WORK(IORBDB), 1, U1, 1 )
  654. DO J = 2, P
  655. U1(1,J) = ZERO
  656. END DO
  657. CALL DLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
  658. $ LDU1 )
  659. CALL DORGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
  660. $ WORK(IORGQR), LORGQR, CHILDINFO )
  661. END IF
  662. IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  663. CALL DCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
  664. DO J = 2, M-P
  665. U2(1,J) = ZERO
  666. END DO
  667. CALL DLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
  668. $ LDU2 )
  669. CALL DORGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
  670. $ WORK(IORGQR), LORGQR, CHILDINFO )
  671. END IF
  672. IF( WANTV1T .AND. Q .GT. 0 ) THEN
  673. CALL DLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
  674. CALL DLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
  675. $ V1T(M-Q+1,M-Q+1), LDV1T )
  676. CALL DLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
  677. $ V1T(P+1,P+1), LDV1T )
  678. CALL DORGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
  679. $ WORK(IORGLQ), LORGLQ, CHILDINFO )
  680. END IF
  681. *
  682. * Simultaneously diagonalize X11 and X21.
  683. *
  684. CALL DBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  685. $ THETA, WORK(IPHI), U2, LDU2, U1, LDU1, 0, 1, V1T,
  686. $ LDV1T, WORK(IB11D), WORK(IB11E), WORK(IB12D),
  687. $ WORK(IB12E), WORK(IB21D), WORK(IB21E),
  688. $ WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  689. $ CHILDINFO )
  690. *
  691. * Permute rows and columns to place identity submatrices in
  692. * preferred positions
  693. *
  694. IF( P .GT. R ) THEN
  695. DO I = 1, R
  696. IWORK(I) = P - R + I
  697. END DO
  698. DO I = R + 1, P
  699. IWORK(I) = I - R
  700. END DO
  701. IF( WANTU1 ) THEN
  702. CALL DLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
  703. END IF
  704. IF( WANTV1T ) THEN
  705. CALL DLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )
  706. END IF
  707. END IF
  708. END IF
  709. *
  710. RETURN
  711. *
  712. * End of DORCSD2BY1
  713. *
  714. END