1       SUBROUTINE ZGEEQUB( M, N, A, LDA, R, C, ROWCND, COLCND, AMAX,
  2      $                    INFO )
  3 *
  4 *     -- LAPACK routine (version 3.2)                                 --
  5 *     -- Contributed by James Demmel, Deaglan Halligan, Yozo Hida and --
  6 *     -- Jason Riedy of Univ. of California Berkeley.                 --
  7 *     -- November 2008                                                --
  8 *
  9 *     -- LAPACK is a software package provided by Univ. of Tennessee, --
 10 *     -- Univ. of California Berkeley and NAG Ltd.                    --
 11 *
 12       IMPLICIT NONE
 13 *     ..
 14 *     .. Scalar Arguments ..
 15       INTEGER            INFO, LDA, M, N
 16       DOUBLE PRECISION   AMAX, COLCND, ROWCND
 17 *     ..
 18 *     .. Array Arguments ..
 19       DOUBLE PRECISION   C( * ), R( * )
 20       COMPLEX*16         A( LDA, * )
 21 *     ..
 22 *
 23 *  Purpose
 24 *  =======
 25 *
 26 *  ZGEEQUB computes row and column scalings intended to equilibrate an
 27 *  M-by-N matrix A and reduce its condition number.  R returns the row
 28 *  scale factors and C the column scale factors, chosen to try to make
 29 *  the largest element in each row and column of the matrix B with
 30 *  elements B(i,j)=R(i)*A(i,j)*C(j) have an absolute value of at most
 31 *  the radix.
 32 *
 33 *  R(i) and C(j) are restricted to be a power of the radix between
 34 *  SMLNUM = smallest safe number and BIGNUM = largest safe number.  Use
 35 *  of these scaling factors is not guaranteed to reduce the condition
 36 *  number of A but works well in practice.
 37 *
 38 *  This routine differs from ZGEEQU by restricting the scaling factors
 39 *  to a power of the radix.  Baring over- and underflow, scaling by
 40 *  these factors introduces no additional rounding errors.  However, the
 41 *  scaled entries' magnitured are no longer approximately 1 but lie
 42 *  between sqrt(radix) and 1/sqrt(radix).
 43 *
 44 *  Arguments
 45 *  =========
 46 *
 47 *  M       (input) INTEGER
 48 *          The number of rows of the matrix A.  M >= 0.
 49 *
 50 *  N       (input) INTEGER
 51 *          The number of columns of the matrix A.  N >= 0.
 52 *
 53 *  A       (input) COMPLEX*16 array, dimension (LDA,N)
 54 *          The M-by-N matrix whose equilibration factors are
 55 *          to be computed.
 56 *
 57 *  LDA     (input) INTEGER
 58 *          The leading dimension of the array A.  LDA >= max(1,M).
 59 *
 60 *  R       (output) DOUBLE PRECISION array, dimension (M)
 61 *          If INFO = 0 or INFO > M, R contains the row scale factors
 62 *          for A.
 63 *
 64 *  C       (output) DOUBLE PRECISION array, dimension (N)
 65 *          If INFO = 0,  C contains the column scale factors for A.
 66 *
 67 *  ROWCND  (output) DOUBLE PRECISION
 68 *          If INFO = 0 or INFO > M, ROWCND contains the ratio of the
 69 *          smallest R(i) to the largest R(i).  If ROWCND >= 0.1 and
 70 *          AMAX is neither too large nor too small, it is not worth
 71 *          scaling by R.
 72 *
 73 *  COLCND  (output) DOUBLE PRECISION
 74 *          If INFO = 0, COLCND contains the ratio of the smallest
 75 *          C(i) to the largest C(i).  If COLCND >= 0.1, it is not
 76 *          worth scaling by C.
 77 *
 78 *  AMAX    (output) DOUBLE PRECISION
 79 *          Absolute value of largest matrix element.  If AMAX is very
 80 *          close to overflow or very close to underflow, the matrix
 81 *          should be scaled.
 82 *
 83 *  INFO    (output) INTEGER
 84 *          = 0:  successful exit
 85 *          < 0:  if INFO = -i, the i-th argument had an illegal value
 86 *          > 0:  if INFO = i,  and i is
 87 *                <= M:  the i-th row of A is exactly zero
 88 *                >  M:  the (i-M)-th column of A is exactly zero
 89 *
 90 *  =====================================================================
 91 *
 92 *     .. Parameters ..
 93       DOUBLE PRECISION   ONE, ZERO
 94       PARAMETER          ( ONE = 1.0D+0, ZERO = 0.0D+0 )
 95 *     ..
 96 *     .. Local Scalars ..
 97       INTEGER            I, J
 98       DOUBLE PRECISION   BIGNUM, RCMAX, RCMIN, SMLNUM, RADIX, LOGRDX
 99       COMPLEX*16         ZDUM
