dgelss.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /* dgelss.f -- translated by f2c (version 20061008).
  2. You must link the resulting object file with libf2c:
  3. on Microsoft Windows system, link with libf2c.lib;
  4. on Linux or Unix systems, link with .../path/to/libf2c.a -lm
  5. or, if you install libf2c.a in a standard place, with -lf2c -lm
  6. -- in that order, at the end of the command line, as in
  7. cc *.o -lf2c -lm
  8. Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
  9. http://www.netlib.org/f2c/libf2c.zip
  10. */
  11. #include "f2c.h"
  12. #include "blaswrap.h"
  13. /* Table of constant values */
  14. static integer c__6 = 6;
  15. static integer c_n1 = -1;
  16. static integer c__1 = 1;
  17. static integer c__0 = 0;
  18. static doublereal c_b74 = 0.;
  19. static doublereal c_b108 = 1.;
  20. /* Subroutine */ int _starpu_dgelss_(integer *m, integer *n, integer *nrhs,
  21. doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
  22. s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,
  23. integer *info)
  24. {
  25. /* System generated locals */
  26. integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4;
  27. doublereal d__1;
  28. /* Local variables */
  29. integer i__, bl, ie, il, mm;
  30. doublereal eps, thr, anrm, bnrm;
  31. integer itau;
  32. doublereal vdum[1];
  33. extern /* Subroutine */ int _starpu_dgemm_(char *, char *, integer *, integer *,
  34. integer *, doublereal *, doublereal *, integer *, doublereal *,
  35. integer *, doublereal *, doublereal *, integer *);
  36. integer iascl, ibscl;
  37. extern /* Subroutine */ int _starpu_dgemv_(char *, integer *, integer *,
  38. doublereal *, doublereal *, integer *, doublereal *, integer *,
  39. doublereal *, doublereal *, integer *), _starpu_drscl_(integer *,
  40. doublereal *, doublereal *, integer *);
  41. integer chunk;
  42. doublereal sfmin;
  43. integer minmn;
  44. extern /* Subroutine */ int _starpu_dcopy_(integer *, doublereal *, integer *,
  45. doublereal *, integer *);
  46. integer maxmn, itaup, itauq, mnthr, iwork;
  47. extern /* Subroutine */ int _starpu_dlabad_(doublereal *, doublereal *), _starpu_dgebrd_(
  48. integer *, integer *, doublereal *, integer *, doublereal *,
  49. doublereal *, doublereal *, doublereal *, doublereal *, integer *,
  50. integer *);
  51. extern doublereal _starpu_dlamch_(char *), _starpu_dlange_(char *, integer *,
  52. integer *, doublereal *, integer *, doublereal *);
  53. integer bdspac;
  54. extern /* Subroutine */ int _starpu_dgelqf_(integer *, integer *, doublereal *,
  55. integer *, doublereal *, doublereal *, integer *, integer *),
  56. _starpu_dlascl_(char *, integer *, integer *, doublereal *, doublereal *,
  57. integer *, integer *, doublereal *, integer *, integer *),
  58. _starpu_dgeqrf_(integer *, integer *, doublereal *, integer *,
  59. doublereal *, doublereal *, integer *, integer *), _starpu_dlacpy_(char *,
  60. integer *, integer *, doublereal *, integer *, doublereal *,
  61. integer *), _starpu_dlaset_(char *, integer *, integer *,
  62. doublereal *, doublereal *, doublereal *, integer *),
  63. _starpu_xerbla_(char *, integer *), _starpu_dbdsqr_(char *, integer *,
  64. integer *, integer *, integer *, doublereal *, doublereal *,
  65. doublereal *, integer *, doublereal *, integer *, doublereal *,
  66. integer *, doublereal *, integer *), _starpu_dorgbr_(char *,
  67. integer *, integer *, integer *, doublereal *, integer *,
  68. doublereal *, doublereal *, integer *, integer *);
  69. doublereal bignum;
  70. extern integer _starpu_ilaenv_(integer *, char *, char *, integer *, integer *,
  71. integer *, integer *);
  72. extern /* Subroutine */ int _starpu_dormbr_(char *, char *, char *, integer *,
  73. integer *, integer *, doublereal *, integer *, doublereal *,
  74. doublereal *, integer *, doublereal *, integer *, integer *), _starpu_dormlq_(char *, char *, integer *,
  75. integer *, integer *, doublereal *, integer *, doublereal *,
  76. doublereal *, integer *, doublereal *, integer *, integer *);
  77. integer ldwork;
  78. extern /* Subroutine */ int _starpu_dormqr_(char *, char *, integer *, integer *,
  79. integer *, doublereal *, integer *, doublereal *, doublereal *,
  80. integer *, doublereal *, integer *, integer *);
  81. integer minwrk, maxwrk;
  82. doublereal smlnum;
  83. logical lquery;
  84. /* -- LAPACK driver routine (version 3.2) -- */
  85. /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
  86. /* November 2006 */
  87. /* .. Scalar Arguments .. */
  88. /* .. */
  89. /* .. Array Arguments .. */
  90. /* .. */
  91. /* Purpose */
  92. /* ======= */
  93. /* DGELSS computes the minimum norm solution to a real linear least */
  94. /* squares problem: */
  95. /* Minimize 2-norm(| b - A*x |). */
  96. /* using the singular value decomposition (SVD) of A. A is an M-by-N */
  97. /* matrix which may be rank-deficient. */
  98. /* Several right hand side vectors b and solution vectors x can be */
  99. /* handled in a single call; they are stored as the columns of the */
  100. /* M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix */
  101. /* X. */
  102. /* The effective rank of A is determined by treating as zero those */
  103. /* singular values which are less than RCOND times the largest singular */
  104. /* value. */
  105. /* Arguments */
  106. /* ========= */
  107. /* M (input) INTEGER */
  108. /* The number of rows of the matrix A. M >= 0. */
  109. /* N (input) INTEGER */
  110. /* The number of columns of the matrix A. N >= 0. */
  111. /* NRHS (input) INTEGER */
  112. /* The number of right hand sides, i.e., the number of columns */
  113. /* of the matrices B and X. NRHS >= 0. */
  114. /* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */
  115. /* On entry, the M-by-N matrix A. */
  116. /* On exit, the first min(m,n) rows of A are overwritten with */
  117. /* its right singular vectors, stored rowwise. */
  118. /* LDA (input) INTEGER */
  119. /* The leading dimension of the array A. LDA >= max(1,M). */
  120. /* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) */
  121. /* On entry, the M-by-NRHS right hand side matrix B. */
  122. /* On exit, B is overwritten by the N-by-NRHS solution */
  123. /* matrix X. If m >= n and RANK = n, the residual */
  124. /* sum-of-squares for the solution in the i-th column is given */
  125. /* by the sum of squares of elements n+1:m in that column. */
  126. /* LDB (input) INTEGER */
  127. /* The leading dimension of the array B. LDB >= max(1,max(M,N)). */
  128. /* S (output) DOUBLE PRECISION array, dimension (min(M,N)) */
  129. /* The singular values of A in decreasing order. */
  130. /* The condition number of A in the 2-norm = S(1)/S(min(m,n)). */
  131. /* RCOND (input) DOUBLE PRECISION */
  132. /* RCOND is used to determine the effective rank of A. */
  133. /* Singular values S(i) <= RCOND*S(1) are treated as zero. */
  134. /* If RCOND < 0, machine precision is used instead. */
  135. /* RANK (output) INTEGER */
  136. /* The effective rank of A, i.e., the number of singular values */
  137. /* which are greater than RCOND*S(1). */
  138. /* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */
  139. /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
  140. /* LWORK (input) INTEGER */
  141. /* The dimension of the array WORK. LWORK >= 1, and also: */
  142. /* LWORK >= 3*min(M,N) + max( 2*min(M,N), max(M,N), NRHS ) */
  143. /* For good performance, LWORK should generally be larger. */
  144. /* If LWORK = -1, then a workspace query is assumed; the routine */
  145. /* only calculates the optimal size of the WORK array, returns */
  146. /* this value as the first entry of the WORK array, and no error */
  147. /* message related to LWORK is issued by XERBLA. */
  148. /* INFO (output) INTEGER */
  149. /* = 0: successful exit */
  150. /* < 0: if INFO = -i, the i-th argument had an illegal value. */
  151. /* > 0: the algorithm for computing the SVD failed to converge; */
  152. /* if INFO = i, i off-diagonal elements of an intermediate */
  153. /* bidiagonal form did not converge to zero. */
  154. /* ===================================================================== */
  155. /* .. Parameters .. */
  156. /* .. */
  157. /* .. Local Scalars .. */
  158. /* .. */
  159. /* .. Local Arrays .. */
  160. /* .. */
  161. /* .. External Subroutines .. */
  162. /* .. */
  163. /* .. External Functions .. */
  164. /* .. */
  165. /* .. Intrinsic Functions .. */
  166. /* .. */
  167. /* .. Executable Statements .. */
  168. /* Test the input arguments */
  169. /* Parameter adjustments */
  170. a_dim1 = *lda;
  171. a_offset = 1 + a_dim1;
  172. a -= a_offset;
  173. b_dim1 = *ldb;
  174. b_offset = 1 + b_dim1;
  175. b -= b_offset;
  176. --s;
  177. --work;
  178. /* Function Body */
  179. *info = 0;
  180. minmn = min(*m,*n);
  181. maxmn = max(*m,*n);
  182. lquery = *lwork == -1;
  183. if (*m < 0) {
  184. *info = -1;
  185. } else if (*n < 0) {
  186. *info = -2;
  187. } else if (*nrhs < 0) {
  188. *info = -3;
  189. } else if (*lda < max(1,*m)) {
  190. *info = -5;
  191. } else if (*ldb < max(1,maxmn)) {
  192. *info = -7;
  193. }
  194. /* Compute workspace */
  195. /* (Note: Comments in the code beginning "Workspace:" describe the */
  196. /* minimal amount of workspace needed at that point in the code, */
  197. /* as well as the preferred amount for good performance. */
  198. /* NB refers to the optimal block size for the immediately */
  199. /* following subroutine, as returned by ILAENV.) */
  200. if (*info == 0) {
  201. minwrk = 1;
  202. maxwrk = 1;
  203. if (minmn > 0) {
  204. mm = *m;
  205. mnthr = _starpu_ilaenv_(&c__6, "DGELSS", " ", m, n, nrhs, &c_n1);
  206. if (*m >= *n && *m >= mnthr) {
  207. /* Path 1a - overdetermined, with many more rows than */
  208. /* columns */
  209. mm = *n;
  210. /* Computing MAX */
  211. i__1 = maxwrk, i__2 = *n + *n * _starpu_ilaenv_(&c__1, "DGEQRF",
  212. " ", m, n, &c_n1, &c_n1);
  213. maxwrk = max(i__1,i__2);
  214. /* Computing MAX */
  215. i__1 = maxwrk, i__2 = *n + *nrhs * _starpu_ilaenv_(&c__1, "DORMQR",
  216. "LT", m, nrhs, n, &c_n1);
  217. maxwrk = max(i__1,i__2);
  218. }
  219. if (*m >= *n) {
  220. /* Path 1 - overdetermined or exactly determined */
  221. /* Compute workspace needed for DBDSQR */
  222. /* Computing MAX */
  223. i__1 = 1, i__2 = *n * 5;
  224. bdspac = max(i__1,i__2);
  225. /* Computing MAX */
  226. i__1 = maxwrk, i__2 = *n * 3 + (mm + *n) * _starpu_ilaenv_(&c__1,
  227. "DGEBRD", " ", &mm, n, &c_n1, &c_n1);
  228. maxwrk = max(i__1,i__2);
  229. /* Computing MAX */
  230. i__1 = maxwrk, i__2 = *n * 3 + *nrhs * _starpu_ilaenv_(&c__1, "DORMBR"
  231. , "QLT", &mm, nrhs, n, &c_n1);
  232. maxwrk = max(i__1,i__2);
  233. /* Computing MAX */
  234. i__1 = maxwrk, i__2 = *n * 3 + (*n - 1) * _starpu_ilaenv_(&c__1,
  235. "DORGBR", "P", n, n, n, &c_n1);
  236. maxwrk = max(i__1,i__2);
  237. maxwrk = max(maxwrk,bdspac);
  238. /* Computing MAX */
  239. i__1 = maxwrk, i__2 = *n * *nrhs;
  240. maxwrk = max(i__1,i__2);
  241. /* Computing MAX */
  242. i__1 = *n * 3 + mm, i__2 = *n * 3 + *nrhs, i__1 = max(i__1,
  243. i__2);
  244. minwrk = max(i__1,bdspac);
  245. maxwrk = max(minwrk,maxwrk);
  246. }
  247. if (*n > *m) {
  248. /* Compute workspace needed for DBDSQR */
  249. /* Computing MAX */
  250. i__1 = 1, i__2 = *m * 5;
  251. bdspac = max(i__1,i__2);
  252. /* Computing MAX */
  253. i__1 = *m * 3 + *nrhs, i__2 = *m * 3 + *n, i__1 = max(i__1,
  254. i__2);
  255. minwrk = max(i__1,bdspac);
  256. if (*n >= mnthr) {
  257. /* Path 2a - underdetermined, with many more columns */
  258. /* than rows */
  259. maxwrk = *m + *m * _starpu_ilaenv_(&c__1, "DGELQF", " ", m, n, &
  260. c_n1, &c_n1);
  261. /* Computing MAX */
  262. i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m << 1) *
  263. _starpu_ilaenv_(&c__1, "DGEBRD", " ", m, m, &c_n1, &c_n1);
  264. maxwrk = max(i__1,i__2);
  265. /* Computing MAX */
  266. i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + *nrhs *
  267. _starpu_ilaenv_(&c__1, "DORMBR", "QLT", m, nrhs, m, &c_n1);
  268. maxwrk = max(i__1,i__2);
  269. /* Computing MAX */
  270. i__1 = maxwrk, i__2 = *m * *m + (*m << 2) + (*m - 1) *
  271. _starpu_ilaenv_(&c__1, "DORGBR", "P", m, m, m, &c_n1);
  272. maxwrk = max(i__1,i__2);
  273. /* Computing MAX */
  274. i__1 = maxwrk, i__2 = *m * *m + *m + bdspac;
  275. maxwrk = max(i__1,i__2);
  276. if (*nrhs > 1) {
  277. /* Computing MAX */
  278. i__1 = maxwrk, i__2 = *m * *m + *m + *m * *nrhs;
  279. maxwrk = max(i__1,i__2);
  280. } else {
  281. /* Computing MAX */
  282. i__1 = maxwrk, i__2 = *m * *m + (*m << 1);
  283. maxwrk = max(i__1,i__2);
  284. }
  285. /* Computing MAX */
  286. i__1 = maxwrk, i__2 = *m + *nrhs * _starpu_ilaenv_(&c__1, "DORMLQ"
  287. , "LT", n, nrhs, m, &c_n1);
  288. maxwrk = max(i__1,i__2);
  289. } else {
  290. /* Path 2 - underdetermined */
  291. maxwrk = *m * 3 + (*n + *m) * _starpu_ilaenv_(&c__1, "DGEBRD",
  292. " ", m, n, &c_n1, &c_n1);
  293. /* Computing MAX */
  294. i__1 = maxwrk, i__2 = *m * 3 + *nrhs * _starpu_ilaenv_(&c__1,
  295. "DORMBR", "QLT", m, nrhs, m, &c_n1);
  296. maxwrk = max(i__1,i__2);
  297. /* Computing MAX */
  298. i__1 = maxwrk, i__2 = *m * 3 + *m * _starpu_ilaenv_(&c__1, "DORG"
  299. "BR", "P", m, n, m, &c_n1);
  300. maxwrk = max(i__1,i__2);
  301. maxwrk = max(maxwrk,bdspac);
  302. /* Computing MAX */
  303. i__1 = maxwrk, i__2 = *n * *nrhs;
  304. maxwrk = max(i__1,i__2);
  305. }
  306. }
  307. maxwrk = max(minwrk,maxwrk);
  308. }
  309. work[1] = (doublereal) maxwrk;
  310. if (*lwork < minwrk && ! lquery) {
  311. *info = -12;
  312. }
  313. }
  314. if (*info != 0) {
  315. i__1 = -(*info);
  316. _starpu_xerbla_("DGELSS", &i__1);
  317. return 0;
  318. } else if (lquery) {
  319. return 0;
  320. }
  321. /* Quick return if possible */
  322. if (*m == 0 || *n == 0) {
  323. *rank = 0;
  324. return 0;
  325. }
  326. /* Get machine parameters */
  327. eps = _starpu_dlamch_("P");
  328. sfmin = _starpu_dlamch_("S");
  329. smlnum = sfmin / eps;
  330. bignum = 1. / smlnum;
  331. _starpu_dlabad_(&smlnum, &bignum);
  332. /* Scale A if max element outside range [SMLNUM,BIGNUM] */
  333. anrm = _starpu_dlange_("M", m, n, &a[a_offset], lda, &work[1]);
  334. iascl = 0;
  335. if (anrm > 0. && anrm < smlnum) {
  336. /* Scale matrix norm up to SMLNUM */
  337. _starpu_dlascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &a[a_offset], lda,
  338. info);
  339. iascl = 1;
  340. } else if (anrm > bignum) {
  341. /* Scale matrix norm down to BIGNUM */
  342. _starpu_dlascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &a[a_offset], lda,
  343. info);
  344. iascl = 2;
  345. } else if (anrm == 0.) {
  346. /* Matrix all zero. Return zero solution. */
  347. i__1 = max(*m,*n);
  348. _starpu_dlaset_("F", &i__1, nrhs, &c_b74, &c_b74, &b[b_offset], ldb);
  349. _starpu_dlaset_("F", &minmn, &c__1, &c_b74, &c_b74, &s[1], &c__1);
  350. *rank = 0;
  351. goto L70;
  352. }
  353. /* Scale B if max element outside range [SMLNUM,BIGNUM] */
  354. bnrm = _starpu_dlange_("M", m, nrhs, &b[b_offset], ldb, &work[1]);
  355. ibscl = 0;
  356. if (bnrm > 0. && bnrm < smlnum) {
  357. /* Scale matrix norm up to SMLNUM */
  358. _starpu_dlascl_("G", &c__0, &c__0, &bnrm, &smlnum, m, nrhs, &b[b_offset], ldb,
  359. info);
  360. ibscl = 1;
  361. } else if (bnrm > bignum) {
  362. /* Scale matrix norm down to BIGNUM */
  363. _starpu_dlascl_("G", &c__0, &c__0, &bnrm, &bignum, m, nrhs, &b[b_offset], ldb,
  364. info);
  365. ibscl = 2;
  366. }
  367. /* Overdetermined case */
  368. if (*m >= *n) {
  369. /* Path 1 - overdetermined or exactly determined */
  370. mm = *m;
  371. if (*m >= mnthr) {
  372. /* Path 1a - overdetermined, with many more rows than columns */
  373. mm = *n;
  374. itau = 1;
  375. iwork = itau + *n;
  376. /* Compute A=Q*R */
  377. /* (Workspace: need 2*N, prefer N+N*NB) */
  378. i__1 = *lwork - iwork + 1;
  379. _starpu_dgeqrf_(m, n, &a[a_offset], lda, &work[itau], &work[iwork], &i__1,
  380. info);
  381. /* Multiply B by transpose(Q) */
  382. /* (Workspace: need N+NRHS, prefer N+NRHS*NB) */
  383. i__1 = *lwork - iwork + 1;
  384. _starpu_dormqr_("L", "T", m, nrhs, n, &a[a_offset], lda, &work[itau], &b[
  385. b_offset], ldb, &work[iwork], &i__1, info);
  386. /* Zero out below R */
  387. if (*n > 1) {
  388. i__1 = *n - 1;
  389. i__2 = *n - 1;
  390. _starpu_dlaset_("L", &i__1, &i__2, &c_b74, &c_b74, &a[a_dim1 + 2],
  391. lda);
  392. }
  393. }
  394. ie = 1;
  395. itauq = ie + *n;
  396. itaup = itauq + *n;
  397. iwork = itaup + *n;
  398. /* Bidiagonalize R in A */
  399. /* (Workspace: need 3*N+MM, prefer 3*N+(MM+N)*NB) */
  400. i__1 = *lwork - iwork + 1;
  401. _starpu_dgebrd_(&mm, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
  402. work[itaup], &work[iwork], &i__1, info);
  403. /* Multiply B by transpose of left bidiagonalizing vectors of R */
  404. /* (Workspace: need 3*N+NRHS, prefer 3*N+NRHS*NB) */
  405. i__1 = *lwork - iwork + 1;
  406. _starpu_dormbr_("Q", "L", "T", &mm, nrhs, n, &a[a_offset], lda, &work[itauq],
  407. &b[b_offset], ldb, &work[iwork], &i__1, info);
  408. /* Generate right bidiagonalizing vectors of R in A */
  409. /* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) */
  410. i__1 = *lwork - iwork + 1;
  411. _starpu_dorgbr_("P", n, n, n, &a[a_offset], lda, &work[itaup], &work[iwork], &
  412. i__1, info);
  413. iwork = ie + *n;
  414. /* Perform bidiagonal QR iteration */
  415. /* multiply B by transpose of left singular vectors */
  416. /* compute right singular vectors in A */
  417. /* (Workspace: need BDSPAC) */
  418. _starpu_dbdsqr_("U", n, n, &c__0, nrhs, &s[1], &work[ie], &a[a_offset], lda,
  419. vdum, &c__1, &b[b_offset], ldb, &work[iwork], info)
  420. ;
  421. if (*info != 0) {
  422. goto L70;
  423. }
  424. /* Multiply B by reciprocals of singular values */
  425. /* Computing MAX */
  426. d__1 = *rcond * s[1];
  427. thr = max(d__1,sfmin);
  428. if (*rcond < 0.) {
  429. /* Computing MAX */
  430. d__1 = eps * s[1];
  431. thr = max(d__1,sfmin);
  432. }
  433. *rank = 0;
  434. i__1 = *n;
  435. for (i__ = 1; i__ <= i__1; ++i__) {
  436. if (s[i__] > thr) {
  437. _starpu_drscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
  438. ++(*rank);
  439. } else {
  440. _starpu_dlaset_("F", &c__1, nrhs, &c_b74, &c_b74, &b[i__ + b_dim1],
  441. ldb);
  442. }
  443. /* L10: */
  444. }
  445. /* Multiply B by right singular vectors */
  446. /* (Workspace: need N, prefer N*NRHS) */
  447. if (*lwork >= *ldb * *nrhs && *nrhs > 1) {
  448. _starpu_dgemm_("T", "N", n, nrhs, n, &c_b108, &a[a_offset], lda, &b[
  449. b_offset], ldb, &c_b74, &work[1], ldb);
  450. _starpu_dlacpy_("G", n, nrhs, &work[1], ldb, &b[b_offset], ldb)
  451. ;
  452. } else if (*nrhs > 1) {
  453. chunk = *lwork / *n;
  454. i__1 = *nrhs;
  455. i__2 = chunk;
  456. for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
  457. /* Computing MIN */
  458. i__3 = *nrhs - i__ + 1;
  459. bl = min(i__3,chunk);
  460. _starpu_dgemm_("T", "N", n, &bl, n, &c_b108, &a[a_offset], lda, &b[
  461. i__ * b_dim1 + 1], ldb, &c_b74, &work[1], n);
  462. _starpu_dlacpy_("G", n, &bl, &work[1], n, &b[i__ * b_dim1 + 1], ldb);
  463. /* L20: */
  464. }
  465. } else {
  466. _starpu_dgemv_("T", n, n, &c_b108, &a[a_offset], lda, &b[b_offset], &c__1,
  467. &c_b74, &work[1], &c__1);
  468. _starpu_dcopy_(n, &work[1], &c__1, &b[b_offset], &c__1);
  469. }
  470. } else /* if(complicated condition) */ {
  471. /* Computing MAX */
  472. i__2 = *m, i__1 = (*m << 1) - 4, i__2 = max(i__2,i__1), i__2 = max(
  473. i__2,*nrhs), i__1 = *n - *m * 3;
  474. if (*n >= mnthr && *lwork >= (*m << 2) + *m * *m + max(i__2,i__1)) {
  475. /* Path 2a - underdetermined, with many more columns than rows */
  476. /* and sufficient workspace for an efficient algorithm */
  477. ldwork = *m;
  478. /* Computing MAX */
  479. /* Computing MAX */
  480. i__3 = *m, i__4 = (*m << 1) - 4, i__3 = max(i__3,i__4), i__3 =
  481. max(i__3,*nrhs), i__4 = *n - *m * 3;
  482. i__2 = (*m << 2) + *m * *lda + max(i__3,i__4), i__1 = *m * *lda +
  483. *m + *m * *nrhs;
  484. if (*lwork >= max(i__2,i__1)) {
  485. ldwork = *lda;
  486. }
  487. itau = 1;
  488. iwork = *m + 1;
  489. /* Compute A=L*Q */
  490. /* (Workspace: need 2*M, prefer M+M*NB) */
  491. i__2 = *lwork - iwork + 1;
  492. _starpu_dgelqf_(m, n, &a[a_offset], lda, &work[itau], &work[iwork], &i__2,
  493. info);
  494. il = iwork;
  495. /* Copy L to WORK(IL), zeroing out above it */
  496. _starpu_dlacpy_("L", m, m, &a[a_offset], lda, &work[il], &ldwork);
  497. i__2 = *m - 1;
  498. i__1 = *m - 1;
  499. _starpu_dlaset_("U", &i__2, &i__1, &c_b74, &c_b74, &work[il + ldwork], &
  500. ldwork);
  501. ie = il + ldwork * *m;
  502. itauq = ie + *m;
  503. itaup = itauq + *m;
  504. iwork = itaup + *m;
  505. /* Bidiagonalize L in WORK(IL) */
  506. /* (Workspace: need M*M+5*M, prefer M*M+4*M+2*M*NB) */
  507. i__2 = *lwork - iwork + 1;
  508. _starpu_dgebrd_(m, m, &work[il], &ldwork, &s[1], &work[ie], &work[itauq],
  509. &work[itaup], &work[iwork], &i__2, info);
  510. /* Multiply B by transpose of left bidiagonalizing vectors of L */
  511. /* (Workspace: need M*M+4*M+NRHS, prefer M*M+4*M+NRHS*NB) */
  512. i__2 = *lwork - iwork + 1;
  513. _starpu_dormbr_("Q", "L", "T", m, nrhs, m, &work[il], &ldwork, &work[
  514. itauq], &b[b_offset], ldb, &work[iwork], &i__2, info);
  515. /* Generate right bidiagonalizing vectors of R in WORK(IL) */
  516. /* (Workspace: need M*M+5*M-1, prefer M*M+4*M+(M-1)*NB) */
  517. i__2 = *lwork - iwork + 1;
  518. _starpu_dorgbr_("P", m, m, m, &work[il], &ldwork, &work[itaup], &work[
  519. iwork], &i__2, info);
  520. iwork = ie + *m;
  521. /* Perform bidiagonal QR iteration, */
  522. /* computing right singular vectors of L in WORK(IL) and */
  523. /* multiplying B by transpose of left singular vectors */
  524. /* (Workspace: need M*M+M+BDSPAC) */
  525. _starpu_dbdsqr_("U", m, m, &c__0, nrhs, &s[1], &work[ie], &work[il], &
  526. ldwork, &a[a_offset], lda, &b[b_offset], ldb, &work[iwork]
  527. , info);
  528. if (*info != 0) {
  529. goto L70;
  530. }
  531. /* Multiply B by reciprocals of singular values */
  532. /* Computing MAX */
  533. d__1 = *rcond * s[1];
  534. thr = max(d__1,sfmin);
  535. if (*rcond < 0.) {
  536. /* Computing MAX */
  537. d__1 = eps * s[1];
  538. thr = max(d__1,sfmin);
  539. }
  540. *rank = 0;
  541. i__2 = *m;
  542. for (i__ = 1; i__ <= i__2; ++i__) {
  543. if (s[i__] > thr) {
  544. _starpu_drscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
  545. ++(*rank);
  546. } else {
  547. _starpu_dlaset_("F", &c__1, nrhs, &c_b74, &c_b74, &b[i__ + b_dim1]
  548. , ldb);
  549. }
  550. /* L30: */
  551. }
  552. iwork = ie;
  553. /* Multiply B by right singular vectors of L in WORK(IL) */
  554. /* (Workspace: need M*M+2*M, prefer M*M+M+M*NRHS) */
  555. if (*lwork >= *ldb * *nrhs + iwork - 1 && *nrhs > 1) {
  556. _starpu_dgemm_("T", "N", m, nrhs, m, &c_b108, &work[il], &ldwork, &b[
  557. b_offset], ldb, &c_b74, &work[iwork], ldb);
  558. _starpu_dlacpy_("G", m, nrhs, &work[iwork], ldb, &b[b_offset], ldb);
  559. } else if (*nrhs > 1) {
  560. chunk = (*lwork - iwork + 1) / *m;
  561. i__2 = *nrhs;
  562. i__1 = chunk;
  563. for (i__ = 1; i__1 < 0 ? i__ >= i__2 : i__ <= i__2; i__ +=
  564. i__1) {
  565. /* Computing MIN */
  566. i__3 = *nrhs - i__ + 1;
  567. bl = min(i__3,chunk);
  568. _starpu_dgemm_("T", "N", m, &bl, m, &c_b108, &work[il], &ldwork, &
  569. b[i__ * b_dim1 + 1], ldb, &c_b74, &work[iwork], m);
  570. _starpu_dlacpy_("G", m, &bl, &work[iwork], m, &b[i__ * b_dim1 + 1]
  571. , ldb);
  572. /* L40: */
  573. }
  574. } else {
  575. _starpu_dgemv_("T", m, m, &c_b108, &work[il], &ldwork, &b[b_dim1 + 1],
  576. &c__1, &c_b74, &work[iwork], &c__1);
  577. _starpu_dcopy_(m, &work[iwork], &c__1, &b[b_dim1 + 1], &c__1);
  578. }
  579. /* Zero out below first M rows of B */
  580. i__1 = *n - *m;
  581. _starpu_dlaset_("F", &i__1, nrhs, &c_b74, &c_b74, &b[*m + 1 + b_dim1],
  582. ldb);
  583. iwork = itau + *m;
  584. /* Multiply transpose(Q) by B */
  585. /* (Workspace: need M+NRHS, prefer M+NRHS*NB) */
  586. i__1 = *lwork - iwork + 1;
  587. _starpu_dormlq_("L", "T", n, nrhs, m, &a[a_offset], lda, &work[itau], &b[
  588. b_offset], ldb, &work[iwork], &i__1, info);
  589. } else {
  590. /* Path 2 - remaining underdetermined cases */
  591. ie = 1;
  592. itauq = ie + *m;
  593. itaup = itauq + *m;
  594. iwork = itaup + *m;
  595. /* Bidiagonalize A */
  596. /* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) */
  597. i__1 = *lwork - iwork + 1;
  598. _starpu_dgebrd_(m, n, &a[a_offset], lda, &s[1], &work[ie], &work[itauq], &
  599. work[itaup], &work[iwork], &i__1, info);
  600. /* Multiply B by transpose of left bidiagonalizing vectors */
  601. /* (Workspace: need 3*M+NRHS, prefer 3*M+NRHS*NB) */
  602. i__1 = *lwork - iwork + 1;
  603. _starpu_dormbr_("Q", "L", "T", m, nrhs, n, &a[a_offset], lda, &work[itauq]
  604. , &b[b_offset], ldb, &work[iwork], &i__1, info);
  605. /* Generate right bidiagonalizing vectors in A */
  606. /* (Workspace: need 4*M, prefer 3*M+M*NB) */
  607. i__1 = *lwork - iwork + 1;
  608. _starpu_dorgbr_("P", m, n, m, &a[a_offset], lda, &work[itaup], &work[
  609. iwork], &i__1, info);
  610. iwork = ie + *m;
  611. /* Perform bidiagonal QR iteration, */
  612. /* computing right singular vectors of A in A and */
  613. /* multiplying B by transpose of left singular vectors */
  614. /* (Workspace: need BDSPAC) */
  615. _starpu_dbdsqr_("L", m, n, &c__0, nrhs, &s[1], &work[ie], &a[a_offset],
  616. lda, vdum, &c__1, &b[b_offset], ldb, &work[iwork], info);
  617. if (*info != 0) {
  618. goto L70;
  619. }
  620. /* Multiply B by reciprocals of singular values */
  621. /* Computing MAX */
  622. d__1 = *rcond * s[1];
  623. thr = max(d__1,sfmin);
  624. if (*rcond < 0.) {
  625. /* Computing MAX */
  626. d__1 = eps * s[1];
  627. thr = max(d__1,sfmin);
  628. }
  629. *rank = 0;
  630. i__1 = *m;
  631. for (i__ = 1; i__ <= i__1; ++i__) {
  632. if (s[i__] > thr) {
  633. _starpu_drscl_(nrhs, &s[i__], &b[i__ + b_dim1], ldb);
  634. ++(*rank);
  635. } else {
  636. _starpu_dlaset_("F", &c__1, nrhs, &c_b74, &c_b74, &b[i__ + b_dim1]
  637. , ldb);
  638. }
  639. /* L50: */
  640. }
  641. /* Multiply B by right singular vectors of A */
  642. /* (Workspace: need N, prefer N*NRHS) */
  643. if (*lwork >= *ldb * *nrhs && *nrhs > 1) {
  644. _starpu_dgemm_("T", "N", n, nrhs, m, &c_b108, &a[a_offset], lda, &b[
  645. b_offset], ldb, &c_b74, &work[1], ldb);
  646. _starpu_dlacpy_("F", n, nrhs, &work[1], ldb, &b[b_offset], ldb);
  647. } else if (*nrhs > 1) {
  648. chunk = *lwork / *n;
  649. i__1 = *nrhs;
  650. i__2 = chunk;
  651. for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ +=
  652. i__2) {
  653. /* Computing MIN */
  654. i__3 = *nrhs - i__ + 1;
  655. bl = min(i__3,chunk);
  656. _starpu_dgemm_("T", "N", n, &bl, m, &c_b108, &a[a_offset], lda, &
  657. b[i__ * b_dim1 + 1], ldb, &c_b74, &work[1], n);
  658. _starpu_dlacpy_("F", n, &bl, &work[1], n, &b[i__ * b_dim1 + 1],
  659. ldb);
  660. /* L60: */
  661. }
  662. } else {
  663. _starpu_dgemv_("T", m, n, &c_b108, &a[a_offset], lda, &b[b_offset], &
  664. c__1, &c_b74, &work[1], &c__1);
  665. _starpu_dcopy_(n, &work[1], &c__1, &b[b_offset], &c__1);
  666. }
  667. }
  668. }
  669. /* Undo scaling */
  670. if (iascl == 1) {
  671. _starpu_dlascl_("G", &c__0, &c__0, &anrm, &smlnum, n, nrhs, &b[b_offset], ldb,
  672. info);
  673. _starpu_dlascl_("G", &c__0, &c__0, &smlnum, &anrm, &minmn, &c__1, &s[1], &
  674. minmn, info);
  675. } else if (iascl == 2) {
  676. _starpu_dlascl_("G", &c__0, &c__0, &anrm, &bignum, n, nrhs, &b[b_offset], ldb,
  677. info);
  678. _starpu_dlascl_("G", &c__0, &c__0, &bignum, &anrm, &minmn, &c__1, &s[1], &
  679. minmn, info);
  680. }
  681. if (ibscl == 1) {
  682. _starpu_dlascl_("G", &c__0, &c__0, &smlnum, &bnrm, n, nrhs, &b[b_offset], ldb,
  683. info);
  684. } else if (ibscl == 2) {
  685. _starpu_dlascl_("G", &c__0, &c__0, &bignum, &bnrm, n, nrhs, &b[b_offset], ldb,
  686. info);
  687. }
  688. L70:
  689. work[1] = (doublereal) maxwrk;
  690. return 0;
  691. /* End of DGELSS */
  692. } /* _starpu_dgelss_ */