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.

zgesvdq.f 59 kB

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