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.

dgesvdq.f 58 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  1. *> \brief <b> DGESVDQ computes the singular value decomposition (SVD) with a QR-Preconditioned QR SVD Method for GE matrices</b>
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download DGESVDQ + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgesvdq.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgesvdq.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvdq.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE DGESVDQ( JOBA, JOBP, JOBR, JOBU, JOBV, M, N, A, LDA,
  22. * S, U, LDU, V, LDV, NUMRANK, IWORK, LIWORK,
  23. * WORK, LWORK, RWORK, LRWORK, INFO )
  24. *
  25. * .. Scalar Arguments ..
  26. * IMPLICIT NONE
  27. * CHARACTER JOBA, JOBP, JOBR, JOBU, JOBV
  28. * INTEGER M, N, LDA, LDU, LDV, NUMRANK, LIWORK, LWORK, LRWORK,
  29. * INFO
  30. * ..
  31. * .. Array Arguments ..
  32. * DOUBLE PRECISION A( LDA, * ), U( LDU, * ), V( LDV, * ), WORK( * )
  33. * DOUBLE PRECISION S( * ), RWORK( * )
  34. * INTEGER IWORK( * )
  35. * ..
  36. *
  37. *
  38. *> \par Purpose:
  39. * =============
  40. *>
  41. *> \verbatim
  42. *>
  43. *> DGESVDQ computes the singular value decomposition (SVD) of a real
  44. *> M-by-N matrix A, where M >= N. The SVD of A is written as
  45. *> [++] [xx] [x0] [xx]
  46. *> A = U * SIGMA * V^*, [++] = [xx] * [ox] * [xx]
  47. *> [++] [xx]
  48. *> where SIGMA is an N-by-N diagonal matrix, U is an M-by-N orthonormal
  49. *> matrix, and V is an N-by-N orthogonal matrix. The diagonal elements
  50. *> of SIGMA are the singular values of A. The columns of U and V are the
  51. *> left and the right singular vectors of A, respectively.
  52. *> \endverbatim
  53. *
  54. * Arguments:
  55. * ==========
  56. *
  57. *> \param[in] JOBA
  58. *> \verbatim
  59. *> JOBA is CHARACTER*1
  60. *> Specifies the level of accuracy in the computed SVD
  61. *> = 'A' The requested accuracy corresponds to having the backward
  62. *> error bounded by || delta A ||_F <= f(m,n) * EPS * || A ||_F,
  63. *> where EPS = DLAMCH('Epsilon'). This authorises DGESVDQ to
  64. *> truncate the computed triangular factor in a rank revealing
  65. *> QR factorization whenever the truncated part is below the
  66. *> threshold of the order of EPS * ||A||_F. This is aggressive
  67. *> truncation level.
  68. *> = 'M' Similarly as with 'A', but the truncation is more gentle: it
  69. *> is allowed only when there is a drop on the diagonal of the
  70. *> triangular factor in the QR factorization. This is medium
  71. *> truncation level.
  72. *> = 'H' High accuracy requested. No numerical rank determination based
  73. *> on the rank revealing QR factorization is attempted.
  74. *> = 'E' Same as 'H', and in addition the condition number of column
  75. *> scaled A is estimated and returned in RWORK(1).
  76. *> N^(-1/4)*RWORK(1) <= ||pinv(A_scaled)||_2 <= N^(1/4)*RWORK(1)
  77. *> \endverbatim
  78. *>
  79. *> \param[in] JOBP
  80. *> \verbatim
  81. *> JOBP is CHARACTER*1
  82. *> = 'P' The rows of A are ordered in decreasing order with respect to
  83. *> ||A(i,:)||_\infty. This enhances numerical accuracy at the cost
  84. *> of extra data movement. Recommended for numerical robustness.
  85. *> = 'N' No row pivoting.
  86. *> \endverbatim
  87. *>
  88. *> \param[in] JOBR
  89. *> \verbatim
  90. *> JOBR is CHARACTER*1
  91. *> = 'T' After the initial pivoted QR factorization, DGESVD is applied to
  92. *> the transposed R**T of the computed triangular factor R. This involves
  93. *> some extra data movement (matrix transpositions). Useful for
  94. *> experiments, research and development.
  95. *> = 'N' The triangular factor R is given as input to DGESVD. This may be
  96. *> preferred as it involves less data movement.
  97. *> \endverbatim
  98. *>
  99. *> \param[in] JOBU
  100. *> \verbatim
  101. *> JOBU is CHARACTER*1
  102. *> = 'A' All M left singular vectors are computed and returned in the
  103. *> matrix U. See the description of U.
  104. *> = 'S' or 'U' N = min(M,N) left singular vectors are computed and returned
  105. *> in the matrix U. See the description of U.
  106. *> = 'R' Numerical rank NUMRANK is determined and only NUMRANK left singular
  107. *> vectors are computed and returned in the matrix U.
  108. *> = 'F' The N left singular vectors are returned in factored form as the
  109. *> product of the Q factor from the initial QR factorization and the
  110. *> N left singular vectors of (R**T , 0)**T. If row pivoting is used,
  111. *> then the necessary information on the row pivoting is stored in
  112. *> IWORK(N+1:N+M-1).
  113. *> = 'N' The left singular vectors are not computed.
  114. *> \endverbatim
  115. *>
  116. *> \param[in] JOBV
  117. *> \verbatim
  118. *> JOBV is CHARACTER*1
  119. *> = 'A', 'V' All N right singular vectors are computed and returned in
  120. *> the matrix V.
  121. *> = 'R' Numerical rank NUMRANK is determined and only NUMRANK right singular
  122. *> vectors are computed and returned in the matrix V. This option is
  123. *> allowed only if JOBU = 'R' or JOBU = 'N'; otherwise it is illegal.
  124. *> = 'N' The right singular vectors are not computed.
  125. *> \endverbatim
  126. *>
  127. *> \param[in] M
  128. *> \verbatim
  129. *> M is INTEGER
  130. *> The number of rows of the input matrix A. M >= 0.
  131. *> \endverbatim
  132. *>
  133. *> \param[in] N
  134. *> \verbatim
  135. *> N is INTEGER
  136. *> The number of columns of the input matrix A. M >= N >= 0.
  137. *> \endverbatim
  138. *>
  139. *> \param[in,out] A
  140. *> \verbatim
  141. *> A is DOUBLE PRECISION array of dimensions LDA x N
  142. *> On entry, the input matrix A.
  143. *> On exit, if JOBU .NE. 'N' or JOBV .NE. 'N', the lower triangle of A contains
  144. *> the Householder vectors as stored by DGEQP3. If JOBU = 'F', these Householder
  145. *> vectors together with WORK(1:N) can be used to restore the Q factors from
  146. *> the initial pivoted QR factorization of A. See the description of U.
  147. *> \endverbatim
  148. *>
  149. *> \param[in] LDA
  150. *> \verbatim
  151. *> LDA is INTEGER.
  152. *> The leading dimension of the array A. LDA >= max(1,M).
  153. *> \endverbatim
  154. *>
  155. *> \param[out] S
  156. *> \verbatim
  157. *> S is DOUBLE PRECISION array of dimension N.
  158. *> The singular values of A, ordered so that S(i) >= S(i+1).
  159. *> \endverbatim
  160. *>
  161. *> \param[out] U
  162. *> \verbatim
  163. *> U is DOUBLE PRECISION array, dimension
  164. *> LDU x M if JOBU = 'A'; see the description of LDU. In this case,
  165. *> on exit, U contains the M left singular vectors.
  166. *> LDU x N if JOBU = 'S', 'U', 'R' ; see the description of LDU. In this
  167. *> case, U contains the leading N or the leading NUMRANK left singular vectors.
  168. *> LDU x N if JOBU = 'F' ; see the description of LDU. In this case U
  169. *> contains N x N orthogonal matrix that can be used to form the left
  170. *> singular vectors.
  171. *> If JOBU = 'N', U is not referenced.
  172. *> \endverbatim
  173. *>
  174. *> \param[in] LDU
  175. *> \verbatim
  176. *> LDU is INTEGER.
  177. *> The leading dimension of the array U.
  178. *> If JOBU = 'A', 'S', 'U', 'R', LDU >= max(1,M).
  179. *> If JOBU = 'F', LDU >= max(1,N).
  180. *> Otherwise, LDU >= 1.
  181. *> \endverbatim
  182. *>
  183. *> \param[out] V
  184. *> \verbatim
  185. *> V is DOUBLE PRECISION array, dimension
  186. *> LDV x N if JOBV = 'A', 'V', 'R' or if JOBA = 'E' .
  187. *> If JOBV = 'A', or 'V', V contains the N-by-N orthogonal matrix V**T;
  188. *> If JOBV = 'R', V contains the first NUMRANK rows of V**T (the right
  189. *> singular vectors, stored rowwise, of the NUMRANK largest singular values).
  190. *> If JOBV = 'N' and JOBA = 'E', V is used as a workspace.
  191. *> If JOBV = 'N', and JOBA.NE.'E', V is not referenced.
  192. *> \endverbatim
  193. *>
  194. *> \param[in] LDV
  195. *> \verbatim
  196. *> LDV is INTEGER
  197. *> The leading dimension of the array V.
  198. *> If JOBV = 'A', 'V', 'R', or JOBA = 'E', LDV >= max(1,N).
  199. *> Otherwise, LDV >= 1.
  200. *> \endverbatim
  201. *>
  202. *> \param[out] NUMRANK
  203. *> \verbatim
  204. *> NUMRANK is INTEGER
  205. *> NUMRANK is the numerical rank first determined after the rank
  206. *> revealing QR factorization, following the strategy specified by the
  207. *> value of JOBA. If JOBV = 'R' and JOBU = 'R', only NUMRANK
  208. *> leading singular values and vectors are then requested in the call
  209. *> of DGESVD. The final value of NUMRANK might be further reduced if
  210. *> some singular values are computed as zeros.
  211. *> \endverbatim
  212. *>
  213. *> \param[out] IWORK
  214. *> \verbatim
  215. *> IWORK is INTEGER array, dimension (max(1, LIWORK)).
  216. *> On exit, IWORK(1:N) contains column pivoting permutation of the
  217. *> rank revealing QR factorization.
  218. *> If JOBP = 'P', IWORK(N+1:N+M-1) contains the indices of the sequence
  219. *> of row swaps used in row pivoting. These can be used to restore the
  220. *> left singular vectors in the case JOBU = 'F'.
  221. *>
  222. *> If LIWORK, LWORK, or LRWORK = -1, then on exit, if INFO = 0,
  223. *> IWORK(1) returns the minimal LIWORK.
  224. *> \endverbatim
  225. *>
  226. *> \param[in] LIWORK
  227. *> \verbatim
  228. *> LIWORK is INTEGER
  229. *> The dimension of the array IWORK.
  230. *> LIWORK >= N + M - 1, if JOBP = 'P' and JOBA .NE. 'E';
  231. *> LIWORK >= N if JOBP = 'N' and JOBA .NE. 'E';
  232. *> LIWORK >= N + M - 1 + N, if JOBP = 'P' and JOBA = 'E';
  233. *> LIWORK >= N + N if JOBP = 'N' and JOBA = 'E'.
  234. *>
  235. *> If LIWORK = -1, then a workspace query is assumed; the routine
  236. *> only calculates and returns the optimal and minimal sizes
  237. *> for the WORK, IWORK, and RWORK arrays, and no error
  238. *> message related to LWORK is issued by XERBLA.
  239. *> \endverbatim
  240. *>
  241. *> \param[out] WORK
  242. *> \verbatim
  243. *> WORK is DOUBLE PRECISION array, dimension (max(2, LWORK)), used as a workspace.
  244. *> On exit, if, on entry, LWORK.NE.-1, WORK(1:N) contains parameters
  245. *> needed to recover the Q factor from the QR factorization computed by
  246. *> DGEQP3.
  247. *>
  248. *> If LIWORK, LWORK, or LRWORK = -1, then on exit, if INFO = 0,
  249. *> WORK(1) returns the optimal LWORK, and
  250. *> WORK(2) returns the minimal LWORK.
  251. *> \endverbatim
  252. *>
  253. *> \param[in,out] LWORK
  254. *> \verbatim
  255. *> LWORK is INTEGER
  256. *> The dimension of the array WORK. It is determined as follows:
  257. *> Let LWQP3 = 3*N+1, LWCON = 3*N, and let
  258. *> LWORQ = { MAX( N, 1 ), if JOBU = 'R', 'S', or 'U'
  259. *> { MAX( M, 1 ), if JOBU = 'A'
  260. *> LWSVD = MAX( 5*N, 1 )
  261. *> LWLQF = MAX( N/2, 1 ), LWSVD2 = MAX( 5*(N/2), 1 ), LWORLQ = MAX( N, 1 ),
  262. *> LWQRF = MAX( N/2, 1 ), LWORQ2 = MAX( N, 1 )
  263. *> Then the minimal value of LWORK is:
  264. *> = MAX( N + LWQP3, LWSVD ) if only the singular values are needed;
  265. *> = MAX( N + LWQP3, LWCON, LWSVD ) if only the singular values are needed,
  266. *> and a scaled condition estimate requested;
  267. *>
  268. *> = N + MAX( LWQP3, LWSVD, LWORQ ) if the singular values and the left
  269. *> singular vectors are requested;
  270. *> = N + MAX( LWQP3, LWCON, LWSVD, LWORQ ) if the singular values and the left
  271. *> singular vectors are requested, and also
  272. *> a scaled condition estimate requested;
  273. *>
  274. *> = N + MAX( LWQP3, LWSVD ) if the singular values and the right
  275. *> singular vectors are requested;
  276. *> = N + MAX( LWQP3, LWCON, LWSVD ) if the singular values and the right
  277. *> singular vectors are requested, and also
  278. *> a scaled condition etimate requested;
  279. *>
  280. *> = N + MAX( LWQP3, LWSVD, LWORQ ) if the full SVD is requested with JOBV = 'R';
  281. *> independent of JOBR;
  282. *> = N + MAX( LWQP3, LWCON, LWSVD, LWORQ ) if the full SVD is requested,
  283. *> JOBV = 'R' and, also a scaled condition
  284. *> estimate requested; independent of JOBR;
  285. *> = MAX( N + MAX( LWQP3, LWSVD, LWORQ ),
  286. *> N + MAX( LWQP3, N/2+LWLQF, N/2+LWSVD2, N/2+LWORLQ, LWORQ) ) if the
  287. *> full SVD is requested with JOBV = 'A' or 'V', and
  288. *> JOBR ='N'
  289. *> = MAX( N + MAX( LWQP3, LWCON, LWSVD, LWORQ ),
  290. *> N + MAX( LWQP3, LWCON, N/2+LWLQF, N/2+LWSVD2, N/2+LWORLQ, LWORQ ) )
  291. *> if the full SVD is requested with JOBV = 'A' or 'V', and
  292. *> JOBR ='N', and also a scaled condition number estimate
  293. *> requested.
  294. *> = MAX( N + MAX( LWQP3, LWSVD, LWORQ ),
  295. *> N + MAX( LWQP3, N/2+LWQRF, N/2+LWSVD2, N/2+LWORQ2, LWORQ ) ) if the
  296. *> full SVD is requested with JOBV = 'A', 'V', and JOBR ='T'
  297. *> = MAX( N + MAX( LWQP3, LWCON, LWSVD, LWORQ ),
  298. *> N + MAX( LWQP3, LWCON, N/2+LWQRF, N/2+LWSVD2, N/2+LWORQ2, LWORQ ) )
  299. *> if the full SVD is requested with JOBV = 'A' or 'V', and
  300. *> JOBR ='T', and also a scaled condition number estimate
  301. *> requested.
  302. *> Finally, LWORK must be at least two: LWORK = MAX( 2, LWORK ).
  303. *>
  304. *> If LWORK = -1, then a workspace query is assumed; the routine
  305. *> only calculates and returns the optimal and minimal sizes
  306. *> for the WORK, IWORK, and RWORK arrays, and no error
  307. *> message related to LWORK is issued by XERBLA.
  308. *> \endverbatim
  309. *>
  310. *> \param[out] RWORK
  311. *> \verbatim
  312. *> RWORK is DOUBLE PRECISION array, dimension (max(1, LRWORK)).
  313. *> On exit,
  314. *> 1. If JOBA = 'E', RWORK(1) contains an estimate of the condition
  315. *> number of column scaled A. If A = C * D where D is diagonal and C
  316. *> has unit columns in the Euclidean norm, then, assuming full column rank,
  317. *> N^(-1/4) * RWORK(1) <= ||pinv(C)||_2 <= N^(1/4) * RWORK(1).
  318. *> Otherwise, RWORK(1) = -1.
  319. *> 2. RWORK(2) contains the number of singular values computed as
  320. *> exact zeros in DGESVD applied to the upper triangular or trapezoidal
  321. *> R (from the initial QR factorization). In case of early exit (no call to
  322. *> DGESVD, such as in the case of zero matrix) RWORK(2) = -1.
  323. *>
  324. *> If LIWORK, LWORK, or LRWORK = -1, then on exit, if INFO = 0,
  325. *> RWORK(1) returns the minimal LRWORK.
  326. *> \endverbatim
  327. *>
  328. *> \param[in] LRWORK
  329. *> \verbatim
  330. *> LRWORK is INTEGER.
  331. *> The dimension of the array RWORK.
  332. *> If JOBP ='P', then LRWORK >= MAX(2, M).
  333. *> Otherwise, LRWORK >= 2
  334. *>
  335. *> If LRWORK = -1, then a workspace query is assumed; the routine
  336. *> only calculates and returns the optimal and minimal sizes
  337. *> for the WORK, IWORK, and RWORK arrays, and no error
  338. *> message related to LWORK is issued by XERBLA.
  339. *> \endverbatim
  340. *>
  341. *> \param[out] INFO
  342. *> \verbatim
  343. *> INFO is INTEGER
  344. *> = 0: successful exit.
  345. *> < 0: if INFO = -i, the i-th argument had an illegal value.
  346. *> > 0: if DBDSQR did not converge, INFO specifies how many superdiagonals
  347. *> of an intermediate bidiagonal form B (computed in DGESVD) did not
  348. *> converge to zero.
  349. *> \endverbatim
  350. *
  351. *> \par Further Details:
  352. * ========================
  353. *>
  354. *> \verbatim
  355. *>
  356. *> 1. The data movement (matrix transpose) is coded using simple nested
  357. *> DO-loops because BLAS and LAPACK do not provide corresponding subroutines.
  358. *> Those DO-loops are easily identified in this source code - by the CONTINUE
  359. *> statements labeled with 11**. In an optimized version of this code, the
  360. *> nested DO loops should be replaced with calls to an optimized subroutine.
  361. *> 2. This code scales A by 1/SQRT(M) if the largest ABS(A(i,j)) could cause
  362. *> column norm overflow. This is the minial precaution and it is left to the
  363. *> SVD routine (CGESVD) to do its own preemptive scaling if potential over-
  364. *> or underflows are detected. To avoid repeated scanning of the array A,
  365. *> an optimal implementation would do all necessary scaling before calling
  366. *> CGESVD and the scaling in CGESVD can be switched off.
  367. *> 3. Other comments related to code optimization are given in comments in the
  368. *> code, enlosed in [[double brackets]].
  369. *> \endverbatim
  370. *
  371. *> \par Bugs, examples and comments
  372. * ===========================
  373. *
  374. *> \verbatim
  375. *> Please report all bugs and send interesting examples and/or comments to
  376. *> drmac@math.hr. Thank you.
  377. *> \endverbatim
  378. *
  379. *> \par References
  380. * ===============
  381. *
  382. *> \verbatim
  383. *> [1] Zlatko Drmac, Algorithm 977: A QR-Preconditioned QR SVD Method for
  384. *> Computing the SVD with High Accuracy. ACM Trans. Math. Softw.
  385. *> 44(1): 11:1-11:30 (2017)
  386. *>
  387. *> SIGMA library, xGESVDQ section updated February 2016.
  388. *> Developed and coded by Zlatko Drmac, Department of Mathematics
  389. *> University of Zagreb, Croatia, drmac@math.hr
  390. *> \endverbatim
  391. *
  392. *
  393. *> \par Contributors:
  394. * ==================
  395. *>
  396. *> \verbatim
  397. *> Developed and coded by Zlatko Drmac, Department of Mathematics
  398. *> University of Zagreb, Croatia, drmac@math.hr
  399. *> \endverbatim
  400. *
  401. * Authors:
  402. * ========
  403. *
  404. *> \author Univ. of Tennessee
  405. *> \author Univ. of California Berkeley
  406. *> \author Univ. of Colorado Denver
  407. *> \author NAG Ltd.
  408. *
  409. *> \ingroup doubleGEsing
  410. *
  411. * =====================================================================
  412. SUBROUTINE DGESVDQ( JOBA, JOBP, JOBR, JOBU, JOBV, M, N, A, LDA,
  413. $ S, U, LDU, V, LDV, NUMRANK, IWORK, LIWORK,
  414. $ WORK, LWORK, RWORK, LRWORK, INFO )
  415. * .. Scalar Arguments ..
  416. IMPLICIT NONE
  417. CHARACTER JOBA, JOBP, JOBR, JOBU, JOBV
  418. INTEGER M, N, LDA, LDU, LDV, NUMRANK, LIWORK, LWORK, LRWORK,
  419. $ INFO
  420. * ..
  421. * .. Array Arguments ..
  422. DOUBLE PRECISION A( LDA, * ), U( LDU, * ), V( LDV, * ), WORK( * )
  423. DOUBLE PRECISION S( * ), RWORK( * )
  424. INTEGER IWORK( * )
  425. *
  426. * =====================================================================
  427. *
  428. * .. Parameters ..
  429. DOUBLE PRECISION ZERO, ONE
  430. PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
  431. * .. Local Scalars ..
  432. INTEGER IERR, IWOFF, NR, N1, OPTRATIO, p, q
  433. INTEGER LWCON, LWQP3, LWRK_DGELQF, LWRK_DGESVD, LWRK_DGESVD2,
  434. $ LWRK_DGEQP3, LWRK_DGEQRF, LWRK_DORMLQ, LWRK_DORMQR,
  435. $ LWRK_DORMQR2, LWLQF, LWQRF, LWSVD, LWSVD2, LWORQ,
  436. $ LWORQ2, LWORLQ, MINWRK, MINWRK2, OPTWRK, OPTWRK2,
  437. $ IMINWRK, RMINWRK
  438. LOGICAL ACCLA, ACCLM, ACCLH, ASCALED, CONDA, DNTWU, DNTWV,
  439. $ LQUERY, LSVC0, LSVEC, ROWPRM, RSVEC, RTRANS, WNTUA,
  440. $ WNTUF, WNTUR, WNTUS, WNTVA, WNTVR
  441. DOUBLE PRECISION BIG, EPSLN, RTMP, SCONDA, SFMIN
  442. * .. Local Arrays
  443. DOUBLE PRECISION RDUMMY(1)
  444. * ..
  445. * .. External Subroutines (BLAS, LAPACK)
  446. EXTERNAL DGELQF, DGEQP3, DGEQRF, DGESVD, DLACPY, DLAPMT,
  447. $ DLASCL, DLASET, DLASWP, DSCAL, DPOCON, DORMLQ,
  448. $ DORMQR, XERBLA
  449. * ..
  450. * .. External Functions (BLAS, LAPACK)
  451. LOGICAL LSAME
  452. INTEGER IDAMAX
  453. DOUBLE PRECISION DLANGE, DNRM2, DLAMCH
  454. EXTERNAL DLANGE, LSAME, IDAMAX, DNRM2, DLAMCH
  455. * ..
  456. * .. Intrinsic Functions ..
  457. *
  458. INTRINSIC ABS, MAX, MIN, DBLE, SQRT
  459. *
  460. * Test the input arguments
  461. *
  462. WNTUS = LSAME( JOBU, 'S' ) .OR. LSAME( JOBU, 'U' )
  463. WNTUR = LSAME( JOBU, 'R' )
  464. WNTUA = LSAME( JOBU, 'A' )
  465. WNTUF = LSAME( JOBU, 'F' )
  466. LSVC0 = WNTUS .OR. WNTUR .OR. WNTUA
  467. LSVEC = LSVC0 .OR. WNTUF
  468. DNTWU = LSAME( JOBU, 'N' )
  469. *
  470. WNTVR = LSAME( JOBV, 'R' )
  471. WNTVA = LSAME( JOBV, 'A' ) .OR. LSAME( JOBV, 'V' )
  472. RSVEC = WNTVR .OR. WNTVA
  473. DNTWV = LSAME( JOBV, 'N' )
  474. *
  475. ACCLA = LSAME( JOBA, 'A' )
  476. ACCLM = LSAME( JOBA, 'M' )
  477. CONDA = LSAME( JOBA, 'E' )
  478. ACCLH = LSAME( JOBA, 'H' ) .OR. CONDA
  479. *
  480. ROWPRM = LSAME( JOBP, 'P' )
  481. RTRANS = LSAME( JOBR, 'T' )
  482. *
  483. IF ( ROWPRM ) THEN
  484. IF ( CONDA ) THEN
  485. IMINWRK = MAX( 1, N + M - 1 + N )
  486. ELSE
  487. IMINWRK = MAX( 1, N + M - 1 )
  488. END IF
  489. RMINWRK = MAX( 2, M )
  490. ELSE
  491. IF ( CONDA ) THEN
  492. IMINWRK = MAX( 1, N + N )
  493. ELSE
  494. IMINWRK = MAX( 1, N )
  495. END IF
  496. RMINWRK = 2
  497. END IF
  498. LQUERY = (LIWORK .EQ. -1 .OR. LWORK .EQ. -1 .OR. LRWORK .EQ. -1)
  499. INFO = 0
  500. IF ( .NOT. ( ACCLA .OR. ACCLM .OR. ACCLH ) ) THEN
  501. INFO = -1
  502. ELSE IF ( .NOT.( ROWPRM .OR. LSAME( JOBP, 'N' ) ) ) THEN
  503. INFO = -2
  504. ELSE IF ( .NOT.( RTRANS .OR. LSAME( JOBR, 'N' ) ) ) THEN
  505. INFO = -3
  506. ELSE IF ( .NOT.( LSVEC .OR. DNTWU ) ) THEN
  507. INFO = -4
  508. ELSE IF ( WNTUR .AND. WNTVA ) THEN
  509. INFO = -5
  510. ELSE IF ( .NOT.( RSVEC .OR. DNTWV )) THEN
  511. INFO = -5
  512. ELSE IF ( M.LT.0 ) THEN
  513. INFO = -6
  514. ELSE IF ( ( N.LT.0 ) .OR. ( N.GT.M ) ) THEN
  515. INFO = -7
  516. ELSE IF ( LDA.LT.MAX( 1, M ) ) THEN
  517. INFO = -9
  518. ELSE IF ( LDU.LT.1 .OR. ( LSVC0 .AND. LDU.LT.M ) .OR.
  519. $ ( WNTUF .AND. LDU.LT.N ) ) THEN
  520. INFO = -12
  521. ELSE IF ( LDV.LT.1 .OR. ( RSVEC .AND. LDV.LT.N ) .OR.
  522. $ ( CONDA .AND. LDV.LT.N ) ) THEN
  523. INFO = -14
  524. ELSE IF ( LIWORK .LT. IMINWRK .AND. .NOT. LQUERY ) THEN
  525. INFO = -17
  526. END IF
  527. *
  528. *
  529. IF ( INFO .EQ. 0 ) THEN
  530. * .. compute the minimal and the optimal workspace lengths
  531. * [[The expressions for computing the minimal and the optimal
  532. * values of LWORK are written with a lot of redundancy and
  533. * can be simplified. However, this detailed form is easier for
  534. * maintenance and modifications of the code.]]
  535. *
  536. * .. minimal workspace length for DGEQP3 of an M x N matrix
  537. LWQP3 = 3 * N + 1
  538. * .. minimal workspace length for DORMQR to build left singular vectors
  539. IF ( WNTUS .OR. WNTUR ) THEN
  540. LWORQ = MAX( N , 1 )
  541. ELSE IF ( WNTUA ) THEN
  542. LWORQ = MAX( M , 1 )
  543. END IF
  544. * .. minimal workspace length for DPOCON of an N x N matrix
  545. LWCON = 3 * N
  546. * .. DGESVD of an N x N matrix
  547. LWSVD = MAX( 5 * N, 1 )
  548. IF ( LQUERY ) THEN
  549. CALL DGEQP3( M, N, A, LDA, IWORK, RDUMMY, RDUMMY, -1,
  550. $ IERR )
  551. LWRK_DGEQP3 = INT( RDUMMY(1) )
  552. IF ( WNTUS .OR. WNTUR ) THEN
  553. CALL DORMQR( 'L', 'N', M, N, N, A, LDA, RDUMMY, U,
  554. $ LDU, RDUMMY, -1, IERR )
  555. LWRK_DORMQR = INT( RDUMMY(1) )
  556. ELSE IF ( WNTUA ) THEN
  557. CALL DORMQR( 'L', 'N', M, M, N, A, LDA, RDUMMY, U,
  558. $ LDU, RDUMMY, -1, IERR )
  559. LWRK_DORMQR = INT( RDUMMY(1) )
  560. ELSE
  561. LWRK_DORMQR = 0
  562. END IF
  563. END IF
  564. MINWRK = 2
  565. OPTWRK = 2
  566. IF ( .NOT. (LSVEC .OR. RSVEC )) THEN
  567. * .. minimal and optimal sizes of the workspace if
  568. * only the singular values are requested
  569. IF ( CONDA ) THEN
  570. MINWRK = MAX( N+LWQP3, LWCON, LWSVD )
  571. ELSE
  572. MINWRK = MAX( N+LWQP3, LWSVD )
  573. END IF
  574. IF ( LQUERY ) THEN
  575. CALL DGESVD( 'N', 'N', N, N, A, LDA, S, U, LDU,
  576. $ V, LDV, RDUMMY, -1, IERR )
  577. LWRK_DGESVD = INT( RDUMMY(1) )
  578. IF ( CONDA ) THEN
  579. OPTWRK = MAX( N+LWRK_DGEQP3, N+LWCON, LWRK_DGESVD )
  580. ELSE
  581. OPTWRK = MAX( N+LWRK_DGEQP3, LWRK_DGESVD )
  582. END IF
  583. END IF
  584. ELSE IF ( LSVEC .AND. (.NOT.RSVEC) ) THEN
  585. * .. minimal and optimal sizes of the workspace if the
  586. * singular values and the left singular vectors are requested
  587. IF ( CONDA ) THEN
  588. MINWRK = N + MAX( LWQP3, LWCON, LWSVD, LWORQ )
  589. ELSE
  590. MINWRK = N + MAX( LWQP3, LWSVD, LWORQ )
  591. END IF
  592. IF ( LQUERY ) THEN
  593. IF ( RTRANS ) THEN
  594. CALL DGESVD( 'N', 'O', N, N, A, LDA, S, U, LDU,
  595. $ V, LDV, RDUMMY, -1, IERR )
  596. ELSE
  597. CALL DGESVD( 'O', 'N', N, N, A, LDA, S, U, LDU,
  598. $ V, LDV, RDUMMY, -1, IERR )
  599. END IF
  600. LWRK_DGESVD = INT( RDUMMY(1) )
  601. IF ( CONDA ) THEN
  602. OPTWRK = N + MAX( LWRK_DGEQP3, LWCON, LWRK_DGESVD,
  603. $ LWRK_DORMQR )
  604. ELSE
  605. OPTWRK = N + MAX( LWRK_DGEQP3, LWRK_DGESVD,
  606. $ LWRK_DORMQR )
  607. END IF
  608. END IF
  609. ELSE IF ( RSVEC .AND. (.NOT.LSVEC) ) THEN
  610. * .. minimal and optimal sizes of the workspace if the
  611. * singular values and the right singular vectors are requested
  612. IF ( CONDA ) THEN
  613. MINWRK = N + MAX( LWQP3, LWCON, LWSVD )
  614. ELSE
  615. MINWRK = N + MAX( LWQP3, LWSVD )
  616. END IF
  617. IF ( LQUERY ) THEN
  618. IF ( RTRANS ) THEN
  619. CALL DGESVD( 'O', 'N', N, N, A, LDA, S, U, LDU,
  620. $ V, LDV, RDUMMY, -1, IERR )
  621. ELSE
  622. CALL DGESVD( 'N', 'O', N, N, A, LDA, S, U, LDU,
  623. $ V, LDV, RDUMMY, -1, IERR )
  624. END IF
  625. LWRK_DGESVD = INT( RDUMMY(1) )
  626. IF ( CONDA ) THEN
  627. OPTWRK = N + MAX( LWRK_DGEQP3, LWCON, LWRK_DGESVD )
  628. ELSE
  629. OPTWRK = N + MAX( LWRK_DGEQP3, LWRK_DGESVD )
  630. END IF
  631. END IF
  632. ELSE
  633. * .. minimal and optimal sizes of the workspace if the
  634. * full SVD is requested
  635. IF ( RTRANS ) THEN
  636. MINWRK = MAX( LWQP3, LWSVD, LWORQ )
  637. IF ( CONDA ) MINWRK = MAX( MINWRK, LWCON )
  638. MINWRK = MINWRK + N
  639. IF ( WNTVA ) THEN
  640. * .. minimal workspace length for N x N/2 DGEQRF
  641. LWQRF = MAX( N/2, 1 )
  642. * .. minimal workspace length for N/2 x N/2 DGESVD
  643. LWSVD2 = MAX( 5 * (N/2), 1 )
  644. LWORQ2 = MAX( N, 1 )
  645. MINWRK2 = MAX( LWQP3, N/2+LWQRF, N/2+LWSVD2,
  646. $ N/2+LWORQ2, LWORQ )
  647. IF ( CONDA ) MINWRK2 = MAX( MINWRK2, LWCON )
  648. MINWRK2 = N + MINWRK2
  649. MINWRK = MAX( MINWRK, MINWRK2 )
  650. END IF
  651. ELSE
  652. MINWRK = MAX( LWQP3, LWSVD, LWORQ )
  653. IF ( CONDA ) MINWRK = MAX( MINWRK, LWCON )
  654. MINWRK = MINWRK + N
  655. IF ( WNTVA ) THEN
  656. * .. minimal workspace length for N/2 x N DGELQF
  657. LWLQF = MAX( N/2, 1 )
  658. LWSVD2 = MAX( 5 * (N/2), 1 )
  659. LWORLQ = MAX( N , 1 )
  660. MINWRK2 = MAX( LWQP3, N/2+LWLQF, N/2+LWSVD2,
  661. $ N/2+LWORLQ, LWORQ )
  662. IF ( CONDA ) MINWRK2 = MAX( MINWRK2, LWCON )
  663. MINWRK2 = N + MINWRK2
  664. MINWRK = MAX( MINWRK, MINWRK2 )
  665. END IF
  666. END IF
  667. IF ( LQUERY ) THEN
  668. IF ( RTRANS ) THEN
  669. CALL DGESVD( 'O', 'A', N, N, A, LDA, S, U, LDU,
  670. $ V, LDV, RDUMMY, -1, IERR )
  671. LWRK_DGESVD = INT( RDUMMY(1) )
  672. OPTWRK = MAX(LWRK_DGEQP3,LWRK_DGESVD,LWRK_DORMQR)
  673. IF ( CONDA ) OPTWRK = MAX( OPTWRK, LWCON )
  674. OPTWRK = N + OPTWRK
  675. IF ( WNTVA ) THEN
  676. CALL DGEQRF(N,N/2,U,LDU,RDUMMY,RDUMMY,-1,IERR)
  677. LWRK_DGEQRF = INT( RDUMMY(1) )
  678. CALL DGESVD( 'S', 'O', N/2,N/2, V,LDV, S, U,LDU,
  679. $ V, LDV, RDUMMY, -1, IERR )
  680. LWRK_DGESVD2 = INT( RDUMMY(1) )
  681. CALL DORMQR( 'R', 'C', N, N, N/2, U, LDU, RDUMMY,
  682. $ V, LDV, RDUMMY, -1, IERR )
  683. LWRK_DORMQR2 = INT( RDUMMY(1) )
  684. OPTWRK2 = MAX( LWRK_DGEQP3, N/2+LWRK_DGEQRF,
  685. $ N/2+LWRK_DGESVD2, N/2+LWRK_DORMQR2 )
  686. IF ( CONDA ) OPTWRK2 = MAX( OPTWRK2, LWCON )
  687. OPTWRK2 = N + OPTWRK2
  688. OPTWRK = MAX( OPTWRK, OPTWRK2 )
  689. END IF
  690. ELSE
  691. CALL DGESVD( 'S', 'O', N, N, A, LDA, S, U, LDU,
  692. $ V, LDV, RDUMMY, -1, IERR )
  693. LWRK_DGESVD = INT( RDUMMY(1) )
  694. OPTWRK = MAX(LWRK_DGEQP3,LWRK_DGESVD,LWRK_DORMQR)
  695. IF ( CONDA ) OPTWRK = MAX( OPTWRK, LWCON )
  696. OPTWRK = N + OPTWRK
  697. IF ( WNTVA ) THEN
  698. CALL DGELQF(N/2,N,U,LDU,RDUMMY,RDUMMY,-1,IERR)
  699. LWRK_DGELQF = INT( RDUMMY(1) )
  700. CALL DGESVD( 'S','O', N/2,N/2, V, LDV, S, U, LDU,
  701. $ V, LDV, RDUMMY, -1, IERR )
  702. LWRK_DGESVD2 = INT( RDUMMY(1) )
  703. CALL DORMLQ( 'R', 'N', N, N, N/2, U, LDU, RDUMMY,
  704. $ V, LDV, RDUMMY,-1,IERR )
  705. LWRK_DORMLQ = INT( RDUMMY(1) )
  706. OPTWRK2 = MAX( LWRK_DGEQP3, N/2+LWRK_DGELQF,
  707. $ N/2+LWRK_DGESVD2, N/2+LWRK_DORMLQ )
  708. IF ( CONDA ) OPTWRK2 = MAX( OPTWRK2, LWCON )
  709. OPTWRK2 = N + OPTWRK2
  710. OPTWRK = MAX( OPTWRK, OPTWRK2 )
  711. END IF
  712. END IF
  713. END IF
  714. END IF
  715. *
  716. MINWRK = MAX( 2, MINWRK )
  717. OPTWRK = MAX( 2, OPTWRK )
  718. IF ( LWORK .LT. MINWRK .AND. (.NOT.LQUERY) ) INFO = -19
  719. *
  720. END IF
  721. *
  722. IF (INFO .EQ. 0 .AND. LRWORK .LT. RMINWRK .AND. .NOT. LQUERY) THEN
  723. INFO = -21
  724. END IF
  725. IF( INFO.NE.0 ) THEN
  726. CALL XERBLA( 'DGESVDQ', -INFO )
  727. RETURN
  728. ELSE IF ( LQUERY ) THEN
  729. *
  730. * Return optimal workspace
  731. *
  732. IWORK(1) = IMINWRK
  733. WORK(1) = OPTWRK
  734. WORK(2) = MINWRK
  735. RWORK(1) = RMINWRK
  736. RETURN
  737. END IF
  738. *
  739. * Quick return if the matrix is void.
  740. *
  741. IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) ) THEN
  742. * .. all output is void.
  743. RETURN
  744. END IF
  745. *
  746. BIG = DLAMCH('O')
  747. ASCALED = .FALSE.
  748. IWOFF = 1
  749. IF ( ROWPRM ) THEN
  750. IWOFF = M
  751. * .. reordering the rows in decreasing sequence in the
  752. * ell-infinity norm - this enhances numerical robustness in
  753. * the case of differently scaled rows.
  754. DO 1904 p = 1, M
  755. * RWORK(p) = ABS( A(p,ICAMAX(N,A(p,1),LDA)) )
  756. * [[DLANGE will return NaN if an entry of the p-th row is Nan]]
  757. RWORK(p) = DLANGE( 'M', 1, N, A(p,1), LDA, RDUMMY )
  758. * .. check for NaN's and Inf's
  759. IF ( ( RWORK(p) .NE. RWORK(p) ) .OR.
  760. $ ( (RWORK(p)*ZERO) .NE. ZERO ) ) THEN
  761. INFO = -8
  762. CALL XERBLA( 'DGESVDQ', -INFO )
  763. RETURN
  764. END IF
  765. 1904 CONTINUE
  766. DO 1952 p = 1, M - 1
  767. q = IDAMAX( M-p+1, RWORK(p), 1 ) + p - 1
  768. IWORK(N+p) = q
  769. IF ( p .NE. q ) THEN
  770. RTMP = RWORK(p)
  771. RWORK(p) = RWORK(q)
  772. RWORK(q) = RTMP
  773. END IF
  774. 1952 CONTINUE
  775. *
  776. IF ( RWORK(1) .EQ. ZERO ) THEN
  777. * Quick return: A is the M x N zero matrix.
  778. NUMRANK = 0
  779. CALL DLASET( 'G', N, 1, ZERO, ZERO, S, N )
  780. IF ( WNTUS ) CALL DLASET('G', M, N, ZERO, ONE, U, LDU)
  781. IF ( WNTUA ) CALL DLASET('G', M, M, ZERO, ONE, U, LDU)
  782. IF ( WNTVA ) CALL DLASET('G', N, N, ZERO, ONE, V, LDV)
  783. IF ( WNTUF ) THEN
  784. CALL DLASET( 'G', N, 1, ZERO, ZERO, WORK, N )
  785. CALL DLASET( 'G', M, N, ZERO, ONE, U, LDU )
  786. END IF
  787. DO 5001 p = 1, N
  788. IWORK(p) = p
  789. 5001 CONTINUE
  790. IF ( ROWPRM ) THEN
  791. DO 5002 p = N + 1, N + M - 1
  792. IWORK(p) = p - N
  793. 5002 CONTINUE
  794. END IF
  795. IF ( CONDA ) RWORK(1) = -1
  796. RWORK(2) = -1
  797. RETURN
  798. END IF
  799. *
  800. IF ( RWORK(1) .GT. BIG / SQRT(DBLE(M)) ) THEN
  801. * .. to prevent overflow in the QR factorization, scale the
  802. * matrix by 1/sqrt(M) if too large entry detected
  803. CALL DLASCL('G',0,0,SQRT(DBLE(M)),ONE, M,N, A,LDA, IERR)
  804. ASCALED = .TRUE.
  805. END IF
  806. CALL DLASWP( N, A, LDA, 1, M-1, IWORK(N+1), 1 )
  807. END IF
  808. *
  809. * .. At this stage, preemptive scaling is done only to avoid column
  810. * norms overflows during the QR factorization. The SVD procedure should
  811. * have its own scaling to save the singular values from overflows and
  812. * underflows. That depends on the SVD procedure.
  813. *
  814. IF ( .NOT.ROWPRM ) THEN
  815. RTMP = DLANGE( 'M', M, N, A, LDA, RDUMMY )
  816. IF ( ( RTMP .NE. RTMP ) .OR.
  817. $ ( (RTMP*ZERO) .NE. ZERO ) ) THEN
  818. INFO = -8
  819. CALL XERBLA( 'DGESVDQ', -INFO )
  820. RETURN
  821. END IF
  822. IF ( RTMP .GT. BIG / SQRT(DBLE(M)) ) THEN
  823. * .. to prevent overflow in the QR factorization, scale the
  824. * matrix by 1/sqrt(M) if too large entry detected
  825. CALL DLASCL('G',0,0, SQRT(DBLE(M)),ONE, M,N, A,LDA, IERR)
  826. ASCALED = .TRUE.
  827. END IF
  828. END IF
  829. *
  830. * .. QR factorization with column pivoting
  831. *
  832. * A * P = Q * [ R ]
  833. * [ 0 ]
  834. *
  835. DO 1963 p = 1, N
  836. * .. all columns are free columns
  837. IWORK(p) = 0
  838. 1963 CONTINUE
  839. CALL DGEQP3( M, N, A, LDA, IWORK, WORK, WORK(N+1), LWORK-N,
  840. $ IERR )
  841. *
  842. * If the user requested accuracy level allows truncation in the
  843. * computed upper triangular factor, the matrix R is examined and,
  844. * if possible, replaced with its leading upper trapezoidal part.
  845. *
  846. EPSLN = DLAMCH('E')
  847. SFMIN = DLAMCH('S')
  848. * SMALL = SFMIN / EPSLN
  849. NR = N
  850. *
  851. IF ( ACCLA ) THEN
  852. *
  853. * Standard absolute error bound suffices. All sigma_i with
  854. * sigma_i < N*EPS*||A||_F are flushed to zero. This is an
  855. * aggressive enforcement of lower numerical rank by introducing a
  856. * backward error of the order of N*EPS*||A||_F.
  857. NR = 1
  858. RTMP = SQRT(DBLE(N))*EPSLN
  859. DO 3001 p = 2, N
  860. IF ( ABS(A(p,p)) .LT. (RTMP*ABS(A(1,1))) ) GO TO 3002
  861. NR = NR + 1
  862. 3001 CONTINUE
  863. 3002 CONTINUE
  864. *
  865. ELSEIF ( ACCLM ) THEN
  866. * .. similarly as above, only slightly more gentle (less aggressive).
  867. * Sudden drop on the diagonal of R is used as the criterion for being
  868. * close-to-rank-deficient. The threshold is set to EPSLN=DLAMCH('E').
  869. * [[This can be made more flexible by replacing this hard-coded value
  870. * with a user specified threshold.]] Also, the values that underflow
  871. * will be truncated.
  872. NR = 1
  873. DO 3401 p = 2, N
  874. IF ( ( ABS(A(p,p)) .LT. (EPSLN*ABS(A(p-1,p-1))) ) .OR.
  875. $ ( ABS(A(p,p)) .LT. SFMIN ) ) GO TO 3402
  876. NR = NR + 1
  877. 3401 CONTINUE
  878. 3402 CONTINUE
  879. *
  880. ELSE
  881. * .. RRQR not authorized to determine numerical rank except in the
  882. * obvious case of zero pivots.
  883. * .. inspect R for exact zeros on the diagonal;
  884. * R(i,i)=0 => R(i:N,i:N)=0.
  885. NR = 1
  886. DO 3501 p = 2, N
  887. IF ( ABS(A(p,p)) .EQ. ZERO ) GO TO 3502
  888. NR = NR + 1
  889. 3501 CONTINUE
  890. 3502 CONTINUE
  891. *
  892. IF ( CONDA ) THEN
  893. * Estimate the scaled condition number of A. Use the fact that it is
  894. * the same as the scaled condition number of R.
  895. * .. V is used as workspace
  896. CALL DLACPY( 'U', N, N, A, LDA, V, LDV )
  897. * Only the leading NR x NR submatrix of the triangular factor
  898. * is considered. Only if NR=N will this give a reliable error
  899. * bound. However, even for NR < N, this can be used on an
  900. * expert level and obtain useful information in the sense of
  901. * perturbation theory.
  902. DO 3053 p = 1, NR
  903. RTMP = DNRM2( p, V(1,p), 1 )
  904. CALL DSCAL( p, ONE/RTMP, V(1,p), 1 )
  905. 3053 CONTINUE
  906. IF ( .NOT. ( LSVEC .OR. RSVEC ) ) THEN
  907. CALL DPOCON( 'U', NR, V, LDV, ONE, RTMP,
  908. $ WORK, IWORK(N+IWOFF), IERR )
  909. ELSE
  910. CALL DPOCON( 'U', NR, V, LDV, ONE, RTMP,
  911. $ WORK(N+1), IWORK(N+IWOFF), IERR )
  912. END IF
  913. SCONDA = ONE / SQRT(RTMP)
  914. * For NR=N, SCONDA is an estimate of SQRT(||(R^* * R)^(-1)||_1),
  915. * N^(-1/4) * SCONDA <= ||R^(-1)||_2 <= N^(1/4) * SCONDA
  916. * See the reference [1] for more details.
  917. END IF
  918. *
  919. ENDIF
  920. *
  921. IF ( WNTUR ) THEN
  922. N1 = NR
  923. ELSE IF ( WNTUS .OR. WNTUF) THEN
  924. N1 = N
  925. ELSE IF ( WNTUA ) THEN
  926. N1 = M
  927. END IF
  928. *
  929. IF ( .NOT. ( RSVEC .OR. LSVEC ) ) THEN
  930. *.......................................................................
  931. * .. only the singular values are requested
  932. *.......................................................................
  933. IF ( RTRANS ) THEN
  934. *
  935. * .. compute the singular values of R**T = [A](1:NR,1:N)**T
  936. * .. set the lower triangle of [A] to [A](1:NR,1:N)**T and
  937. * the upper triangle of [A] to zero.
  938. DO 1146 p = 1, MIN( N, NR )
  939. DO 1147 q = p + 1, N
  940. A(q,p) = A(p,q)
  941. IF ( q .LE. NR ) A(p,q) = ZERO
  942. 1147 CONTINUE
  943. 1146 CONTINUE
  944. *
  945. CALL DGESVD( 'N', 'N', N, NR, A, LDA, S, U, LDU,
  946. $ V, LDV, WORK, LWORK, INFO )
  947. *
  948. ELSE
  949. *
  950. * .. compute the singular values of R = [A](1:NR,1:N)
  951. *
  952. IF ( NR .GT. 1 )
  953. $ CALL DLASET( 'L', NR-1,NR-1, ZERO,ZERO, A(2,1), LDA )
  954. CALL DGESVD( 'N', 'N', NR, N, A, LDA, S, U, LDU,
  955. $ V, LDV, WORK, LWORK, INFO )
  956. *
  957. END IF
  958. *
  959. ELSE IF ( LSVEC .AND. ( .NOT. RSVEC) ) THEN
  960. *.......................................................................
  961. * .. the singular values and the left singular vectors requested
  962. *.......................................................................""""""""
  963. IF ( RTRANS ) THEN
  964. * .. apply DGESVD to R**T
  965. * .. copy R**T into [U] and overwrite [U] with the right singular
  966. * vectors of R
  967. DO 1192 p = 1, NR
  968. DO 1193 q = p, N
  969. U(q,p) = A(p,q)
  970. 1193 CONTINUE
  971. 1192 CONTINUE
  972. IF ( NR .GT. 1 )
  973. $ CALL DLASET( 'U', NR-1,NR-1, ZERO,ZERO, U(1,2), LDU )
  974. * .. the left singular vectors not computed, the NR right singular
  975. * vectors overwrite [U](1:NR,1:NR) as transposed. These
  976. * will be pre-multiplied by Q to build the left singular vectors of A.
  977. CALL DGESVD( 'N', 'O', N, NR, U, LDU, S, U, LDU,
  978. $ U, LDU, WORK(N+1), LWORK-N, INFO )
  979. *
  980. DO 1119 p = 1, NR
  981. DO 1120 q = p + 1, NR
  982. RTMP = U(q,p)
  983. U(q,p) = U(p,q)
  984. U(p,q) = RTMP
  985. 1120 CONTINUE
  986. 1119 CONTINUE
  987. *
  988. ELSE
  989. * .. apply DGESVD to R
  990. * .. copy R into [U] and overwrite [U] with the left singular vectors
  991. CALL DLACPY( 'U', NR, N, A, LDA, U, LDU )
  992. IF ( NR .GT. 1 )
  993. $ CALL DLASET( 'L', NR-1, NR-1, ZERO, ZERO, U(2,1), LDU )
  994. * .. the right singular vectors not computed, the NR left singular
  995. * vectors overwrite [U](1:NR,1:NR)
  996. CALL DGESVD( 'O', 'N', NR, N, U, LDU, S, U, LDU,
  997. $ V, LDV, WORK(N+1), LWORK-N, INFO )
  998. * .. now [U](1:NR,1:NR) contains the NR left singular vectors of
  999. * R. These will be pre-multiplied by Q to build the left singular
  1000. * vectors of A.
  1001. END IF
  1002. *
  1003. * .. assemble the left singular vector matrix U of dimensions
  1004. * (M x NR) or (M x N) or (M x M).
  1005. IF ( ( NR .LT. M ) .AND. ( .NOT.WNTUF ) ) THEN
  1006. CALL DLASET('A', M-NR, NR, ZERO, ZERO, U(NR+1,1), LDU)
  1007. IF ( NR .LT. N1 ) THEN
  1008. CALL DLASET( 'A',NR,N1-NR,ZERO,ZERO,U(1,NR+1), LDU )
  1009. CALL DLASET( 'A',M-NR,N1-NR,ZERO,ONE,
  1010. $ U(NR+1,NR+1), LDU )
  1011. END IF
  1012. END IF
  1013. *
  1014. * The Q matrix from the first QRF is built into the left singular
  1015. * vectors matrix U.
  1016. *
  1017. IF ( .NOT.WNTUF )
  1018. $ CALL DORMQR( 'L', 'N', M, N1, N, A, LDA, WORK, U,
  1019. $ LDU, WORK(N+1), LWORK-N, IERR )
  1020. IF ( ROWPRM .AND. .NOT.WNTUF )
  1021. $ CALL DLASWP( N1, U, LDU, 1, M-1, IWORK(N+1), -1 )
  1022. *
  1023. ELSE IF ( RSVEC .AND. ( .NOT. LSVEC ) ) THEN
  1024. *.......................................................................
  1025. * .. the singular values and the right singular vectors requested
  1026. *.......................................................................
  1027. IF ( RTRANS ) THEN
  1028. * .. apply DGESVD to R**T
  1029. * .. copy R**T into V and overwrite V with the left singular vectors
  1030. DO 1165 p = 1, NR
  1031. DO 1166 q = p, N
  1032. V(q,p) = (A(p,q))
  1033. 1166 CONTINUE
  1034. 1165 CONTINUE
  1035. IF ( NR .GT. 1 )
  1036. $ CALL DLASET( 'U', NR-1,NR-1, ZERO,ZERO, V(1,2), LDV )
  1037. * .. the left singular vectors of R**T overwrite V, the right singular
  1038. * vectors not computed
  1039. IF ( WNTVR .OR. ( NR .EQ. N ) ) THEN
  1040. CALL DGESVD( 'O', 'N', N, NR, V, LDV, S, U, LDU,
  1041. $ U, LDU, WORK(N+1), LWORK-N, INFO )
  1042. *
  1043. DO 1121 p = 1, NR
  1044. DO 1122 q = p + 1, NR
  1045. RTMP = V(q,p)
  1046. V(q,p) = V(p,q)
  1047. V(p,q) = RTMP
  1048. 1122 CONTINUE
  1049. 1121 CONTINUE
  1050. *
  1051. IF ( NR .LT. N ) THEN
  1052. DO 1103 p = 1, NR
  1053. DO 1104 q = NR + 1, N
  1054. V(p,q) = V(q,p)
  1055. 1104 CONTINUE
  1056. 1103 CONTINUE
  1057. END IF
  1058. CALL DLAPMT( .FALSE., NR, N, V, LDV, IWORK )
  1059. ELSE
  1060. * .. need all N right singular vectors and NR < N
  1061. * [!] This is simple implementation that augments [V](1:N,1:NR)
  1062. * by padding a zero block. In the case NR << N, a more efficient
  1063. * way is to first use the QR factorization. For more details
  1064. * how to implement this, see the " FULL SVD " branch.
  1065. CALL DLASET('G', N, N-NR, ZERO, ZERO, V(1,NR+1), LDV)
  1066. CALL DGESVD( 'O', 'N', N, N, V, LDV, S, U, LDU,
  1067. $ U, LDU, WORK(N+1), LWORK-N, INFO )
  1068. *
  1069. DO 1123 p = 1, N
  1070. DO 1124 q = p + 1, N
  1071. RTMP = V(q,p)
  1072. V(q,p) = V(p,q)
  1073. V(p,q) = RTMP
  1074. 1124 CONTINUE
  1075. 1123 CONTINUE
  1076. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1077. END IF
  1078. *
  1079. ELSE
  1080. * .. aply DGESVD to R
  1081. * .. copy R into V and overwrite V with the right singular vectors
  1082. CALL DLACPY( 'U', NR, N, A, LDA, V, LDV )
  1083. IF ( NR .GT. 1 )
  1084. $ CALL DLASET( 'L', NR-1, NR-1, ZERO, ZERO, V(2,1), LDV )
  1085. * .. the right singular vectors overwrite V, the NR left singular
  1086. * vectors stored in U(1:NR,1:NR)
  1087. IF ( WNTVR .OR. ( NR .EQ. N ) ) THEN
  1088. CALL DGESVD( 'N', 'O', NR, N, V, LDV, S, U, LDU,
  1089. $ V, LDV, WORK(N+1), LWORK-N, INFO )
  1090. CALL DLAPMT( .FALSE., NR, N, V, LDV, IWORK )
  1091. * .. now [V](1:NR,1:N) contains V(1:N,1:NR)**T
  1092. ELSE
  1093. * .. need all N right singular vectors and NR < N
  1094. * [!] This is simple implementation that augments [V](1:NR,1:N)
  1095. * by padding a zero block. In the case NR << N, a more efficient
  1096. * way is to first use the LQ factorization. For more details
  1097. * how to implement this, see the " FULL SVD " branch.
  1098. CALL DLASET('G', N-NR, N, ZERO,ZERO, V(NR+1,1), LDV)
  1099. CALL DGESVD( 'N', 'O', N, N, V, LDV, S, U, LDU,
  1100. $ V, LDV, WORK(N+1), LWORK-N, INFO )
  1101. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1102. END IF
  1103. * .. now [V] contains the transposed matrix of the right singular
  1104. * vectors of A.
  1105. END IF
  1106. *
  1107. ELSE
  1108. *.......................................................................
  1109. * .. FULL SVD requested
  1110. *.......................................................................
  1111. IF ( RTRANS ) THEN
  1112. *
  1113. * .. apply DGESVD to R**T [[this option is left for R&D&T]]
  1114. *
  1115. IF ( WNTVR .OR. ( NR .EQ. N ) ) THEN
  1116. * .. copy R**T into [V] and overwrite [V] with the left singular
  1117. * vectors of R**T
  1118. DO 1168 p = 1, NR
  1119. DO 1169 q = p, N
  1120. V(q,p) = A(p,q)
  1121. 1169 CONTINUE
  1122. 1168 CONTINUE
  1123. IF ( NR .GT. 1 )
  1124. $ CALL DLASET( 'U', NR-1,NR-1, ZERO,ZERO, V(1,2), LDV )
  1125. *
  1126. * .. the left singular vectors of R**T overwrite [V], the NR right
  1127. * singular vectors of R**T stored in [U](1:NR,1:NR) as transposed
  1128. CALL DGESVD( 'O', 'A', N, NR, V, LDV, S, V, LDV,
  1129. $ U, LDU, WORK(N+1), LWORK-N, INFO )
  1130. * .. assemble V
  1131. DO 1115 p = 1, NR
  1132. DO 1116 q = p + 1, NR
  1133. RTMP = V(q,p)
  1134. V(q,p) = V(p,q)
  1135. V(p,q) = RTMP
  1136. 1116 CONTINUE
  1137. 1115 CONTINUE
  1138. IF ( NR .LT. N ) THEN
  1139. DO 1101 p = 1, NR
  1140. DO 1102 q = NR+1, N
  1141. V(p,q) = V(q,p)
  1142. 1102 CONTINUE
  1143. 1101 CONTINUE
  1144. END IF
  1145. CALL DLAPMT( .FALSE., NR, N, V, LDV, IWORK )
  1146. *
  1147. DO 1117 p = 1, NR
  1148. DO 1118 q = p + 1, NR
  1149. RTMP = U(q,p)
  1150. U(q,p) = U(p,q)
  1151. U(p,q) = RTMP
  1152. 1118 CONTINUE
  1153. 1117 CONTINUE
  1154. *
  1155. IF ( ( NR .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1156. CALL DLASET('A', M-NR,NR, ZERO,ZERO, U(NR+1,1), LDU)
  1157. IF ( NR .LT. N1 ) THEN
  1158. CALL DLASET('A',NR,N1-NR,ZERO,ZERO,U(1,NR+1),LDU)
  1159. CALL DLASET( 'A',M-NR,N1-NR,ZERO,ONE,
  1160. $ U(NR+1,NR+1), LDU )
  1161. END IF
  1162. END IF
  1163. *
  1164. ELSE
  1165. * .. need all N right singular vectors and NR < N
  1166. * .. copy R**T into [V] and overwrite [V] with the left singular
  1167. * vectors of R**T
  1168. * [[The optimal ratio N/NR for using QRF instead of padding
  1169. * with zeros. Here hard coded to 2; it must be at least
  1170. * two due to work space constraints.]]
  1171. * OPTRATIO = ILAENV(6, 'DGESVD', 'S' // 'O', NR,N,0,0)
  1172. * OPTRATIO = MAX( OPTRATIO, 2 )
  1173. OPTRATIO = 2
  1174. IF ( OPTRATIO*NR .GT. N ) THEN
  1175. DO 1198 p = 1, NR
  1176. DO 1199 q = p, N
  1177. V(q,p) = A(p,q)
  1178. 1199 CONTINUE
  1179. 1198 CONTINUE
  1180. IF ( NR .GT. 1 )
  1181. $ CALL DLASET('U',NR-1,NR-1, ZERO,ZERO, V(1,2),LDV)
  1182. *
  1183. CALL DLASET('A',N,N-NR,ZERO,ZERO,V(1,NR+1),LDV)
  1184. CALL DGESVD( 'O', 'A', N, N, V, LDV, S, V, LDV,
  1185. $ U, LDU, WORK(N+1), LWORK-N, INFO )
  1186. *
  1187. DO 1113 p = 1, N
  1188. DO 1114 q = p + 1, N
  1189. RTMP = V(q,p)
  1190. V(q,p) = V(p,q)
  1191. V(p,q) = RTMP
  1192. 1114 CONTINUE
  1193. 1113 CONTINUE
  1194. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1195. * .. assemble the left singular vector matrix U of dimensions
  1196. * (M x N1), i.e. (M x N) or (M x M).
  1197. *
  1198. DO 1111 p = 1, N
  1199. DO 1112 q = p + 1, N
  1200. RTMP = U(q,p)
  1201. U(q,p) = U(p,q)
  1202. U(p,q) = RTMP
  1203. 1112 CONTINUE
  1204. 1111 CONTINUE
  1205. *
  1206. IF ( ( N .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1207. CALL DLASET('A',M-N,N,ZERO,ZERO,U(N+1,1),LDU)
  1208. IF ( N .LT. N1 ) THEN
  1209. CALL DLASET('A',N,N1-N,ZERO,ZERO,U(1,N+1),LDU)
  1210. CALL DLASET('A',M-N,N1-N,ZERO,ONE,
  1211. $ U(N+1,N+1), LDU )
  1212. END IF
  1213. END IF
  1214. ELSE
  1215. * .. copy R**T into [U] and overwrite [U] with the right
  1216. * singular vectors of R
  1217. DO 1196 p = 1, NR
  1218. DO 1197 q = p, N
  1219. U(q,NR+p) = A(p,q)
  1220. 1197 CONTINUE
  1221. 1196 CONTINUE
  1222. IF ( NR .GT. 1 )
  1223. $ CALL DLASET('U',NR-1,NR-1,ZERO,ZERO,U(1,NR+2),LDU)
  1224. CALL DGEQRF( N, NR, U(1,NR+1), LDU, WORK(N+1),
  1225. $ WORK(N+NR+1), LWORK-N-NR, IERR )
  1226. DO 1143 p = 1, NR
  1227. DO 1144 q = 1, N
  1228. V(q,p) = U(p,NR+q)
  1229. 1144 CONTINUE
  1230. 1143 CONTINUE
  1231. CALL DLASET('U',NR-1,NR-1,ZERO,ZERO,V(1,2),LDV)
  1232. CALL DGESVD( 'S', 'O', NR, NR, V, LDV, S, U, LDU,
  1233. $ V,LDV, WORK(N+NR+1),LWORK-N-NR, INFO )
  1234. CALL DLASET('A',N-NR,NR,ZERO,ZERO,V(NR+1,1),LDV)
  1235. CALL DLASET('A',NR,N-NR,ZERO,ZERO,V(1,NR+1),LDV)
  1236. CALL DLASET('A',N-NR,N-NR,ZERO,ONE,V(NR+1,NR+1),LDV)
  1237. CALL DORMQR('R','C', N, N, NR, U(1,NR+1), LDU,
  1238. $ WORK(N+1),V,LDV,WORK(N+NR+1),LWORK-N-NR,IERR)
  1239. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1240. * .. assemble the left singular vector matrix U of dimensions
  1241. * (M x NR) or (M x N) or (M x M).
  1242. IF ( ( NR .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1243. CALL DLASET('A',M-NR,NR,ZERO,ZERO,U(NR+1,1),LDU)
  1244. IF ( NR .LT. N1 ) THEN
  1245. CALL DLASET('A',NR,N1-NR,ZERO,ZERO,U(1,NR+1),LDU)
  1246. CALL DLASET( 'A',M-NR,N1-NR,ZERO,ONE,
  1247. $ U(NR+1,NR+1),LDU)
  1248. END IF
  1249. END IF
  1250. END IF
  1251. END IF
  1252. *
  1253. ELSE
  1254. *
  1255. * .. apply DGESVD to R [[this is the recommended option]]
  1256. *
  1257. IF ( WNTVR .OR. ( NR .EQ. N ) ) THEN
  1258. * .. copy R into [V] and overwrite V with the right singular vectors
  1259. CALL DLACPY( 'U', NR, N, A, LDA, V, LDV )
  1260. IF ( NR .GT. 1 )
  1261. $ CALL DLASET( 'L', NR-1,NR-1, ZERO,ZERO, V(2,1), LDV )
  1262. * .. the right singular vectors of R overwrite [V], the NR left
  1263. * singular vectors of R stored in [U](1:NR,1:NR)
  1264. CALL DGESVD( 'S', 'O', NR, N, V, LDV, S, U, LDU,
  1265. $ V, LDV, WORK(N+1), LWORK-N, INFO )
  1266. CALL DLAPMT( .FALSE., NR, N, V, LDV, IWORK )
  1267. * .. now [V](1:NR,1:N) contains V(1:N,1:NR)**T
  1268. * .. assemble the left singular vector matrix U of dimensions
  1269. * (M x NR) or (M x N) or (M x M).
  1270. IF ( ( NR .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1271. CALL DLASET('A', M-NR,NR, ZERO,ZERO, U(NR+1,1), LDU)
  1272. IF ( NR .LT. N1 ) THEN
  1273. CALL DLASET('A',NR,N1-NR,ZERO,ZERO,U(1,NR+1),LDU)
  1274. CALL DLASET( 'A',M-NR,N1-NR,ZERO,ONE,
  1275. $ U(NR+1,NR+1), LDU )
  1276. END IF
  1277. END IF
  1278. *
  1279. ELSE
  1280. * .. need all N right singular vectors and NR < N
  1281. * .. the requested number of the left singular vectors
  1282. * is then N1 (N or M)
  1283. * [[The optimal ratio N/NR for using LQ instead of padding
  1284. * with zeros. Here hard coded to 2; it must be at least
  1285. * two due to work space constraints.]]
  1286. * OPTRATIO = ILAENV(6, 'DGESVD', 'S' // 'O', NR,N,0,0)
  1287. * OPTRATIO = MAX( OPTRATIO, 2 )
  1288. OPTRATIO = 2
  1289. IF ( OPTRATIO * NR .GT. N ) THEN
  1290. CALL DLACPY( 'U', NR, N, A, LDA, V, LDV )
  1291. IF ( NR .GT. 1 )
  1292. $ CALL DLASET('L', NR-1,NR-1, ZERO,ZERO, V(2,1),LDV)
  1293. * .. the right singular vectors of R overwrite [V], the NR left
  1294. * singular vectors of R stored in [U](1:NR,1:NR)
  1295. CALL DLASET('A', N-NR,N, ZERO,ZERO, V(NR+1,1),LDV)
  1296. CALL DGESVD( 'S', 'O', N, N, V, LDV, S, U, LDU,
  1297. $ V, LDV, WORK(N+1), LWORK-N, INFO )
  1298. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1299. * .. now [V] contains the transposed matrix of the right
  1300. * singular vectors of A. The leading N left singular vectors
  1301. * are in [U](1:N,1:N)
  1302. * .. assemble the left singular vector matrix U of dimensions
  1303. * (M x N1), i.e. (M x N) or (M x M).
  1304. IF ( ( N .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1305. CALL DLASET('A',M-N,N,ZERO,ZERO,U(N+1,1),LDU)
  1306. IF ( N .LT. N1 ) THEN
  1307. CALL DLASET('A',N,N1-N,ZERO,ZERO,U(1,N+1),LDU)
  1308. CALL DLASET( 'A',M-N,N1-N,ZERO,ONE,
  1309. $ U(N+1,N+1), LDU )
  1310. END IF
  1311. END IF
  1312. ELSE
  1313. CALL DLACPY( 'U', NR, N, A, LDA, U(NR+1,1), LDU )
  1314. IF ( NR .GT. 1 )
  1315. $ CALL DLASET('L',NR-1,NR-1,ZERO,ZERO,U(NR+2,1),LDU)
  1316. CALL DGELQF( NR, N, U(NR+1,1), LDU, WORK(N+1),
  1317. $ WORK(N+NR+1), LWORK-N-NR, IERR )
  1318. CALL DLACPY('L',NR,NR,U(NR+1,1),LDU,V,LDV)
  1319. IF ( NR .GT. 1 )
  1320. $ CALL DLASET('U',NR-1,NR-1,ZERO,ZERO,V(1,2),LDV)
  1321. CALL DGESVD( 'S', 'O', NR, NR, V, LDV, S, U, LDU,
  1322. $ V, LDV, WORK(N+NR+1), LWORK-N-NR, INFO )
  1323. CALL DLASET('A',N-NR,NR,ZERO,ZERO,V(NR+1,1),LDV)
  1324. CALL DLASET('A',NR,N-NR,ZERO,ZERO,V(1,NR+1),LDV)
  1325. CALL DLASET('A',N-NR,N-NR,ZERO,ONE,V(NR+1,NR+1),LDV)
  1326. CALL DORMLQ('R','N',N,N,NR,U(NR+1,1),LDU,WORK(N+1),
  1327. $ V, LDV, WORK(N+NR+1),LWORK-N-NR,IERR)
  1328. CALL DLAPMT( .FALSE., N, N, V, LDV, IWORK )
  1329. * .. assemble the left singular vector matrix U of dimensions
  1330. * (M x NR) or (M x N) or (M x M).
  1331. IF ( ( NR .LT. M ) .AND. .NOT.(WNTUF)) THEN
  1332. CALL DLASET('A',M-NR,NR,ZERO,ZERO,U(NR+1,1),LDU)
  1333. IF ( NR .LT. N1 ) THEN
  1334. CALL DLASET('A',NR,N1-NR,ZERO,ZERO,U(1,NR+1),LDU)
  1335. CALL DLASET( 'A',M-NR,N1-NR,ZERO,ONE,
  1336. $ U(NR+1,NR+1), LDU )
  1337. END IF
  1338. END IF
  1339. END IF
  1340. END IF
  1341. * .. end of the "R**T or R" branch
  1342. END IF
  1343. *
  1344. * The Q matrix from the first QRF is built into the left singular
  1345. * vectors matrix U.
  1346. *
  1347. IF ( .NOT. WNTUF )
  1348. $ CALL DORMQR( 'L', 'N', M, N1, N, A, LDA, WORK, U,
  1349. $ LDU, WORK(N+1), LWORK-N, IERR )
  1350. IF ( ROWPRM .AND. .NOT.WNTUF )
  1351. $ CALL DLASWP( N1, U, LDU, 1, M-1, IWORK(N+1), -1 )
  1352. *
  1353. * ... end of the "full SVD" branch
  1354. END IF
  1355. *
  1356. * Check whether some singular values are returned as zeros, e.g.
  1357. * due to underflow, and update the numerical rank.
  1358. p = NR
  1359. DO 4001 q = p, 1, -1
  1360. IF ( S(q) .GT. ZERO ) GO TO 4002
  1361. NR = NR - 1
  1362. 4001 CONTINUE
  1363. 4002 CONTINUE
  1364. *
  1365. * .. if numerical rank deficiency is detected, the truncated
  1366. * singular values are set to zero.
  1367. IF ( NR .LT. N ) CALL DLASET( 'G', N-NR,1, ZERO,ZERO, S(NR+1), N )
  1368. * .. undo scaling; this may cause overflow in the largest singular
  1369. * values.
  1370. IF ( ASCALED )
  1371. $ CALL DLASCL( 'G',0,0, ONE,SQRT(DBLE(M)), NR,1, S, N, IERR )
  1372. IF ( CONDA ) RWORK(1) = SCONDA
  1373. RWORK(2) = p - NR
  1374. * .. p-NR is the number of singular values that are computed as
  1375. * exact zeros in DGESVD() applied to the (possibly truncated)
  1376. * full row rank triangular (trapezoidal) factor of A.
  1377. NUMRANK = NR
  1378. *
  1379. RETURN
  1380. *
  1381. * End of DGESVDQ
  1382. *
  1383. END