1       SUBROUTINE ZGGBAL( JOB, N, A, LDA, B, LDB, ILO, IHI, LSCALE,
  2      $                   RSCALE, WORK, INFO )
  3 *
  4 *  -- LAPACK routine (version 3.2) --
  5 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  6 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  7 *     November 2006
  8 *
  9 *     .. Scalar Arguments ..
 10       CHARACTER          JOB
 11       INTEGER            IHI, ILO, INFO, LDA, LDB, N
 12 *     ..
 13 *     .. Array Arguments ..
 14       DOUBLE PRECISION   LSCALE( * ), RSCALE( * ), WORK( * )
 15       COMPLEX*16         A( LDA, * ), B( LDB, * )
 16 *     ..
 17 *
 18 *  Purpose
 19 *  =======
 20 *
 21 *  ZGGBAL balances a pair of general complex matrices (A,B).  This
 22 *  involves, first, permuting A and B by similarity transformations to
 23 *  isolate eigenvalues in the first 1 to ILO$-$1 and last IHI+1 to N
 24 *  elements on the diagonal; and second, applying a diagonal similarity
 25 *  transformation to rows and columns ILO to IHI to make the rows
 26 *  and columns as close in norm as possible. Both steps are optional.
 27 *
 28 *  Balancing may reduce the 1-norm of the matrices, and improve the
 29 *  accuracy of the computed eigenvalues and/or eigenvectors in the
 30 *  generalized eigenvalue problem A*x = lambda*B*x.
 31 *
 32 *  Arguments
 33 *  =========
 34 *
 35 *  JOB     (input) CHARACTER*1
 36 *          Specifies the operations to be performed on A and B:
 37 *          = 'N':  none:  simply set ILO = 1, IHI = N, LSCALE(I) = 1.0
 38 *                  and RSCALE(I) = 1.0 for i=1,...,N;
 39 *          = 'P':  permute only;
 40 *          = 'S':  scale only;
 41 *          = 'B':  both permute and scale.
 42 *
 43 *  N       (input) INTEGER
 44 *          The order of the matrices A and B.  N >= 0.
 45 *
 46 *  A       (input/output) COMPLEX*16 array, dimension (LDA,N)
 47 *          On entry, the input matrix A.
 48 *          On exit, A is overwritten by the balanced matrix.
 49 *          If JOB = 'N', A is not referenced.
 50 *
 51 *  LDA     (input) INTEGER
 52 *          The leading dimension of the array A. LDA >= max(1,N).
 53 *
 54 *  B       (input/output) COMPLEX*16 array, dimension (LDB,N)
 55 *          On entry, the input matrix B.
 56 *          On exit, B is overwritten by the balanced matrix.
 57 *          If JOB = 'N', B is not referenced.
 58 *
 59 *  LDB     (input) INTEGER
 60 *          The leading dimension of the array B. LDB >= max(1,N).
 61 *
 62 *  ILO     (output) INTEGER
 63 *  IHI     (output) INTEGER
 64 *          ILO and IHI are set to integers such that on exit
 65 *          A(i,j) = 0 and B(i,j) = 0 if i > j and
 66 *          j = 1,...,ILO-1 or i = IHI+1,...,N.
 67 *          If JOB = 'N' or 'S', ILO = 1 and IHI = N.
 68 *
 69 *  LSCALE  (output) DOUBLE PRECISION array, dimension (N)
 70 *          Details of the permutations and scaling factors applied
 71 *          to the left side of A and B.  If P(j) is the index of the
 72 *          row interchanged with row j, and D(j) is the scaling factor
 73 *          applied to row j, then
 74 *            LSCALE(j) = P(j)    for J = 1,...,ILO-1
 75 *                      = D(j)    for J = ILO,...,IHI
 76 *                      = P(j)    for J = IHI+1,...,N.
 77 *          The order in which the interchanges are made is N to IHI+1,
 78 *          then 1 to ILO-1.
 79 *
 80 *  RSCALE  (output) DOUBLE PRECISION array, dimension (N)
 81 *          Details of the permutations and scaling factors applied
 82 *          to the right side of A and B.  If P(j) is the index of the
 83 *          column interchanged with column j, and D(j) is the scaling
 84 *          factor applied to column j, then
 85 *            RSCALE(j) = P(j)    for J = 1,...,ILO-1
 86 *                      = D(j)    for J = ILO,...,IHI
 87 *                      = P(j)    for J = IHI+1,...,N.
 88 *          The order in which the interchanges are made is N to IHI+1,
 89 *          then 1 to ILO-1.
 90 *
 91 *  WORK    (workspace) REAL array, dimension (lwork)
 92 *          lwork must be at least max(1,6*N) when JOB = 'S' or 'B', and
 93 *          at least 1 when JOB = 'N' or 'P'.
 94 *
 95 *  INFO    (output) INTEGER
 96 *          = 0:  successful exit
 97 *          < 0:  if INFO = -i, the i-th argument had an illegal value.
 98 *
 99 *  Further Details