100 *     ..
101 *     .. External Functions ..
102       DOUBLE PRECISION   DLAMCH
103       EXTERNAL           DLAMCH
104 *     ..
105 *     .. External Subroutines ..
106       EXTERNAL           XERBLA
107 *     ..
108 *     .. Intrinsic Functions ..
109       INTRINSIC          ABSMAXMINLOG, REAL, DIMAG
110 *     ..
111 *     .. Statement Functions ..
112       DOUBLE PRECISION   CABS1
113 *     ..
114 *     .. Statement Function definitions ..
115       CABS1( ZDUM ) = ABSDBLE( ZDUM ) ) + ABSDIMAG( ZDUM ) )
116 *     ..
117 *     .. Executable Statements ..
118 *
119 *     Test the input parameters.
120 *
121       INFO = 0
122       IF( M.LT.0 ) THEN
123          INFO = -1
124       ELSE IF( N.LT.0 ) THEN
125          INFO = -2
126       ELSE IF( LDA.LT.MAX1, M ) ) THEN
127          INFO = -4
128       END IF
129       IF( INFO.NE.0 ) THEN
130          CALL XERBLA( 'ZGEEQUB'-INFO )
131          RETURN
132       END IF
133 *
134 *     Quick return if possible.
135 *
136       IF( M.EQ.0 .OR. N.EQ.0 ) THEN
137          ROWCND = ONE
138          COLCND = ONE
139          AMAX = ZERO
140          RETURN
141       END IF
142 *
143 *     Get machine constants.  Assume SMLNUM is a power of the radix.
144 *
145       SMLNUM = DLAMCH( 'S' )
146       BIGNUM = ONE / SMLNUM
147       RADIX = DLAMCH( 'B' )
148       LOGRDX = LOGRADIX )
149 *
150 *     Compute row scale factors.
151 *
152       DO 10 I = 1, M
153          R( I ) = ZERO
154    10 CONTINUE
155 *
156 *     Find the maximum element in each row.
157 *
158       DO 30 J = 1, N
159          DO 20 I = 1, M
160             R( I ) = MAX( R( I ), CABS1( A( I, J ) ) )
161    20    CONTINUE
162    30 CONTINUE
163       DO I = 1, M
164          IF( R( I ).GT.ZERO ) THEN
165             R( I ) = RADIX**INTLOG(R( I ) ) / LOGRDX )
166          END IF
167       END DO
168 *
169 *     Find the maximum and minimum scale factors.
170 *
171       RCMIN = BIGNUM
172       RCMAX = ZERO
173       DO 40 I = 1, M
174          RCMAX = MAX( RCMAX, R( I ) )
175          RCMIN = MIN( RCMIN, R( I ) )
176    40 CONTINUE
177       AMAX = RCMAX
178 *
179       IF( RCMIN.EQ.ZERO ) THEN
180 *
181 *        Find the first zero scale factor and return an error code.
182 *
183          DO 50 I = 1, M
184             IF( R( I ).EQ.ZERO ) THEN
185                INFO = I
186                RETURN
187             END IF
188    50    CONTINUE
189       ELSE
190 *
191 *        Invert the scale factors.
192 *
193          DO 60 I = 1, M
194             R( I ) = ONE / MINMAX( R( I ), SMLNUM ), BIGNUM )
195    60    CONTINUE
196 *
197 *        Compute ROWCND = min(R(I)) / max(R(I)).
198 *
199          ROWCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )
200       END IF
201 *
202 *     Compute column scale factors.
203 *
204       DO 70 J = 1, N
205          C( J ) = ZERO
206    70 CONTINUE
207 *
208 *     Find the maximum element in each column,
209 *     assuming the row scaling computed above.
210 *
211       DO 90 J = 1, N
212          DO 80 I = 1, M
213             C( J ) = MAX( C( J ), CABS1( A( I, J ) )*R( I ) )
214    80    CONTINUE
215          IF( C( J ).GT.ZERO ) THEN
216             C( J ) = RADIX**INTLOG( C( J ) ) / LOGRDX )
217          END IF
218    90 CONTINUE
219 *
220 *     Find the maximum and minimum scale factors.
221 *
222       RCMIN = BIGNUM
223       RCMAX = ZERO
224       DO 100 J = 1, N
225          RCMIN = MIN( RCMIN, C( J ) )
226          RCMAX = MAX( RCMAX, C( J ) )
227   100 CONTINUE
228 *
229       IF( RCMIN.EQ.ZERO ) THEN
230 *
231 *        Find the first zero scale factor and return an error code.
232 *
233          DO 110 J = 1, N
234             IF( C( J ).EQ.ZERO ) THEN
235                INFO = M + J
236                RETURN
237             END IF
238   110    CONTINUE
239       ELSE
240 *
241 *        Invert the scale factors.
242 *
243          DO 120 J = 1, N
244             C( J ) = ONE / MINMAX( C( J ), SMLNUM ), BIGNUM )
245   120    CONTINUE
246 *
247 *        Compute COLCND = min(C(J)) / max(C(J)).
248 *
249          COLCND = MAX( RCMIN, SMLNUM ) / MIN( RCMAX, BIGNUM )
250       END IF
251 *
252       RETURN
253 *
254 *     End of ZGEEQUB
255 *
256       END