00001 SUBROUTINE SPTRFS( N, NRHS, D, E, DF, EF, B, LDB, X, LDX, FERR,
00002 $ BERR, WORK, INFO )
00003
00004
00005
00006
00007
00008
00009
00010 INTEGER INFO, LDB, LDX, N, NRHS
00011
00012
00013 REAL B( LDB, * ), BERR( * ), D( * ), DF( * ),
00014 $ E( * ), EF( * ), FERR( * ), WORK( * ),
00015 $ X( LDX, * )
00016
00017
00018
00019
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 INTEGER ITMAX
00091 PARAMETER ( ITMAX = 5 )
00092 REAL ZERO
00093 PARAMETER ( ZERO = 0.0E+0 )
00094 REAL ONE
00095 PARAMETER ( ONE = 1.0E+0 )
00096 REAL TWO
00097 PARAMETER ( TWO = 2.0E+0 )
00098 REAL THREE
00099 PARAMETER ( THREE = 3.0E+0 )
00100
00101
00102 INTEGER COUNT, I, IX, J, NZ
00103 REAL BI, CX, DX, EPS, EX, LSTRES, S, SAFE1, SAFE2,
00104 $ SAFMIN
00105
00106
00107 EXTERNAL SAXPY, SPTTRS, XERBLA
00108
00109
00110 INTRINSIC ABS, MAX
00111
00112
00113 INTEGER ISAMAX
00114 REAL SLAMCH
00115 EXTERNAL ISAMAX, SLAMCH
00116
00117
00118
00119
00120
00121 INFO = 0
00122 IF( N.LT.0 ) THEN
00123 INFO = -1
00124 ELSE IF( NRHS.LT.0 ) THEN
00125 INFO = -2
00126 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00127 INFO = -8
00128 ELSE IF( LDX.LT.MAX( 1, N ) ) THEN
00129 INFO = -10
00130 END IF
00131 IF( INFO.NE.0 ) THEN
00132 CALL XERBLA( 'SPTRFS', -INFO )
00133 RETURN
00134 END IF
00135
00136
00137
00138 IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
00139 DO 10 J = 1, NRHS
00140 FERR( J ) = ZERO
00141 BERR( J ) = ZERO
00142 10 CONTINUE
00143 RETURN
00144 END IF
00145
00146
00147
00148 NZ = 4
00149 EPS = SLAMCH( 'Epsilon' )
00150 SAFMIN = SLAMCH( 'Safe minimum' )
00151 SAFE1 = NZ*SAFMIN
00152 SAFE2 = SAFE1 / EPS
00153
00154
00155
00156 DO 90 J = 1, NRHS
00157
00158 COUNT = 1
00159 LSTRES = THREE
00160 20 CONTINUE
00161
00162
00163
00164
00165
00166
00167 IF( N.EQ.1 ) THEN
00168 BI = B( 1, J )
00169 DX = D( 1 )*X( 1, J )
00170 WORK( N+1 ) = BI - DX
00171 WORK( 1 ) = ABS( BI ) + ABS( DX )
00172 ELSE
00173 BI = B( 1, J )
00174 DX = D( 1 )*X( 1, J )
00175 EX = E( 1 )*X( 2, J )
00176 WORK( N+1 ) = BI - DX - EX
00177 WORK( 1 ) = ABS( BI ) + ABS( DX ) + ABS( EX )
00178 DO 30 I = 2, N - 1
00179 BI = B( I, J )
00180 CX = E( I-1 )*X( I-1, J )
00181 DX = D( I )*X( I, J )
00182 EX = E( I )*X( I+1, J )
00183 WORK( N+I ) = BI - CX - DX - EX
00184 WORK( I ) = ABS( BI ) + ABS( CX ) + ABS( DX ) + ABS( EX )
00185 30 CONTINUE
00186 BI = B( N, J )
00187 CX = E( N-1 )*X( N-1, J )
00188 DX = D( N )*X( N, J )
00189 WORK( N+N ) = BI - CX - DX
00190 WORK( N ) = ABS( BI ) + ABS( CX ) + ABS( DX )
00191 END IF
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 S = ZERO
00203 DO 40 I = 1, N
00204 IF( WORK( I ).GT.SAFE2 ) THEN
00205 S = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )
00206 ELSE
00207 S = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /
00208 $ ( WORK( I )+SAFE1 ) )
00209 END IF
00210 40 CONTINUE
00211 BERR( J ) = S
00212
00213
00214
00215
00216
00217
00218
00219 IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.
00220 $ COUNT.LE.ITMAX ) THEN
00221
00222
00223
00224 CALL SPTTRS( N, 1, DF, EF, WORK( N+1 ), N, INFO )
00225 CALL SAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )
00226 LSTRES = BERR( J )
00227 COUNT = COUNT + 1
00228 GO TO 20
00229 END IF
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 DO 50 I = 1, N
00250 IF( WORK( I ).GT.SAFE2 ) THEN
00251 WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )
00252 ELSE
00253 WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1
00254 END IF
00255 50 CONTINUE
00256 IX = ISAMAX( N, WORK, 1 )
00257 FERR( J ) = WORK( IX )
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 WORK( 1 ) = ONE
00271 DO 60 I = 2, N
00272 WORK( I ) = ONE + WORK( I-1 )*ABS( EF( I-1 ) )
00273 60 CONTINUE
00274
00275
00276
00277 WORK( N ) = WORK( N ) / DF( N )
00278 DO 70 I = N - 1, 1, -1
00279 WORK( I ) = WORK( I ) / DF( I ) + WORK( I+1 )*ABS( EF( I ) )
00280 70 CONTINUE
00281
00282
00283
00284 IX = ISAMAX( N, WORK, 1 )
00285 FERR( J ) = FERR( J )*ABS( WORK( IX ) )
00286
00287
00288
00289 LSTRES = ZERO
00290 DO 80 I = 1, N
00291 LSTRES = MAX( LSTRES, ABS( X( I, J ) ) )
00292 80 CONTINUE
00293 IF( LSTRES.NE.ZERO )
00294 $ FERR( J ) = FERR( J ) / LSTRES
00295
00296 90 CONTINUE
00297
00298 RETURN
00299
00300
00301
00302 END