a8c8b12aea86d53ebac67d130cb0a98b7f75fd6f
[platform/upstream/lapack.git] / SRC / stprfs.f
1 *> \brief \b STPRFS
2 *
3 *  =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at 
6 *            http://www.netlib.org/lapack/explore-html/ 
7 *
8 *> \htmlonly
9 *> Download STPRFS + dependencies 
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/stprfs.f"> 
11 *> [TGZ]</a> 
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/stprfs.f"> 
13 *> [ZIP]</a> 
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stprfs.f"> 
15 *> [TXT]</a>
16 *> \endhtmlonly 
17 *
18 *  Definition:
19 *  ===========
20 *
21 *       SUBROUTINE STPRFS( UPLO, TRANS, DIAG, N, NRHS, AP, B, LDB, X, LDX,
22 *                          FERR, BERR, WORK, IWORK, INFO )
23
24 *       .. Scalar Arguments ..
25 *       CHARACTER          DIAG, TRANS, UPLO
26 *       INTEGER            INFO, LDB, LDX, N, NRHS
27 *       ..
28 *       .. Array Arguments ..
29 *       INTEGER            IWORK( * )
30 *       REAL               AP( * ), B( LDB, * ), BERR( * ), FERR( * ),
31 *      $                   WORK( * ), X( LDX, * )
32 *       ..
33 *  
34 *
35 *> \par Purpose:
36 *  =============
37 *>
38 *> \verbatim
39 *>
40 *> STPRFS provides error bounds and backward error estimates for the
41 *> solution to a system of linear equations with a triangular packed
42 *> coefficient matrix.
43 *>
44 *> The solution matrix X must be computed by STPTRS or some other
45 *> means before entering this routine.  STPRFS does not do iterative
46 *> refinement because doing so cannot improve the backward error.
47 *> \endverbatim
48 *
49 *  Arguments:
50 *  ==========
51 *
52 *> \param[in] UPLO
53 *> \verbatim
54 *>          UPLO is CHARACTER*1
55 *>          = 'U':  A is upper triangular;
56 *>          = 'L':  A is lower triangular.
57 *> \endverbatim
58 *>
59 *> \param[in] TRANS
60 *> \verbatim
61 *>          TRANS is CHARACTER*1
62 *>          Specifies the form of the system of equations:
63 *>          = 'N':  A * X = B  (No transpose)
64 *>          = 'T':  A**T * X = B  (Transpose)
65 *>          = 'C':  A**H * X = B  (Conjugate transpose = Transpose)
66 *> \endverbatim
67 *>
68 *> \param[in] DIAG
69 *> \verbatim
70 *>          DIAG is CHARACTER*1
71 *>          = 'N':  A is non-unit triangular;
72 *>          = 'U':  A is unit triangular.
73 *> \endverbatim
74 *>
75 *> \param[in] N
76 *> \verbatim
77 *>          N is INTEGER
78 *>          The order of the matrix A.  N >= 0.
79 *> \endverbatim
80 *>
81 *> \param[in] NRHS
82 *> \verbatim
83 *>          NRHS is INTEGER
84 *>          The number of right hand sides, i.e., the number of columns
85 *>          of the matrices B and X.  NRHS >= 0.
86 *> \endverbatim
87 *>
88 *> \param[in] AP
89 *> \verbatim
90 *>          AP is REAL array, dimension (N*(N+1)/2)
91 *>          The upper or lower triangular matrix A, packed columnwise in
92 *>          a linear array.  The j-th column of A is stored in the array
93 *>          AP as follows:
94 *>          if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
95 *>          if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.
96 *>          If DIAG = 'U', the diagonal elements of A are not referenced
97 *>          and are assumed to be 1.
98 *> \endverbatim
99 *>
100 *> \param[in] B
101 *> \verbatim
102 *>          B is REAL array, dimension (LDB,NRHS)
103 *>          The right hand side matrix B.
104 *> \endverbatim
105 *>
106 *> \param[in] LDB
107 *> \verbatim
108 *>          LDB is INTEGER
109 *>          The leading dimension of the array B.  LDB >= max(1,N).
110 *> \endverbatim
111 *>
112 *> \param[in] X
113 *> \verbatim
114 *>          X is REAL array, dimension (LDX,NRHS)
115 *>          The solution matrix X.
116 *> \endverbatim
117 *>
118 *> \param[in] LDX
119 *> \verbatim
120 *>          LDX is INTEGER
121 *>          The leading dimension of the array X.  LDX >= max(1,N).
122 *> \endverbatim
123 *>
124 *> \param[out] FERR
125 *> \verbatim
126 *>          FERR is REAL array, dimension (NRHS)
127 *>          The estimated forward error bound for each solution vector
128 *>          X(j) (the j-th column of the solution matrix X).
129 *>          If XTRUE is the true solution corresponding to X(j), FERR(j)
130 *>          is an estimated upper bound for the magnitude of the largest
131 *>          element in (X(j) - XTRUE) divided by the magnitude of the
132 *>          largest element in X(j).  The estimate is as reliable as
133 *>          the estimate for RCOND, and is almost always a slight
134 *>          overestimate of the true error.
135 *> \endverbatim
136 *>
137 *> \param[out] BERR
138 *> \verbatim
139 *>          BERR is REAL array, dimension (NRHS)
140 *>          The componentwise relative backward error of each solution
141 *>          vector X(j) (i.e., the smallest relative change in
142 *>          any element of A or B that makes X(j) an exact solution).
143 *> \endverbatim
144 *>
145 *> \param[out] WORK
146 *> \verbatim
147 *>          WORK is REAL array, dimension (3*N)
148 *> \endverbatim
149 *>
150 *> \param[out] IWORK
151 *> \verbatim
152 *>          IWORK is INTEGER array, dimension (N)
153 *> \endverbatim
154 *>
155 *> \param[out] INFO
156 *> \verbatim
157 *>          INFO is INTEGER
158 *>          = 0:  successful exit
159 *>          < 0:  if INFO = -i, the i-th argument had an illegal value
160 *> \endverbatim
161 *
162 *  Authors:
163 *  ========
164 *
165 *> \author Univ. of Tennessee 
166 *> \author Univ. of California Berkeley 
167 *> \author Univ. of Colorado Denver 
168 *> \author NAG Ltd. 
169 *
170 *> \date November 2011
171 *
172 *> \ingroup realOTHERcomputational
173 *
174 *  =====================================================================
175       SUBROUTINE STPRFS( UPLO, TRANS, DIAG, N, NRHS, AP, B, LDB, X, LDX,
176      $                   FERR, BERR, WORK, IWORK, INFO )
177 *
178 *  -- LAPACK computational routine (version 3.4.0) --
179 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
180 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
181 *     November 2011
182 *
183 *     .. Scalar Arguments ..
184       CHARACTER          DIAG, TRANS, UPLO
185       INTEGER            INFO, LDB, LDX, N, NRHS
186 *     ..
187 *     .. Array Arguments ..
188       INTEGER            IWORK( * )
189       REAL               AP( * ), B( LDB, * ), BERR( * ), FERR( * ),
190      $                   WORK( * ), X( LDX, * )
191 *     ..
192 *
193 *  =====================================================================
194 *
195 *     .. Parameters ..
196       REAL               ZERO
197       PARAMETER          ( ZERO = 0.0E+0 )
198       REAL               ONE
199       PARAMETER          ( ONE = 1.0E+0 )
200 *     ..
201 *     .. Local Scalars ..
202       LOGICAL            NOTRAN, NOUNIT, UPPER
203       CHARACTER          TRANST
204       INTEGER            I, J, K, KASE, KC, NZ
205       REAL               EPS, LSTRES, S, SAFE1, SAFE2, SAFMIN, XK
206 *     ..
207 *     .. Local Arrays ..
208       INTEGER            ISAVE( 3 )
209 *     ..
210 *     .. External Subroutines ..
211       EXTERNAL           SAXPY, SCOPY, SLACN2, STPMV, STPSV, XERBLA
212 *     ..
213 *     .. Intrinsic Functions ..
214       INTRINSIC          ABS, MAX
215 *     ..
216 *     .. External Functions ..
217       LOGICAL            LSAME
218       REAL               SLAMCH
219       EXTERNAL           LSAME, SLAMCH
220 *     ..
221 *     .. Executable Statements ..
222 *
223 *     Test the input parameters.
224 *
225       INFO = 0
226       UPPER = LSAME( UPLO, 'U' )
227       NOTRAN = LSAME( TRANS, 'N' )
228       NOUNIT = LSAME( DIAG, 'N' )
229 *
230       IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
231          INFO = -1
232       ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT.
233      $         LSAME( TRANS, 'C' ) ) THEN
234          INFO = -2
235       ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN
236          INFO = -3
237       ELSE IF( N.LT.0 ) THEN
238          INFO = -4
239       ELSE IF( NRHS.LT.0 ) THEN
240          INFO = -5
241       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
242          INFO = -8
243       ELSE IF( LDX.LT.MAX( 1, N ) ) THEN
244          INFO = -10
245       END IF
246       IF( INFO.NE.0 ) THEN
247          CALL XERBLA( 'STPRFS', -INFO )
248          RETURN
249       END IF
250 *
251 *     Quick return if possible
252 *
253       IF( N.EQ.0 .OR. NRHS.EQ.0 ) THEN
254          DO 10 J = 1, NRHS
255             FERR( J ) = ZERO
256             BERR( J ) = ZERO
257    10    CONTINUE
258          RETURN
259       END IF
260 *
261       IF( NOTRAN ) THEN
262          TRANST = 'T'
263       ELSE
264          TRANST = 'N'
265       END IF
266 *
267 *     NZ = maximum number of nonzero elements in each row of A, plus 1
268 *
269       NZ = N + 1
270       EPS = SLAMCH( 'Epsilon' )
271       SAFMIN = SLAMCH( 'Safe minimum' )
272       SAFE1 = NZ*SAFMIN
273       SAFE2 = SAFE1 / EPS
274 *
275 *     Do for each right hand side
276 *
277       DO 250 J = 1, NRHS
278 *
279 *        Compute residual R = B - op(A) * X,
280 *        where op(A) = A or A**T, depending on TRANS.
281 *
282          CALL SCOPY( N, X( 1, J ), 1, WORK( N+1 ), 1 )
283          CALL STPMV( UPLO, TRANS, DIAG, N, AP, WORK( N+1 ), 1 )
284          CALL SAXPY( N, -ONE, B( 1, J ), 1, WORK( N+1 ), 1 )
285 *
286 *        Compute componentwise relative backward error from formula
287 *
288 *        max(i) ( abs(R(i)) / ( abs(op(A))*abs(X) + abs(B) )(i) )
289 *
290 *        where abs(Z) is the componentwise absolute value of the matrix
291 *        or vector Z.  If the i-th component of the denominator is less
292 *        than SAFE2, then SAFE1 is added to the i-th components of the
293 *        numerator and denominator before dividing.
294 *
295          DO 20 I = 1, N
296             WORK( I ) = ABS( B( I, J ) )
297    20    CONTINUE
298 *
299          IF( NOTRAN ) THEN
300 *
301 *           Compute abs(A)*abs(X) + abs(B).
302 *
303             IF( UPPER ) THEN
304                KC = 1
305                IF( NOUNIT ) THEN
306                   DO 40 K = 1, N
307                      XK = ABS( X( K, J ) )
308                      DO 30 I = 1, K
309                         WORK( I ) = WORK( I ) + ABS( AP( KC+I-1 ) )*XK
310    30                CONTINUE
311                      KC = KC + K
312    40             CONTINUE
313                ELSE
314                   DO 60 K = 1, N
315                      XK = ABS( X( K, J ) )
316                      DO 50 I = 1, K - 1
317                         WORK( I ) = WORK( I ) + ABS( AP( KC+I-1 ) )*XK
318    50                CONTINUE
319                      WORK( K ) = WORK( K ) + XK
320                      KC = KC + K
321    60             CONTINUE
322                END IF
323             ELSE
324                KC = 1
325                IF( NOUNIT ) THEN
326                   DO 80 K = 1, N
327                      XK = ABS( X( K, J ) )
328                      DO 70 I = K, N
329                         WORK( I ) = WORK( I ) + ABS( AP( KC+I-K ) )*XK
330    70                CONTINUE
331                      KC = KC + N - K + 1
332    80             CONTINUE
333                ELSE
334                   DO 100 K = 1, N
335                      XK = ABS( X( K, J ) )
336                      DO 90 I = K + 1, N
337                         WORK( I ) = WORK( I ) + ABS( AP( KC+I-K ) )*XK
338    90                CONTINUE
339                      WORK( K ) = WORK( K ) + XK
340                      KC = KC + N - K + 1
341   100             CONTINUE
342                END IF
343             END IF
344          ELSE
345 *
346 *           Compute abs(A**T)*abs(X) + abs(B).
347 *
348             IF( UPPER ) THEN
349                KC = 1
350                IF( NOUNIT ) THEN
351                   DO 120 K = 1, N
352                      S = ZERO
353                      DO 110 I = 1, K
354                         S = S + ABS( AP( KC+I-1 ) )*ABS( X( I, J ) )
355   110                CONTINUE
356                      WORK( K ) = WORK( K ) + S
357                      KC = KC + K
358   120             CONTINUE
359                ELSE
360                   DO 140 K = 1, N
361                      S = ABS( X( K, J ) )
362                      DO 130 I = 1, K - 1
363                         S = S + ABS( AP( KC+I-1 ) )*ABS( X( I, J ) )
364   130                CONTINUE
365                      WORK( K ) = WORK( K ) + S
366                      KC = KC + K
367   140             CONTINUE
368                END IF
369             ELSE
370                KC = 1
371                IF( NOUNIT ) THEN
372                   DO 160 K = 1, N
373                      S = ZERO
374                      DO 150 I = K, N
375                         S = S + ABS( AP( KC+I-K ) )*ABS( X( I, J ) )
376   150                CONTINUE
377                      WORK( K ) = WORK( K ) + S
378                      KC = KC + N - K + 1
379   160             CONTINUE
380                ELSE
381                   DO 180 K = 1, N
382                      S = ABS( X( K, J ) )
383                      DO 170 I = K + 1, N
384                         S = S + ABS( AP( KC+I-K ) )*ABS( X( I, J ) )
385   170                CONTINUE
386                      WORK( K ) = WORK( K ) + S
387                      KC = KC + N - K + 1
388   180             CONTINUE
389                END IF
390             END IF
391          END IF
392          S = ZERO
393          DO 190 I = 1, N
394             IF( WORK( I ).GT.SAFE2 ) THEN
395                S = MAX( S, ABS( WORK( N+I ) ) / WORK( I ) )
396             ELSE
397                S = MAX( S, ( ABS( WORK( N+I ) )+SAFE1 ) /
398      $             ( WORK( I )+SAFE1 ) )
399             END IF
400   190    CONTINUE
401          BERR( J ) = S
402 *
403 *        Bound error from formula
404 *
405 *        norm(X - XTRUE) / norm(X) .le. FERR =
406 *        norm( abs(inv(op(A)))*
407 *           ( abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) ))) / norm(X)
408 *
409 *        where
410 *          norm(Z) is the magnitude of the largest component of Z
411 *          inv(op(A)) is the inverse of op(A)
412 *          abs(Z) is the componentwise absolute value of the matrix or
413 *             vector Z
414 *          NZ is the maximum number of nonzeros in any row of A, plus 1
415 *          EPS is machine epsilon
416 *
417 *        The i-th component of abs(R)+NZ*EPS*(abs(op(A))*abs(X)+abs(B))
418 *        is incremented by SAFE1 if the i-th component of
419 *        abs(op(A))*abs(X) + abs(B) is less than SAFE2.
420 *
421 *        Use SLACN2 to estimate the infinity-norm of the matrix
422 *           inv(op(A)) * diag(W),
423 *        where W = abs(R) + NZ*EPS*( abs(op(A))*abs(X)+abs(B) )))
424 *
425          DO 200 I = 1, N
426             IF( WORK( I ).GT.SAFE2 ) THEN
427                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I )
428             ELSE
429                WORK( I ) = ABS( WORK( N+I ) ) + NZ*EPS*WORK( I ) + SAFE1
430             END IF
431   200    CONTINUE
432 *
433          KASE = 0
434   210    CONTINUE
435          CALL SLACN2( N, WORK( 2*N+1 ), WORK( N+1 ), IWORK, FERR( J ),
436      $                KASE, ISAVE )
437          IF( KASE.NE.0 ) THEN
438             IF( KASE.EQ.1 ) THEN
439 *
440 *              Multiply by diag(W)*inv(op(A)**T).
441 *
442                CALL STPSV( UPLO, TRANST, DIAG, N, AP, WORK( N+1 ), 1 )
443                DO 220 I = 1, N
444                   WORK( N+I ) = WORK( I )*WORK( N+I )
445   220          CONTINUE
446             ELSE
447 *
448 *              Multiply by inv(op(A))*diag(W).
449 *
450                DO 230 I = 1, N
451                   WORK( N+I ) = WORK( I )*WORK( N+I )
452   230          CONTINUE
453                CALL STPSV( UPLO, TRANS, DIAG, N, AP, WORK( N+1 ), 1 )
454             END IF
455             GO TO 210
456          END IF
457 *
458 *        Normalize error.
459 *
460          LSTRES = ZERO
461          DO 240 I = 1, N
462             LSTRES = MAX( LSTRES, ABS( X( I, J ) ) )
463   240    CONTINUE
464          IF( LSTRES.NE.ZERO )
465      $      FERR( J ) = FERR( J ) / LSTRES
466 *
467   250 CONTINUE
468 *
469       RETURN
470 *
471 *     End of STPRFS
472 *
473       END