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