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 define 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*> \ingroup complexPOcomputational
378*
379*  =====================================================================
380      SUBROUTINE CLA_PORFSX_EXTENDED( PREC_TYPE, UPLO, N, NRHS, A, LDA,
381     $                                AF, LDAF, COLEQU, C, B, LDB, Y,
382     $                                LDY, BERR_OUT, N_NORMS,
383     $                                ERR_BNDS_NORM, ERR_BNDS_COMP, RES,
384     $                                AYB, DY, Y_TAIL, RCOND, ITHRESH,
385     $                                RTHRESH, DZ_UB, IGNORE_CWISE,
386     $                                INFO )
387*
388*  -- LAPACK computational routine --
389*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
390*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
391*
392*     .. Scalar Arguments ..
393      INTEGER            INFO, LDA, LDAF, LDB, LDY, N, NRHS, PREC_TYPE,
394     $                   N_NORMS, ITHRESH
395      CHARACTER          UPLO
396      LOGICAL            COLEQU, IGNORE_CWISE
397      REAL               RTHRESH, DZ_UB
398*     ..
399*     .. Array Arguments ..
400      COMPLEX            A( LDA, * ), AF( LDAF, * ), B( LDB, * ),
401     $                   Y( LDY, * ), RES( * ), DY( * ), Y_TAIL( * )
402      REAL               C( * ), AYB( * ), RCOND, BERR_OUT( * ),
403     $                   ERR_BNDS_NORM( NRHS, * ),
404     $                   ERR_BNDS_COMP( NRHS, * )
405*     ..
406*
407*  =====================================================================
408*
409*     .. Local Scalars ..
410      INTEGER            UPLO2, CNT, I, J, X_STATE, Z_STATE,
411     $                   Y_PREC_STATE
412      REAL               YK, DYK, YMIN, NORMY, NORMX, NORMDX, DXRAT,
413     $                   DZRAT, PREVNORMDX, PREV_DZ_Z, DXRATMAX,
414     $                   DZRATMAX, DX_X, DZ_Z, FINAL_DX_X, FINAL_DZ_Z,
415     $                   EPS, HUGEVAL, INCR_THRESH
416      LOGICAL            INCR_PREC
417      COMPLEX            ZDUM
418*     ..
419*     .. Parameters ..
420      INTEGER            UNSTABLE_STATE, WORKING_STATE, CONV_STATE,
421     $                   NOPROG_STATE, BASE_RESIDUAL, EXTRA_RESIDUAL,
422     $                   EXTRA_Y
423      PARAMETER          ( UNSTABLE_STATE = 0, WORKING_STATE = 1,
424     $                   CONV_STATE = 2, NOPROG_STATE = 3 )
425      PARAMETER          ( BASE_RESIDUAL = 0, EXTRA_RESIDUAL = 1,
426     $                   EXTRA_Y = 2 )
427      INTEGER            FINAL_NRM_ERR_I, FINAL_CMP_ERR_I, BERR_I
428      INTEGER            RCOND_I, NRM_RCOND_I, NRM_ERR_I, CMP_RCOND_I
429      INTEGER            CMP_ERR_I, PIV_GROWTH_I
430      PARAMETER          ( FINAL_NRM_ERR_I = 1, FINAL_CMP_ERR_I = 2,
431     $                   BERR_I = 3 )
432      PARAMETER          ( RCOND_I = 4, NRM_RCOND_I = 5, NRM_ERR_I = 6 )
433      PARAMETER          ( CMP_RCOND_I = 7, CMP_ERR_I = 8,
434     $                   PIV_GROWTH_I = 9 )
435      INTEGER            LA_LINRX_ITREF_I, LA_LINRX_ITHRESH_I,
436     $                   LA_LINRX_CWISE_I
437      PARAMETER          ( LA_LINRX_ITREF_I = 1,
438     $                   LA_LINRX_ITHRESH_I = 2 )
439      PARAMETER          ( LA_LINRX_CWISE_I = 3 )
440      INTEGER            LA_LINRX_TRUST_I, LA_LINRX_ERR_I,
441     $                   LA_LINRX_RCOND_I
442      PARAMETER          ( LA_LINRX_TRUST_I = 1, LA_LINRX_ERR_I = 2 )
443      PARAMETER          ( LA_LINRX_RCOND_I = 3 )
444*     ..
445*     .. External Functions ..
446      LOGICAL            LSAME
447      EXTERNAL           ILAUPLO
448      INTEGER            ILAUPLO
449*     ..
450*     .. External Subroutines ..
451      EXTERNAL           CAXPY, CCOPY, CPOTRS, CHEMV, BLAS_CHEMV_X,
452     $                   BLAS_CHEMV2_X, CLA_HEAMV, CLA_WWADDW,
453     $                   CLA_LIN_BERR, SLAMCH
454      REAL               SLAMCH
455*     ..
456*     .. Intrinsic Functions ..
457      INTRINSIC          ABS, REAL, AIMAG, MAX, MIN
458*     ..
459*     .. Statement Functions ..
460      REAL               CABS1
461*     ..
462*     .. Statement Function Definitions ..
463      CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
464*     ..
465*     .. Executable Statements ..
466*
467      IF (INFO.NE.0) RETURN
468      EPS = SLAMCH( 'Epsilon' )
469      HUGEVAL = SLAMCH( 'Overflow' )
470*     Force HUGEVAL to Inf
471      HUGEVAL = HUGEVAL * HUGEVAL
472*     Using HUGEVAL may lead to spurious underflows.
473      INCR_THRESH = REAL(N) * EPS
474
475      IF (LSAME (UPLO, 'L')) THEN
476         UPLO2 = ILAUPLO( 'L' )
477      ELSE
478         UPLO2 = ILAUPLO( 'U' )
479      ENDIF
480
481      DO J = 1, NRHS
482         Y_PREC_STATE = EXTRA_RESIDUAL
483         IF (Y_PREC_STATE .EQ. EXTRA_Y) THEN
484            DO I = 1, N
485               Y_TAIL( I ) = 0.0
486            END DO
487         END IF
488
489         DXRAT = 0.0
490         DXRATMAX = 0.0
491         DZRAT = 0.0
492         DZRATMAX = 0.0
493         FINAL_DX_X = HUGEVAL
494         FINAL_DZ_Z = HUGEVAL
495         PREVNORMDX = HUGEVAL
496         PREV_DZ_Z = HUGEVAL
497         DZ_Z = HUGEVAL
498         DX_X = HUGEVAL
499
500         X_STATE = WORKING_STATE
501         Z_STATE = UNSTABLE_STATE
502         INCR_PREC = .FALSE.
503
504         DO CNT = 1, ITHRESH
505*
506*         Compute residual RES = B_s - op(A_s) * Y,
507*             op(A) = A, A**T, or A**H depending on TRANS (and type).
508*
509            CALL CCOPY( N, B( 1, J ), 1, RES, 1 )
510            IF (Y_PREC_STATE .EQ. BASE_RESIDUAL) THEN
511               CALL CHEMV(UPLO, N, CMPLX(-1.0), A, LDA, Y(1,J), 1,
512     $              CMPLX(1.0), RES, 1)
513            ELSE IF (Y_PREC_STATE .EQ. EXTRA_RESIDUAL) THEN
514               CALL BLAS_CHEMV_X(UPLO2, N, CMPLX(-1.0), A, LDA,
515     $              Y( 1, J ), 1, CMPLX(1.0), RES, 1, PREC_TYPE)
516            ELSE
517               CALL BLAS_CHEMV2_X(UPLO2, N, CMPLX(-1.0), A, LDA,
518     $              Y(1, J), Y_TAIL, 1, CMPLX(1.0), RES, 1, PREC_TYPE)
519            END IF
520
521!         XXX: RES is no longer needed.
522            CALL CCOPY( N, RES, 1, DY, 1 )
523            CALL CPOTRS( UPLO, N, 1, AF, LDAF, DY, N, INFO)
524*
525*         Calculate relative changes DX_X, DZ_Z and ratios DXRAT, DZRAT.
526*
527            NORMX = 0.0
528            NORMY = 0.0
529            NORMDX = 0.0
530            DZ_Z = 0.0
531            YMIN = HUGEVAL
532
533            DO I = 1, N
534               YK = CABS1(Y(I, J))
535               DYK = CABS1(DY(I))
536
537               IF (YK .NE. 0.0) THEN
538                  DZ_Z = MAX( DZ_Z, DYK / YK )
539               ELSE IF (DYK .NE. 0.0) THEN
540                  DZ_Z = HUGEVAL
541               END IF
542
543               YMIN = MIN( YMIN, YK )
544
545               NORMY = MAX( NORMY, YK )
546
547               IF ( COLEQU ) THEN
548                  NORMX = MAX(NORMX, YK * C(I))
549                  NORMDX = MAX(NORMDX, DYK * C(I))
550               ELSE
551                  NORMX = NORMY
552                  NORMDX = MAX(NORMDX, DYK)
553               END IF
554            END DO
555
556            IF (NORMX .NE. 0.0) THEN
557               DX_X = NORMDX / NORMX
558            ELSE IF (NORMDX .EQ. 0.0) THEN
559               DX_X = 0.0
560            ELSE
561               DX_X = HUGEVAL
562            END IF
563
564            DXRAT = NORMDX / PREVNORMDX
565            DZRAT = DZ_Z / PREV_DZ_Z
566*
567*         Check termination criteria.
568*
569            IF (YMIN*RCOND .LT. INCR_THRESH*NORMY
570     $           .AND. Y_PREC_STATE .LT. EXTRA_Y)
571     $           INCR_PREC = .TRUE.
572
573            IF (X_STATE .EQ. NOPROG_STATE .AND. DXRAT .LE. RTHRESH)
574     $           X_STATE = WORKING_STATE
575            IF (X_STATE .EQ. WORKING_STATE) THEN
576               IF (DX_X .LE. EPS) THEN
577                  X_STATE = CONV_STATE
578               ELSE IF (DXRAT .GT. RTHRESH) THEN
579                  IF (Y_PREC_STATE .NE. EXTRA_Y) THEN
580                     INCR_PREC = .TRUE.
581                  ELSE
582                     X_STATE = NOPROG_STATE
583                  END IF
584               ELSE
585                  IF (DXRAT .GT. DXRATMAX) DXRATMAX = DXRAT
586               END IF
587               IF (X_STATE .GT. WORKING_STATE) FINAL_DX_X = DX_X
588            END IF
589
590            IF (Z_STATE .EQ. UNSTABLE_STATE .AND. DZ_Z .LE. DZ_UB)
591     $           Z_STATE = WORKING_STATE
592            IF (Z_STATE .EQ. NOPROG_STATE .AND. DZRAT .LE. RTHRESH)
593     $           Z_STATE = WORKING_STATE
594            IF (Z_STATE .EQ. WORKING_STATE) THEN
595               IF (DZ_Z .LE. EPS) THEN
596                  Z_STATE = CONV_STATE
597               ELSE IF (DZ_Z .GT. DZ_UB) THEN
598                  Z_STATE = UNSTABLE_STATE
599                  DZRATMAX = 0.0
600                  FINAL_DZ_Z = HUGEVAL
601               ELSE IF (DZRAT .GT. RTHRESH) THEN
602                  IF (Y_PREC_STATE .NE. EXTRA_Y) THEN
603                     INCR_PREC = .TRUE.
604                  ELSE
605                     Z_STATE = NOPROG_STATE
606                  END IF
607               ELSE
608                  IF (DZRAT .GT. DZRATMAX) DZRATMAX = DZRAT
609               END IF
610               IF (Z_STATE .GT. WORKING_STATE) FINAL_DZ_Z = DZ_Z
611            END IF
612
613            IF ( X_STATE.NE.WORKING_STATE.AND.
614     $           (IGNORE_CWISE.OR.Z_STATE.NE.WORKING_STATE) )
615     $           GOTO 666
616
617            IF (INCR_PREC) THEN
618               INCR_PREC = .FALSE.
619               Y_PREC_STATE = Y_PREC_STATE + 1
620               DO I = 1, N
621                  Y_TAIL( I ) = 0.0
622               END DO
623            END IF
624
625            PREVNORMDX = NORMDX
626            PREV_DZ_Z = DZ_Z
627*
628*           Update soluton.
629*
630            IF (Y_PREC_STATE .LT. EXTRA_Y) THEN
631               CALL CAXPY( N, CMPLX(1.0), DY, 1, Y(1,J), 1 )
632            ELSE
633               CALL CLA_WWADDW(N, Y(1,J), Y_TAIL, DY)
634            END IF
635
636         END DO
637*        Target of "IF (Z_STOP .AND. X_STOP)".  Sun's f77 won't EXIT.
638 666     CONTINUE
639*
640*     Set final_* when cnt hits ithresh.
641*
642         IF (X_STATE .EQ. WORKING_STATE) FINAL_DX_X = DX_X
643         IF (Z_STATE .EQ. WORKING_STATE) FINAL_DZ_Z = DZ_Z
644*
645*     Compute error bounds.
646*
647         IF (N_NORMS .GE. 1) THEN
648            ERR_BNDS_NORM( J, LA_LINRX_ERR_I ) =
649     $           FINAL_DX_X / (1 - DXRATMAX)
650         END IF
651         IF (N_NORMS .GE. 2) THEN
652            ERR_BNDS_COMP( J, LA_LINRX_ERR_I ) =
653     $           FINAL_DZ_Z / (1 - DZRATMAX)
654         END IF
655*
656*     Compute componentwise relative backward error from formula
657*         max(i) ( abs(R(i)) / ( abs(op(A_s))*abs(Y) + abs(B_s) )(i) )
658*     where abs(Z) is the componentwise absolute value of the matrix
659*     or vector Z.
660*
661*        Compute residual RES = B_s - op(A_s) * Y,
662*            op(A) = A, A**T, or A**H depending on TRANS (and type).
663*
664         CALL CCOPY( N, B( 1, J ), 1, RES, 1 )
665         CALL CHEMV(UPLO, N, CMPLX(-1.0), A, LDA, Y(1,J), 1, CMPLX(1.0),
666     $        RES, 1)
667
668         DO I = 1, N
669            AYB( I ) = CABS1( B( I, J ) )
670         END DO
671*
672*     Compute abs(op(A_s))*abs(Y) + abs(B_s).
673*
674         CALL CLA_HEAMV (UPLO2, N, 1.0,
675     $        A, LDA, Y(1, J), 1, 1.0, AYB, 1)
676
677         CALL CLA_LIN_BERR (N, N, 1, RES, AYB, BERR_OUT(J))
678*
679*     End of loop for each RHS.
680*
681      END DO
682*
683      RETURN
684*
685*     End of CLA_PORFSX_EXTENDED
686*
687      END
688