00001 
00002 
00003 
00004 
00005 
00006 #include "f2c.h"
00007 
00008 
00009 
00010 static integer c__1 = 1;
00011 static doublereal c_b15 = -1.;
00012 static doublereal c_b17 = 1.;
00013 
00014  int dgerfs_(trans, n, nrhs, a, lda, af, ldaf, ipiv, b, ldb, 
00015         x, ldx, ferr, berr, work, iwork, info, trans_len)
00016 char *trans;
00017 integer *n, *nrhs;
00018 doublereal *a;
00019 integer *lda;
00020 doublereal *af;
00021 integer *ldaf, *ipiv;
00022 doublereal *b;
00023 integer *ldb;
00024 doublereal *x;
00025 integer *ldx;
00026 doublereal *ferr, *berr, *work;
00027 integer *iwork, *info;
00028 ftnlen trans_len;
00029 {
00030     
00031     integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, x_dim1, 
00032             x_offset, i__1, i__2, i__3;
00033     doublereal d__1, d__2, d__3;
00034 
00035     
00036     static integer kase;
00037     static doublereal safe1, safe2;
00038     static integer i, j, k;
00039     static doublereal s;
00040     extern logical lsame_();
00041     extern  int dgemv_(), dcopy_(), daxpy_();
00042     static integer count;
00043     extern doublereal dlamch_();
00044     extern  int dlacon_();
00045     static doublereal xk;
00046     static integer nz;
00047     static doublereal safmin;
00048     extern  int xerbla_(), dgetrs_();
00049     static logical notran;
00050     static char transt[1];
00051     static doublereal lstres, eps;
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163     
00164     a_dim1 = *lda;
00165     a_offset = a_dim1 + 1;
00166     a -= a_offset;
00167     af_dim1 = *ldaf;
00168     af_offset = af_dim1 + 1;
00169     af -= af_offset;
00170     --ipiv;
00171     b_dim1 = *ldb;
00172     b_offset = b_dim1 + 1;
00173     b -= b_offset;
00174     x_dim1 = *ldx;
00175     x_offset = x_dim1 + 1;
00176     x -= x_offset;
00177     --ferr;
00178     --berr;
00179     --work;
00180     --iwork;
00181 
00182     
00183     *info = 0;
00184     notran = lsame_(trans, "N", 1L, 1L);
00185     if (! notran && ! lsame_(trans, "T", 1L, 1L) && ! lsame_(trans, "C", 1L, 
00186             1L)) {
00187         *info = -1;
00188     } else if (*n < 0) {
00189         *info = -2;
00190     } else if (*nrhs < 0) {
00191         *info = -3;
00192     } else if (*lda < max(1,*n)) {
00193         *info = -5;
00194     } else if (*ldaf < max(1,*n)) {
00195         *info = -7;
00196     } else if (*ldb < max(1,*n)) {
00197         *info = -10;
00198     } else if (*ldx < max(1,*n)) {
00199         *info = -12;
00200     }
00201     if (*info != 0) {
00202         i__1 = -(*info);
00203         xerbla_("DGERFS", &i__1, 6L);
00204         return 0;
00205     }
00206 
00207 
00208 
00209     if (*n == 0 || *nrhs == 0) {
00210         i__1 = *nrhs;
00211         for (j = 1; j <= i__1; ++j) {
00212             ferr[j] = 0.;
00213             berr[j] = 0.;
00214 
00215         }
00216         return 0;
00217     }
00218 
00219     if (notran) {
00220         *(unsigned char *)transt = 'T';
00221     } else {
00222         *(unsigned char *)transt = 'N';
00223     }
00224 
00225 
00226 
00227     nz = *n + 1;
00228     eps = dlamch_("Epsilon", 7L);
00229     safmin = dlamch_("Safe minimum", 12L);
00230     safe1 = nz * safmin;
00231     safe2 = safe1 / eps;
00232 
00233 
00234 
00235     i__1 = *nrhs;
00236     for (j = 1; j <= i__1; ++j) {
00237 
00238         count = 1;
00239         lstres = 3.;
00240 L20:
00241 
00242 
00243 
00244 
00245 
00246 
00247         dcopy_(n, &b[j * b_dim1 + 1], &c__1, &work[*n + 1], &c__1);
00248         dgemv_(trans, n, n, &c_b15, &a[a_offset], lda, &x[j * x_dim1 + 1], &
00249                 c__1, &c_b17, &work[*n + 1], &c__1, 1L);
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264         i__2 = *n;
00265         for (i = 1; i <= i__2; ++i) {
00266             work[i] = (d__1 = b[i + j * b_dim1], abs(d__1));
00267 
00268         }
00269 
00270 
00271 
00272         if (notran) {
00273             i__2 = *n;
00274             for (k = 1; k <= i__2; ++k) {
00275                 xk = (d__1 = x[k + j * x_dim1], abs(d__1));
00276                 i__3 = *n;
00277                 for (i = 1; i <= i__3; ++i) {
00278                     work[i] += (d__1 = a[i + k * a_dim1], abs(d__1)) * xk;
00279 
00280                 }
00281 
00282             }
00283         } else {
00284             i__2 = *n;
00285             for (k = 1; k <= i__2; ++k) {
00286                 s = 0.;
00287                 i__3 = *n;
00288                 for (i = 1; i <= i__3; ++i) {
00289                     s += (d__1 = a[i + k * a_dim1], abs(d__1)) * (d__2 = x[i 
00290                             + j * x_dim1], abs(d__2));
00291 
00292                 }
00293                 work[k] += s;
00294 
00295             }
00296         }
00297         s = 0.;
00298         i__2 = *n;
00299         for (i = 1; i <= i__2; ++i) {
00300             if (work[i] > safe2) {
00301 
00302                 d__2 = s, d__3 = (d__1 = work[*n + i], abs(d__1)) / work[i];
00303                 s = max(d__2,d__3);
00304             } else {
00305 
00306                 d__2 = s, d__3 = ((d__1 = work[*n + i], abs(d__1)) + safe1) / 
00307                         (work[i] + safe1);
00308                 s = max(d__2,d__3);
00309             }
00310 
00311         }
00312         berr[j] = s;
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322         if (berr[j] > eps && berr[j] * 2. <= lstres && count <= 5) {
00323 
00324 
00325 
00326             dgetrs_(trans, n, &c__1, &af[af_offset], ldaf, &ipiv[1], &work[*n 
00327                     + 1], n, info, 1L);
00328             daxpy_(n, &c_b17, &work[*n + 1], &c__1, &x[j * x_dim1 + 1], &c__1)
00329                     ;
00330             lstres = berr[j];
00331             ++count;
00332             goto L20;
00333         }
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361         i__2 = *n;
00362         for (i = 1; i <= i__2; ++i) {
00363             if (work[i] > safe2) {
00364                 work[i] = (d__1 = work[*n + i], abs(d__1)) + nz * eps * work[
00365                         i];
00366             } else {
00367                 work[i] = (d__1 = work[*n + i], abs(d__1)) + nz * eps * work[
00368                         i] + safe1;
00369             }
00370 
00371         }
00372 
00373         kase = 0;
00374 L100:
00375         dlacon_(n, &work[(*n << 1) + 1], &work[*n + 1], &iwork[1], &ferr[j], &
00376                 kase);
00377         if (kase != 0) {
00378             if (kase == 1) {
00379 
00380 
00381 
00382                 dgetrs_(transt, n, &c__1, &af[af_offset], ldaf, &ipiv[1], &
00383                         work[*n + 1], n, info, 1L);
00384                 i__2 = *n;
00385                 for (i = 1; i <= i__2; ++i) {
00386                     work[*n + i] = work[i] * work[*n + i];
00387 
00388                 }
00389             } else {
00390 
00391 
00392 
00393                 i__2 = *n;
00394                 for (i = 1; i <= i__2; ++i) {
00395                     work[*n + i] = work[i] * work[*n + i];
00396 
00397                 }
00398                 dgetrs_(trans, n, &c__1, &af[af_offset], ldaf, &ipiv[1], &
00399                         work[*n + 1], n, info, 1L);
00400             }
00401             goto L100;
00402         }
00403 
00404 
00405 
00406         lstres = 0.;
00407         i__2 = *n;
00408         for (i = 1; i <= i__2; ++i) {
00409 
00410             d__2 = lstres, d__3 = (d__1 = x[i + j * x_dim1], abs(d__1));
00411             lstres = max(d__2,d__3);
00412 
00413         }
00414         if (lstres != 0.) {
00415             ferr[j] /= lstres;
00416         }
00417 
00418 
00419     }
00420 
00421     return 0;
00422 
00423 
00424 
00425 } 
00426