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