3 /* Table of constant values */
5 static integer c__0 = 0;
6 static real c_b11 = 0.f;
7 static real c_b12 = 1.f;
8 static integer c__1 = 1;
9 static integer c__2 = 2;
11 /* Subroutine */ int slasda_(integer *icompq, integer *smlsiz, integer *n,
12 integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt,
13 integer *k, real *difl, real *difr, real *z__, real *poles, integer *
14 givptr, integer *givcol, integer *ldgcol, integer *perm, real *givnum,
15 real *c__, real *s, real *work, integer *iwork, integer *info)
17 /* System generated locals */
18 integer givcol_dim1, givcol_offset, perm_dim1, perm_offset, difl_dim1,
19 difl_offset, difr_dim1, difr_offset, givnum_dim1, givnum_offset,
20 poles_dim1, poles_offset, u_dim1, u_offset, vt_dim1, vt_offset,
21 z_dim1, z_offset, i__1, i__2;
23 /* Builtin functions */
24 integer pow_ii(integer *, integer *);
27 integer i__, j, m, i1, ic, lf, nd, ll, nl, vf, nr, vl, im1, ncc, nlf, nrf,
28 vfi, iwk, vli, lvl, nru, ndb1, nlp1, lvl2, nrp1;
32 integer inode, ndiml, ndimr, idxqi, itemp, sqrei;
33 extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *,
34 integer *), slasd6_(integer *, integer *, integer *, integer *,
35 real *, real *, real *, real *, real *, integer *, integer *,
36 integer *, integer *, integer *, real *, integer *, real *, real *
37 , real *, real *, integer *, real *, real *, real *, integer *,
39 integer nwork1, nwork2;
40 extern /* Subroutine */ int xerbla_(char *, integer *), slasdq_(
41 char *, integer *, integer *, integer *, integer *, integer *,
42 real *, real *, real *, integer *, real *, integer *, real *,
43 integer *, real *, integer *), slasdt_(integer *, integer
44 *, integer *, integer *, integer *, integer *, integer *),
45 slaset_(char *, integer *, integer *, real *, real *, real *,
50 /* -- LAPACK auxiliary routine (version 3.1) -- */
51 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
54 /* .. Scalar Arguments .. */
56 /* .. Array Arguments .. */
62 /* Using a divide and conquer approach, SLASDA computes the singular */
63 /* value decomposition (SVD) of a real upper bidiagonal N-by-M matrix */
64 /* B with diagonal D and offdiagonal E, where M = N + SQRE. The */
65 /* algorithm computes the singular values in the SVD B = U * S * VT. */
66 /* The orthogonal matrices U and VT are optionally computed in */
69 /* A related subroutine, SLASD0, computes the singular values and */
70 /* the singular vectors in explicit form. */
75 /* ICOMPQ (input) INTEGER */
76 /* Specifies whether singular vectors are to be computed */
77 /* in compact form, as follows */
78 /* = 0: Compute singular values only. */
79 /* = 1: Compute singular vectors of upper bidiagonal */
80 /* matrix in compact form. */
82 /* SMLSIZ (input) INTEGER */
83 /* The maximum size of the subproblems at the bottom of the */
84 /* computation tree. */
86 /* N (input) INTEGER */
87 /* The row dimension of the upper bidiagonal matrix. This is */
88 /* also the dimension of the main diagonal array D. */
90 /* SQRE (input) INTEGER */
91 /* Specifies the column dimension of the bidiagonal matrix. */
92 /* = 0: The bidiagonal matrix has column dimension M = N; */
93 /* = 1: The bidiagonal matrix has column dimension M = N + 1. */
95 /* D (input/output) REAL array, dimension ( N ) */
96 /* On entry D contains the main diagonal of the bidiagonal */
97 /* matrix. On exit D, if INFO = 0, contains its singular values. */
99 /* E (input) REAL array, dimension ( M-1 ) */
100 /* Contains the subdiagonal entries of the bidiagonal matrix. */
101 /* On exit, E has been destroyed. */
103 /* U (output) REAL array, */
104 /* dimension ( LDU, SMLSIZ ) if ICOMPQ = 1, and not referenced */
105 /* if ICOMPQ = 0. If ICOMPQ = 1, on exit, U contains the left */
106 /* singular vector matrices of all subproblems at the bottom */
109 /* LDU (input) INTEGER, LDU = > N. */
110 /* The leading dimension of arrays U, VT, DIFL, DIFR, POLES, */
113 /* VT (output) REAL array, */
114 /* dimension ( LDU, SMLSIZ+1 ) if ICOMPQ = 1, and not referenced */
115 /* if ICOMPQ = 0. If ICOMPQ = 1, on exit, VT' contains the right */
116 /* singular vector matrices of all subproblems at the bottom */
119 /* K (output) INTEGER array, dimension ( N ) */
120 /* if ICOMPQ = 1 and dimension 1 if ICOMPQ = 0. */
121 /* If ICOMPQ = 1, on exit, K(I) is the dimension of the I-th */
122 /* secular equation on the computation tree. */
124 /* DIFL (output) REAL array, dimension ( LDU, NLVL ), */
125 /* where NLVL = floor(log_2 (N/SMLSIZ))). */
127 /* DIFR (output) REAL array, */
128 /* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1 and */
129 /* dimension ( N ) if ICOMPQ = 0. */
130 /* If ICOMPQ = 1, on exit, DIFL(1:N, I) and DIFR(1:N, 2 * I - 1) */
131 /* record distances between singular values on the I-th */
132 /* level and singular values on the (I -1)-th level, and */
133 /* DIFR(1:N, 2 * I ) contains the normalizing factors for */
134 /* the right singular vector matrix. See SLASD8 for details. */
136 /* Z (output) REAL array, */
137 /* dimension ( LDU, NLVL ) if ICOMPQ = 1 and */
138 /* dimension ( N ) if ICOMPQ = 0. */
139 /* The first K elements of Z(1, I) contain the components of */
140 /* the deflation-adjusted updating row vector for subproblems */
141 /* on the I-th level. */
143 /* POLES (output) REAL array, */
144 /* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1, and not referenced */
145 /* if ICOMPQ = 0. If ICOMPQ = 1, on exit, POLES(1, 2*I - 1) and */
146 /* POLES(1, 2*I) contain the new and old singular values */
147 /* involved in the secular equations on the I-th level. */
149 /* GIVPTR (output) INTEGER array, */
150 /* dimension ( N ) if ICOMPQ = 1, and not referenced if */
151 /* ICOMPQ = 0. If ICOMPQ = 1, on exit, GIVPTR( I ) records */
152 /* the number of Givens rotations performed on the I-th */
153 /* problem on the computation tree. */
155 /* GIVCOL (output) INTEGER array, */
156 /* dimension ( LDGCOL, 2 * NLVL ) if ICOMPQ = 1, and not */
157 /* referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I, */
158 /* GIVCOL(1, 2 *I - 1) and GIVCOL(1, 2 *I) record the locations */
159 /* of Givens rotations performed on the I-th level on the */
160 /* computation tree. */
162 /* LDGCOL (input) INTEGER, LDGCOL = > N. */
163 /* The leading dimension of arrays GIVCOL and PERM. */
165 /* PERM (output) INTEGER array, dimension ( LDGCOL, NLVL ) */
166 /* if ICOMPQ = 1, and not referenced */
167 /* if ICOMPQ = 0. If ICOMPQ = 1, on exit, PERM(1, I) records */
168 /* permutations done on the I-th level of the computation tree. */
170 /* GIVNUM (output) REAL array, */
171 /* dimension ( LDU, 2 * NLVL ) if ICOMPQ = 1, and not */
172 /* referenced if ICOMPQ = 0. If ICOMPQ = 1, on exit, for each I, */
173 /* GIVNUM(1, 2 *I - 1) and GIVNUM(1, 2 *I) record the C- and S- */
174 /* values of Givens rotations performed on the I-th level on */
175 /* the computation tree. */
177 /* C (output) REAL array, */
178 /* dimension ( N ) if ICOMPQ = 1, and dimension 1 if ICOMPQ = 0. */
179 /* If ICOMPQ = 1 and the I-th subproblem is not square, on exit, */
180 /* C( I ) contains the C-value of a Givens rotation related to */
181 /* the right null space of the I-th subproblem. */
183 /* S (output) REAL array, dimension ( N ) if */
184 /* ICOMPQ = 1, and dimension 1 if ICOMPQ = 0. If ICOMPQ = 1 */
185 /* and the I-th subproblem is not square, on exit, S( I ) */
186 /* contains the S-value of a Givens rotation related to */
187 /* the right null space of the I-th subproblem. */
189 /* WORK (workspace) REAL array, dimension */
190 /* (6 * N + (SMLSIZ + 1)*(SMLSIZ + 1)). */
192 /* IWORK (workspace) INTEGER array, dimension (7*N). */
194 /* INFO (output) INTEGER */
195 /* = 0: successful exit. */
196 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
197 /* > 0: if INFO = 1, an singular value did not converge */
199 /* Further Details */
200 /* =============== */
202 /* Based on contributions by */
203 /* Ming Gu and Huan Ren, Computer Science Division, University of */
204 /* California at Berkeley, USA */
206 /* ===================================================================== */
208 /* .. Parameters .. */
210 /* .. Local Scalars .. */
212 /* .. External Subroutines .. */
214 /* .. Executable Statements .. */
216 /* Test the input parameters. */
218 /* Parameter adjustments */
222 givnum_offset = 1 + givnum_dim1;
223 givnum -= givnum_offset;
225 poles_offset = 1 + poles_dim1;
226 poles -= poles_offset;
228 z_offset = 1 + z_dim1;
231 difr_offset = 1 + difr_dim1;
234 difl_offset = 1 + difl_dim1;
237 vt_offset = 1 + vt_dim1;
240 u_offset = 1 + u_dim1;
245 perm_offset = 1 + perm_dim1;
247 givcol_dim1 = *ldgcol;
248 givcol_offset = 1 + givcol_dim1;
249 givcol -= givcol_offset;
258 if (*icompq < 0 || *icompq > 1) {
260 } else if (*smlsiz < 3) {
264 } else if (*sqre < 0 || *sqre > 1) {
266 } else if (*ldu < *n + *sqre) {
268 } else if (*ldgcol < *n) {
273 xerbla_("SLASDA", &i__1);
279 /* If the input matrix is too small, call SLASDQ to find the SVD. */
283 slasdq_("U", sqre, n, &c__0, &c__0, &c__0, &d__[1], &e[1], &vt[
284 vt_offset], ldu, &u[u_offset], ldu, &u[u_offset], ldu, &
287 slasdq_("U", sqre, n, &m, n, &c__0, &d__[1], &e[1], &vt[vt_offset]
288 , ldu, &u[u_offset], ldu, &u[u_offset], ldu, &work[1],
294 /* Book-keeping and set up the computation tree. */
305 smlszp = *smlsiz + 1;
309 nwork2 = nwork1 + smlszp * smlszp;
311 slasdt_(n, &nlvl, &nd, &iwork[inode], &iwork[ndiml], &iwork[ndimr],
314 /* for the nodes on bottom level of the tree, solve */
315 /* their subproblems by SLASDQ. */
319 for (i__ = ndb1; i__ <= i__1; ++i__) {
321 /* IC : center row of each node */
322 /* NL : number of rows of left subproblem */
323 /* NR : number of rows of right subproblem */
324 /* NLF: starting row of the left subproblem */
325 /* NRF: starting row of the right subproblem */
328 ic = iwork[inode + i1];
329 nl = iwork[ndiml + i1];
331 nr = iwork[ndimr + i1];
334 idxqi = idxq + nlf - 2;
339 slaset_("A", &nlp1, &nlp1, &c_b11, &c_b12, &work[nwork1], &smlszp);
340 slasdq_("U", &sqrei, &nl, &nlp1, &nru, &ncc, &d__[nlf], &e[nlf], &
341 work[nwork1], &smlszp, &work[nwork2], &nl, &work[nwork2],
342 &nl, &work[nwork2], info);
343 itemp = nwork1 + nl * smlszp;
344 scopy_(&nlp1, &work[nwork1], &c__1, &work[vfi], &c__1);
345 scopy_(&nlp1, &work[itemp], &c__1, &work[vli], &c__1);
347 slaset_("A", &nl, &nl, &c_b11, &c_b12, &u[nlf + u_dim1], ldu);
348 slaset_("A", &nlp1, &nlp1, &c_b11, &c_b12, &vt[nlf + vt_dim1],
350 slasdq_("U", &sqrei, &nl, &nlp1, &nl, &ncc, &d__[nlf], &e[nlf], &
351 vt[nlf + vt_dim1], ldu, &u[nlf + u_dim1], ldu, &u[nlf +
352 u_dim1], ldu, &work[nwork1], info);
353 scopy_(&nlp1, &vt[nlf + vt_dim1], &c__1, &work[vfi], &c__1);
354 scopy_(&nlp1, &vt[nlf + nlp1 * vt_dim1], &c__1, &work[vli], &c__1)
361 for (j = 1; j <= i__2; ++j) {
362 iwork[idxqi + j] = j;
365 if (i__ == nd && *sqre == 0) {
375 slaset_("A", &nrp1, &nrp1, &c_b11, &c_b12, &work[nwork1], &smlszp);
376 slasdq_("U", &sqrei, &nr, &nrp1, &nru, &ncc, &d__[nrf], &e[nrf], &
377 work[nwork1], &smlszp, &work[nwork2], &nr, &work[nwork2],
378 &nr, &work[nwork2], info);
379 itemp = nwork1 + (nrp1 - 1) * smlszp;
380 scopy_(&nrp1, &work[nwork1], &c__1, &work[vfi], &c__1);
381 scopy_(&nrp1, &work[itemp], &c__1, &work[vli], &c__1);
383 slaset_("A", &nr, &nr, &c_b11, &c_b12, &u[nrf + u_dim1], ldu);
384 slaset_("A", &nrp1, &nrp1, &c_b11, &c_b12, &vt[nrf + vt_dim1],
386 slasdq_("U", &sqrei, &nr, &nrp1, &nr, &ncc, &d__[nrf], &e[nrf], &
387 vt[nrf + vt_dim1], ldu, &u[nrf + u_dim1], ldu, &u[nrf +
388 u_dim1], ldu, &work[nwork1], info);
389 scopy_(&nrp1, &vt[nrf + vt_dim1], &c__1, &work[vfi], &c__1);
390 scopy_(&nrp1, &vt[nrf + nrp1 * vt_dim1], &c__1, &work[vli], &c__1)
397 for (j = 1; j <= i__2; ++j) {
398 iwork[idxqi + j] = j;
404 /* Now conquer each subproblem bottom-up. */
406 j = pow_ii(&c__2, &nlvl);
407 for (lvl = nlvl; lvl >= 1; --lvl) {
408 lvl2 = (lvl << 1) - 1;
410 /* Find the first node LF and last node LL on */
411 /* the current level LVL. */
418 lf = pow_ii(&c__2, &i__1);
422 for (i__ = lf; i__ <= i__1; ++i__) {
424 ic = iwork[inode + im1];
425 nl = iwork[ndiml + im1];
426 nr = iwork[ndimr + im1];
436 idxqi = idxq + nlf - 1;
440 slasd6_(icompq, &nl, &nr, &sqrei, &d__[nlf], &work[vfi], &
441 work[vli], &alpha, &beta, &iwork[idxqi], &perm[
442 perm_offset], &givptr[1], &givcol[givcol_offset],
443 ldgcol, &givnum[givnum_offset], ldu, &poles[
444 poles_offset], &difl[difl_offset], &difr[difr_offset],
445 &z__[z_offset], &k[1], &c__[1], &s[1], &work[nwork1],
449 slasd6_(icompq, &nl, &nr, &sqrei, &d__[nlf], &work[vfi], &
450 work[vli], &alpha, &beta, &iwork[idxqi], &perm[nlf +
451 lvl * perm_dim1], &givptr[j], &givcol[nlf + lvl2 *
452 givcol_dim1], ldgcol, &givnum[nlf + lvl2 *
453 givnum_dim1], ldu, &poles[nlf + lvl2 * poles_dim1], &
454 difl[nlf + lvl * difl_dim1], &difr[nlf + lvl2 *
455 difr_dim1], &z__[nlf + lvl * z_dim1], &k[j], &c__[j],
456 &s[j], &work[nwork1], &iwork[iwk], info);