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