dlasd0.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /* dlasd0.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__0 = 0;
  15. static integer c__2 = 2;
  16. /* Subroutine */ int _starpu_dlasd0_(integer *n, integer *sqre, doublereal *d__,
  17. doublereal *e, doublereal *u, integer *ldu, doublereal *vt, integer *
  18. ldvt, integer *smlsiz, integer *iwork, doublereal *work, integer *
  19. info)
  20. {
  21. /* System generated locals */
  22. integer u_dim1, u_offset, vt_dim1, vt_offset, i__1, i__2;
  23. /* Builtin functions */
  24. integer pow_ii(integer *, integer *);
  25. /* Local variables */
  26. integer i__, j, m, i1, ic, lf, nd, ll, nl, nr, im1, ncc, nlf, nrf, iwk,
  27. lvl, ndb1, nlp1, nrp1;
  28. doublereal beta;
  29. integer idxq, nlvl;
  30. doublereal alpha;
  31. integer inode, ndiml, idxqc, ndimr, itemp, sqrei;
  32. extern /* Subroutine */ int _starpu_dlasd1_(integer *, integer *, integer *,
  33. doublereal *, doublereal *, doublereal *, doublereal *, integer *,
  34. doublereal *, integer *, integer *, integer *, doublereal *,
  35. integer *), _starpu_dlasdq_(char *, integer *, integer *, integer *,
  36. integer *, integer *, doublereal *, doublereal *, doublereal *,
  37. integer *, doublereal *, integer *, doublereal *, integer *,
  38. doublereal *, integer *), _starpu_dlasdt_(integer *, integer *,
  39. integer *, integer *, integer *, integer *, integer *), _starpu_xerbla_(
  40. char *, integer *);
  41. /* -- LAPACK auxiliary routine (version 3.2) -- */
  42. /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
  43. /* November 2006 */
  44. /* .. Scalar Arguments .. */
  45. /* .. */
  46. /* .. Array Arguments .. */
  47. /* .. */
  48. /* Purpose */
  49. /* ======= */
  50. /* Using a divide and conquer approach, DLASD0 computes the singular */
  51. /* value decomposition (SVD) of a real upper bidiagonal N-by-M */
  52. /* matrix B with diagonal D and offdiagonal E, where M = N + SQRE. */
  53. /* The algorithm computes orthogonal matrices U and VT such that */
  54. /* B = U * S * VT. The singular values S are overwritten on D. */
  55. /* A related subroutine, DLASDA, computes only the singular values, */
  56. /* and optionally, the singular vectors in compact form. */
  57. /* Arguments */
  58. /* ========= */
  59. /* N (input) INTEGER */
  60. /* On entry, the row dimension of the upper bidiagonal matrix. */
  61. /* This is also the dimension of the main diagonal array D. */
  62. /* SQRE (input) INTEGER */
  63. /* Specifies the column dimension of the bidiagonal matrix. */
  64. /* = 0: The bidiagonal matrix has column dimension M = N; */
  65. /* = 1: The bidiagonal matrix has column dimension M = N+1; */
  66. /* D (input/output) DOUBLE PRECISION array, dimension (N) */
  67. /* On entry D contains the main diagonal of the bidiagonal */
  68. /* matrix. */
  69. /* On exit D, if INFO = 0, contains its singular values. */
  70. /* E (input) DOUBLE PRECISION array, dimension (M-1) */
  71. /* Contains the subdiagonal entries of the bidiagonal matrix. */
  72. /* On exit, E has been destroyed. */
  73. /* U (output) DOUBLE PRECISION array, dimension at least (LDQ, N) */
  74. /* On exit, U contains the left singular vectors. */
  75. /* LDU (input) INTEGER */
  76. /* On entry, leading dimension of U. */
  77. /* VT (output) DOUBLE PRECISION array, dimension at least (LDVT, M) */
  78. /* On exit, VT' contains the right singular vectors. */
  79. /* LDVT (input) INTEGER */
  80. /* On entry, leading dimension of VT. */
  81. /* SMLSIZ (input) INTEGER */
  82. /* On entry, maximum size of the subproblems at the */
  83. /* bottom of the computation tree. */
  84. /* IWORK (workspace) INTEGER work array. */
  85. /* Dimension must be at least (8 * N) */
  86. /* WORK (workspace) DOUBLE PRECISION work array. */
  87. /* Dimension must be at least (3 * M**2 + 2 * M) */
  88. /* INFO (output) INTEGER */
  89. /* = 0: successful exit. */
  90. /* < 0: if INFO = -i, the i-th argument had an illegal value. */
  91. /* > 0: if INFO = 1, an singular value did not converge */
  92. /* Further Details */
  93. /* =============== */
  94. /* Based on contributions by */
  95. /* Ming Gu and Huan Ren, Computer Science Division, University of */
  96. /* California at Berkeley, USA */
  97. /* ===================================================================== */
  98. /* .. Local Scalars .. */
  99. /* .. */
  100. /* .. External Subroutines .. */
  101. /* .. */
  102. /* .. Executable Statements .. */
  103. /* Test the input parameters. */
  104. /* Parameter adjustments */
  105. --d__;
  106. --e;
  107. u_dim1 = *ldu;
  108. u_offset = 1 + u_dim1;
  109. u -= u_offset;
  110. vt_dim1 = *ldvt;
  111. vt_offset = 1 + vt_dim1;
  112. vt -= vt_offset;
  113. --iwork;
  114. --work;
  115. /* Function Body */
  116. *info = 0;
  117. if (*n < 0) {
  118. *info = -1;
  119. } else if (*sqre < 0 || *sqre > 1) {
  120. *info = -2;
  121. }
  122. m = *n + *sqre;
  123. if (*ldu < *n) {
  124. *info = -6;
  125. } else if (*ldvt < m) {
  126. *info = -8;
  127. } else if (*smlsiz < 3) {
  128. *info = -9;
  129. }
  130. if (*info != 0) {
  131. i__1 = -(*info);
  132. _starpu_xerbla_("DLASD0", &i__1);
  133. return 0;
  134. }
  135. /* If the input matrix is too small, call DLASDQ to find the SVD. */
  136. if (*n <= *smlsiz) {
  137. _starpu_dlasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset],
  138. ldvt, &u[u_offset], ldu, &u[u_offset], ldu, &work[1], info);
  139. return 0;
  140. }
  141. /* Set up the computation tree. */
  142. inode = 1;
  143. ndiml = inode + *n;
  144. ndimr = ndiml + *n;
  145. idxq = ndimr + *n;
  146. iwk = idxq + *n;
  147. _starpu_dlasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr],
  148. smlsiz);
  149. /* For the nodes on bottom level of the tree, solve */
  150. /* their subproblems by DLASDQ. */
  151. ndb1 = (nd + 1) / 2;
  152. ncc = 0;
  153. i__1 = nd;
  154. for (i__ = ndb1; i__ <= i__1; ++i__) {
  155. /* IC : center row of each node */
  156. /* NL : number of rows of left subproblem */
  157. /* NR : number of rows of right subproblem */
  158. /* NLF: starting row of the left subproblem */
  159. /* NRF: starting row of the right subproblem */
  160. i1 = i__ - 1;
  161. ic = iwork[inode + i1];
  162. nl = iwork[ndiml + i1];
  163. nlp1 = nl + 1;
  164. nr = iwork[ndimr + i1];
  165. nrp1 = nr + 1;
  166. nlf = ic - nl;
  167. nrf = ic + 1;
  168. sqrei = 1;
  169. _starpu_dlasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &vt[
  170. nlf + nlf * vt_dim1], ldvt, &u[nlf + nlf * u_dim1], ldu, &u[
  171. nlf + nlf * u_dim1], ldu, &work[1], info);
  172. if (*info != 0) {
  173. return 0;
  174. }
  175. itemp = idxq + nlf - 2;
  176. i__2 = nl;
  177. for (j = 1; j <= i__2; ++j) {
  178. iwork[itemp + j] = j;
  179. /* L10: */
  180. }
  181. if (i__ == nd) {
  182. sqrei = *sqre;
  183. } else {
  184. sqrei = 1;
  185. }
  186. nrp1 = nr + sqrei;
  187. _starpu_dlasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &vt[
  188. nrf + nrf * vt_dim1], ldvt, &u[nrf + nrf * u_dim1], ldu, &u[
  189. nrf + nrf * u_dim1], ldu, &work[1], info);
  190. if (*info != 0) {
  191. return 0;
  192. }
  193. itemp = idxq + ic;
  194. i__2 = nr;
  195. for (j = 1; j <= i__2; ++j) {
  196. iwork[itemp + j - 1] = j;
  197. /* L20: */
  198. }
  199. /* L30: */
  200. }
  201. /* Now conquer each subproblem bottom-up. */
  202. for (lvl = nlvl; lvl >= 1; --lvl) {
  203. /* Find the first node LF and last node LL on the */
  204. /* current level LVL. */
  205. if (lvl == 1) {
  206. lf = 1;
  207. ll = 1;
  208. } else {
  209. i__1 = lvl - 1;
  210. lf = pow_ii(&c__2, &i__1);
  211. ll = (lf << 1) - 1;
  212. }
  213. i__1 = ll;
  214. for (i__ = lf; i__ <= i__1; ++i__) {
  215. im1 = i__ - 1;
  216. ic = iwork[inode + im1];
  217. nl = iwork[ndiml + im1];
  218. nr = iwork[ndimr + im1];
  219. nlf = ic - nl;
  220. if (*sqre == 0 && i__ == ll) {
  221. sqrei = *sqre;
  222. } else {
  223. sqrei = 1;
  224. }
  225. idxqc = idxq + nlf - 1;
  226. alpha = d__[ic];
  227. beta = e[ic];
  228. _starpu_dlasd1_(&nl, &nr, &sqrei, &d__[nlf], &alpha, &beta, &u[nlf + nlf *
  229. u_dim1], ldu, &vt[nlf + nlf * vt_dim1], ldvt, &iwork[
  230. idxqc], &iwork[iwk], &work[1], info);
  231. if (*info != 0) {
  232. return 0;
  233. }
  234. /* L40: */
  235. }
  236. /* L50: */
  237. }
  238. return 0;
  239. /* End of DLASD0 */
  240. } /* _starpu_dlasd0_ */