100 *  ===============
101 *
102 *  See R.C. WARD, Balancing the generalized eigenvalue problem,
103 *                 SIAM J. Sci. Stat. Comp. 2 (1981), 141-152.
104 *
105 *  =====================================================================
106 *
107 *     .. Parameters ..
108       DOUBLE PRECISION   ZERO, HALF, ONE
109       PARAMETER          ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 )
110       DOUBLE PRECISION   THREE, SCLFAC
111       PARAMETER          ( THREE = 3.0D+0, SCLFAC = 1.0D+1 )
112       COMPLEX*16         CZERO
113       PARAMETER          ( CZERO = ( 0.0D+00.0D+0 ) )
114 *     ..
115 *     .. Local Scalars ..
116       INTEGER            I, ICAB, IFLOW, IP1, IR, IRAB, IT, J, JC, JP1,
117      $                   K, KOUNT, L, LCAB, LM1, LRAB, LSFMAX, LSFMIN,
118      $                   M, NR, NRP2
119       DOUBLE PRECISION   ALPHA, BASL, BETA, CAB, CMAX, COEF, COEF2,
120      $                   COEF5, COR, EW, EWC, GAMMA, PGAMMA, RAB, SFMAX,
121      $                   SFMIN, SUM, T, TA, TB, TC
122       COMPLEX*16         CDUM
123 *     ..
124 *     .. External Functions ..
125       LOGICAL            LSAME
126       INTEGER            IZAMAX
127       DOUBLE PRECISION   DDOT, DLAMCH
128       EXTERNAL           LSAME, IZAMAX, DDOT, DLAMCH
129 *     ..
130 *     .. External Subroutines ..
131       EXTERNAL           DAXPY, DSCAL, XERBLA, ZDSCAL, ZSWAP
132 *     ..
133 *     .. Intrinsic Functions ..
134       INTRINSIC          ABSDBLEDIMAGINTLOG10MAXMINSIGN
135 *     ..
136 *     .. Statement Functions ..
137       DOUBLE PRECISION   CABS1
138 *     ..
139 *     .. Statement Function definitions ..
140       CABS1( CDUM ) = ABSDBLE( CDUM ) ) + ABSDIMAG( CDUM ) )
141 *     ..
142 *     .. Executable Statements ..
143 *
144 *     Test the input parameters
145 *
146       INFO = 0
147       IF.NOT.LSAME( JOB, 'N' ) .AND. .NOT.LSAME( JOB, 'P' ) .AND.
148      $    .NOT.LSAME( JOB, 'S' ) .AND. .NOT.LSAME( JOB, 'B' ) ) THEN
149          INFO = -1
150       ELSE IF( N.LT.0 ) THEN
151          INFO = -2
152       ELSE IF( LDA.LT.MAX1, N ) ) THEN
153          INFO = -4
154       ELSE IF( LDB.LT.MAX1, N ) ) THEN
155          INFO = -6
156       END IF
157       IF( INFO.NE.0 ) THEN
158          CALL XERBLA( 'ZGGBAL'-INFO )
159          RETURN
160       END IF
161 *
162 *     Quick return if possible
163 *
164       IF( N.EQ.0 ) THEN
165          ILO = 1
166          IHI = N
167          RETURN
168       END IF
169 *
170       IF( N.EQ.1 ) THEN
171          ILO = 1
172          IHI = N
173          LSCALE( 1 ) = ONE
174          RSCALE( 1 ) = ONE
175          RETURN
176       END IF
177 *
178       IF( LSAME( JOB, 'N' ) ) THEN
179          ILO = 1
180          IHI = N
181          DO 10 I = 1, N
182             LSCALE( I ) = ONE
183             RSCALE( I ) = ONE
184    10    CONTINUE
185          RETURN
186       END IF
187 *
188       K = 1
189       L = N
190       IF( LSAME( JOB, 'S' ) )
191      $   GO TO 190
192 *
193       GO TO 30
194 *
195 *     Permute the matrices A and B to isolate the eigenvalues.
196 *
197 *     Find row with one nonzero in columns 1 through L
198 *
199    20 CONTINUE
200       L = LM1
201       IF( L.NE.1 )
202      $   GO TO 30
203 *
204       RSCALE( 1 ) = 1
205       LSCALE( 1 ) = 1
206       GO TO 190
207 *
208    30 CONTINUE
209       LM1 = L - 1
210       DO 80 I = L, 1-1
211          DO 40 J = 1, LM1
212             JP1 = J + 1
213             IF( A( I, J ).NE.CZERO .OR. B( I, J ).NE.CZERO )
214      $         GO TO 50
215    40    CONTINUE
216          J = L
217          GO TO 70
218 *
219    50    CONTINUE
220          DO 60 J = JP1, L
221             IF( A( I, J ).NE.CZERO .OR. B( I, J ).NE.CZERO )
222      $         GO TO 80
223    60    CONTINUE
224          J = JP1 - 1
225 *
226    70    CONTINUE
227          M = L
228          IFLOW = 1
229          GO TO 160
230    80 CONTINUE
231       GO TO 100
232 *
233 *     Find column with one nonzero in rows K through N
234 *
235    90 CONTINUE
236       K = K + 1
237 *
238   100 CONTINUE
239       DO 150 J = K, L
240          DO 110 I = K, LM1
241             IP1 = I + 1
242             IF( A( I, J ).NE.CZERO .OR. B( I, J ).NE.CZERO )
243      $         GO TO 120
244   110    CONTINUE
245          I = L
246          GO TO 140
247   120    CONTINUE
248          DO 130 I = IP1, L
249             IF( A( I, J ).NE.CZERO .OR. B( I, J ).NE.CZERO )
250      $         GO TO 150
251   130    CONTINUE
252          I = IP1 - 1
253   140    CONTINUE
254          M = K
255          IFLOW = 2
256          GO TO 160
257   150 CONTINUE
258       GO TO 190
259 *
260 *     Permute rows M and I
261 *
262   160 CONTINUE
263       LSCALE( M ) = I
264       IF( I.EQ.M )
265      $   GO TO 170
266       CALL ZSWAP( N-K+1, A( I, K ), LDA, A( M, K ), LDA )
267       CALL ZSWAP( N-K+1, B( I, K ), LDB, B( M, K ), LDB )
268 *
269 *     Permute columns M and J
270 *
271   170 CONTINUE
272       RSCALE( M ) = J
273       IF( J.EQ.M )
274      $   GO TO 180
275       CALL ZSWAP( L, A( 1, J ), 1, A( 1, M ), 1 )
276       CALL ZSWAP( L, B( 1, J ), 1, B( 1, M ), 1 )
277 *
278   180 CONTINUE
279       GO TO ( 2090 )IFLOW
280 *
281   190 CONTINUE
282       ILO = K
283       IHI = L
284 *
285       IF( LSAME( JOB, 'P' ) ) THEN
286          DO 195 I = ILO, IHI
287             LSCALE( I ) = ONE
288             RSCALE( I ) = ONE
289   195    CONTINUE
290          RETURN
291       END IF
292 *
293       IF( ILO.EQ.IHI )
294      $   RETURN
295 *
296 *     Balance the submatrix in rows ILO to IHI.
297 *
298       NR = IHI - ILO + 1
299       DO 200 I = ILO, IHI
300          RSCALE( I ) = ZERO
301          LSCALE( I ) = ZERO
302 *
303          WORK( I ) = ZERO
304          WORK( I+N ) = ZERO
305          WORK( I+2*N ) = ZERO
306          WORK( I+3*N ) = ZERO
307          WORK( I+4*N ) = ZERO
308          WORK( I+5*N ) = ZERO
309   200 CONTINUE
310 *
311 *     Compute right side vector in resulting linear equations
312 *
313       BASL = LOG10( SCLFAC )
314       DO 240 I = ILO, IHI
315          DO 230 J = ILO, IHI
316             IF( A( I, J ).EQ.CZERO ) THEN
317                TA = ZERO
318                GO TO 210
319             END IF
320             TA = LOG10( CABS1( A( I, J ) ) ) / BASL
321 *
322   210       CONTINUE
323             IF( B( I, J ).EQ.CZERO ) THEN
324                TB = ZERO
325                GO TO 220
326             END IF
327             TB = LOG10( CABS1( B( I, J ) ) ) / BASL
328 *
329   220       CONTINUE
330             WORK( I+4*N ) = WORK( I+4*N ) - TA - TB
331             WORK( J+5*N ) = WORK( J+5*N ) - TA - TB
332   230    CONTINUE
333   240 CONTINUE
334 *
335       COEF = ONE / DBLE2*NR )
336       COEF2 = COEF*COEF
337       COEF5 = HALF*COEF2
338       NRP2 = NR + 2
339       BETA = ZERO
340       IT = 1
341 *
342 *     Start generalized conjugate gradient iteration
343 *
344   250 CONTINUE
345 *
346       GAMMA = DDOT( NR, WORK( ILO+4*N ), 1, WORK( ILO+4*N ), 1 ) +
347      $        DDOT( NR, WORK( ILO+5*N ), 1, WORK( ILO+5*N ), 1 )
348 *
349       EW = ZERO
350       EWC = ZERO
351       DO 260 I = ILO, IHI
352          EW = EW + WORK( I+4*N )
353          EWC = EWC + WORK( I+5*N )
354   260 CONTINUE
355 *
356       GAMMA = COEF*GAMMA - COEF2*( EW**2+EWC**2 ) - COEF5*( EW-EWC )**2
357       IFGAMMA.EQ.ZERO )
358      $   GO TO 350
359       IF( IT.NE.1 )
360      $   BETA = GAMMA / PGAMMA
361       T = COEF5*( EWC-THREE*EW )
362       TC = COEF5*( EW-THREE*EWC )
363 *
364       CALL DSCAL( NR, BETA, WORK( ILO ), 1 )
365       CALL DSCAL( NR, BETA, WORK( ILO+N ), 1 )
366 *
367       CALL DAXPY( NR, COEF, WORK( ILO+4*N ), 1, WORK( ILO+N ), 1 )
368       CALL DAXPY( NR, COEF, WORK( ILO+5*N ), 1, WORK( ILO ), 1 )
369 *
370       DO 270 I = ILO, IHI
371          WORK( I ) = WORK( I ) + TC
372          WORK( I+N ) = WORK( I+N ) + T
373   270 CONTINUE
374 *
375 *     Apply matrix to vector
376 *
377       DO 300 I = ILO, IHI
378          KOUNT = 0
379          SUM = ZERO
380          DO 290 J = ILO, IHI
381             IF( A( I, J ).EQ.CZERO )
382      $         GO TO 280
383             KOUNT = KOUNT + 1
384             SUM = SUM + WORK( J )
385   280       CONTINUE
386             IF( B( I, J ).EQ.CZERO )
387      $         GO TO 290
388             KOUNT = KOUNT + 1
389             SUM = SUM + WORK( J )
390   290    CONTINUE
391          WORK( I+2*N ) = DBLE( KOUNT )*WORK( I+N ) + SUM
392   300 CONTINUE
393 *
394       DO 330 J = ILO, IHI
395          KOUNT = 0
396          SUM = ZERO
397          DO 320 I = ILO, IHI
398             IF( A( I, J ).EQ.CZERO )
399      $         GO TO 310
400             KOUNT = KOUNT + 1
401             SUM = SUM + WORK( I+N )
402   310       CONTINUE
403             IF( B( I, J ).EQ.CZERO )
404      $         GO TO 320
405             KOUNT = KOUNT + 1
406             SUM = SUM + WORK( I+N )
407   320    CONTINUE
408          WORK( J+3*N ) = DBLE( KOUNT )*WORK( J ) + SUM
409   330 CONTINUE
410 *
411       SUM = DDOT( NR, WORK( ILO+N ), 1, WORK( ILO+2*N ), 1 ) +
412      $      DDOT( NR, WORK( ILO ), 1, WORK( ILO+3*N ), 1 )
413       ALPHA = GAMMA / SUM
414 *
415 *     Determine correction to current iteration
416 *
417       CMAX = ZERO
418       DO 340 I = ILO, IHI
419          COR = ALPHA*WORK( I+N )
420          IFABS( COR ).GT.CMAX )
421      $      CMAX = ABS( COR )
422          LSCALE( I ) = LSCALE( I ) + COR
423          COR = ALPHA*WORK( I )
424          IFABS( COR ).GT.CMAX )
425      $      CMAX = ABS( COR )
426          RSCALE( I ) = RSCALE( I ) + COR
427   340 CONTINUE
428       IF( CMAX.LT.HALF )
429      $   GO TO 350
430 *
431       CALL DAXPY( NR, -ALPHA, WORK( ILO+2*N ), 1, WORK( ILO+4*N ), 1 )
432       CALL DAXPY( NR, -ALPHA, WORK( ILO+3*N ), 1, WORK( ILO+5*N ), 1 )
433 *
434       PGAMMA = GAMMA
435       IT = IT + 1
436       IF( IT.LE.NRP2 )
437      $   GO TO 250
438 *
439 *     End generalized conjugate gradient iteration
440 *
441   350 CONTINUE
442       SFMIN = DLAMCH( 'S' )
443       SFMAX = ONE / SFMIN
444       LSFMIN = INTLOG10( SFMIN ) / BASL+ONE )
445       LSFMAX = INTLOG10( SFMAX ) / BASL )
446       DO 360 I = ILO, IHI
447          IRAB = IZAMAX( N-ILO+1, A( I, ILO ), LDA )
448          RAB = ABS( A( I, IRAB+ILO-1 ) )
449          IRAB = IZAMAX( N-ILO+1, B( I, ILO ), LDB )
450          RAB = MAX( RAB, ABS( B( I, IRAB+ILO-1 ) ) )
451          LRAB = INTLOG10( RAB+SFMIN ) / BASL+ONE )
452          IR = LSCALE( I ) + SIGN( HALF, LSCALE( I ) )
453          IR = MINMAX( IR, LSFMIN ), LSFMAX, LSFMAX-LRAB )
454          LSCALE( I ) = SCLFAC**IR
455          ICAB = IZAMAX( IHI, A( 1, I ), 1 )
456          CAB = ABS( A( ICAB, I ) )
457          ICAB = IZAMAX( IHI, B( 1, I ), 1 )
458          CAB = MAX( CAB, ABS( B( ICAB, I ) ) )
459          LCAB = INTLOG10( CAB+SFMIN ) / BASL+ONE )
460          JC = RSCALE( I ) + SIGN( HALF, RSCALE( I ) )
461          JC = MINMAX( JC, LSFMIN ), LSFMAX, LSFMAX-LCAB )
462          RSCALE( I ) = SCLFAC**JC
463   360 CONTINUE
464 *
465 *     Row scaling of matrices A and B
466 *
467       DO 370 I = ILO, IHI
468          CALL ZDSCAL( N-ILO+1, LSCALE( I ), A( I, ILO ), LDA )
469          CALL ZDSCAL( N-ILO+1, LSCALE( I ), B( I, ILO ), LDB )
470   370 CONTINUE
471 *
472 *     Column scaling of matrices A and B
473 *
474       DO 380 J = ILO, IHI
475          CALL ZDSCAL( IHI, RSCALE( J ), A( 1, J ), 1 )
476          CALL ZDSCAL( IHI, RSCALE( J ), B( 1, J ), 1 )
477   380 CONTINUE
478 *
479       RETURN
480 *
481 *     End of ZGGBAL
482 *
483       END