00001 /* dlaed3.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 doublereal c_b22 = 1.; 00020 static doublereal c_b23 = 0.; 00021 00022 /* Subroutine */ int dlaed3_(integer *k, integer *n, integer *n1, doublereal * 00023 d__, doublereal *q, integer *ldq, doublereal *rho, doublereal *dlamda, 00024 doublereal *q2, integer *indx, integer *ctot, doublereal *w, 00025 doublereal *s, integer *info) 00026 { 00027 /* System generated locals */ 00028 integer q_dim1, q_offset, i__1, i__2; 00029 doublereal d__1; 00030 00031 /* Builtin functions */ 00032 double sqrt(doublereal), d_sign(doublereal *, doublereal *); 00033 00034 /* Local variables */ 00035 integer i__, j, n2, n12, ii, n23, iq2; 00036 doublereal temp; 00037 extern doublereal dnrm2_(integer *, doublereal *, integer *); 00038 extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, 00039 integer *, doublereal *, doublereal *, integer *, doublereal *, 00040 integer *, doublereal *, doublereal *, integer *), 00041 dcopy_(integer *, doublereal *, integer *, doublereal *, integer 00042 *), dlaed4_(integer *, integer *, doublereal *, doublereal *, 00043 doublereal *, doublereal *, doublereal *, integer *); 00044 extern doublereal dlamc3_(doublereal *, doublereal *); 00045 extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, 00046 doublereal *, integer *, doublereal *, integer *), 00047 dlaset_(char *, integer *, integer *, doublereal *, doublereal *, 00048 doublereal *, integer *), xerbla_(char *, integer *); 00049 00050 00051 /* -- LAPACK routine (version 3.2) -- */ 00052 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00053 /* November 2006 */ 00054 00055 /* .. Scalar Arguments .. */ 00056 /* .. */ 00057 /* .. Array Arguments .. */ 00058 /* .. */ 00059 00060 /* Purpose */ 00061 /* ======= */ 00062 00063 /* DLAED3 finds the roots of the secular equation, as defined by the */ 00064 /* values in D, W, and RHO, between 1 and K. It makes the */ 00065 /* appropriate calls to DLAED4 and then updates the eigenvectors by */ 00066 /* multiplying the matrix of eigenvectors of the pair of eigensystems */ 00067 /* being combined by the matrix of eigenvectors of the K-by-K system */ 00068 /* which is solved here. */ 00069 00070 /* This code makes very mild assumptions about floating point */ 00071 /* arithmetic. It will work on machines with a guard digit in */ 00072 /* add/subtract, or on those binary machines without guard digits */ 00073 /* which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. */ 00074 /* It could conceivably fail on hexadecimal or decimal machines */ 00075 /* without guard digits, but we know of none. */ 00076 00077 /* Arguments */ 00078 /* ========= */ 00079 00080 /* K (input) INTEGER */ 00081 /* The number of terms in the rational function to be solved by */ 00082 /* DLAED4. K >= 0. */ 00083 00084 /* N (input) INTEGER */ 00085 /* The number of rows and columns in the Q matrix. */ 00086 /* N >= K (deflation may result in N>K). */ 00087 00088 /* N1 (input) INTEGER */ 00089 /* The location of the last eigenvalue in the leading submatrix. */ 00090 /* min(1,N) <= N1 <= N/2. */ 00091 00092 /* D (output) DOUBLE PRECISION array, dimension (N) */ 00093 /* D(I) contains the updated eigenvalues for */ 00094 /* 1 <= I <= K. */ 00095 00096 /* Q (output) DOUBLE PRECISION array, dimension (LDQ,N) */ 00097 /* Initially the first K columns are used as workspace. */ 00098 /* On output the columns 1 to K contain */ 00099 /* the updated eigenvectors. */ 00100 00101 /* LDQ (input) INTEGER */ 00102 /* The leading dimension of the array Q. LDQ >= max(1,N). */ 00103 00104 /* RHO (input) DOUBLE PRECISION */ 00105 /* The value of the parameter in the rank one update equation. */ 00106 /* RHO >= 0 required. */ 00107 00108 /* DLAMDA (input/output) DOUBLE PRECISION array, dimension (K) */ 00109 /* The first K elements of this array contain the old roots */ 00110 /* of the deflated updating problem. These are the poles */ 00111 /* of the secular equation. May be changed on output by */ 00112 /* having lowest order bit set to zero on Cray X-MP, Cray Y-MP, */ 00113 /* Cray-2, or Cray C-90, as described above. */ 00114 00115 /* Q2 (input) DOUBLE PRECISION array, dimension (LDQ2, N) */ 00116 /* The first K columns of this matrix contain the non-deflated */ 00117 /* eigenvectors for the split problem. */ 00118 00119 /* INDX (input) INTEGER array, dimension (N) */ 00120 /* The permutation used to arrange the columns of the deflated */ 00121 /* Q matrix into three groups (see DLAED2). */ 00122 /* The rows of the eigenvectors found by DLAED4 must be likewise */ 00123 /* permuted before the matrix multiply can take place. */ 00124 00125 /* CTOT (input) INTEGER array, dimension (4) */ 00126 /* A count of the total number of the various types of columns */ 00127 /* in Q, as described in INDX. The fourth column type is any */ 00128 /* column which has been deflated. */ 00129 00130 /* W (input/output) DOUBLE PRECISION array, dimension (K) */ 00131 /* The first K elements of this array contain the components */ 00132 /* of the deflation-adjusted updating vector. Destroyed on */ 00133 /* output. */ 00134 00135 /* S (workspace) DOUBLE PRECISION array, dimension (N1 + 1)*K */ 00136 /* Will contain the eigenvectors of the repaired matrix which */ 00137 /* will be multiplied by the previously accumulated eigenvectors */ 00138 /* to update the system. */ 00139 00140 /* LDS (input) INTEGER */ 00141 /* The leading dimension of S. LDS >= max(1,K). */ 00142 00143 /* INFO (output) INTEGER */ 00144 /* = 0: successful exit. */ 00145 /* < 0: if INFO = -i, the i-th argument had an illegal value. */ 00146 /* > 0: if INFO = 1, an eigenvalue did not converge */ 00147 00148 /* Further Details */ 00149 /* =============== */ 00150 00151 /* Based on contributions by */ 00152 /* Jeff Rutter, Computer Science Division, University of California */ 00153 /* at Berkeley, USA */ 00154 /* Modified by Francoise Tisseur, University of Tennessee. */ 00155 00156 /* ===================================================================== */ 00157 00158 /* .. Parameters .. */ 00159 /* .. */ 00160 /* .. Local Scalars .. */ 00161 /* .. */ 00162 /* .. External Functions .. */ 00163 /* .. */ 00164 /* .. External Subroutines .. */ 00165 /* .. */ 00166 /* .. Intrinsic Functions .. */ 00167 /* .. */ 00168 /* .. Executable Statements .. */ 00169 00170 /* Test the input parameters. */ 00171 00172 /* Parameter adjustments */ 00173 --d__; 00174 q_dim1 = *ldq; 00175 q_offset = 1 + q_dim1; 00176 q -= q_offset; 00177 --dlamda; 00178 --q2; 00179 --indx; 00180 --ctot; 00181 --w; 00182 --s; 00183 00184 /* Function Body */ 00185 *info = 0; 00186 00187 if (*k < 0) { 00188 *info = -1; 00189 } else if (*n < *k) { 00190 *info = -2; 00191 } else if (*ldq < max(1,*n)) { 00192 *info = -6; 00193 } 00194 if (*info != 0) { 00195 i__1 = -(*info); 00196 xerbla_("DLAED3", &i__1); 00197 return 0; 00198 } 00199 00200 /* Quick return if possible */ 00201 00202 if (*k == 0) { 00203 return 0; 00204 } 00205 00206 /* Modify values DLAMDA(i) to make sure all DLAMDA(i)-DLAMDA(j) can */ 00207 /* be computed with high relative accuracy (barring over/underflow). */ 00208 /* This is a problem on machines without a guard digit in */ 00209 /* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). */ 00210 /* The following code replaces DLAMDA(I) by 2*DLAMDA(I)-DLAMDA(I), */ 00211 /* which on any of these machines zeros out the bottommost */ 00212 /* bit of DLAMDA(I) if it is 1; this makes the subsequent */ 00213 /* subtractions DLAMDA(I)-DLAMDA(J) unproblematic when cancellation */ 00214 /* occurs. On binary machines with a guard digit (almost all */ 00215 /* machines) it does not change DLAMDA(I) at all. On hexadecimal */ 00216 /* and decimal machines with a guard digit, it slightly */ 00217 /* changes the bottommost bits of DLAMDA(I). It does not account */ 00218 /* for hexadecimal or decimal machines without guard digits */ 00219 /* (we know of none). We use a subroutine call to compute */ 00220 /* 2*DLAMBDA(I) to prevent optimizing compilers from eliminating */ 00221 /* this code. */ 00222 00223 i__1 = *k; 00224 for (i__ = 1; i__ <= i__1; ++i__) { 00225 dlamda[i__] = dlamc3_(&dlamda[i__], &dlamda[i__]) - dlamda[i__]; 00226 /* L10: */ 00227 } 00228 00229 i__1 = *k; 00230 for (j = 1; j <= i__1; ++j) { 00231 dlaed4_(k, &j, &dlamda[1], &w[1], &q[j * q_dim1 + 1], rho, &d__[j], 00232 info); 00233 00234 /* If the zero finder fails, the computation is terminated. */ 00235 00236 if (*info != 0) { 00237 goto L120; 00238 } 00239 /* L20: */ 00240 } 00241 00242 if (*k == 1) { 00243 goto L110; 00244 } 00245 if (*k == 2) { 00246 i__1 = *k; 00247 for (j = 1; j <= i__1; ++j) { 00248 w[1] = q[j * q_dim1 + 1]; 00249 w[2] = q[j * q_dim1 + 2]; 00250 ii = indx[1]; 00251 q[j * q_dim1 + 1] = w[ii]; 00252 ii = indx[2]; 00253 q[j * q_dim1 + 2] = w[ii]; 00254 /* L30: */ 00255 } 00256 goto L110; 00257 } 00258 00259 /* Compute updated W. */ 00260 00261 dcopy_(k, &w[1], &c__1, &s[1], &c__1); 00262 00263 /* Initialize W(I) = Q(I,I) */ 00264 00265 i__1 = *ldq + 1; 00266 dcopy_(k, &q[q_offset], &i__1, &w[1], &c__1); 00267 i__1 = *k; 00268 for (j = 1; j <= i__1; ++j) { 00269 i__2 = j - 1; 00270 for (i__ = 1; i__ <= i__2; ++i__) { 00271 w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]); 00272 /* L40: */ 00273 } 00274 i__2 = *k; 00275 for (i__ = j + 1; i__ <= i__2; ++i__) { 00276 w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]); 00277 /* L50: */ 00278 } 00279 /* L60: */ 00280 } 00281 i__1 = *k; 00282 for (i__ = 1; i__ <= i__1; ++i__) { 00283 d__1 = sqrt(-w[i__]); 00284 w[i__] = d_sign(&d__1, &s[i__]); 00285 /* L70: */ 00286 } 00287 00288 /* Compute eigenvectors of the modified rank-1 modification. */ 00289 00290 i__1 = *k; 00291 for (j = 1; j <= i__1; ++j) { 00292 i__2 = *k; 00293 for (i__ = 1; i__ <= i__2; ++i__) { 00294 s[i__] = w[i__] / q[i__ + j * q_dim1]; 00295 /* L80: */ 00296 } 00297 temp = dnrm2_(k, &s[1], &c__1); 00298 i__2 = *k; 00299 for (i__ = 1; i__ <= i__2; ++i__) { 00300 ii = indx[i__]; 00301 q[i__ + j * q_dim1] = s[ii] / temp; 00302 /* L90: */ 00303 } 00304 /* L100: */ 00305 } 00306 00307 /* Compute the updated eigenvectors. */ 00308 00309 L110: 00310 00311 n2 = *n - *n1; 00312 n12 = ctot[1] + ctot[2]; 00313 n23 = ctot[2] + ctot[3]; 00314 00315 dlacpy_("A", &n23, k, &q[ctot[1] + 1 + q_dim1], ldq, &s[1], &n23); 00316 iq2 = *n1 * n12 + 1; 00317 if (n23 != 0) { 00318 dgemm_("N", "N", &n2, k, &n23, &c_b22, &q2[iq2], &n2, &s[1], &n23, & 00319 c_b23, &q[*n1 + 1 + q_dim1], ldq); 00320 } else { 00321 dlaset_("A", &n2, k, &c_b23, &c_b23, &q[*n1 + 1 + q_dim1], ldq); 00322 } 00323 00324 dlacpy_("A", &n12, k, &q[q_offset], ldq, &s[1], &n12); 00325 if (n12 != 0) { 00326 dgemm_("N", "N", n1, k, &n12, &c_b22, &q2[1], n1, &s[1], &n12, &c_b23, 00327 &q[q_offset], ldq); 00328 } else { 00329 dlaset_("A", n1, k, &c_b23, &c_b23, &q[q_dim1 + 1], ldq); 00330 } 00331 00332 00333 L120: 00334 return 0; 00335 00336 /* End of DLAED3 */ 00337 00338 } /* dlaed3_ */