00001 SUBROUTINE CGERFS( TRANS, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB,
00002 $ X, LDX, FERR, BERR, WORK, RWORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 CHARACTER TRANS
00013 INTEGER INFO, LDA, LDAF, LDB, LDX, N, NRHS
00014
00015
00016 INTEGER IPIV( * )
00017 REAL BERR( * ), FERR( * ), RWORK( * )
00018 COMPLEX A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
00019 $ WORK( * ), X( LDX, * )
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
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 INTEGER ITMAX
00107 PARAMETER ( ITMAX = 5 )
00108 REAL ZERO
00109 PARAMETER ( ZERO = 0.0E+0 )
00110 COMPLEX ONE
00111 PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) )
00112 REAL TWO
00113 PARAMETER ( TWO = 2.0E+0 )
00114 REAL THREE
00115 PARAMETER ( THREE = 3.0E+0 )
00116
00117
00118 LOGICAL NOTRAN
00119 CHARACTER TRANSN, TRANST
00120 INTEGER COUNT, I, J, K, KASE, NZ
00121 REAL EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK
00122 COMPLEX ZDUM
00123
00124
00125 INTEGER ISAVE( 3 )
00126
00127
00128 LOGICAL LSAME
00129 REAL SLAMCH
00130 EXTERNAL LSAME, SLAMCH
00131
00132
00133 EXTERNAL CAXPY, CCOPY, CGEMV, CGETRS, CLACN2, XERBLA
00134
00135
00136 INTRINSIC ABS, AIMAG, MAX, REAL
00137
00138
00139 REAL CABS1
00140
00141
00142 CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
00143
00144
00145
00146
00147
00148 INFO = 0
00149 NOTRAN = LSAME( TRANS, 'N' )
00150 IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
00151 $ LSAME( TRANS, 'C' ) ) THEN
00152 INFO = -1
00153 ELSE IF( N.LT.0 ) THEN
00154 INFO = -2
00155 ELSE IF( NRHS.LT.0 ) THEN
00156 INFO = -3
00157 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00158 INFO = -5
00159 ELSE IF( LDAF.LT.MAX( 1, N ) ) THEN
00160 INFO = -7
00161 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00162 INFO = -10
00163 ELSE IF( LDX.LT.MAX( 1, N ) ) THEN
00164 INFO = -12
00165 END IF
00166 IF( INFO.NE.0 ) THEN
00167 CALL XERBLA( 'CGERFS', -INFO )
00168 RETURN
00169 END IF
00170
00171
00172
00173 IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
00174 DO 10 J = 1, NRHS
00175 FERR( J ) = ZERO
00176 BERR( J ) = ZERO
00177 10 CONTINUE
00178 RETURN
00179 END IF
00180
00181 IF( NOTRAN ) THEN
00182 TRANSN = 'N'
00183 TRANST = 'C'
00184 ELSE
00185 TRANSN = 'C'
00186 TRANST = 'N'
00187 END IF
00188
00189
00190
00191 NZ = N + 1
00192 EPS = SLAMCH( 'Epsilon' )
00193 SAFMIN = SLAMCH( 'Safe minimum' )
00194 SAFE1 = NZ*SAFMIN
00195 SAFE2 = SAFE1 / EPS
00196
00197
00198
00199 DO 140 J = 1, NRHS
00200
00201 COUNT = 1
00202 LSTRES = THREE
00203 20 CONTINUE
00204
00205
00206
00207
00208
00209
00210 CALL CCOPY( N, B( 1, J ), 1, WORK, 1 )
00211 CALL CGEMV( TRANS, N, N, -ONE, A, LDA, X( 1, J ), 1, ONE, WORK,
00212 $ 1 )
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 DO 30 I = 1, N
00224 RWORK( I ) = CABS1( B( I, J ) )
00225 30 CONTINUE
00226
00227
00228
00229 IF( NOTRAN ) THEN
00230 DO 50 K = 1, N
00231 XK = CABS1( X( K, J ) )
00232 DO 40 I = 1, N
00233 RWORK( I ) = RWORK( I ) + CABS1( A( I, K ) )*XK
00234 40 CONTINUE
00235 50 CONTINUE
00236 ELSE
00237 DO 70 K = 1, N
00238 S = ZERO
00239 DO 60 I = 1, N
00240 S = S + CABS1( A( I, K ) )*CABS1( X( I, J ) )
00241 60 CONTINUE
00242 RWORK( K ) = RWORK( K ) + S
00243 70 CONTINUE
00244 END IF
00245 S = ZERO
00246 DO 80 I = 1, N
00247 IF( RWORK( I ).GT.SAFE2 ) THEN
00248 S = MAX( S, CABS1( WORK( I ) ) / RWORK( I ) )
00249 ELSE
00250 S = MAX( S, ( CABS1( WORK( I ) )+SAFE1 ) /
00251 $ ( RWORK( I )+SAFE1 ) )
00252 END IF
00253 80 CONTINUE
00254 BERR( J ) = S
00255
00256
00257
00258
00259
00260
00261
00262 IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.
00263 $ COUNT.LE.ITMAX ) THEN
00264
00265
00266
00267 CALL CGETRS( TRANS, N, 1, AF, LDAF, IPIV, WORK, N, INFO )
00268 CALL CAXPY( N, ONE, WORK, 1, X( 1, J ), 1 )
00269 LSTRES = BERR( J )
00270 COUNT = COUNT + 1
00271 GO TO 20
00272 END IF
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 DO 90 I = 1, N
00297 IF( RWORK( I ).GT.SAFE2 ) THEN
00298 RWORK( I ) = CABS1( WORK( I ) ) + NZ*EPS*RWORK( I )
00299 ELSE
00300 RWORK( I ) = CABS1( WORK( I ) ) + NZ*EPS*RWORK( I ) +
00301 $ SAFE1
00302 END IF
00303 90 CONTINUE
00304
00305 KASE = 0
00306 100 CONTINUE
00307 CALL CLACN2( N, WORK( N+1 ), WORK, FERR( J ), KASE, ISAVE )
00308 IF( KASE.NE.0 ) THEN
00309 IF( KASE.EQ.1 ) THEN
00310
00311
00312
00313 CALL CGETRS( TRANST, N, 1, AF, LDAF, IPIV, WORK, N,
00314 $ INFO )
00315 DO 110 I = 1, N
00316 WORK( I ) = RWORK( I )*WORK( I )
00317 110 CONTINUE
00318 ELSE
00319
00320
00321
00322 DO 120 I = 1, N
00323 WORK( I ) = RWORK( I )*WORK( I )
00324 120 CONTINUE
00325 CALL CGETRS( TRANSN, N, 1, AF, LDAF, IPIV, WORK, N,
00326 $ INFO )
00327 END IF
00328 GO TO 100
00329 END IF
00330
00331
00332
00333 LSTRES = ZERO
00334 DO 130 I = 1, N
00335 LSTRES = MAX( LSTRES, CABS1( X( I, J ) ) )
00336 130 CONTINUE
00337 IF( LSTRES.NE.ZERO )
00338 $ FERR( J ) = FERR( J ) / LSTRES
00339
00340 140 CONTINUE
00341
00342 RETURN
00343
00344
00345
00346 END