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