1       SUBROUTINE DSYRFS( UPLO, N, NRHS, A, LDA, AF, LDAF, IPIV, B, LDB,
  2      $                   X, LDX, FERR, BERR, WORK, IWORK, INFO )
  3 *
  4 *  -- LAPACK routine (version 3.2) --
  5 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  6 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  7 *     November 2006
  8 *
  9 *     Modified to call DLACN2 in place of DLACON, 5 Feb 03, SJH.
 10 *
 11 *     .. Scalar Arguments ..
 12       CHARACTER          UPLO
 13       INTEGER            INFO, LDA, LDAF, LDB, LDX, N, NRHS
 14 *     ..
 15 *     .. Array Arguments ..
 16       INTEGER            IPIV( * ), IWORK( * )
 17       DOUBLE PRECISION   A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
 18      $                   BERR( * ), FERR( * ), WORK( * ), X( LDX, * )
 19 *     ..
 20 *
 21 *  Purpose
 22 *  =======
 23 *
 24 *  DSYRFS improves the computed solution to a system of linear
 25 *  equations when the coefficient matrix is symmetric indefinite, and
 26 *  provides error bounds and backward error estimates for the solution.
 27 *
 28 *  Arguments
 29 *  =========
 30 *
 31 *  UPLO    (input) CHARACTER*1
 32 *          = 'U':  Upper triangle of A is stored;
 33 *          = 'L':  Lower triangle of A is stored.
 34 *
 35 *  N       (input) INTEGER
 36 *          The order of the matrix A.  N >= 0.
 37 *
 38 *  NRHS    (input) INTEGER
 39 *          The number of right hand sides, i.e., the number of columns
 40 *          of the matrices B and X.  NRHS >= 0.
 41 *
 42 *  A       (input) DOUBLE PRECISION array, dimension (LDA,N)
 43 *          The symmetric matrix A.  If UPLO = 'U', the leading N-by-N
 44 *          upper triangular part of A contains the upper triangular part
 45 *          of the matrix A, and the strictly lower triangular part of A
 46 *          is not referenced.  If UPLO = 'L', the leading N-by-N lower
 47 *          triangular part of A contains the lower triangular part of
 48 *          the matrix A, and the strictly upper triangular part of A is
 49 *          not referenced.
 50 *
 51 *  LDA     (input) INTEGER
 52 *          The leading dimension of the array A.  LDA >= max(1,N).
 53 *
 54 *  AF      (input) DOUBLE PRECISION array, dimension (LDAF,N)
 55 *          The factored form of the matrix A.  AF contains the block
 56 *          diagonal matrix D and the multipliers used to obtain the
 57 *          factor U or L from the factorization A = U*D*U**T or
 58 *          A = L*D*L**T as computed by DSYTRF.
 59 *
 60 *  LDAF    (input) INTEGER
 61 *          The leading dimension of the array AF.  LDAF >= max(1,N).
 62 *
 63 *  IPIV    (input) INTEGER array, dimension (N)
 64 *          Details of the interchanges and the block structure of D
 65 *          as determined by DSYTRF.
 66 *
 67 *  B       (input) DOUBLE PRECISION array, dimension (LDB,NRHS)
 68 *          The right hand side matrix B.
 69 *
 70 *  LDB     (input) INTEGER
 71 *          The leading dimension of the array B.  LDB >= max(1,N).
 72 *
 73 *  X       (input/output) DOUBLE PRECISION array, dimension (LDX,NRHS)
 74 *          On entry, the solution matrix X, as computed by DSYTRS.
 75 *          On exit, the improved solution matrix X.
 76 *
 77 *  LDX     (input) INTEGER
 78 *          The leading dimension of the array X.  LDX >= max(1,N).
 79 *
 80 *  FERR    (output) DOUBLE PRECISION array, dimension (NRHS)
 81 *          The estimated forward error bound for each solution vector
 82 *          X(j) (the j-th column of the solution matrix X).
 83 *          If XTRUE is the true solution corresponding to X(j), FERR(j)
 84 *          is an estimated upper bound for the magnitude of the largest
 85 *          element in (X(j) - XTRUE) divided by the magnitude of the
 86 *          largest element in X(j).  The estimate is as reliable as
 87 *          the estimate for RCOND, and is almost always a slight
 88 *          overestimate of the true error.
 89 *
 90 *  BERR    (output) DOUBLE PRECISION array, dimension (NRHS)
 91 *          The componentwise relative backward error of each solution
 92 *          vector X(j) (i.e., the smallest relative change in
 93 *          any element of A or B that makes X(j) an exact solution).
 94 *
 95 *  WORK    (workspace) DOUBLE PRECISION array, dimension (3*N)
 96 *
 97 *  IWORK   (workspace) INTEGER array, dimension (N)
 98 *
 99 *  INFO    (output) INTEGER
