3 /* Table of constant values */
5 static real c_b5 = -1.f;
6 static integer c__1 = 1;
7 static real c_b11 = 1.f;
8 static real c_b13 = 0.f;
9 static integer c__0 = 0;
11 /* Subroutine */ int slals0_(integer *icompq, integer *nl, integer *nr,
12 integer *sqre, integer *nrhs, real *b, integer *ldb, real *bx,
13 integer *ldbx, integer *perm, integer *givptr, integer *givcol,
14 integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
15 difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
18 /* System generated locals */
19 integer givcol_dim1, givcol_offset, b_dim1, b_offset, bx_dim1, bx_offset,
20 difr_dim1, difr_offset, givnum_dim1, givnum_offset, poles_dim1,
21 poles_offset, i__1, i__2;
29 extern /* Subroutine */ int srot_(integer *, real *, integer *, real *,
30 integer *, real *, real *);
31 extern doublereal snrm2_(integer *, real *, integer *);
32 real diflj, difrj, dsigj;
33 extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *),
34 sgemv_(char *, integer *, integer *, real *, real *, integer *,
35 real *, integer *, real *, real *, integer *), scopy_(
36 integer *, real *, integer *, real *, integer *);
37 extern doublereal slamc3_(real *, real *);
38 extern /* Subroutine */ int xerbla_(char *, integer *);
40 extern /* Subroutine */ int slascl_(char *, integer *, integer *, real *,
41 real *, integer *, integer *, real *, integer *, integer *), slacpy_(char *, integer *, integer *, real *, integer *,
45 /* -- LAPACK routine (version 3.1) -- */
46 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
49 /* .. Scalar Arguments .. */
51 /* .. Array Arguments .. */
57 /* SLALS0 applies back the multiplying factors of either the left or the */
58 /* right singular vector matrix of a diagonal matrix appended by a row */
59 /* to the right hand side matrix B in solving the least squares problem */
60 /* using the divide-and-conquer SVD approach. */
62 /* For the left singular vector matrix, three types of orthogonal */
63 /* matrices are involved: */
65 /* (1L) Givens rotations: the number of such rotations is GIVPTR; the */
66 /* pairs of columns/rows they were applied to are stored in GIVCOL; */
67 /* and the C- and S-values of these rotations are stored in GIVNUM. */
69 /* (2L) Permutation. The (NL+1)-st row of B is to be moved to the first */
70 /* row, and for J=2:N, PERM(J)-th row of B is to be moved to the */
73 /* (3L) The left singular vector matrix of the remaining matrix. */
75 /* For the right singular vector matrix, four types of orthogonal */
76 /* matrices are involved: */
78 /* (1R) The right singular vector matrix of the remaining matrix. */
80 /* (2R) If SQRE = 1, one extra Givens rotation to generate the right */
83 /* (3R) The inverse transformation of (2L). */
85 /* (4R) The inverse transformation of (1L). */
90 /* ICOMPQ (input) INTEGER */
91 /* Specifies whether singular vectors are to be computed in */
93 /* = 0: Left singular vector matrix. */
94 /* = 1: Right singular vector matrix. */
96 /* NL (input) INTEGER */
97 /* The row dimension of the upper block. NL >= 1. */
99 /* NR (input) INTEGER */
100 /* The row dimension of the lower block. NR >= 1. */
102 /* SQRE (input) INTEGER */
103 /* = 0: the lower block is an NR-by-NR square matrix. */
104 /* = 1: the lower block is an NR-by-(NR+1) rectangular matrix. */
106 /* The bidiagonal matrix has row dimension N = NL + NR + 1, */
107 /* and column dimension M = N + SQRE. */
109 /* NRHS (input) INTEGER */
110 /* The number of columns of B and BX. NRHS must be at least 1. */
112 /* B (input/output) REAL array, dimension ( LDB, NRHS ) */
113 /* On input, B contains the right hand sides of the least */
114 /* squares problem in rows 1 through M. On output, B contains */
115 /* the solution X in rows 1 through N. */
117 /* LDB (input) INTEGER */
118 /* The leading dimension of B. LDB must be at least */
119 /* max(1,MAX( M, N ) ). */
121 /* BX (workspace) REAL array, dimension ( LDBX, NRHS ) */
123 /* LDBX (input) INTEGER */
124 /* The leading dimension of BX. */
126 /* PERM (input) INTEGER array, dimension ( N ) */
127 /* The permutations (from deflation and sorting) applied */
128 /* to the two blocks. */
130 /* GIVPTR (input) INTEGER */
131 /* The number of Givens rotations which took place in this */
134 /* GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 ) */
135 /* Each pair of numbers indicates a pair of rows/columns */
136 /* involved in a Givens rotation. */
138 /* LDGCOL (input) INTEGER */
139 /* The leading dimension of GIVCOL, must be at least N. */
141 /* GIVNUM (input) REAL array, dimension ( LDGNUM, 2 ) */
142 /* Each number indicates the C or S value used in the */
143 /* corresponding Givens rotation. */
145 /* LDGNUM (input) INTEGER */
146 /* The leading dimension of arrays DIFR, POLES and */
147 /* GIVNUM, must be at least K. */
149 /* POLES (input) REAL array, dimension ( LDGNUM, 2 ) */
150 /* On entry, POLES(1:K, 1) contains the new singular */
151 /* values obtained from solving the secular equation, and */
152 /* POLES(1:K, 2) is an array containing the poles in the secular */
155 /* DIFL (input) REAL array, dimension ( K ). */
156 /* On entry, DIFL(I) is the distance between I-th updated */
157 /* (undeflated) singular value and the I-th (undeflated) old */
158 /* singular value. */
160 /* DIFR (input) REAL array, dimension ( LDGNUM, 2 ). */
161 /* On entry, DIFR(I, 1) contains the distances between I-th */
162 /* updated (undeflated) singular value and the I+1-th */
163 /* (undeflated) old singular value. And DIFR(I, 2) is the */
164 /* normalizing factor for the I-th right singular vector. */
166 /* Z (input) REAL array, dimension ( K ) */
167 /* Contain the components of the deflation-adjusted updating row */
170 /* K (input) INTEGER */
171 /* Contains the dimension of the non-deflated matrix, */
172 /* This is the order of the related secular equation. 1 <= K <=N. */
175 /* C contains garbage if SQRE =0 and the C-value of a Givens */
176 /* rotation related to the right null space if SQRE = 1. */
179 /* S contains garbage if SQRE =0 and the S-value of a Givens */
180 /* rotation related to the right null space if SQRE = 1. */
182 /* WORK (workspace) REAL array, dimension ( K ) */
184 /* INFO (output) INTEGER */
185 /* = 0: successful exit. */
186 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
188 /* Further Details */
189 /* =============== */
191 /* Based on contributions by */
192 /* Ming Gu and Ren-Cang Li, Computer Science Division, University of */
193 /* California at Berkeley, USA */
194 /* Osni Marques, LBNL/NERSC, USA */
196 /* ===================================================================== */
198 /* .. Parameters .. */
200 /* .. Local Scalars .. */
202 /* .. External Subroutines .. */
204 /* .. External Functions .. */
206 /* .. Intrinsic Functions .. */
208 /* .. Executable Statements .. */
210 /* Test the input parameters. */
212 /* Parameter adjustments */
214 b_offset = 1 + b_dim1;
217 bx_offset = 1 + bx_dim1;
220 givcol_dim1 = *ldgcol;
221 givcol_offset = 1 + givcol_dim1;
222 givcol -= givcol_offset;
224 difr_offset = 1 + difr_dim1;
226 poles_dim1 = *ldgnum;
227 poles_offset = 1 + poles_dim1;
228 poles -= poles_offset;
229 givnum_dim1 = *ldgnum;
230 givnum_offset = 1 + givnum_dim1;
231 givnum -= givnum_offset;
239 if (*icompq < 0 || *icompq > 1) {
241 } else if (*nl < 1) {
243 } else if (*nr < 1) {
245 } else if (*sqre < 0 || *sqre > 1) {
253 } else if (*ldb < n) {
255 } else if (*ldbx < n) {
257 } else if (*givptr < 0) {
259 } else if (*ldgcol < n) {
261 } else if (*ldgnum < n) {
268 xerbla_("SLALS0", &i__1);
277 /* Apply back orthogonal transformations from the left. */
279 /* Step (1L): apply back the Givens rotations performed. */
282 for (i__ = 1; i__ <= i__1; ++i__) {
283 srot_(nrhs, &b[givcol[i__ + (givcol_dim1 << 1)] + b_dim1], ldb, &
284 b[givcol[i__ + givcol_dim1] + b_dim1], ldb, &givnum[i__ +
285 (givnum_dim1 << 1)], &givnum[i__ + givnum_dim1]);
289 /* Step (2L): permute rows of B. */
291 scopy_(nrhs, &b[nlp1 + b_dim1], ldb, &bx[bx_dim1 + 1], ldbx);
293 for (i__ = 2; i__ <= i__1; ++i__) {
294 scopy_(nrhs, &b[perm[i__] + b_dim1], ldb, &bx[i__ + bx_dim1],
299 /* Step (3L): apply the inverse of the left singular vector */
303 scopy_(nrhs, &bx[bx_offset], ldbx, &b[b_offset], ldb);
305 sscal_(nrhs, &c_b5, &b[b_offset], ldb);
309 for (j = 1; j <= i__1; ++j) {
311 dj = poles[j + poles_dim1];
312 dsigj = -poles[j + (poles_dim1 << 1)];
314 difrj = -difr[j + difr_dim1];
315 dsigjp = -poles[j + 1 + (poles_dim1 << 1)];
317 if (z__[j] == 0.f || poles[j + (poles_dim1 << 1)] == 0.f) {
320 work[j] = -poles[j + (poles_dim1 << 1)] * z__[j] / diflj /
321 (poles[j + (poles_dim1 << 1)] + dj);
324 for (i__ = 1; i__ <= i__2; ++i__) {
325 if (z__[i__] == 0.f || poles[i__ + (poles_dim1 << 1)] ==
329 work[i__] = poles[i__ + (poles_dim1 << 1)] * z__[i__]
330 / (slamc3_(&poles[i__ + (poles_dim1 << 1)], &
331 dsigj) - diflj) / (poles[i__ + (poles_dim1 <<
337 for (i__ = j + 1; i__ <= i__2; ++i__) {
338 if (z__[i__] == 0.f || poles[i__ + (poles_dim1 << 1)] ==
342 work[i__] = poles[i__ + (poles_dim1 << 1)] * z__[i__]
343 / (slamc3_(&poles[i__ + (poles_dim1 << 1)], &
344 dsigjp) + difrj) / (poles[i__ + (poles_dim1 <<
350 temp = snrm2_(k, &work[1], &c__1);
351 sgemv_("T", k, nrhs, &c_b11, &bx[bx_offset], ldbx, &work[1], &
352 c__1, &c_b13, &b[j + b_dim1], ldb);
353 slascl_("G", &c__0, &c__0, &temp, &c_b11, &c__1, nrhs, &b[j +
359 /* Move the deflated rows of BX to B also. */
363 slacpy_("A", &i__1, nrhs, &bx[*k + 1 + bx_dim1], ldbx, &b[*k + 1
368 /* Apply back the right orthogonal transformations. */
370 /* Step (1R): apply back the new right singular vector matrix */
374 scopy_(nrhs, &b[b_offset], ldb, &bx[bx_offset], ldbx);
377 for (j = 1; j <= i__1; ++j) {
378 dsigj = poles[j + (poles_dim1 << 1)];
382 work[j] = -z__[j] / difl[j] / (dsigj + poles[j +
383 poles_dim1]) / difr[j + (difr_dim1 << 1)];
386 for (i__ = 1; i__ <= i__2; ++i__) {
390 r__1 = -poles[i__ + 1 + (poles_dim1 << 1)];
391 work[i__] = z__[j] / (slamc3_(&dsigj, &r__1) - difr[
392 i__ + difr_dim1]) / (dsigj + poles[i__ +
393 poles_dim1]) / difr[i__ + (difr_dim1 << 1)];
398 for (i__ = j + 1; i__ <= i__2; ++i__) {
402 r__1 = -poles[i__ + (poles_dim1 << 1)];
403 work[i__] = z__[j] / (slamc3_(&dsigj, &r__1) - difl[
404 i__]) / (dsigj + poles[i__ + poles_dim1]) /
405 difr[i__ + (difr_dim1 << 1)];
409 sgemv_("T", k, nrhs, &c_b11, &b[b_offset], ldb, &work[1], &
410 c__1, &c_b13, &bx[j + bx_dim1], ldbx);
415 /* Step (2R): if SQRE = 1, apply back the rotation that is */
416 /* related to the right null space of the subproblem. */
419 scopy_(nrhs, &b[m + b_dim1], ldb, &bx[m + bx_dim1], ldbx);
420 srot_(nrhs, &bx[bx_dim1 + 1], ldbx, &bx[m + bx_dim1], ldbx, c__,
425 slacpy_("A", &i__1, nrhs, &b[*k + 1 + b_dim1], ldb, &bx[*k + 1 +
429 /* Step (3R): permute rows of B. */
431 scopy_(nrhs, &bx[bx_dim1 + 1], ldbx, &b[nlp1 + b_dim1], ldb);
433 scopy_(nrhs, &bx[m + bx_dim1], ldbx, &b[m + b_dim1], ldb);
436 for (i__ = 2; i__ <= i__1; ++i__) {
437 scopy_(nrhs, &bx[i__ + bx_dim1], ldbx, &b[perm[i__] + b_dim1],
442 /* Step (4R): apply back the Givens rotations performed. */
444 for (i__ = *givptr; i__ >= 1; --i__) {
445 r__1 = -givnum[i__ + givnum_dim1];
446 srot_(nrhs, &b[givcol[i__ + (givcol_dim1 << 1)] + b_dim1], ldb, &
447 b[givcol[i__ + givcol_dim1] + b_dim1], ldb, &givnum[i__ +
448 (givnum_dim1 << 1)], &r__1);