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