00001 /* dlasd8.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__1 = 1; 00019 static integer c__0 = 0; 00020 static doublereal c_b8 = 1.; 00021 00022 /* Subroutine */ int dlasd8_(integer *icompq, integer *k, doublereal *d__, 00023 doublereal *z__, doublereal *vf, doublereal *vl, doublereal *difl, 00024 doublereal *difr, integer *lddifr, doublereal *dsigma, doublereal * 00025 work, integer *info) 00026 { 00027 /* System generated locals */ 00028 integer difr_dim1, difr_offset, i__1, i__2; 00029 doublereal d__1, d__2; 00030 00031 /* Builtin functions */ 00032 double sqrt(doublereal), d_sign(doublereal *, doublereal *); 00033 00034 /* Local variables */ 00035 integer i__, j; 00036 doublereal dj, rho; 00037 integer iwk1, iwk2, iwk3; 00038 extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, 00039 integer *); 00040 doublereal temp; 00041 extern doublereal dnrm2_(integer *, doublereal *, integer *); 00042 integer iwk2i, iwk3i; 00043 doublereal diflj, difrj, dsigj; 00044 extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 00045 doublereal *, integer *); 00046 extern doublereal dlamc3_(doublereal *, doublereal *); 00047 extern /* Subroutine */ int dlasd4_(integer *, integer *, doublereal *, 00048 doublereal *, doublereal *, doublereal *, doublereal *, 00049 doublereal *, integer *), dlascl_(char *, integer *, integer *, 00050 doublereal *, doublereal *, integer *, integer *, doublereal *, 00051 integer *, integer *), dlaset_(char *, integer *, integer 00052 *, doublereal *, doublereal *, doublereal *, integer *), 00053 xerbla_(char *, integer *); 00054 doublereal dsigjp; 00055 00056 00057 /* -- LAPACK auxiliary routine (version 3.2) -- */ 00058 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00059 /* October 2006 */ 00060 00061 /* .. Scalar Arguments .. */ 00062 /* .. */ 00063 /* .. Array Arguments .. */ 00064 /* .. */ 00065 00066 /* Purpose */ 00067 /* ======= */ 00068 00069 /* DLASD8 finds the square roots of the roots of the secular equation, */ 00070 /* as defined by the values in DSIGMA and Z. It makes the appropriate */ 00071 /* calls to DLASD4, and stores, for each element in D, the distance */ 00072 /* to its two nearest poles (elements in DSIGMA). It also updates */ 00073 /* the arrays VF and VL, the first and last components of all the */ 00074 /* right singular vectors of the original bidiagonal matrix. */ 00075 00076 /* DLASD8 is called from DLASD6. */ 00077 00078 /* Arguments */ 00079 /* ========= */ 00080 00081 /* ICOMPQ (input) INTEGER */ 00082 /* Specifies whether singular vectors are to be computed in */ 00083 /* factored form in the calling routine: */ 00084 /* = 0: Compute singular values only. */ 00085 /* = 1: Compute singular vectors in factored form as well. */ 00086 00087 /* K (input) INTEGER */ 00088 /* The number of terms in the rational function to be solved */ 00089 /* by DLASD4. K >= 1. */ 00090 00091 /* D (output) DOUBLE PRECISION array, dimension ( K ) */ 00092 /* On output, D contains the updated singular values. */ 00093 00094 /* Z (input/output) DOUBLE PRECISION array, dimension ( K ) */ 00095 /* On entry, the first K elements of this array contain the */ 00096 /* components of the deflation-adjusted updating row vector. */ 00097 /* On exit, Z is updated. */ 00098 00099 /* VF (input/output) DOUBLE PRECISION array, dimension ( K ) */ 00100 /* On entry, VF contains information passed through DBEDE8. */ 00101 /* On exit, VF contains the first K components of the first */ 00102 /* components of all right singular vectors of the bidiagonal */ 00103 /* matrix. */ 00104 00105 /* VL (input/output) DOUBLE PRECISION array, dimension ( K ) */ 00106 /* On entry, VL contains information passed through DBEDE8. */ 00107 /* On exit, VL contains the first K components of the last */ 00108 /* components of all right singular vectors of the bidiagonal */ 00109 /* matrix. */ 00110 00111 /* DIFL (output) DOUBLE PRECISION array, dimension ( K ) */ 00112 /* On exit, DIFL(I) = D(I) - DSIGMA(I). */ 00113 00114 /* DIFR (output) DOUBLE PRECISION array, */ 00115 /* dimension ( LDDIFR, 2 ) if ICOMPQ = 1 and */ 00116 /* dimension ( K ) if ICOMPQ = 0. */ 00117 /* On exit, DIFR(I,1) = D(I) - DSIGMA(I+1), DIFR(K,1) is not */ 00118 /* defined and will not be referenced. */ 00119 00120 /* If ICOMPQ = 1, DIFR(1:K,2) is an array containing the */ 00121 /* normalizing factors for the right singular vector matrix. */ 00122 00123 /* LDDIFR (input) INTEGER */ 00124 /* The leading dimension of DIFR, must be at least K. */ 00125 00126 /* DSIGMA (input/output) DOUBLE PRECISION array, dimension ( K ) */ 00127 /* On entry, the first K elements of this array contain the old */ 00128 /* roots of the deflated updating problem. These are the poles */ 00129 /* of the secular equation. */ 00130 /* On exit, the elements of DSIGMA may be very slightly altered */ 00131 /* in value. */ 00132 00133 /* WORK (workspace) DOUBLE PRECISION array, dimension at least 3 * K */ 00134 00135 /* INFO (output) INTEGER */ 00136 /* = 0: successful exit. */ 00137 /* < 0: if INFO = -i, the i-th argument had an illegal value. */ 00138 /* > 0: if INFO = 1, an singular value did not converge */ 00139 00140 /* Further Details */ 00141 /* =============== */ 00142 00143 /* Based on contributions by */ 00144 /* Ming Gu and Huan Ren, Computer Science Division, University of */ 00145 /* California at Berkeley, USA */ 00146 00147 /* ===================================================================== */ 00148 00149 /* .. Parameters .. */ 00150 /* .. */ 00151 /* .. Local Scalars .. */ 00152 /* .. */ 00153 /* .. External Subroutines .. */ 00154 /* .. */ 00155 /* .. External Functions .. */ 00156 /* .. */ 00157 /* .. Intrinsic Functions .. */ 00158 /* .. */ 00159 /* .. Executable Statements .. */ 00160 00161 /* Test the input parameters. */ 00162 00163 /* Parameter adjustments */ 00164 --d__; 00165 --z__; 00166 --vf; 00167 --vl; 00168 --difl; 00169 difr_dim1 = *lddifr; 00170 difr_offset = 1 + difr_dim1; 00171 difr -= difr_offset; 00172 --dsigma; 00173 --work; 00174 00175 /* Function Body */ 00176 *info = 0; 00177 00178 if (*icompq < 0 || *icompq > 1) { 00179 *info = -1; 00180 } else if (*k < 1) { 00181 *info = -2; 00182 } else if (*lddifr < *k) { 00183 *info = -9; 00184 } 00185 if (*info != 0) { 00186 i__1 = -(*info); 00187 xerbla_("DLASD8", &i__1); 00188 return 0; 00189 } 00190 00191 /* Quick return if possible */ 00192 00193 if (*k == 1) { 00194 d__[1] = abs(z__[1]); 00195 difl[1] = d__[1]; 00196 if (*icompq == 1) { 00197 difl[2] = 1.; 00198 difr[(difr_dim1 << 1) + 1] = 1.; 00199 } 00200 return 0; 00201 } 00202 00203 /* Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can */ 00204 /* be computed with high relative accuracy (barring over/underflow). */ 00205 /* This is a problem on machines without a guard digit in */ 00206 /* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). */ 00207 /* The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I), */ 00208 /* which on any of these machines zeros out the bottommost */ 00209 /* bit of DSIGMA(I) if it is 1; this makes the subsequent */ 00210 /* subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation */ 00211 /* occurs. On binary machines with a guard digit (almost all */ 00212 /* machines) it does not change DSIGMA(I) at all. On hexadecimal */ 00213 /* and decimal machines with a guard digit, it slightly */ 00214 /* changes the bottommost bits of DSIGMA(I). It does not account */ 00215 /* for hexadecimal or decimal machines without guard digits */ 00216 /* (we know of none). We use a subroutine call to compute */ 00217 /* 2*DLAMBDA(I) to prevent optimizing compilers from eliminating */ 00218 /* this code. */ 00219 00220 i__1 = *k; 00221 for (i__ = 1; i__ <= i__1; ++i__) { 00222 dsigma[i__] = dlamc3_(&dsigma[i__], &dsigma[i__]) - dsigma[i__]; 00223 /* L10: */ 00224 } 00225 00226 /* Book keeping. */ 00227 00228 iwk1 = 1; 00229 iwk2 = iwk1 + *k; 00230 iwk3 = iwk2 + *k; 00231 iwk2i = iwk2 - 1; 00232 iwk3i = iwk3 - 1; 00233 00234 /* Normalize Z. */ 00235 00236 rho = dnrm2_(k, &z__[1], &c__1); 00237 dlascl_("G", &c__0, &c__0, &rho, &c_b8, k, &c__1, &z__[1], k, info); 00238 rho *= rho; 00239 00240 /* Initialize WORK(IWK3). */ 00241 00242 dlaset_("A", k, &c__1, &c_b8, &c_b8, &work[iwk3], k); 00243 00244 /* Compute the updated singular values, the arrays DIFL, DIFR, */ 00245 /* and the updated Z. */ 00246 00247 i__1 = *k; 00248 for (j = 1; j <= i__1; ++j) { 00249 dlasd4_(k, &j, &dsigma[1], &z__[1], &work[iwk1], &rho, &d__[j], &work[ 00250 iwk2], info); 00251 00252 /* If the root finder fails, the computation is terminated. */ 00253 00254 if (*info != 0) { 00255 return 0; 00256 } 00257 work[iwk3i + j] = work[iwk3i + j] * work[j] * work[iwk2i + j]; 00258 difl[j] = -work[j]; 00259 difr[j + difr_dim1] = -work[j + 1]; 00260 i__2 = j - 1; 00261 for (i__ = 1; i__ <= i__2; ++i__) { 00262 work[iwk3i + i__] = work[iwk3i + i__] * work[i__] * work[iwk2i + 00263 i__] / (dsigma[i__] - dsigma[j]) / (dsigma[i__] + dsigma[ 00264 j]); 00265 /* L20: */ 00266 } 00267 i__2 = *k; 00268 for (i__ = j + 1; i__ <= i__2; ++i__) { 00269 work[iwk3i + i__] = work[iwk3i + i__] * work[i__] * work[iwk2i + 00270 i__] / (dsigma[i__] - dsigma[j]) / (dsigma[i__] + dsigma[ 00271 j]); 00272 /* L30: */ 00273 } 00274 /* L40: */ 00275 } 00276 00277 /* Compute updated Z. */ 00278 00279 i__1 = *k; 00280 for (i__ = 1; i__ <= i__1; ++i__) { 00281 d__2 = sqrt((d__1 = work[iwk3i + i__], abs(d__1))); 00282 z__[i__] = d_sign(&d__2, &z__[i__]); 00283 /* L50: */ 00284 } 00285 00286 /* Update VF and VL. */ 00287 00288 i__1 = *k; 00289 for (j = 1; j <= i__1; ++j) { 00290 diflj = difl[j]; 00291 dj = d__[j]; 00292 dsigj = -dsigma[j]; 00293 if (j < *k) { 00294 difrj = -difr[j + difr_dim1]; 00295 dsigjp = -dsigma[j + 1]; 00296 } 00297 work[j] = -z__[j] / diflj / (dsigma[j] + dj); 00298 i__2 = j - 1; 00299 for (i__ = 1; i__ <= i__2; ++i__) { 00300 work[i__] = z__[i__] / (dlamc3_(&dsigma[i__], &dsigj) - diflj) / ( 00301 dsigma[i__] + dj); 00302 /* L60: */ 00303 } 00304 i__2 = *k; 00305 for (i__ = j + 1; i__ <= i__2; ++i__) { 00306 work[i__] = z__[i__] / (dlamc3_(&dsigma[i__], &dsigjp) + difrj) / 00307 (dsigma[i__] + dj); 00308 /* L70: */ 00309 } 00310 temp = dnrm2_(k, &work[1], &c__1); 00311 work[iwk2i + j] = ddot_(k, &work[1], &c__1, &vf[1], &c__1) / temp; 00312 work[iwk3i + j] = ddot_(k, &work[1], &c__1, &vl[1], &c__1) / temp; 00313 if (*icompq == 1) { 00314 difr[j + (difr_dim1 << 1)] = temp; 00315 } 00316 /* L80: */ 00317 } 00318 00319 dcopy_(k, &work[iwk2], &c__1, &vf[1], &c__1); 00320 dcopy_(k, &work[iwk3], &c__1, &vl[1], &c__1); 00321 00322 return 0; 00323 00324 /* End of DLASD8 */ 00325 00326 } /* dlasd8_ */