1*> \brief \b DLA_GERCOND estimates the Skeel condition number for a general matrix.
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download DLA_GERCOND + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dla_gercond.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dla_gercond.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dla_gercond.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       DOUBLE PRECISION FUNCTION DLA_GERCOND( TRANS, N, A, LDA, AF,
22*                                              LDAF, IPIV, CMODE, C,
23*                                              INFO, WORK, IWORK )
24*
25*       .. Scalar Arguments ..
26*       CHARACTER          TRANS
27*       INTEGER            N, LDA, LDAF, INFO, CMODE
28*       ..
29*       .. Array Arguments ..
30*       INTEGER            IPIV( * ), IWORK( * )
31*       DOUBLE PRECISION   A( LDA, * ), AF( LDAF, * ), WORK( * ),
32*      $                   C( * )
33*       ..
34*
35*
36*> \par Purpose:
37*  =============
38*>
39*> \verbatim
40*>
41*>    DLA_GERCOND estimates the Skeel condition number of op(A) * op2(C)
42*>    where op2 is determined by CMODE as follows
43*>    CMODE =  1    op2(C) = C
44*>    CMODE =  0    op2(C) = I
45*>    CMODE = -1    op2(C) = inv(C)
46*>    The Skeel condition number cond(A) = norminf( |inv(A)||A| )
47*>    is computed by computing scaling factors R such that
48*>    diag(R)*A*op2(C) is row equilibrated and computing the standard
49*>    infinity-norm condition number.
50*> \endverbatim
51*
52*  Arguments:
53*  ==========
54*
55*> \param[in] TRANS
56*> \verbatim
57*>          TRANS is CHARACTER*1
58*>     Specifies the form of the system of equations:
59*>       = 'N':  A * X = B     (No transpose)
60*>       = 'T':  A**T * X = B  (Transpose)
61*>       = 'C':  A**H * X = B  (Conjugate Transpose = Transpose)
62*> \endverbatim
63*>
64*> \param[in] N
65*> \verbatim
66*>          N is INTEGER
67*>     The number of linear equations, i.e., the order of the
68*>     matrix A.  N >= 0.
69*> \endverbatim
70*>
71*> \param[in] A
72*> \verbatim
73*>          A is DOUBLE PRECISION array, dimension (LDA,N)
74*>     On entry, the N-by-N matrix A.
75*> \endverbatim
76*>
77*> \param[in] LDA
78*> \verbatim
79*>          LDA is INTEGER
80*>     The leading dimension of the array A.  LDA >= max(1,N).
81*> \endverbatim
82*>
83*> \param[in] AF
84*> \verbatim
85*>          AF is DOUBLE PRECISION array, dimension (LDAF,N)
86*>     The factors L and U from the factorization
87*>     A = P*L*U as computed by DGETRF.
88*> \endverbatim
89*>
90*> \param[in] LDAF
91*> \verbatim
92*>          LDAF is INTEGER
93*>     The leading dimension of the array AF.  LDAF >= max(1,N).
94*> \endverbatim
95*>
96*> \param[in] IPIV
97*> \verbatim
98*>          IPIV is INTEGER array, dimension (N)
99*>     The pivot indices from the factorization A = P*L*U
100*>     as computed by DGETRF; row i of the matrix was interchanged
101*>     with row IPIV(i).
102*> \endverbatim
103*>
104*> \param[in] CMODE
105*> \verbatim
106*>          CMODE is INTEGER
107*>     Determines op2(C) in the formula op(A) * op2(C) as follows:
108*>     CMODE =  1    op2(C) = C
109*>     CMODE =  0    op2(C) = I
110*>     CMODE = -1    op2(C) = inv(C)
111*> \endverbatim
112*>
113*> \param[in] C
114*> \verbatim
115*>          C is DOUBLE PRECISION array, dimension (N)
116*>     The vector C in the formula op(A) * op2(C).
117*> \endverbatim
118*>
119*> \param[out] INFO
120*> \verbatim
121*>          INFO is INTEGER
122*>       = 0:  Successful exit.
123*>     i > 0:  The ith argument is invalid.
124*> \endverbatim
125*>
126*> \param[out] WORK
127*> \verbatim
128*>          WORK is DOUBLE PRECISION array, dimension (3*N).
129*>     Workspace.
130*> \endverbatim
131*>
132*> \param[out] IWORK
133*> \verbatim
134*>          IWORK is INTEGER array, dimension (N).
135*>     Workspace.
136*> \endverbatim
137*
138*  Authors:
139*  ========
140*
141*> \author Univ. of Tennessee
142*> \author Univ. of California Berkeley
143*> \author Univ. of Colorado Denver
144*> \author NAG Ltd.
145*
146*> \ingroup doubleGEcomputational
147*
148*  =====================================================================
149      DOUBLE PRECISION FUNCTION DLA_GERCOND( TRANS, N, A, LDA, AF,
150     $                                       LDAF, IPIV, CMODE, C,
151     $                                       INFO, WORK, IWORK )
152*
153*  -- LAPACK computational routine --
154*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
155*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
156*
157*     .. Scalar Arguments ..
158      CHARACTER          TRANS
159      INTEGER            N, LDA, LDAF, INFO, CMODE
160*     ..
161*     .. Array Arguments ..
162      INTEGER            IPIV( * ), IWORK( * )
163      DOUBLE PRECISION   A( LDA, * ), AF( LDAF, * ), WORK( * ),
164     $                   C( * )
165*     ..
166*
167*  =====================================================================
168*
169*     .. Local Scalars ..
170      LOGICAL            NOTRANS
171      INTEGER            KASE, I, J
172      DOUBLE PRECISION   AINVNM, TMP
173*     ..
174*     .. Local Arrays ..
175      INTEGER            ISAVE( 3 )
176*     ..
177*     .. External Functions ..
178      LOGICAL            LSAME
179      EXTERNAL           LSAME
180*     ..
181*     .. External Subroutines ..
182      EXTERNAL           DLACN2, DGETRS, XERBLA
183*     ..
184*     .. Intrinsic Functions ..
185      INTRINSIC          ABS, MAX
186*     ..
187*     .. Executable Statements ..
188*
189      DLA_GERCOND = 0.0D+0
190*
191      INFO = 0
192      NOTRANS = LSAME( TRANS, 'N' )
193      IF ( .NOT. NOTRANS .AND. .NOT. LSAME(TRANS, 'T')
194     $     .AND. .NOT. LSAME(TRANS, 'C') ) THEN
195         INFO = -1
196      ELSE IF( N.LT.0 ) THEN
197         INFO = -2
198      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
199         INFO = -4
200      ELSE IF( LDAF.LT.MAX( 1, N ) ) THEN
201         INFO = -6
202      END IF
203      IF( INFO.NE.0 ) THEN
204         CALL XERBLA( 'DLA_GERCOND', -INFO )
205         RETURN
206      END IF
207      IF( N.EQ.0 ) THEN
208         DLA_GERCOND = 1.0D+0
209         RETURN
210      END IF
211*
212*     Compute the equilibration matrix R such that
213*     inv(R)*A*C has unit 1-norm.
214*
215      IF (NOTRANS) THEN
216         DO I = 1, N
217            TMP = 0.0D+0
218            IF ( CMODE .EQ. 1 ) THEN
219               DO J = 1, N
220                  TMP = TMP + ABS( A( I, J ) * C( J ) )
221               END DO
222            ELSE IF ( CMODE .EQ. 0 ) THEN
223               DO J = 1, N
224                  TMP = TMP + ABS( A( I, J ) )
225               END DO
226            ELSE
227               DO J = 1, N
228                  TMP = TMP + ABS( A( I, J ) / C( J ) )
229               END DO
230            END IF
231            WORK( 2*N+I ) = TMP
232         END DO
233      ELSE
234         DO I = 1, N
235            TMP = 0.0D+0
236            IF ( CMODE .EQ. 1 ) THEN
237               DO J = 1, N
238                  TMP = TMP + ABS( A( J, I ) * C( J ) )
239               END DO
240            ELSE IF ( CMODE .EQ. 0 ) THEN
241               DO J = 1, N
242                  TMP = TMP + ABS( A( J, I ) )
243               END DO
244            ELSE
245               DO J = 1, N
246                  TMP = TMP + ABS( A( J, I ) / C( J ) )
247               END DO
248            END IF
249            WORK( 2*N+I ) = TMP
250         END DO
251      END IF
252*
253*     Estimate the norm of inv(op(A)).
254*
255      AINVNM = 0.0D+0
256
257      KASE = 0
258   10 CONTINUE
259      CALL DLACN2( N, WORK( N+1 ), WORK, IWORK, AINVNM, KASE, ISAVE )
260      IF( KASE.NE.0 ) THEN
261         IF( KASE.EQ.2 ) THEN
262*
263*           Multiply by R.
264*
265            DO I = 1, N
266               WORK(I) = WORK(I) * WORK(2*N+I)
267            END DO
268
269            IF (NOTRANS) THEN
270               CALL DGETRS( 'No transpose', N, 1, AF, LDAF, IPIV,
271     $            WORK, N, INFO )
272            ELSE
273               CALL DGETRS( 'Transpose', N, 1, AF, LDAF, IPIV,
274     $            WORK, N, INFO )
275            END IF
276*
277*           Multiply by inv(C).
278*
279            IF ( CMODE .EQ. 1 ) THEN
280               DO I = 1, N
281                  WORK( I ) = WORK( I ) / C( I )
282               END DO
283            ELSE IF ( CMODE .EQ. -1 ) THEN
284               DO I = 1, N
285                  WORK( I ) = WORK( I ) * C( I )
286               END DO
287            END IF
288         ELSE
289*
290*           Multiply by inv(C**T).
291*
292            IF ( CMODE .EQ. 1 ) THEN
293               DO I = 1, N
294                  WORK( I ) = WORK( I ) / C( I )
295               END DO
296            ELSE IF ( CMODE .EQ. -1 ) THEN
297               DO I = 1, N
298                  WORK( I ) = WORK( I ) * C( I )
299               END DO
300            END IF
301
302            IF (NOTRANS) THEN
303               CALL DGETRS( 'Transpose', N, 1, AF, LDAF, IPIV,
304     $            WORK, N, INFO )
305            ELSE
306               CALL DGETRS( 'No transpose', N, 1, AF, LDAF, IPIV,
307     $            WORK, N, INFO )
308            END IF
309*
310*           Multiply by R.
311*
312            DO I = 1, N
313               WORK( I ) = WORK( I ) * WORK( 2*N+I )
314            END DO
315         END IF
316         GO TO 10
317      END IF
318*
319*     Compute the estimate of the reciprocal condition number.
320*
321      IF( AINVNM .NE. 0.0D+0 )
322     $   DLA_GERCOND = ( 1.0D+0 / AINVNM )
323*
324      RETURN
325*
326*     End of DLA_GERCOND
327*
328      END
329