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