1 /* ../netlib/slasd1.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib;
2  on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */
3 #include "FLA_f2c.h" /* Table of constant values */
4 static integer c__0 = 0;
5 static real c_b7 = 1.f;
6 static integer c__1 = 1;
7 static integer c_n1 = -1;
8 /* > \brief \b SLASD1 computes the SVD of an upper bidiagonal matrix B of the specified size. Used by sbdsdc. */
9 /* =========== DOCUMENTATION =========== */
10 /* Online html documentation available at */
11 /* http://www.netlib.org/lapack/explore-html/ */
12 /* > \htmlonly */
13 /* > Download SLASD1 + dependencies */
14 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slasd1. f"> */
15 /* > [TGZ]</a> */
16 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slasd1. f"> */
17 /* > [ZIP]</a> */
18 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slasd1. f"> */
19 /* > [TXT]</a> */
20 /* > \endhtmlonly */
21 /* Definition: */
22 /* =========== */
23 /* SUBROUTINE SLASD1( NL, NR, SQRE, D, ALPHA, BETA, U, LDU, VT, LDVT, */
24 /* IDXQ, IWORK, WORK, INFO ) */
25 /* .. Scalar Arguments .. */
26 /* INTEGER INFO, LDU, LDVT, NL, NR, SQRE */
27 /* REAL ALPHA, BETA */
28 /* .. */
29 /* .. Array Arguments .. */
30 /* INTEGER IDXQ( * ), IWORK( * ) */
31 /* REAL D( * ), U( LDU, * ), VT( LDVT, * ), WORK( * ) */
32 /* .. */
33 /* > \par Purpose: */
34 /* ============= */
35 /* > */
36 /* > \verbatim */
37 /* > */
38 /* > SLASD1 computes the SVD of an upper bidiagonal N-by-M matrix B, */
39 /* > where N = NL + NR + 1 and M = N + SQRE. SLASD1 is called from SLASD0. */
40 /* > */
41 /* > A related subroutine SLASD7 handles the case in which the singular */
42 /* > values (and the singular vectors in factored form) are desired. */
43 /* > */
44 /* > SLASD1 computes the SVD as follows: */
45 /* > */
46 /* > ( D1(in) 0 0 0 ) */
47 /* > B = U(in) * ( Z1**T a Z2**T b ) * VT(in) */
48 /* > ( 0 0 D2(in) 0 ) */
49 /* > */
50 /* > = U(out) * ( D(out) 0) * VT(out) */
51 /* > */
52 /* > where Z**T = (Z1**T a Z2**T b) = u**T VT**T, and u is a vector of dimension M */
53 /* > with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros */
54 /* > elsewhere;
55 and the entry b is empty if SQRE = 0. */
56 /* > */
57 /* > The left singular vectors of the original matrix are stored in U, and */
58 /* > the transpose of the right singular vectors are stored in VT, and the */
59 /* > singular values are in D. The algorithm consists of three stages: */
60 /* > */
61 /* > The first stage consists of deflating the size of the problem */
62 /* > when there are multiple singular values or when there are zeros in */
63 /* > the Z vector. For each such occurence the dimension of the */
64 /* > secular equation problem is reduced by one. This stage is */
65 /* > performed by the routine SLASD2. */
66 /* > */
67 /* > The second stage consists of calculating the updated */
68 /* > singular values. This is done by finding the square roots of the */
69 /* > roots of the secular equation via the routine SLASD4 (as called */
70 /* > by SLASD3). This routine also calculates the singular vectors of */
71 /* > the current problem. */
72 /* > */
73 /* > The final stage consists of computing the updated singular vectors */
74 /* > directly using the updated singular values. The singular vectors */
75 /* > for the current problem are multiplied with the singular vectors */
76 /* > from the overall problem. */
77 /* > \endverbatim */
78 /* Arguments: */
79 /* ========== */
80 /* > \param[in] NL */
81 /* > \verbatim */
82 /* > NL is INTEGER */
83 /* > The row dimension of the upper block. NL >= 1. */
84 /* > \endverbatim */
85 /* > */
86 /* > \param[in] NR */
87 /* > \verbatim */
88 /* > NR is INTEGER */
89 /* > The row dimension of the lower block. NR >= 1. */
90 /* > \endverbatim */
91 /* > */
92 /* > \param[in] SQRE */
93 /* > \verbatim */
94 /* > SQRE is INTEGER */
95 /* > = 0: the lower block is an NR-by-NR square matrix. */
96 /* > = 1: the lower block is an NR-by-(NR+1) rectangular matrix. */
97 /* > */
98 /* > The bidiagonal matrix has row dimension N = NL + NR + 1, */
99 /* > and column dimension M = N + SQRE. */
100 /* > \endverbatim */
101 /* > */
102 /* > \param[in,out] D */
103 /* > \verbatim */
104 /* > D is REAL array, dimension (NL+NR+1). */
105 /* > N = NL+NR+1 */
106 /* > On entry D(1:NL,1:NL) contains the singular values of the */
107 /* > upper block;
108 and D(NL+2:N) contains the singular values of */
109 /* > the lower block. On exit D(1:N) contains the singular values */
110 /* > of the modified matrix. */
111 /* > \endverbatim */
112 /* > */
113 /* > \param[in,out] ALPHA */
114 /* > \verbatim */
115 /* > ALPHA is REAL */
116 /* > Contains the diagonal element associated with the added row. */
117 /* > \endverbatim */
118 /* > */
119 /* > \param[in,out] BETA */
120 /* > \verbatim */
121 /* > BETA is REAL */
122 /* > Contains the off-diagonal element associated with the added */
123 /* > row. */
124 /* > \endverbatim */
125 /* > */
126 /* > \param[in,out] U */
127 /* > \verbatim */
128 /* > U is REAL array, dimension (LDU,N) */
129 /* > On entry U(1:NL, 1:NL) contains the left singular vectors of */
130 /* > the upper block;
131 U(NL+2:N, NL+2:N) contains the left singular */
132 /* > vectors of the lower block. On exit U contains the left */
133 /* > singular vectors of the bidiagonal matrix. */
134 /* > \endverbatim */
135 /* > */
136 /* > \param[in] LDU */
137 /* > \verbatim */
138 /* > LDU is INTEGER */
139 /* > The leading dimension of the array U. LDU >= max( 1, N ). */
140 /* > \endverbatim */
141 /* > */
142 /* > \param[in,out] VT */
143 /* > \verbatim */
144 /* > VT is REAL array, dimension (LDVT,M) */
145 /* > where M = N + SQRE. */
146 /* > On entry VT(1:NL+1, 1:NL+1)**T contains the right singular */
147 /* > vectors of the upper block;
148 VT(NL+2:M, NL+2:M)**T contains */
149 /* > the right singular vectors of the lower block. On exit */
150 /* > VT**T contains the right singular vectors of the */
151 /* > bidiagonal matrix. */
152 /* > \endverbatim */
153 /* > */
154 /* > \param[in] LDVT */
155 /* > \verbatim */
156 /* > LDVT is INTEGER */
157 /* > The leading dimension of the array VT. LDVT >= max( 1, M ). */
158 /* > \endverbatim */
159 /* > */
160 /* > \param[out] IDXQ */
161 /* > \verbatim */
162 /* > IDXQ is INTEGER array, dimension (N) */
163 /* > This contains the permutation which will reintegrate the */
164 /* > subproblem just solved back into sorted order, i.e. */
165 /* > D( IDXQ( I = 1, N ) ) will be in ascending order. */
166 /* > \endverbatim */
167 /* > */
168 /* > \param[out] IWORK */
169 /* > \verbatim */
170 /* > IWORK is INTEGER array, dimension (4*N) */
171 /* > \endverbatim */
172 /* > */
173 /* > \param[out] WORK */
174 /* > \verbatim */
175 /* > WORK is REAL array, dimension (3*M**2+2*M) */
176 /* > \endverbatim */
177 /* > */
178 /* > \param[out] INFO */
179 /* > \verbatim */
180 /* > INFO is INTEGER */
181 /* > = 0: successful exit. */
182 /* > < 0: if INFO = -i, the i-th argument had an illegal value. */
183 /* > > 0: if INFO = 1, a singular value did not converge */
184 /* > \endverbatim */
185 /* Authors: */
186 /* ======== */
187 /* > \author Univ. of Tennessee */
188 /* > \author Univ. of California Berkeley */
189 /* > \author Univ. of Colorado Denver */
190 /* > \author NAG Ltd. */
191 /* > \date September 2012 */
192 /* > \ingroup auxOTHERauxiliary */
193 /* > \par Contributors: */
194 /* ================== */
195 /* > */
196 /* > Ming Gu and Huan Ren, Computer Science Division, University of */
197 /* > California at Berkeley, USA */
198 /* > */
199 /* ===================================================================== */
200 /* Subroutine */
slasd1_(integer * nl,integer * nr,integer * sqre,real * d__,real * alpha,real * beta,real * u,integer * ldu,real * vt,integer * ldvt,integer * idxq,integer * iwork,real * work,integer * info)201 int slasd1_(integer *nl, integer *nr, integer *sqre, real * d__, real *alpha, real *beta, real *u, integer *ldu, real *vt, integer *ldvt, integer *idxq, integer *iwork, real *work, integer * info)
202 {
203     /* System generated locals */
204     integer u_dim1, u_offset, vt_dim1, vt_offset, i__1;
205     real r__1, r__2;
206     /* Local variables */
207     integer i__, k, m, n, n1, n2, iq, iz, iu2, ldq, idx, ldu2, ivt2, idxc, idxp, ldvt2;
208     extern /* Subroutine */
209     int slasd2_(integer *, integer *, integer *, integer *, real *, real *, real *, real *, real *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *, integer *, integer *, integer *, integer *, integer *), slasd3_(integer *, integer *, integer *, integer *, real *, real *, integer *, real *, real *, integer *, real *, integer *, real * , integer *, real *, integer *, integer *, integer *, real *, integer *);
210     integer isigma;
211     extern /* Subroutine */
212     int xerbla_(char *, integer *), slascl_( char *, integer *, integer *, real *, real *, integer *, integer * , real *, integer *, integer *), slamrg_(integer *, integer *, real *, integer *, integer *, integer *);
213     real orgnrm;
214     integer coltyp;
215     /* -- LAPACK auxiliary routine (version 3.4.2) -- */
216     /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
217     /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
218     /* September 2012 */
219     /* .. Scalar Arguments .. */
220     /* .. */
221     /* .. Array Arguments .. */
222     /* .. */
223     /* ===================================================================== */
224     /* .. Parameters .. */
225     /* .. */
226     /* .. Local Scalars .. */
227     /* .. */
228     /* .. External Subroutines .. */
229     /* .. */
230     /* .. Intrinsic Functions .. */
231     /* .. */
232     /* .. Executable Statements .. */
233     /* Test the input parameters. */
234     /* Parameter adjustments */
235     --d__;
236     u_dim1 = *ldu;
237     u_offset = 1 + u_dim1;
238     u -= u_offset;
239     vt_dim1 = *ldvt;
240     vt_offset = 1 + vt_dim1;
241     vt -= vt_offset;
242     --idxq;
243     --iwork;
244     --work;
245     /* Function Body */
246     *info = 0;
247     if (*nl < 1)
248     {
249         *info = -1;
250     }
251     else if (*nr < 1)
252     {
253         *info = -2;
254     }
255     else if (*sqre < 0 || *sqre > 1)
256     {
257         *info = -3;
258     }
259     if (*info != 0)
260     {
261         i__1 = -(*info);
262         xerbla_("SLASD1", &i__1);
263         return 0;
264     }
265     n = *nl + *nr + 1;
266     m = n + *sqre;
267     /* The following values are for bookkeeping purposes only. They are */
268     /* integer pointers which indicate the portion of the workspace */
269     /* used by a particular array in SLASD2 and SLASD3. */
270     ldu2 = n;
271     ldvt2 = m;
272     iz = 1;
273     isigma = iz + m;
274     iu2 = isigma + n;
275     ivt2 = iu2 + ldu2 * n;
276     iq = ivt2 + ldvt2 * m;
277     idx = 1;
278     idxc = idx + n;
279     coltyp = idxc + n;
280     idxp = coltyp + n;
281     /* Scale. */
282     /* Computing MAX */
283     r__1 = f2c_abs(*alpha);
284     r__2 = f2c_abs(*beta); // , expr subst
285     orgnrm = max(r__1,r__2);
286     d__[*nl + 1] = 0.f;
287     i__1 = n;
288     for (i__ = 1;
289             i__ <= i__1;
290             ++i__)
291     {
292         if ((r__1 = d__[i__], f2c_abs(r__1)) > orgnrm)
293         {
294             orgnrm = (r__1 = d__[i__], f2c_abs(r__1));
295         }
296         /* L10: */
297     }
298     slascl_("G", &c__0, &c__0, &orgnrm, &c_b7, &n, &c__1, &d__[1], &n, info);
299     *alpha /= orgnrm;
300     *beta /= orgnrm;
301     /* Deflate singular values. */
302     slasd2_(nl, nr, sqre, &k, &d__[1], &work[iz], alpha, beta, &u[u_offset], ldu, &vt[vt_offset], ldvt, &work[isigma], &work[iu2], &ldu2, & work[ivt2], &ldvt2, &iwork[idxp], &iwork[idx], &iwork[idxc], & idxq[1], &iwork[coltyp], info);
303     /* Solve Secular Equation and update singular vectors. */
304     ldq = k;
305     slasd3_(nl, nr, sqre, &k, &d__[1], &work[iq], &ldq, &work[isigma], &u[ u_offset], ldu, &work[iu2], &ldu2, &vt[vt_offset], ldvt, &work[ ivt2], &ldvt2, &iwork[idxc], &iwork[coltyp], &work[iz], info);
306     if (*info != 0)
307     {
308         return 0;
309     }
310     /* Unscale. */
311     slascl_("G", &c__0, &c__0, &c_b7, &orgnrm, &n, &c__1, &d__[1], &n, info);
312     /* Prepare the IDXQ sorting permutation. */
313     n1 = k;
314     n2 = n - k;
315     slamrg_(&n1, &n2, &d__[1], &c__1, &c_n1, &idxq[1]);
316     return 0;
317     /* End of SLASD1 */
318 }
319 /* slasd1_ */
320