00001 /* dlasd6.f -- translated by f2c (version 20061008). 00002 You must link the resulting object file with libf2c: 00003 on Microsoft Windows system, link with libf2c.lib; 00004 on Linux or Unix systems, link with .../path/to/libf2c.a -lm 00005 or, if you install libf2c.a in a standard place, with -lf2c -lm 00006 -- in that order, at the end of the command line, as in 00007 cc *.o -lf2c -lm 00008 Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., 00009 00010 http://www.netlib.org/f2c/libf2c.zip 00011 */ 00012 00013 #include "f2c.h" 00014 #include "blaswrap.h" 00015 00016 /* Table of constant values */ 00017 00018 static integer c__0 = 0; 00019 static doublereal c_b7 = 1.; 00020 static integer c__1 = 1; 00021 static integer c_n1 = -1; 00022 00023 /* Subroutine */ int dlasd6_(integer *icompq, integer *nl, integer *nr, 00024 integer *sqre, doublereal *d__, doublereal *vf, doublereal *vl, 00025 doublereal *alpha, doublereal *beta, integer *idxq, integer *perm, 00026 integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum, 00027 integer *ldgnum, doublereal *poles, doublereal *difl, doublereal * 00028 difr, doublereal *z__, integer *k, doublereal *c__, doublereal *s, 00029 doublereal *work, integer *iwork, integer *info) 00030 { 00031 /* System generated locals */ 00032 integer givcol_dim1, givcol_offset, givnum_dim1, givnum_offset, 00033 poles_dim1, poles_offset, i__1; 00034 doublereal d__1, d__2; 00035 00036 /* Local variables */ 00037 integer i__, m, n, n1, n2, iw, idx, idxc, idxp, ivfw, ivlw; 00038 extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 00039 doublereal *, integer *), dlasd7_(integer *, integer *, integer *, 00040 integer *, integer *, doublereal *, doublereal *, doublereal *, 00041 doublereal *, doublereal *, doublereal *, doublereal *, 00042 doublereal *, doublereal *, doublereal *, integer *, integer *, 00043 integer *, integer *, integer *, integer *, integer *, doublereal 00044 *, integer *, doublereal *, doublereal *, integer *), dlasd8_( 00045 integer *, integer *, doublereal *, doublereal *, doublereal *, 00046 doublereal *, doublereal *, doublereal *, integer *, doublereal *, 00047 doublereal *, integer *), dlascl_(char *, integer *, integer *, 00048 doublereal *, doublereal *, integer *, integer *, doublereal *, 00049 integer *, integer *), dlamrg_(integer *, integer *, 00050 doublereal *, integer *, integer *, integer *); 00051 integer isigma; 00052 extern /* Subroutine */ int xerbla_(char *, integer *); 00053 doublereal orgnrm; 00054 00055 00056 /* -- LAPACK auxiliary routine (version 3.2) -- */ 00057 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00058 /* November 2006 */ 00059 00060 /* .. Scalar Arguments .. */ 00061 /* .. */ 00062 /* .. Array Arguments .. */ 00063 /* .. */ 00064 00065 /* Purpose */ 00066 /* ======= */ 00067 00068 /* DLASD6 computes the SVD of an updated upper bidiagonal matrix B */ 00069 /* obtained by merging two smaller ones by appending a row. This */ 00070 /* routine is used only for the problem which requires all singular */ 00071 /* values and optionally singular vector matrices in factored form. */ 00072 /* B is an N-by-M matrix with N = NL + NR + 1 and M = N + SQRE. */ 00073 /* A related subroutine, DLASD1, handles the case in which all singular */ 00074 /* values and singular vectors of the bidiagonal matrix are desired. */ 00075 00076 /* DLASD6 computes the SVD as follows: */ 00077 00078 /* ( D1(in) 0 0 0 ) */ 00079 /* B = U(in) * ( Z1' a Z2' b ) * VT(in) */ 00080 /* ( 0 0 D2(in) 0 ) */ 00081 00082 /* = U(out) * ( D(out) 0) * VT(out) */ 00083 00084 /* where Z' = (Z1' a Z2' b) = u' VT', and u is a vector of dimension M */ 00085 /* with ALPHA and BETA in the NL+1 and NL+2 th entries and zeros */ 00086 /* elsewhere; and the entry b is empty if SQRE = 0. */ 00087 00088 /* The singular values of B can be computed using D1, D2, the first */ 00089 /* components of all the right singular vectors of the lower block, and */ 00090 /* the last components of all the right singular vectors of the upper */ 00091 /* block. These components are stored and updated in VF and VL, */ 00092 /* respectively, in DLASD6. Hence U and VT are not explicitly */ 00093 /* referenced. */ 00094 00095 /* The singular values are stored in D. The algorithm consists of two */ 00096 /* stages: */ 00097 00098 /* The first stage consists of deflating the size of the problem */ 00099 /* when there are multiple singular values or if there is a zero */ 00100 /* in the Z vector. For each such occurence the dimension of the */ 00101 /* secular equation problem is reduced by one. This stage is */ 00102 /* performed by the routine DLASD7. */ 00103 00104 /* The second stage consists of calculating the updated */ 00105 /* singular values. This is done by finding the roots of the */ 00106 /* secular equation via the routine DLASD4 (as called by DLASD8). */ 00107 /* This routine also updates VF and VL and computes the distances */ 00108 /* between the updated singular values and the old singular */ 00109 /* values. */ 00110 00111 /* DLASD6 is called from DLASDA. */ 00112 00113 /* Arguments */ 00114 /* ========= */ 00115 00116 /* ICOMPQ (input) INTEGER */ 00117 /* Specifies whether singular vectors are to be computed in */ 00118 /* factored form: */ 00119 /* = 0: Compute singular values only. */ 00120 /* = 1: Compute singular vectors in factored form as well. */ 00121 00122 /* NL (input) INTEGER */ 00123 /* The row dimension of the upper block. NL >= 1. */ 00124 00125 /* NR (input) INTEGER */ 00126 /* The row dimension of the lower block. NR >= 1. */ 00127 00128 /* SQRE (input) INTEGER */ 00129 /* = 0: the lower block is an NR-by-NR square matrix. */ 00130 /* = 1: the lower block is an NR-by-(NR+1) rectangular matrix. */ 00131 00132 /* The bidiagonal matrix has row dimension N = NL + NR + 1, */ 00133 /* and column dimension M = N + SQRE. */ 00134 00135 /* D (input/output) DOUBLE PRECISION array, dimension ( NL+NR+1 ). */ 00136 /* On entry D(1:NL,1:NL) contains the singular values of the */ 00137 /* upper block, and D(NL+2:N) contains the singular values */ 00138 /* of the lower block. On exit D(1:N) contains the singular */ 00139 /* values of the modified matrix. */ 00140 00141 /* VF (input/output) DOUBLE PRECISION array, dimension ( M ) */ 00142 /* On entry, VF(1:NL+1) contains the first components of all */ 00143 /* right singular vectors of the upper block; and VF(NL+2:M) */ 00144 /* contains the first components of all right singular vectors */ 00145 /* of the lower block. On exit, VF contains the first components */ 00146 /* of all right singular vectors of the bidiagonal matrix. */ 00147 00148 /* VL (input/output) DOUBLE PRECISION array, dimension ( M ) */ 00149 /* On entry, VL(1:NL+1) contains the last components of all */ 00150 /* right singular vectors of the upper block; and VL(NL+2:M) */ 00151 /* contains the last components of all right singular vectors of */ 00152 /* the lower block. On exit, VL contains the last components of */ 00153 /* all right singular vectors of the bidiagonal matrix. */ 00154 00155 /* ALPHA (input/output) DOUBLE PRECISION */ 00156 /* Contains the diagonal element associated with the added row. */ 00157 00158 /* BETA (input/output) DOUBLE PRECISION */ 00159 /* Contains the off-diagonal element associated with the added */ 00160 /* row. */ 00161 00162 /* IDXQ (output) INTEGER array, dimension ( N ) */ 00163 /* This contains the permutation which will reintegrate the */ 00164 /* subproblem just solved back into sorted order, i.e. */ 00165 /* D( IDXQ( I = 1, N ) ) will be in ascending order. */ 00166 00167 /* PERM (output) INTEGER array, dimension ( N ) */ 00168 /* The permutations (from deflation and sorting) to be applied */ 00169 /* to each block. Not referenced if ICOMPQ = 0. */ 00170 00171 /* GIVPTR (output) INTEGER */ 00172 /* The number of Givens rotations which took place in this */ 00173 /* subproblem. Not referenced if ICOMPQ = 0. */ 00174 00175 /* GIVCOL (output) INTEGER array, dimension ( LDGCOL, 2 ) */ 00176 /* Each pair of numbers indicates a pair of columns to take place */ 00177 /* in a Givens rotation. Not referenced if ICOMPQ = 0. */ 00178 00179 /* LDGCOL (input) INTEGER */ 00180 /* leading dimension of GIVCOL, must be at least N. */ 00181 00182 /* GIVNUM (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 ) */ 00183 /* Each number indicates the C or S value to be used in the */ 00184 /* corresponding Givens rotation. Not referenced if ICOMPQ = 0. */ 00185 00186 /* LDGNUM (input) INTEGER */ 00187 /* The leading dimension of GIVNUM and POLES, must be at least N. */ 00188 00189 /* POLES (output) DOUBLE PRECISION array, dimension ( LDGNUM, 2 ) */ 00190 /* On exit, POLES(1,*) is an array containing the new singular */ 00191 /* values obtained from solving the secular equation, and */ 00192 /* POLES(2,*) is an array containing the poles in the secular */ 00193 /* equation. Not referenced if ICOMPQ = 0. */ 00194 00195 /* DIFL (output) DOUBLE PRECISION array, dimension ( N ) */ 00196 /* On exit, DIFL(I) is the distance between I-th updated */ 00197 /* (undeflated) singular value and the I-th (undeflated) old */ 00198 /* singular value. */ 00199 00200 /* DIFR (output) DOUBLE PRECISION array, */ 00201 /* dimension ( LDGNUM, 2 ) if ICOMPQ = 1 and */ 00202 /* dimension ( N ) if ICOMPQ = 0. */ 00203 /* On exit, DIFR(I, 1) is the distance between I-th updated */ 00204 /* (undeflated) singular value and the I+1-th (undeflated) old */ 00205 /* singular value. */ 00206 00207 /* If ICOMPQ = 1, DIFR(1:K,2) is an array containing the */ 00208 /* normalizing factors for the right singular vector matrix. */ 00209 00210 /* See DLASD8 for details on DIFL and DIFR. */ 00211 00212 /* Z (output) DOUBLE PRECISION array, dimension ( M ) */ 00213 /* The first elements of this array contain the components */ 00214 /* of the deflation-adjusted updating row vector. */ 00215 00216 /* K (output) INTEGER */ 00217 /* Contains the dimension of the non-deflated matrix, */ 00218 /* This is the order of the related secular equation. 1 <= K <=N. */ 00219 00220 /* C (output) DOUBLE PRECISION */ 00221 /* C contains garbage if SQRE =0 and the C-value of a Givens */ 00222 /* rotation related to the right null space if SQRE = 1. */ 00223 00224 /* S (output) DOUBLE PRECISION */ 00225 /* S contains garbage if SQRE =0 and the S-value of a Givens */ 00226 /* rotation related to the right null space if SQRE = 1. */ 00227 00228 /* WORK (workspace) DOUBLE PRECISION array, dimension ( 4 * M ) */ 00229 00230 /* IWORK (workspace) INTEGER array, dimension ( 3 * N ) */ 00231 00232 /* INFO (output) INTEGER */ 00233 /* = 0: successful exit. */ 00234 /* < 0: if INFO = -i, the i-th argument had an illegal value. */ 00235 /* > 0: if INFO = 1, an singular value did not converge */ 00236 00237 /* Further Details */ 00238 /* =============== */ 00239 00240 /* Based on contributions by */ 00241 /* Ming Gu and Huan Ren, Computer Science Division, University of */ 00242 /* California at Berkeley, USA */ 00243 00244 /* ===================================================================== */ 00245 00246 /* .. Parameters .. */ 00247 /* .. */ 00248 /* .. Local Scalars .. */ 00249 /* .. */ 00250 /* .. External Subroutines .. */ 00251 /* .. */ 00252 /* .. Intrinsic Functions .. */ 00253 /* .. */ 00254 /* .. Executable Statements .. */ 00255 00256 /* Test the input parameters. */ 00257 00258 /* Parameter adjustments */ 00259 --d__; 00260 --vf; 00261 --vl; 00262 --idxq; 00263 --perm; 00264 givcol_dim1 = *ldgcol; 00265 givcol_offset = 1 + givcol_dim1; 00266 givcol -= givcol_offset; 00267 poles_dim1 = *ldgnum; 00268 poles_offset = 1 + poles_dim1; 00269 poles -= poles_offset; 00270 givnum_dim1 = *ldgnum; 00271 givnum_offset = 1 + givnum_dim1; 00272 givnum -= givnum_offset; 00273 --difl; 00274 --difr; 00275 --z__; 00276 --work; 00277 --iwork; 00278 00279 /* Function Body */ 00280 *info = 0; 00281 n = *nl + *nr + 1; 00282 m = n + *sqre; 00283 00284 if (*icompq < 0 || *icompq > 1) { 00285 *info = -1; 00286 } else if (*nl < 1) { 00287 *info = -2; 00288 } else if (*nr < 1) { 00289 *info = -3; 00290 } else if (*sqre < 0 || *sqre > 1) { 00291 *info = -4; 00292 } else if (*ldgcol < n) { 00293 *info = -14; 00294 } else if (*ldgnum < n) { 00295 *info = -16; 00296 } 00297 if (*info != 0) { 00298 i__1 = -(*info); 00299 xerbla_("DLASD6", &i__1); 00300 return 0; 00301 } 00302 00303 /* The following values are for bookkeeping purposes only. They are */ 00304 /* integer pointers which indicate the portion of the workspace */ 00305 /* used by a particular array in DLASD7 and DLASD8. */ 00306 00307 isigma = 1; 00308 iw = isigma + n; 00309 ivfw = iw + m; 00310 ivlw = ivfw + m; 00311 00312 idx = 1; 00313 idxc = idx + n; 00314 idxp = idxc + n; 00315 00316 /* Scale. */ 00317 00318 /* Computing MAX */ 00319 d__1 = abs(*alpha), d__2 = abs(*beta); 00320 orgnrm = max(d__1,d__2); 00321 d__[*nl + 1] = 0.; 00322 i__1 = n; 00323 for (i__ = 1; i__ <= i__1; ++i__) { 00324 if ((d__1 = d__[i__], abs(d__1)) > orgnrm) { 00325 orgnrm = (d__1 = d__[i__], abs(d__1)); 00326 } 00327 /* L10: */ 00328 } 00329 dlascl_("G", &c__0, &c__0, &orgnrm, &c_b7, &n, &c__1, &d__[1], &n, info); 00330 *alpha /= orgnrm; 00331 *beta /= orgnrm; 00332 00333 /* Sort and Deflate singular values. */ 00334 00335 dlasd7_(icompq, nl, nr, sqre, k, &d__[1], &z__[1], &work[iw], &vf[1], & 00336 work[ivfw], &vl[1], &work[ivlw], alpha, beta, &work[isigma], & 00337 iwork[idx], &iwork[idxp], &idxq[1], &perm[1], givptr, &givcol[ 00338 givcol_offset], ldgcol, &givnum[givnum_offset], ldgnum, c__, s, 00339 info); 00340 00341 /* Solve Secular Equation, compute DIFL, DIFR, and update VF, VL. */ 00342 00343 dlasd8_(icompq, k, &d__[1], &z__[1], &vf[1], &vl[1], &difl[1], &difr[1], 00344 ldgnum, &work[isigma], &work[iw], info); 00345 00346 /* Save the poles if ICOMPQ = 1. */ 00347 00348 if (*icompq == 1) { 00349 dcopy_(k, &d__[1], &c__1, &poles[poles_dim1 + 1], &c__1); 00350 dcopy_(k, &work[isigma], &c__1, &poles[(poles_dim1 << 1) + 1], &c__1); 00351 } 00352 00353 /* Unscale. */ 00354 00355 dlascl_("G", &c__0, &c__0, &c_b7, &orgnrm, &n, &c__1, &d__[1], &n, info); 00356 00357 /* Prepare the IDXQ sorting permutation. */ 00358 00359 n1 = *k; 00360 n2 = n - *k; 00361 dlamrg_(&n1, &n2, &d__[1], &c__1, &c_n1, &idxq[1]); 00362 00363 return 0; 00364 00365 /* End of DLASD6 */ 00366 00367 } /* dlasd6_ */