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