1*> \brief \b SLA_SYRFSX_EXTENDED improves the computed solution to a system of linear equations for symmetric indefinite matrices by performing extra-precise iterative refinement and provides error bounds and backward error estimates for the solution.
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download SLA_SYRFSX_EXTENDED + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sla_syrfsx_extended.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sla_syrfsx_extended.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sla_syrfsx_extended.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE SLA_SYRFSX_EXTENDED( PREC_TYPE, UPLO, N, NRHS, A, LDA,
22*                                       AF, LDAF, IPIV, COLEQU, C, B, LDB,
23*                                       Y, LDY, BERR_OUT, N_NORMS,
24*                                       ERR_BNDS_NORM, ERR_BNDS_COMP, RES,
25*                                       AYB, DY, Y_TAIL, RCOND, ITHRESH,
26*                                       RTHRESH, DZ_UB, IGNORE_CWISE,
27*                                       INFO )
28*
29*       .. Scalar Arguments ..
30*       INTEGER            INFO, LDA, LDAF, LDB, LDY, N, NRHS, PREC_TYPE,
31*      $                   N_NORMS, ITHRESH
32*       CHARACTER          UPLO
33*       LOGICAL            COLEQU, IGNORE_CWISE
34*       REAL               RTHRESH, DZ_UB
35*       ..
36*       .. Array Arguments ..
37*       INTEGER            IPIV( * )
38*       REAL               A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
39*      $                   Y( LDY, * ), RES( * ), DY( * ), Y_TAIL( * )
40*       REAL               C( * ), AYB( * ), RCOND, BERR_OUT( * ),
41*      $                   ERR_BNDS_NORM( NRHS, * ),
42*      $                   ERR_BNDS_COMP( NRHS, * )
43*       ..
44*
45*
46*> \par Purpose:
47*  =============
48*>
49*> \verbatim
50*>
51*>
52*> SLA_SYRFSX_EXTENDED improves the computed solution to a system of
53*> linear equations by performing extra-precise iterative refinement
54*> and provides error bounds and backward error estimates for the solution.
55*> This subroutine is called by SSYRFSX to perform iterative refinement.
56*> In addition to normwise error bound, the code provides maximum
57*> componentwise error bound if possible. See comments for ERR_BNDS_NORM
58*> and ERR_BNDS_COMP for details of the error bounds. Note that this
59*> subroutine is only resonsible for setting the second fields of
60*> ERR_BNDS_NORM and ERR_BNDS_COMP.
61*> \endverbatim
62*
63*  Arguments:
64*  ==========
65*
66*> \param[in] PREC_TYPE
67*> \verbatim
68*>          PREC_TYPE is INTEGER
69*>     Specifies the intermediate precision to be used in refinement.
70*>     The value is defined by ILAPREC(P) where P is a CHARACTER and P
71*>          = 'S':  Single
72*>          = 'D':  Double
73*>          = 'I':  Indigenous
74*>          = 'X' or 'E':  Extra
75*> \endverbatim
76*>
77*> \param[in] UPLO
78*> \verbatim
79*>          UPLO is CHARACTER*1
80*>       = 'U':  Upper triangle of A is stored;
81*>       = 'L':  Lower triangle of A is stored.
82*> \endverbatim
83*>
84*> \param[in] N
85*> \verbatim
86*>          N is INTEGER
87*>     The number of linear equations, i.e., the order of the
88*>     matrix A.  N >= 0.
89*> \endverbatim
90*>
91*> \param[in] NRHS
92*> \verbatim
93*>          NRHS is INTEGER
94*>     The number of right-hand-sides, i.e., the number of columns of the
95*>     matrix B.
96*> \endverbatim
97*>
98*> \param[in] A
99*> \verbatim
100*>          A is REAL array, dimension (LDA,N)
101*>     On entry, the N-by-N matrix A.
102*> \endverbatim
103*>
104*> \param[in] LDA
105*> \verbatim
106*>          LDA is INTEGER
107*>     The leading dimension of the array A.  LDA >= max(1,N).
108*> \endverbatim
109*>
110*> \param[in] AF
111*> \verbatim
112*>          AF is REAL array, dimension (LDAF,N)
113*>     The block diagonal matrix D and the multipliers used to
114*>     obtain the factor U or L as computed by SSYTRF.
115*> \endverbatim
116*>
117*> \param[in] LDAF
118*> \verbatim
119*>          LDAF is INTEGER
120*>     The leading dimension of the array AF.  LDAF >= max(1,N).
121*> \endverbatim
122*>
123*> \param[in] IPIV
124*> \verbatim
125*>          IPIV is INTEGER array, dimension (N)
126*>     Details of the interchanges and the block structure of D
127*>     as determined by SSYTRF.
128*> \endverbatim
129*>
130*> \param[in] COLEQU
131*> \verbatim
132*>          COLEQU is LOGICAL
133*>     If .TRUE. then column equilibration was done to A before calling
134*>     this routine. This is needed to compute the solution and error
135*>     bounds correctly.
136*> \endverbatim
137*>
138*> \param[in] C
139*> \verbatim
140*>          C is REAL array, dimension (N)
141*>     The column scale factors for A. If COLEQU = .FALSE., C
142*>     is not accessed. If C is input, each element of C should be a power
143*>     of the radix to ensure a reliable solution and error estimates.
144*>     Scaling by powers of the radix does not cause rounding errors unless
145*>     the result underflows or overflows. Rounding errors during scaling
146*>     lead to refining with a matrix that is not equivalent to the
147*>     input matrix, producing error estimates that may not be
148*>     reliable.
149*> \endverbatim
150*>
151*> \param[in] B
152*> \verbatim
153*>          B is REAL array, dimension (LDB,NRHS)
154*>     The right-hand-side matrix B.
155*> \endverbatim
156*>
157*> \param[in] LDB
158*> \verbatim
159*>          LDB is INTEGER
160*>     The leading dimension of the array B.  LDB >= max(1,N).
161*> \endverbatim
162*>
163*> \param[in,out] Y
164*> \verbatim
165*>          Y is REAL array, dimension (LDY,NRHS)
166*>     On entry, the solution matrix X, as computed by SSYTRS.
167*>     On exit, the improved solution matrix Y.
168*> \endverbatim
169*>
170*> \param[in] LDY
171*> \verbatim
172*>          LDY is INTEGER
173*>     The leading dimension of the array Y.  LDY >= max(1,N).
174*> \endverbatim
175*>
176*> \param[out] BERR_OUT
177*> \verbatim
178*>          BERR_OUT is REAL array, dimension (NRHS)
179*>     On exit, BERR_OUT(j) contains the componentwise relative backward
180*>     error for right-hand-side j from the formula
181*>         max(i) ( abs(RES(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) )
182*>     where abs(Z) is the componentwise absolute value of the matrix
183*>     or vector Z. This is computed by SLA_LIN_BERR.
184*> \endverbatim
185*>
186*> \param[in] N_NORMS
187*> \verbatim
188*>          N_NORMS is INTEGER
189*>     Determines which error bounds to return (see ERR_BNDS_NORM
190*>     and ERR_BNDS_COMP).
191*>     If N_NORMS >= 1 return normwise error bounds.
192*>     If N_NORMS >= 2 return componentwise error bounds.
193*> \endverbatim
194*>
195*> \param[in,out] ERR_BNDS_NORM
196*> \verbatim
197*>          ERR_BNDS_NORM is REAL array, dimension (NRHS, N_ERR_BNDS)
198*>     For each right-hand side, this array contains information about
199*>     various error bounds and condition numbers corresponding to the
200*>     normwise relative error, which is defined as follows:
201*>
202*>     Normwise relative error in the ith solution vector:
203*>             max_j (abs(XTRUE(j,i) - X(j,i)))
204*>            ------------------------------
205*>                  max_j abs(X(j,i))
206*>
207*>     The array is indexed by the type of error information as described
208*>     below. There currently are up to three pieces of information
209*>     returned.
210*>
211*>     The first index in ERR_BNDS_NORM(i,:) corresponds to the ith
212*>     right-hand side.
213*>
214*>     The second index in ERR_BNDS_NORM(:,err) contains the following
215*>     three fields:
216*>     err = 1 "Trust/don't trust" boolean. Trust the answer if the
217*>              reciprocal condition number is less than the threshold
218*>              sqrt(n) * slamch('Epsilon').
219*>
220*>     err = 2 "Guaranteed" error bound: The estimated forward error,
221*>              almost certainly within a factor of 10 of the true error
222*>              so long as the next entry is greater than the threshold
223*>              sqrt(n) * slamch('Epsilon'). This error bound should only
224*>              be trusted if the previous boolean is true.
225*>
226*>     err = 3  Reciprocal condition number: Estimated normwise
227*>              reciprocal condition number.  Compared with the threshold
228*>              sqrt(n) * slamch('Epsilon') to determine if the error
229*>              estimate is "guaranteed". These reciprocal condition
230*>              numbers are 1 / (norm(Z^{-1},inf) * norm(Z,inf)) for some
231*>              appropriately scaled matrix Z.
232*>              Let Z = S*A, where S scales each row by a power of the
233*>              radix so all absolute row sums of Z are approximately 1.
234*>
235*>     This subroutine is only responsible for setting the second field
236*>     above.
237*>     See Lapack Working Note 165 for further details and extra
238*>     cautions.
239*> \endverbatim
240*>
241*> \param[in,out] ERR_BNDS_COMP
242*> \verbatim
243*>          ERR_BNDS_COMP is REAL array, dimension (NRHS, N_ERR_BNDS)
244*>     For each right-hand side, this array contains information about
245*>     various error bounds and condition numbers corresponding to the
246*>     componentwise relative error, which is defined as follows:
247*>
248*>     Componentwise relative error in the ith solution vector:
249*>                    abs(XTRUE(j,i) - X(j,i))
250*>             max_j ----------------------
251*>                         abs(X(j,i))
252*>
253*>     The array is indexed by the right-hand side i (on which the
254*>     componentwise relative error depends), and the type of error
255*>     information as described below. There currently are up to three
256*>     pieces of information returned for each right-hand side. If
257*>     componentwise accuracy is not requested (PARAMS(3) = 0.0), then
258*>     ERR_BNDS_COMP is not accessed.  If N_ERR_BNDS < 3, then at most
259*>     the first (:,N_ERR_BNDS) entries are returned.
260*>
261*>     The first index in ERR_BNDS_COMP(i,:) corresponds to the ith
262*>     right-hand side.
263*>
264*>     The second index in ERR_BNDS_COMP(:,err) contains the following
265*>     three fields:
266*>     err = 1 "Trust/don't trust" boolean. Trust the answer if the
267*>              reciprocal condition number is less than the threshold
268*>              sqrt(n) * slamch('Epsilon').
269*>
270*>     err = 2 "Guaranteed" error bound: The estimated forward error,
271*>              almost certainly within a factor of 10 of the true error
272*>              so long as the next entry is greater than the threshold
273*>              sqrt(n) * slamch('Epsilon'). This error bound should only
274*>              be trusted if the previous boolean is true.
275*>
276*>     err = 3  Reciprocal condition number: Estimated componentwise
277*>              reciprocal condition number.  Compared with the threshold
278*>              sqrt(n) * slamch('Epsilon') to determine if the error
279*>              estimate is "guaranteed". These reciprocal condition
280*>              numbers are 1 / (norm(Z^{-1},inf) * norm(Z,inf)) for some
281*>              appropriately scaled matrix Z.
282*>              Let Z = S*(A*diag(x)), where x is the solution for the
283*>              current right-hand side and S scales each row of
284*>              A*diag(x) by a power of the radix so all absolute row
285*>              sums of Z are approximately 1.
286*>
287*>     This subroutine is only responsible for setting the second field
288*>     above.
289*>     See Lapack Working Note 165 for further details and extra
290*>     cautions.
291*> \endverbatim
292*>
293*> \param[in] RES
294*> \verbatim
295*>          RES is REAL array, dimension (N)
296*>     Workspace to hold the intermediate residual.
297*> \endverbatim
298*>
299*> \param[in] AYB
300*> \verbatim
301*>          AYB is REAL array, dimension (N)
302*>     Workspace. This can be the same workspace passed for Y_TAIL.
303*> \endverbatim
304*>
305*> \param[in] DY
306*> \verbatim
307*>          DY is REAL array, dimension (N)
308*>     Workspace to hold the intermediate solution.
309*> \endverbatim
310*>
311*> \param[in] Y_TAIL
312*> \verbatim
313*>          Y_TAIL is REAL array, dimension (N)
314*>     Workspace to hold the trailing bits of the intermediate solution.
315*> \endverbatim
316*>
317*> \param[in] RCOND
318*> \verbatim
319*>          RCOND is REAL
320*>     Reciprocal scaled condition number.  This is an estimate of the
321*>     reciprocal Skeel condition number of the matrix A after
322*>     equilibration (if done).  If this is less than the machine
323*>     precision (in particular, if it is zero), the matrix is singular
324*>     to working precision.  Note that the error may still be small even
325*>     if this number is very small and the matrix appears ill-
326*>     conditioned.
327*> \endverbatim
328*>
329*> \param[in] ITHRESH
330*> \verbatim
331*>          ITHRESH is INTEGER
332*>     The maximum number of residual computations allowed for
333*>     refinement. The default is 10. For 'aggressive' set to 100 to
334*>     permit convergence using approximate factorizations or
335*>     factorizations other than LU. If the factorization uses a
336*>     technique other than Gaussian elimination, the guarantees in
337*>     ERR_BNDS_NORM and ERR_BNDS_COMP may no longer be trustworthy.
338*> \endverbatim
339*>
340*> \param[in] RTHRESH
341*> \verbatim
342*>          RTHRESH is REAL
343*>     Determines when to stop refinement if the error estimate stops
344*>     decreasing. Refinement will stop when the next solution no longer
345*>     satisfies norm(dx_{i+1}) < RTHRESH * norm(dx_i) where norm(Z) is
346*>     the infinity norm of Z. RTHRESH satisfies 0 < RTHRESH <= 1. The
347*>     default value is 0.5. For 'aggressive' set to 0.9 to permit
348*>     convergence on extremely ill-conditioned matrices. See LAWN 165
349*>     for more details.
350*> \endverbatim
351*>
352*> \param[in] DZ_UB
353*> \verbatim
354*>          DZ_UB is REAL
355*>     Determines when to start considering componentwise convergence.
356*>     Componentwise convergence is only considered after each component
357*>     of the solution Y is stable, which we definte as the relative
358*>     change in each component being less than DZ_UB. The default value
359*>     is 0.25, requiring the first bit to be stable. See LAWN 165 for
360*>     more details.
361*> \endverbatim
362*>
363*> \param[in] IGNORE_CWISE
364*> \verbatim
365*>          IGNORE_CWISE is LOGICAL
366*>     If .TRUE. then ignore componentwise convergence. Default value
367*>     is .FALSE..
368*> \endverbatim
369*>
370*> \param[out] INFO
371*> \verbatim
372*>          INFO is INTEGER
373*>       = 0:  Successful exit.
374*>       < 0:  if INFO = -i, the ith argument to SLA_SYRFSX_EXTENDED had an illegal
375*>             value
376*> \endverbatim
377*
378*  Authors:
379*  ========
380*
381*> \author Univ. of Tennessee
382*> \author Univ. of California Berkeley
383*> \author Univ. of Colorado Denver
384*> \author NAG Ltd.
385*
386*> \date December 2016
387*
388*> \ingroup realSYcomputational
389*
390*  =====================================================================
391      SUBROUTINE SLA_SYRFSX_EXTENDED( PREC_TYPE, UPLO, N, NRHS, A, LDA,
392     $                                AF, LDAF, IPIV, COLEQU, C, B, LDB,
393     $                                Y, LDY, BERR_OUT, N_NORMS,
394     $                                ERR_BNDS_NORM, ERR_BNDS_COMP, RES,
395     $                                AYB, DY, Y_TAIL, RCOND, ITHRESH,
396     $                                RTHRESH, DZ_UB, IGNORE_CWISE,
397     $                                INFO )
398*
399*  -- LAPACK computational routine (version 3.7.0) --
400*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
401*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
402*     December 2016
403*
404*     .. Scalar Arguments ..
405      INTEGER            INFO, LDA, LDAF, LDB, LDY, N, NRHS, PREC_TYPE,
406     $                   N_NORMS, ITHRESH
407      CHARACTER          UPLO
408      LOGICAL            COLEQU, IGNORE_CWISE
409      REAL               RTHRESH, DZ_UB
410*     ..
411*     .. Array Arguments ..
412      INTEGER            IPIV( * )
413      REAL               A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
414     $                   Y( LDY, * ), RES( * ), DY( * ), Y_TAIL( * )
415      REAL               C( * ), AYB( * ), RCOND, BERR_OUT( * ),
416     $                   ERR_BNDS_NORM( NRHS, * ),
417     $                   ERR_BNDS_COMP( NRHS, * )
418*     ..
419*
420*  =====================================================================
421*
422*     .. Local Scalars ..
423      INTEGER            UPLO2, CNT, I, J, X_STATE, Z_STATE
424      REAL               YK, DYK, YMIN, NORMY, NORMX, NORMDX, DXRAT,
425     $                   DZRAT, PREVNORMDX, PREV_DZ_Z, DXRATMAX,
426     $                   DZRATMAX, DX_X, DZ_Z, FINAL_DX_X, FINAL_DZ_Z,
427     $                   EPS, HUGEVAL, INCR_THRESH
428      LOGICAL            INCR_PREC, UPPER
429*     ..
430*     .. Parameters ..
431      INTEGER            UNSTABLE_STATE, WORKING_STATE, CONV_STATE,
432     $                   NOPROG_STATE, Y_PREC_STATE, BASE_RESIDUAL,
433     $                   EXTRA_RESIDUAL, EXTRA_Y
434      PARAMETER          ( UNSTABLE_STATE = 0, WORKING_STATE = 1,
435     $                   CONV_STATE = 2, NOPROG_STATE = 3 )
436      PARAMETER          ( BASE_RESIDUAL = 0, EXTRA_RESIDUAL = 1,
437     $                   EXTRA_Y = 2 )
438      INTEGER            FINAL_NRM_ERR_I, FINAL_CMP_ERR_I, BERR_I
439      INTEGER            RCOND_I, NRM_RCOND_I, NRM_ERR_I, CMP_RCOND_I
440      INTEGER            CMP_ERR_I, PIV_GROWTH_I
441      PARAMETER          ( FINAL_NRM_ERR_I = 1, FINAL_CMP_ERR_I = 2,
442     $                   BERR_I = 3 )
443      PARAMETER          ( RCOND_I = 4, NRM_RCOND_I = 5, NRM_ERR_I = 6 )
444      PARAMETER          ( CMP_RCOND_I = 7, CMP_ERR_I = 8,
445     $                   PIV_GROWTH_I = 9 )
446      INTEGER            LA_LINRX_ITREF_I, LA_LINRX_ITHRESH_I,
447     $                   LA_LINRX_CWISE_I
448      PARAMETER          ( LA_LINRX_ITREF_I = 1,
449     $                   LA_LINRX_ITHRESH_I = 2 )
450      PARAMETER          ( LA_LINRX_CWISE_I = 3 )
451      INTEGER            LA_LINRX_TRUST_I, LA_LINRX_ERR_I,
452     $                   LA_LINRX_RCOND_I
453      PARAMETER          ( LA_LINRX_TRUST_I = 1, LA_LINRX_ERR_I = 2 )
454      PARAMETER          ( LA_LINRX_RCOND_I = 3 )
455*     ..
456*     .. External Functions ..
457      LOGICAL            LSAME
458      EXTERNAL           ILAUPLO
459      INTEGER            ILAUPLO
460*     ..
461*     .. External Subroutines ..
462      EXTERNAL           SAXPY, SCOPY, SSYTRS, SSYMV, BLAS_SSYMV_X,
463     $                   BLAS_SSYMV2_X, SLA_SYAMV, SLA_WWADDW,
464     $                   SLA_LIN_BERR
465      REAL               SLAMCH
466*     ..
467*     .. Intrinsic Functions ..
468      INTRINSIC          ABS, MAX, MIN
469*     ..
470*     .. Executable Statements ..
471*
472      INFO = 0
473      UPPER = LSAME( UPLO, 'U' )
474      IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
475         INFO = -2
476      ELSE IF( N.LT.0 ) THEN
477         INFO = -3
478      ELSE IF( NRHS.LT.0 ) THEN
479         INFO = -4
480      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
481         INFO = -6
482      ELSE IF( LDAF.LT.MAX( 1, N ) ) THEN
483         INFO = -8
484      ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
485         INFO = -13
486      ELSE IF( LDY.LT.MAX( 1, N ) ) THEN
487         INFO = -15
488      END IF
489      IF( INFO.NE.0 ) THEN
490         CALL XERBLA( 'SLA_SYRFSX_EXTENDED', -INFO )
491         RETURN
492      END IF
493      EPS = SLAMCH( 'Epsilon' )
494      HUGEVAL = SLAMCH( 'Overflow' )
495*     Force HUGEVAL to Inf
496      HUGEVAL = HUGEVAL * HUGEVAL
497*     Using HUGEVAL may lead to spurious underflows.
498      INCR_THRESH = REAL( N )*EPS
499
500      IF ( LSAME ( UPLO, 'L' ) ) THEN
501         UPLO2 = ILAUPLO( 'L' )
502      ELSE
503         UPLO2 = ILAUPLO( 'U' )
504      ENDIF
505
506      DO J = 1, NRHS
507         Y_PREC_STATE = EXTRA_RESIDUAL
508         IF ( Y_PREC_STATE .EQ. EXTRA_Y ) THEN
509            DO I = 1, N
510               Y_TAIL( I ) = 0.0
511            END DO
512         END IF
513
514         DXRAT = 0.0
515         DXRATMAX = 0.0
516         DZRAT = 0.0
517         DZRATMAX = 0.0
518         FINAL_DX_X = HUGEVAL
519         FINAL_DZ_Z = HUGEVAL
520         PREVNORMDX = HUGEVAL
521         PREV_DZ_Z = HUGEVAL
522         DZ_Z = HUGEVAL
523         DX_X = HUGEVAL
524
525         X_STATE = WORKING_STATE
526         Z_STATE = UNSTABLE_STATE
527         INCR_PREC = .FALSE.
528
529         DO CNT = 1, ITHRESH
530*
531*        Compute residual RES = B_s - op(A_s) * Y,
532*            op(A) = A, A**T, or A**H depending on TRANS (and type).
533*
534            CALL SCOPY( N, B( 1, J ), 1, RES, 1 )
535            IF (Y_PREC_STATE .EQ. BASE_RESIDUAL) THEN
536               CALL SSYMV( UPLO, N, -1.0, A, LDA, Y(1,J), 1,
537     $              1.0, RES, 1 )
538            ELSE IF (Y_PREC_STATE .EQ. EXTRA_RESIDUAL) THEN
539               CALL BLAS_SSYMV_X( UPLO2, N, -1.0, A, LDA,
540     $              Y( 1, J ), 1, 1.0, RES, 1, PREC_TYPE )
541            ELSE
542               CALL BLAS_SSYMV2_X(UPLO2, N, -1.0, A, LDA,
543     $              Y(1, J), Y_TAIL, 1, 1.0, RES, 1, PREC_TYPE)
544            END IF
545
546!         XXX: RES is no longer needed.
547            CALL SCOPY( N, RES, 1, DY, 1 )
548            CALL SSYTRS( UPLO, N, 1, AF, LDAF, IPIV, DY, N, INFO )
549*
550*         Calculate relative changes DX_X, DZ_Z and ratios DXRAT, DZRAT.
551*
552            NORMX = 0.0
553            NORMY = 0.0
554            NORMDX = 0.0
555            DZ_Z = 0.0
556            YMIN = HUGEVAL
557
558            DO I = 1, N
559               YK = ABS( Y( I, J ) )
560               DYK = ABS( DY( I ) )
561
562               IF ( YK .NE. 0.0 ) THEN
563                  DZ_Z = MAX( DZ_Z, DYK / YK )
564               ELSE IF ( DYK .NE. 0.0 ) THEN
565                  DZ_Z = HUGEVAL
566               END IF
567
568               YMIN = MIN( YMIN, YK )
569
570               NORMY = MAX( NORMY, YK )
571
572               IF ( COLEQU ) THEN
573                  NORMX = MAX( NORMX, YK * C( I ) )
574                  NORMDX = MAX( NORMDX, DYK * C( I ) )
575               ELSE
576                  NORMX = NORMY
577                  NORMDX = MAX(NORMDX, DYK)
578               END IF
579            END DO
580
581            IF ( NORMX .NE. 0.0 ) THEN
582               DX_X = NORMDX / NORMX
583            ELSE IF ( NORMDX .EQ. 0.0 ) THEN
584               DX_X = 0.0
585            ELSE
586               DX_X = HUGEVAL
587            END IF
588
589            DXRAT = NORMDX / PREVNORMDX
590            DZRAT = DZ_Z / PREV_DZ_Z
591*
592*         Check termination criteria.
593*
594            IF ( YMIN*RCOND .LT. INCR_THRESH*NORMY
595     $           .AND. Y_PREC_STATE .LT. EXTRA_Y )
596     $           INCR_PREC = .TRUE.
597
598            IF ( X_STATE .EQ. NOPROG_STATE .AND. DXRAT .LE. RTHRESH )
599     $           X_STATE = WORKING_STATE
600            IF ( X_STATE .EQ. WORKING_STATE ) THEN
601               IF ( DX_X .LE. EPS ) THEN
602                  X_STATE = CONV_STATE
603               ELSE IF ( DXRAT .GT. RTHRESH ) THEN
604                  IF ( Y_PREC_STATE .NE. EXTRA_Y ) THEN
605                     INCR_PREC = .TRUE.
606                  ELSE
607                     X_STATE = NOPROG_STATE
608                  END IF
609               ELSE
610                  IF ( DXRAT .GT. DXRATMAX ) DXRATMAX = DXRAT
611               END IF
612               IF ( X_STATE .GT. WORKING_STATE ) FINAL_DX_X = DX_X
613            END IF
614
615            IF ( Z_STATE .EQ. UNSTABLE_STATE .AND. DZ_Z .LE. DZ_UB )
616     $           Z_STATE = WORKING_STATE
617            IF ( Z_STATE .EQ. NOPROG_STATE .AND. DZRAT .LE. RTHRESH )
618     $           Z_STATE = WORKING_STATE
619            IF ( Z_STATE .EQ. WORKING_STATE ) THEN
620               IF ( DZ_Z .LE. EPS ) THEN
621                  Z_STATE = CONV_STATE
622               ELSE IF ( DZ_Z .GT. DZ_UB ) THEN
623                  Z_STATE = UNSTABLE_STATE
624                  DZRATMAX = 0.0
625                  FINAL_DZ_Z = HUGEVAL
626               ELSE IF ( DZRAT .GT. RTHRESH ) THEN
627                  IF ( Y_PREC_STATE .NE. EXTRA_Y ) THEN
628                     INCR_PREC = .TRUE.
629                  ELSE
630                     Z_STATE = NOPROG_STATE
631                  END IF
632               ELSE
633                  IF ( DZRAT .GT. DZRATMAX ) DZRATMAX = DZRAT
634               END IF
635               IF ( Z_STATE .GT. WORKING_STATE ) FINAL_DZ_Z = DZ_Z
636            END IF
637
638            IF ( X_STATE.NE.WORKING_STATE.AND.
639     $           ( IGNORE_CWISE.OR.Z_STATE.NE.WORKING_STATE ) )
640     $           GOTO 666
641
642            IF ( INCR_PREC ) THEN
643               INCR_PREC = .FALSE.
644               Y_PREC_STATE = Y_PREC_STATE + 1
645               DO I = 1, N
646                  Y_TAIL( I ) = 0.0
647               END DO
648            END IF
649
650            PREVNORMDX = NORMDX
651            PREV_DZ_Z = DZ_Z
652*
653*           Update soluton.
654*
655            IF (Y_PREC_STATE .LT. EXTRA_Y) THEN
656               CALL SAXPY( N, 1.0, DY, 1, Y(1,J), 1 )
657            ELSE
658               CALL SLA_WWADDW( N, Y(1,J), Y_TAIL, DY )
659            END IF
660
661         END DO
662*        Target of "IF (Z_STOP .AND. X_STOP)".  Sun's f77 won't EXIT.
663 666     CONTINUE
664*
665*     Set final_* when cnt hits ithresh.
666*
667         IF ( X_STATE .EQ. WORKING_STATE ) FINAL_DX_X = DX_X
668         IF ( Z_STATE .EQ. WORKING_STATE ) FINAL_DZ_Z = DZ_Z
669*
670*     Compute error bounds.
671*
672         IF ( N_NORMS .GE. 1 ) THEN
673            ERR_BNDS_NORM( J, LA_LINRX_ERR_I ) =
674     $           FINAL_DX_X / (1 - DXRATMAX)
675         END IF
676         IF ( N_NORMS .GE. 2 ) THEN
677            ERR_BNDS_COMP( J, LA_LINRX_ERR_I ) =
678     $           FINAL_DZ_Z / (1 - DZRATMAX)
679         END IF
680*
681*     Compute componentwise relative backward error from formula
682*         max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) )
683*     where abs(Z) is the componentwise absolute value of the matrix
684*     or vector Z.
685*
686*        Compute residual RES = B_s - op(A_s) * Y,
687*            op(A) = A, A**T, or A**H depending on TRANS (and type).
688         CALL SCOPY( N, B( 1, J ), 1, RES, 1 )
689         CALL SSYMV( UPLO, N, -1.0, A, LDA, Y(1,J), 1, 1.0, RES, 1 )
690
691         DO I = 1, N
692            AYB( I ) = ABS( B( I, J ) )
693         END DO
694*
695*     Compute abs(op(A_s))*abs(Y) + abs(B_s).
696*
697         CALL SLA_SYAMV( UPLO2, N, 1.0,
698     $        A, LDA, Y(1, J), 1, 1.0, AYB, 1 )
699
700         CALL SLA_LIN_BERR( N, N, 1, RES, AYB, BERR_OUT( J ) )
701*
702*     End of loop for each RHS.
703*
704      END DO
705*
706      RETURN
707      END
708