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