3 /* Table of constant values */
5 static integer c__1 = 1;
6 static real c_b6 = 0.f;
7 static integer c__0 = 0;
8 static real c_b11 = 1.f;
10 /* Subroutine */ int slalsd_(char *uplo, integer *smlsiz, integer *n, integer
11 *nrhs, real *d__, real *e, real *b, integer *ldb, real *rcond,
12 integer *rank, real *work, integer *iwork, integer *info)
14 /* System generated locals */
15 integer b_dim1, b_offset, i__1, i__2;
18 /* Builtin functions */
19 double log(doublereal), r_sign(real *, real *);
22 integer c__, i__, j, k;
28 integer st, vt, nm1, st1;
34 integer perm, nsub, nlvl, sqre, bxst;
35 extern /* Subroutine */ int srot_(integer *, real *, integer *, real *,
36 integer *, real *, real *), sgemm_(char *, char *, integer *,
37 integer *, integer *, real *, real *, integer *, real *, integer *
38 , real *, real *, integer *);
39 integer poles, sizei, nsize;
40 extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *,
42 integer nwork, icmpq1, icmpq2;
43 extern doublereal slamch_(char *);
44 extern /* Subroutine */ int slasda_(integer *, integer *, integer *,
45 integer *, real *, real *, real *, integer *, real *, integer *,
46 real *, real *, real *, real *, integer *, integer *, integer *,
47 integer *, real *, real *, real *, real *, integer *, integer *),
48 xerbla_(char *, integer *), slalsa_(integer *, integer *,
49 integer *, integer *, real *, integer *, real *, integer *, real *
50 , integer *, real *, integer *, real *, real *, real *, real *,
51 integer *, integer *, integer *, integer *, real *, real *, real *
52 , real *, integer *, integer *), slascl_(char *, integer *,
53 integer *, real *, real *, integer *, integer *, real *, integer *
56 extern integer isamax_(integer *, real *, integer *);
57 extern /* Subroutine */ int slasdq_(char *, integer *, integer *, integer
58 *, integer *, integer *, real *, real *, real *, integer *, real *
59 , integer *, real *, integer *, real *, integer *),
60 slacpy_(char *, integer *, integer *, real *, integer *, real *,
61 integer *), slartg_(real *, real *, real *, real *, real *
62 ), slaset_(char *, integer *, integer *, real *, real *, real *,
66 extern doublereal slanst_(char *, integer *, real *, real *);
67 extern /* Subroutine */ int slasrt_(char *, integer *, real *, integer *);
68 integer givptr, smlszp;
71 /* -- LAPACK routine (version 3.1) -- */
72 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
75 /* .. Scalar Arguments .. */
77 /* .. Array Arguments .. */
83 /* SLALSD uses the singular value decomposition of A to solve the least */
84 /* squares problem of finding X to minimize the Euclidean norm of each */
85 /* column of A*X-B, where A is N-by-N upper bidiagonal, and X and B */
86 /* are N-by-NRHS. The solution X overwrites B. */
88 /* The singular values of A smaller than RCOND times the largest */
89 /* singular value are treated as zero in solving the least squares */
90 /* problem; in this case a minimum norm solution is returned. */
91 /* The actual singular values are returned in D in ascending order. */
93 /* This code makes very mild assumptions about floating point */
94 /* arithmetic. It will work on machines with a guard digit in */
95 /* add/subtract, or on those binary machines without guard digits */
96 /* which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2. */
97 /* It could conceivably fail on hexadecimal or decimal machines */
98 /* without guard digits, but we know of none. */
103 /* UPLO (input) CHARACTER*1 */
104 /* = 'U': D and E define an upper bidiagonal matrix. */
105 /* = 'L': D and E define a lower bidiagonal matrix. */
107 /* SMLSIZ (input) INTEGER */
108 /* The maximum size of the subproblems at the bottom of the */
109 /* computation tree. */
111 /* N (input) INTEGER */
112 /* The dimension of the bidiagonal matrix. N >= 0. */
114 /* NRHS (input) INTEGER */
115 /* The number of columns of B. NRHS must be at least 1. */
117 /* D (input/output) REAL array, dimension (N) */
118 /* On entry D contains the main diagonal of the bidiagonal */
119 /* matrix. On exit, if INFO = 0, D contains its singular values. */
121 /* E (input/output) REAL array, dimension (N-1) */
122 /* Contains the super-diagonal entries of the bidiagonal matrix. */
123 /* On exit, E has been destroyed. */
125 /* B (input/output) REAL array, dimension (LDB,NRHS) */
126 /* On input, B contains the right hand sides of the least */
127 /* squares problem. On output, B contains the solution X. */
129 /* LDB (input) INTEGER */
130 /* The leading dimension of B in the calling subprogram. */
131 /* LDB must be at least max(1,N). */
133 /* RCOND (input) REAL */
134 /* The singular values of A less than or equal to RCOND times */
135 /* the largest singular value are treated as zero in solving */
136 /* the least squares problem. If RCOND is negative, */
137 /* machine precision is used instead. */
138 /* For example, if diag(S)*X=B were the least squares problem, */
139 /* where diag(S) is a diagonal matrix of singular values, the */
140 /* solution would be X(i) = B(i) / S(i) if S(i) is greater than */
141 /* RCOND*max(S), and X(i) = 0 if S(i) is less than or equal to */
144 /* RANK (output) INTEGER */
145 /* The number of singular values of A greater than RCOND times */
146 /* the largest singular value. */
148 /* WORK (workspace) REAL array, dimension at least */
149 /* (9*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2), */
150 /* where NLVL = max(0, INT(log_2 (N/(SMLSIZ+1))) + 1). */
152 /* IWORK (workspace) INTEGER array, dimension at least */
153 /* (3*N*NLVL + 11*N) */
155 /* INFO (output) INTEGER */
156 /* = 0: successful exit. */
157 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
158 /* > 0: The algorithm failed to compute an singular value while */
159 /* working on the submatrix lying in rows and columns */
160 /* INFO/(N+1) through MOD(INFO,N+1). */
162 /* Further Details */
163 /* =============== */
165 /* Based on contributions by */
166 /* Ming Gu and Ren-Cang Li, Computer Science Division, University of */
167 /* California at Berkeley, USA */
168 /* Osni Marques, LBNL/NERSC, USA */
170 /* ===================================================================== */
172 /* .. Parameters .. */
174 /* .. Local Scalars .. */
176 /* .. External Functions .. */
178 /* .. External Subroutines .. */
180 /* .. Intrinsic Functions .. */
182 /* .. Executable Statements .. */
184 /* Test the input parameters. */
186 /* Parameter adjustments */
190 b_offset = 1 + b_dim1;
200 } else if (*nrhs < 1) {
202 } else if (*ldb < 1 || *ldb < *n) {
207 xerbla_("SLALSD", &i__1);
211 eps = slamch_("Epsilon");
213 /* Set up the tolerance. */
215 if (*rcond <= 0.f || *rcond >= 1.f) {
223 /* Quick return if possible. */
227 } else if (*n == 1) {
229 slaset_("A", &c__1, nrhs, &c_b6, &c_b6, &b[b_offset], ldb);
232 slascl_("G", &c__0, &c__0, &d__[1], &c_b11, &c__1, nrhs, &b[
233 b_offset], ldb, info);
234 d__[1] = dabs(d__[1]);
239 /* Rotate the matrix if it is lower bidiagonal. */
241 if (*(unsigned char *)uplo == 'L') {
243 for (i__ = 1; i__ <= i__1; ++i__) {
244 slartg_(&d__[i__], &e[i__], &cs, &sn, &r__);
246 e[i__] = sn * d__[i__ + 1];
247 d__[i__ + 1] = cs * d__[i__ + 1];
249 srot_(&c__1, &b[i__ + b_dim1], &c__1, &b[i__ + 1 + b_dim1], &
252 work[(i__ << 1) - 1] = cs;
259 for (i__ = 1; i__ <= i__1; ++i__) {
261 for (j = 1; j <= i__2; ++j) {
262 cs = work[(j << 1) - 1];
264 srot_(&c__1, &b[j + i__ * b_dim1], &c__1, &b[j + 1 + i__ *
265 b_dim1], &c__1, &cs, &sn);
276 orgnrm = slanst_("M", n, &d__[1], &e[1]);
278 slaset_("A", n, nrhs, &c_b6, &c_b6, &b[b_offset], ldb);
282 slascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, &c__1, &d__[1], n, info);
283 slascl_("G", &c__0, &c__0, &orgnrm, &c_b11, &nm1, &c__1, &e[1], &nm1,
286 /* If N is smaller than the minimum divide size SMLSIZ, then solve */
287 /* the problem with another solver. */
291 slaset_("A", n, n, &c_b6, &c_b11, &work[1], n);
292 slasdq_("U", &c__0, n, n, &c__0, nrhs, &d__[1], &e[1], &work[1], n, &
293 work[1], n, &b[b_offset], ldb, &work[nwork], info);
297 tol = rcnd * (r__1 = d__[isamax_(n, &d__[1], &c__1)], dabs(r__1));
299 for (i__ = 1; i__ <= i__1; ++i__) {
300 if (d__[i__] <= tol) {
301 slaset_("A", &c__1, nrhs, &c_b6, &c_b6, &b[i__ + b_dim1], ldb);
303 slascl_("G", &c__0, &c__0, &d__[i__], &c_b11, &c__1, nrhs, &b[
304 i__ + b_dim1], ldb, info);
309 sgemm_("T", "N", n, nrhs, n, &c_b11, &work[1], n, &b[b_offset], ldb, &
310 c_b6, &work[nwork], n);
311 slacpy_("A", n, nrhs, &work[nwork], n, &b[b_offset], ldb);
315 slascl_("G", &c__0, &c__0, &c_b11, &orgnrm, n, &c__1, &d__[1], n,
317 slasrt_("D", n, &d__[1], info);
318 slascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, nrhs, &b[b_offset],
324 /* Book-keeping and setting up some constants. */
326 nlvl = (integer) (log((real) (*n) / (real) (*smlsiz + 1)) / log(2.f)) + 1;
328 smlszp = *smlsiz + 1;
331 vt = *smlsiz * *n + 1;
332 difl = vt + smlszp * *n;
333 difr = difl + nlvl * *n;
334 z__ = difr + (nlvl * *n << 1);
335 c__ = z__ + nlvl * *n;
338 givnum = poles + (nlvl << 1) * *n;
339 bx = givnum + (nlvl << 1) * *n;
340 nwork = bx + *n * *nrhs;
346 givcol = perm + nlvl * *n;
347 iwk = givcol + (nlvl * *n << 1);
356 for (i__ = 1; i__ <= i__1; ++i__) {
357 if ((r__1 = d__[i__], dabs(r__1)) < eps) {
358 d__[i__] = r_sign(&eps, &d__[i__]);
364 for (i__ = 1; i__ <= i__1; ++i__) {
365 if ((r__1 = e[i__], dabs(r__1)) < eps || i__ == nm1) {
369 /* Subproblem found. First determine its size and then */
370 /* apply divide and conquer on it. */
374 /* A subproblem with E(I) small for I < NM1. */
376 nsize = i__ - st + 1;
377 iwork[sizei + nsub - 1] = nsize;
378 } else if ((r__1 = e[i__], dabs(r__1)) >= eps) {
380 /* A subproblem with E(NM1) not too small but I = NM1. */
383 iwork[sizei + nsub - 1] = nsize;
386 /* A subproblem with E(NM1) small. This implies an */
387 /* 1-by-1 subproblem at D(N), which is not solved */
390 nsize = i__ - st + 1;
391 iwork[sizei + nsub - 1] = nsize;
394 iwork[sizei + nsub - 1] = 1;
395 scopy_(nrhs, &b[*n + b_dim1], ldb, &work[bx + nm1], n);
400 /* This is a 1-by-1 subproblem and is not solved */
403 scopy_(nrhs, &b[st + b_dim1], ldb, &work[bx + st1], n);
404 } else if (nsize <= *smlsiz) {
406 /* This is a small subproblem and is solved by SLASDQ. */
408 slaset_("A", &nsize, &nsize, &c_b6, &c_b11, &work[vt + st1],
410 slasdq_("U", &c__0, &nsize, &nsize, &c__0, nrhs, &d__[st], &e[
411 st], &work[vt + st1], n, &work[nwork], n, &b[st +
412 b_dim1], ldb, &work[nwork], info);
416 slacpy_("A", &nsize, nrhs, &b[st + b_dim1], ldb, &work[bx +
420 /* A large problem. Solve it using divide and conquer. */
422 slasda_(&icmpq1, smlsiz, &nsize, &sqre, &d__[st], &e[st], &
423 work[u + st1], n, &work[vt + st1], &iwork[k + st1], &
424 work[difl + st1], &work[difr + st1], &work[z__ + st1],
425 &work[poles + st1], &iwork[givptr + st1], &iwork[
426 givcol + st1], n, &iwork[perm + st1], &work[givnum +
427 st1], &work[c__ + st1], &work[s + st1], &work[nwork],
433 slalsa_(&icmpq2, smlsiz, &nsize, nrhs, &b[st + b_dim1], ldb, &
434 work[bxst], n, &work[u + st1], n, &work[vt + st1], &
435 iwork[k + st1], &work[difl + st1], &work[difr + st1],
436 &work[z__ + st1], &work[poles + st1], &iwork[givptr +
437 st1], &iwork[givcol + st1], n, &iwork[perm + st1], &
438 work[givnum + st1], &work[c__ + st1], &work[s + st1],
439 &work[nwork], &iwork[iwk], info);
449 /* Apply the singular values and treat the tiny ones as zero. */
451 tol = rcnd * (r__1 = d__[isamax_(n, &d__[1], &c__1)], dabs(r__1));
454 for (i__ = 1; i__ <= i__1; ++i__) {
456 /* Some of the elements in D can be negative because 1-by-1 */
457 /* subproblems were not solved explicitly. */
459 if ((r__1 = d__[i__], dabs(r__1)) <= tol) {
460 slaset_("A", &c__1, nrhs, &c_b6, &c_b6, &work[bx + i__ - 1], n);
463 slascl_("G", &c__0, &c__0, &d__[i__], &c_b11, &c__1, nrhs, &work[
464 bx + i__ - 1], n, info);
466 d__[i__] = (r__1 = d__[i__], dabs(r__1));
470 /* Now apply back the right singular vectors. */
474 for (i__ = 1; i__ <= i__1; ++i__) {
477 nsize = iwork[sizei + i__ - 1];
480 scopy_(nrhs, &work[bxst], n, &b[st + b_dim1], ldb);
481 } else if (nsize <= *smlsiz) {
482 sgemm_("T", "N", &nsize, nrhs, &nsize, &c_b11, &work[vt + st1], n,
483 &work[bxst], n, &c_b6, &b[st + b_dim1], ldb);
485 slalsa_(&icmpq2, smlsiz, &nsize, nrhs, &work[bxst], n, &b[st +
486 b_dim1], ldb, &work[u + st1], n, &work[vt + st1], &iwork[
487 k + st1], &work[difl + st1], &work[difr + st1], &work[z__
488 + st1], &work[poles + st1], &iwork[givptr + st1], &iwork[
489 givcol + st1], n, &iwork[perm + st1], &work[givnum + st1],
490 &work[c__ + st1], &work[s + st1], &work[nwork], &iwork[
499 /* Unscale and sort the singular values. */
501 slascl_("G", &c__0, &c__0, &c_b11, &orgnrm, n, &c__1, &d__[1], n, info);
502 slasrt_("D", n, &d__[1], info);
503 slascl_("G", &c__0, &c__0, &orgnrm, &c_b11, n, nrhs, &b[b_offset], ldb,