100 *          = 0:  successful exit
101 *          < 0:  if INFO = -i, the i-th argument had an illegal value
102 *
103 *  Internal Parameters
104 *  ===================
105 *
106 *  ITMAX is the maximum number of steps of iterative refinement.
107 *
108 *  =====================================================================
109 *
110 *     .. Parameters ..
111       INTEGER            ITMAX
112       PARAMETER          ( ITMAX = 5 )
113       DOUBLE PRECISION   ZERO
114       PARAMETER          ( ZERO = 0.0D+0 )
115       DOUBLE PRECISION   ONE
116       PARAMETER          ( ONE = 1.0D+0 )
117       DOUBLE PRECISION   TWO
118       PARAMETER          ( TWO = 2.0D+0 )
119       DOUBLE PRECISION   THREE
120       PARAMETER          ( THREE = 3.0D+0 )
121 *     ..
122 *     .. Local Scalars ..
123       LOGICAL            UPPER
124       INTEGER            COUNT, I, J, K, KASE, NZ
125       DOUBLE PRECISION   EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK
126 *     ..
127 *     .. Local Arrays ..
128       INTEGER            ISAVE( 3 )
129 *     ..
130 *     .. External Subroutines ..
131       EXTERNAL           DAXPY, DCOPY, DLACN2, DSYMV, DSYTRS, XERBLA
132 *     ..
133 *     .. Intrinsic Functions ..
134       INTRINSIC          ABSMAX
135 *     ..
136 *     .. External Functions ..
137       LOGICAL            LSAME
138       DOUBLE PRECISION   DLAMCH
139       EXTERNAL           LSAME, DLAMCH
140 *     ..
141 *     .. Executable Statements ..
142 *
143 *     Test the input parameters.
144 *
145       INFO = 0
146       UPPER = LSAME( UPLO, 'U' )
147       IF.NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
148          INFO = -1
149       ELSE IF( N.LT.0 ) THEN
150          INFO = -2
151       ELSE IF( NRHS.LT.0 ) THEN
152          INFO = -3
153       ELSE IF( LDA.LT.MAX1, N ) ) THEN
154          INFO = -5
155       ELSE IF( LDAF.LT.MAX1, N ) ) THEN
156          INFO = -7
157       ELSE IF( LDB.LT.MAX1, N ) ) THEN
158          INFO = -10
159       ELSE IF( LDX.LT.MAX1, N ) ) THEN
160          INFO = -12
161       END IF
162       IF( INFO.NE.0 ) THEN
163          CALL XERBLA( 'DSYRFS'-INFO )
164          RETURN
165       END IF
166 *
167 *     Quick return if possible
168 *
169       IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
170          DO 10 J = 1, NRHS
171             FERR( J ) = ZERO
172             BERR( J ) = ZERO
173    10    CONTINUE
174          RETURN
175       END IF
176 *
177 *     NZ = maximum number of nonzero elements in each row of A, plus 1
178 *
179       NZ = N + 1
180       EPS = DLAMCH( 'Epsilon' )
181       SAFMIN = DLAMCH( 'Safe minimum' )
182       SAFE1 = NZ*SAFMIN
183       SAFE2 = SAFE1 / EPS
184 *
185 *     Do for each right hand side
186 *
187       DO 140 J = 1, NRHS
188 *
189          COUNT = 1
190          LSTRES = THREE
191    20    CONTINUE
192 *
193 *        Loop until stopping criterion is satisfied.
194 *
195 *        Compute residual R = B - A * X
196 *
197          CALL DCOPY( N, B( 1, J ), 1, WORK( N+1 ), 1 )
198          CALL DSYMV( UPLO, N, -ONE, A, LDA, X( 1, J ), 1, ONE,
199      $               WORK( N+1 ), 1 )
200 *
201 *        Compute componentwise relative backward error from formula
202 *
203 *        max(i) ( abs(R(i)) / ( abs(A)*abs(X) + abs(B) )(i) )
204 *
205 *        where abs(Z) is the componentwise absolute value of the matrix
206 *        or vector Z.  If the i-th component of the denominator is less
207 *        than SAFE2, then SAFE1 is added to the i-th components of the
208 *        numerator and denominator before dividing.
209 *
210          DO 30 I = 1, N
211             WORK( I ) = ABS( B( I, J ) )
212    30    CONTINUE
213 *
214 *        Compute abs(A)*abs(X) + abs(B).
215 *
216          IF( UPPER ) THEN
217             DO 50 K = 1, N
218                S = ZERO
219                XK = ABS( X( K, J ) )
220                DO 40 I = 1, K - 1
221                   WORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK
222                   S = S + ABS( A( I, K ) )*ABS( X( I, J ) )
223    40          CONTINUE
224                WORK( K ) = WORK( K ) + ABS( A( K, K ) )*XK + S
225    50       CONTINUE
226          ELSE
227             DO 70 K = 1, N
228                S = ZERO
229                XK = ABS( X( K, J ) )
230                WORK( K ) = WORK( K ) + ABS( A( K, K ) )*XK
231                DO 60 I = K + 1, N
232                   WORK( I ) = WORK( I ) + ABS( A( I, K ) )*XK
233                   S = S + ABS( A( I, K ) )*ABS( X( I, J ) )
234    60          CONTINUE
235                WORK( K ) = WORK( K ) + S
236    70       CONTINUE
237          END IF
238          S = ZERO
239          DO 80 I = 1, N
240             IF( WORK( I ).GT.SAFE2 ) THEN
241                S = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )
242             ELSE
243                S = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /
244      $             ( WORK( I )+SAFE1 ) )
245             END IF
246    80    CONTINUE
247          BERR( J ) = S
248 *
249 *        Test stopping criterion. Continue iterating if
250 *           1) The residual BERR(J) is larger than machine epsilon, and
251 *           2) BERR(J) decreased by at least a factor of 2 during the
252 *              last iteration, and
253 *           3) At most ITMAX iterations tried.
254 *
255          IF( BERR( J ).GT.EPS .AND. TWO*BERR( J ).LE.LSTRES .AND.
256      $       COUNT.LE.ITMAX ) THEN
257 *
258 *           Update solution and try again.
259 *
260             CALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,
261      $                   INFO )
262             CALL DAXPY( N, ONE, WORK( N+1 ), 1, X( 1, J ), 1 )
263             LSTRES = BERR( J )
264             COUNT = COUNT + 1
265             GO TO 20
266          END IF
267 *
268 *        Bound error from formula
269 *
270 *        norm(X - XTRUE) / norm(X) .le. FERR =
271 *        norm( abs(inv(A))*
272 *           ( abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) ))) / norm(X)
273 *
274 *        where
275 *          norm(Z) is the magnitude of the largest component of Z
276 *          inv(A) is the inverse of A
277 *          abs(Z) is the componentwise absolute value of the matrix or
278 *             vector Z
279 *          NZ is the maximum number of nonzeros in any row of A, plus 1
280 *          EPS is machine epsilon
281 *
282 *        The i-th component of abs(R)+NZ*EPS*(abs(A)*abs(X)+abs(B))
283 *        is incremented by SAFE1 if the i-th component of
284 *        abs(A)*abs(X) + abs(B) is less than SAFE2.
285 *
286 *        Use DLACN2 to estimate the infinity-norm of the matrix
287 *           inv(A) * diag(W),
288 *        where W = abs(R) + NZ*EPS*( abs(A)*abs(X)+abs(B) )))
289 *
290          DO 90 I = 1, N
291             IF( WORK( I ).GT.SAFE2 ) THEN
292                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )
293             ELSE
294                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1
295             END IF
296    90    CONTINUE
297 *
298          KASE = 0
299   100    CONTINUE
300          CALL DLACN2( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),
301      $                KASE, ISAVE )
302          IF( KASE.NE.0 ) THEN
303             IF( KASE.EQ.1 ) THEN
304 *
305 *              Multiply by diag(W)*inv(A**T).
306 *
307                CALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,
308      $                      INFO )
309                DO 110 I = 1, N
310                   WORK( N+I ) = WORK( I )*WORK( N+I )
311   110          CONTINUE
312             ELSE IF( KASE.EQ.2 ) THEN
313 *
314 *              Multiply by inv(A)*diag(W).
315 *
316                DO 120 I = 1, N
317                   WORK( N+I ) = WORK( I )*WORK( N+I )
318   120          CONTINUE
319                CALL DSYTRS( UPLO, N, 1, AF, LDAF, IPIV, WORK( N+1 ), N,
320      $                      INFO )
321             END IF
322             GO TO 100
323          END IF
324 *
325 *        Normalize error.
326 *
327          LSTRES = ZERO
328          DO 130 I = 1, N
329             LSTRES = MAX( LSTRES, ABS( X( I, J ) ) )
330   130    CONTINUE
331          IF( LSTRES.NE.ZERO )
332      $      FERR( J ) = FERR( J ) / LSTRES
333 *
334   140 CONTINUE
335 *
336       RETURN
337 *
338 *     End of DSYRFS
339 *
340       END