1       SUBROUTINE DLALN2( LTRANS, NA, NW, SMIN, CA, A, LDA, D1, D2, B,
  2      $                   LDB, WR, WI, X, LDX, SCALE, XNORM, INFO )
  3 *
  4 *  -- LAPACK auxiliary 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       LOGICAL            LTRANS
 11       INTEGER            INFO, LDA, LDB, LDX, NA, NW
 12       DOUBLE PRECISION   CA, D1, D2, SCALE, SMIN, WI, WR, XNORM
 13 *     ..
 14 *     .. Array Arguments ..
 15       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), X( LDX, * )
 16 *     ..
 17 *
 18 *  Purpose
 19 *  =======
 20 *
 21 *  DLALN2 solves a system of the form  (ca A - w D ) X = s B
 22 *  or (ca A**T - w D) X = s B   with possible scaling ("s") and
 23 *  perturbation of A.  (A**T means A-transpose.)
 24 *
 25 *  A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA
 26 *  real diagonal matrix, w is a real or complex value, and X and B are
 27 *  NA x 1 matrices -- real if w is real, complex if w is complex.  NA
 28 *  may be 1 or 2.
 29 *
 30 *  If w is complex, X and B are represented as NA x 2 matrices,
 31 *  the first column of each being the real part and the second
 32 *  being the imaginary part.
 33 *
 34 *  "s" is a scaling factor (.LE. 1), computed by DLALN2, which is
 35 *  so chosen that X can be computed without overflow.  X is further
 36 *  scaled if necessary to assure that norm(ca A - w D)*norm(X) is less
 37 *  than overflow.
 38 *
 39 *  If both singular values of (ca A - w D) are less than SMIN,
 40 *  SMIN*identity will be used instead of (ca A - w D).  If only one
 41 *  singular value is less than SMIN, one element of (ca A - w D) will be
 42 *  perturbed enough to make the smallest singular value roughly SMIN.
 43 *  If both singular values are at least SMIN, (ca A - w D) will not be
 44 *  perturbed.  In any case, the perturbation will be at most some small
 45 *  multiple of max( SMIN, ulp*norm(ca A - w D) ).  The singular values
 46 *  are computed by infinity-norm approximations, and thus will only be
 47 *  correct to a factor of 2 or so.
 48 *
 49 *  Note: all input quantities are assumed to be smaller than overflow
 50 *  by a reasonable factor.  (See BIGNUM.)
 51 *
 52 *  Arguments
 53 *  ==========
 54 *
 55 *  LTRANS  (input) LOGICAL
 56 *          =.TRUE.:  A-transpose will be used.
 57 *          =.FALSE.: A will be used (not transposed.)
 58 *
 59 *  NA      (input) INTEGER
 60 *          The size of the matrix A.  It may (only) be 1 or 2.
 61 *
 62 *  NW      (input) INTEGER
 63 *          1 if "w" is real, 2 if "w" is complex.  It may only be 1
 64 *          or 2.
 65 *
 66 *  SMIN    (input) DOUBLE PRECISION
 67 *          The desired lower bound on the singular values of A.  This
 68 *          should be a safe distance away from underflow or overflow,
 69 *          say, between (underflow/machine precision) and  (machine
 70 *          precision * overflow ).  (See BIGNUM and ULP.)
 71 *
 72 *  CA      (input) DOUBLE PRECISION
 73 *          The coefficient c, which A is multiplied by.
 74 *
 75 *  A       (input) DOUBLE PRECISION array, dimension (LDA,NA)
 76 *          The NA x NA matrix A.
 77 *
 78 *  LDA     (input) INTEGER
 79 *          The leading dimension of A.  It must be at least NA.
 80 *
 81 *  D1      (input) DOUBLE PRECISION
 82 *          The 1,1 element in the diagonal matrix D.
 83 *
 84 *  D2      (input) DOUBLE PRECISION
 85 *          The 2,2 element in the diagonal matrix D.  Not used if NW=1.
 86 *
 87 *  B       (input) DOUBLE PRECISION array, dimension (LDB,NW)
 88 *          The NA x NW matrix B (right-hand side).  If NW=2 ("w" is
 89 *          complex), column 1 contains the real part of B and column 2
 90 *          contains the imaginary part.
 91 *
 92 *  LDB     (input) INTEGER
 93 *          The leading dimension of B.  It must be at least NA.
 94 *
 95 *  WR      (input) DOUBLE PRECISION
 96 *          The real part of the scalar "w".
 97 *
 98 *  WI      (input) DOUBLE PRECISION
 99 *          The imaginary part of the scalar "w".  Not used if NW=1.
100 *
101 *  X       (output) DOUBLE PRECISION array, dimension (LDX,NW)
102 *          The NA x NW matrix X (unknowns), as computed by DLALN2.
103 *          If NW=2 ("w" is complex), on exit, column 1 will contain
104 *          the real part of X and column 2 will contain the imaginary
105 *          part.
106 *
107 *  LDX     (input) INTEGER
108 *          The leading dimension of X.  It must be at least NA.
109 *
110 *  SCALE   (output) DOUBLE PRECISION
111 *          The scale factor that B must be multiplied by to insure
112 *          that overflow does not occur when computing X.  Thus,
113 *          (ca A - w D) X  will be SCALE*B, not B (ignoring
114 *          perturbations of A.)  It will be at most 1.
115 *
116 *  XNORM   (output) DOUBLE PRECISION
117 *          The infinity-norm of X, when X is regarded as an NA x NW
118 *          real matrix.
119 *
120 *  INFO    (output) INTEGER
121 *          An error flag.  It will be set to zero if no error occurs,
122 *          a negative number if an argument is in error, or a positive
123 *          number if  ca A - w D  had to be perturbed.
124 *          The possible values are:
125 *          = 0: No error occurred, and (ca A - w D) did not have to be
126 *                 perturbed.
127 *          = 1: (ca A - w D) had to be perturbed to make its smallest
128 *               (or only) singular value greater than SMIN.
129 *          NOTE: In the interests of speed, this routine does not
130 *                check the inputs for errors.
131 *
132 * =====================================================================
133 *
134 *     .. Parameters ..
135       DOUBLE PRECISION   ZERO, ONE
136       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
137       DOUBLE PRECISION   TWO
138       PARAMETER          ( TWO = 2.0D0 )
139 *     ..
140 *     .. Local Scalars ..
141       INTEGER            ICMAX, J
142       DOUBLE PRECISION   BBND, BI1, BI2, BIGNUM, BNORM, BR1, BR2, CI21,
143      $                   CI22, CMAX, CNORM, CR21, CR22, CSI, CSR, LI21,
144      $                   LR21, SMINI, SMLNUM, TEMP, U22ABS, UI11, UI11R,
145      $                   UI12, UI12S, UI22, UR11, UR11R, UR12, UR12S,
146      $                   UR22, XI1, XI2, XR1, XR2
147 *     ..
148 *     .. Local Arrays ..
149       LOGICAL            RSWAP( 4 ), ZSWAP( 4 )
150       INTEGER            IPIVOT( 44 )
151       DOUBLE PRECISION   CI( 22 ), CIV( 4 ), CR( 22 ), CRV( 4 )
152 *     ..
153 *     .. External Functions ..
154       DOUBLE PRECISION   DLAMCH
155       EXTERNAL           DLAMCH
156 *     ..
157 *     .. External Subroutines ..
158       EXTERNAL           DLADIV
159 *     ..
160 *     .. Intrinsic Functions ..
161       INTRINSIC          ABSMAX
162 *     ..
163 *     .. Equivalences ..
164       EQUIVALENCE        ( CI( 11 ), CIV( 1 ) ),
165      $                   ( CR( 11 ), CRV( 1 ) )
166 *     ..
167 *     .. Data statements ..
168       DATA               ZSWAP / .FALSE..FALSE..TRUE..TRUE. /
169       DATA               RSWAP / .FALSE..TRUE..FALSE..TRUE. /
170       DATA               IPIVOT / 1234214334124,
171      $                   321 /
172 *     ..
173 *     .. Executable Statements ..
174 *
175 *     Compute BIGNUM
176 *
177       SMLNUM = TWO*DLAMCH( 'Safe minimum' )
178       BIGNUM = ONE / SMLNUM
179       SMINI = MAX( SMIN, SMLNUM )
180 *
181 *     Don't check for input errors
182 *
183       INFO = 0
184 *
185 *     Standard Initializations
186 *
187       SCALE = ONE
188 *
189       IF( NA.EQ.1 ) THEN
190 *
191 *        1 x 1  (i.e., scalar) system   C X = B
192 *
193          IF( NW.EQ.1 ) THEN
194 *
195 *           Real 1x1 system.
196 *
197 *           C = ca A - w D
198 *
199             CSR = CA*A( 11 ) - WR*D1
200             CNORM = ABS( CSR )
201 *
202 *           If | C | < SMINI, use C = SMINI
203 *
204             IF( CNORM.LT.SMINI ) THEN
205                CSR = SMINI
206                CNORM = SMINI
207                INFO = 1
208             END IF
209 *
210 *           Check scaling for  X = B / C
211 *
212             BNORM = ABS( B( 11 ) )
213             IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THEN
214                IF( BNORM.GT.BIGNUM*CNORM )
215      $            SCALE = ONE / BNORM
216             END IF
217 *
218 *           Compute X
219 *
220             X( 11 ) = ( B( 11 )*SCALE ) / CSR
221             XNORM = ABS( X( 11 ) )
222          ELSE
223 *
224 *           Complex 1x1 system (w is complex)
225 *
226 *           C = ca A - w D
227 *
228             CSR = CA*A( 11 ) - WR*D1
229             CSI = -WI*D1
230             CNORM = ABS( CSR ) + ABS( CSI )
231 *
232 *           If | C | < SMINI, use C = SMINI
233 *
234             IF( CNORM.LT.SMINI ) THEN
235                CSR = SMINI
236                CSI = ZERO
237                CNORM = SMINI
238                INFO = 1
239             END IF
240 *
241 *           Check scaling for  X = B / C
242 *
243             BNORM = ABS( B( 11 ) ) + ABS( B( 12 ) )
244             IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THEN
245                IF( BNORM.GT.BIGNUM*CNORM )
246      $            SCALE = ONE / BNORM
247             END IF
248 *
249 *           Compute X
250 *
251             CALL DLADIV( SCALE*B( 11 ), SCALE*B( 12 ), CSR, CSI,
252      $                   X( 11 ), X( 12 ) )
253             XNORM = ABS( X( 11 ) ) + ABS( X( 12 ) )
254          END IF
255 *
256       ELSE
257 *
258 *        2x2 System
259 *
260 *        Compute the real part of  C = ca A - w D  (or  ca A**T - w D )
261 *
262          CR( 11 ) = CA*A( 11 ) - WR*D1
263          CR( 22 ) = CA*A( 22 ) - WR*D2
264          IF( LTRANS ) THEN
265             CR( 12 ) = CA*A( 21 )
266             CR( 21 ) = CA*A( 12 )
267          ELSE
268             CR( 21 ) = CA*A( 21 )
269             CR( 12 ) = CA*A( 12 )
270          END IF
271 *
272          IF( NW.EQ.1 ) THEN
273 *
274 *           Real 2x2 system  (w is real)
275 *
276 *           Find the largest element in C
277 *
278             CMAX = ZERO
279             ICMAX = 0
280 *
281             DO 10 J = 14
282                IFABS( CRV( J ) ).GT.CMAX ) THEN
283                   CMAX = ABS( CRV( J ) )
284                   ICMAX = J
285                END IF
286    10       CONTINUE
287 *
288 *           If norm(C) < SMINI, use SMINI*identity.
289 *
290             IF( CMAX.LT.SMINI ) THEN
291                BNORM = MAXABS( B( 11 ) ), ABS( B( 21 ) ) )
292                IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THEN
293                   IF( BNORM.GT.BIGNUM*SMINI )
294      $               SCALE = ONE / BNORM
295                END IF
296                TEMP = SCALE / SMINI
297                X( 11 ) = TEMP*B( 11 )
298                X( 21 ) = TEMP*B( 21 )
299                XNORM = TEMP*BNORM
300                INFO = 1
301                RETURN
302             END IF
303 *
304 *           Gaussian elimination with complete pivoting.
305 *
306             UR11 = CRV( ICMAX )
307             CR21 = CRV( IPIVOT( 2, ICMAX ) )
308             UR12 = CRV( IPIVOT( 3, ICMAX ) )
309             CR22 = CRV( IPIVOT( 4, ICMAX ) )
310             UR11R = ONE / UR11
311             LR21 = UR11R*CR21
312             UR22 = CR22 - UR12*LR21
313 *
314 *           If smaller pivot < SMINI, use SMINI
315 *
316             IFABS( UR22 ).LT.SMINI ) THEN
317                UR22 = SMINI
318                INFO = 1
319             END IF
320             IF( RSWAP( ICMAX ) ) THEN
321                BR1 = B( 21 )
322                BR2 = B( 11 )
323             ELSE
324                BR1 = B( 11 )
325                BR2 = B( 21 )
326             END IF
327             BR2 = BR2 - LR21*BR1
328             BBND = MAXABS( BR1*( UR22*UR11R ) ), ABS( BR2 ) )
329             IF( BBND.GT.ONE .AND. ABS( UR22 ).LT.ONE ) THEN
330                IF( BBND.GE.BIGNUM*ABS( UR22 ) )
331      $            SCALE = ONE / BBND
332             END IF
333 *
334             XR2 = ( BR2*SCALE ) / UR22
335             XR1 = ( SCALE*BR1 )*UR11R - XR2*( UR11R*UR12 )
336             IF( ZSWAP( ICMAX ) ) THEN
337                X( 11 ) = XR2
338                X( 21 ) = XR1
339             ELSE
340                X( 11 ) = XR1
341                X( 21 ) = XR2
342             END IF
343             XNORM = MAXABS( XR1 ), ABS( XR2 ) )
344 *
345 *           Further scaling if  norm(A) norm(X) > overflow
346 *
347             IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THEN
348                IF( XNORM.GT.BIGNUM / CMAX ) THEN
349                   TEMP = CMAX / BIGNUM
350                   X( 11 ) = TEMP*X( 11 )
351                   X( 21 ) = TEMP*X( 21 )
352                   XNORM = TEMP*XNORM
353                   SCALE = TEMP*SCALE
354                END IF
355             END IF
356          ELSE
357 *
358 *           Complex 2x2 system  (w is complex)
359 *
360 *           Find the largest element in C
361 *
362             CI( 11 ) = -WI*D1
363             CI( 21 ) = ZERO
364             CI( 12 ) = ZERO
365             CI( 22 ) = -WI*D2
366             CMAX = ZERO
367             ICMAX = 0
368 *
369             DO 20 J = 14
370                IFABS( CRV( J ) )+ABS( CIV( J ) ).GT.CMAX ) THEN
371                   CMAX = ABS( CRV( J ) ) + ABS( CIV( J ) )
372                   ICMAX = J
373                END IF
374    20       CONTINUE
375 *
376 *           If norm(C) < SMINI, use SMINI*identity.
377 *
378             IF( CMAX.LT.SMINI ) THEN
379                BNORM = MAXABS( B( 11 ) )+ABS( B( 12 ) ),
380      $                 ABS( B( 21 ) )+ABS( B( 22 ) ) )
381                IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THEN
382                   IF( BNORM.GT.BIGNUM*SMINI )
383      $               SCALE = ONE / BNORM
384                END IF
385                TEMP = SCALE / SMINI
386                X( 11 ) = TEMP*B( 11 )
387                X( 21 ) = TEMP*B( 21 )
388                X( 12 ) = TEMP*B( 12 )
389                X( 22 ) = TEMP*B( 22 )
390                XNORM = TEMP*BNORM
391                INFO = 1
392                RETURN
393             END IF
394 *
395 *           Gaussian elimination with complete pivoting.
396 *
397             UR11 = CRV( ICMAX )
398             UI11 = CIV( ICMAX )
399             CR21 = CRV( IPIVOT( 2, ICMAX ) )
400             CI21 = CIV( IPIVOT( 2, ICMAX ) )
401             UR12 = CRV( IPIVOT( 3, ICMAX ) )
402             UI12 = CIV( IPIVOT( 3, ICMAX ) )
403             CR22 = CRV( IPIVOT( 4, ICMAX ) )
404             CI22 = CIV( IPIVOT( 4, ICMAX ) )
405             IF( ICMAX.EQ.1 .OR. ICMAX.EQ.4 ) THEN
406 *
407 *              Code when off-diagonals of pivoted C are real
408 *
409                IFABS( UR11 ).GT.ABS( UI11 ) ) THEN
410                   TEMP = UI11 / UR11
411                   UR11R = ONE / ( UR11*( ONE+TEMP**2 ) )
412                   UI11R = -TEMP*UR11R
413                ELSE
414                   TEMP = UR11 / UI11
415                   UI11R = -ONE / ( UI11*( ONE+TEMP**2 ) )
416                   UR11R = -TEMP*UI11R
417                END IF
418                LR21 = CR21*UR11R
419                LI21 = CR21*UI11R
420                UR12S = UR12*UR11R
421                UI12S = UR12*UI11R
422                UR22 = CR22 - UR12*LR21
423                UI22 = CI22 - UR12*LI21
424             ELSE
425 *
426 *              Code when diagonals of pivoted C are real
427 *
428                UR11R = ONE / UR11
429                UI11R = ZERO
430                LR21 = CR21*UR11R
431                LI21 = CI21*UR11R
432                UR12S = UR12*UR11R
433                UI12S = UI12*UR11R
434                UR22 = CR22 - UR12*LR21 + UI12*LI21
435                UI22 = -UR12*LI21 - UI12*LR21
436             END IF
437             U22ABS = ABS( UR22 ) + ABS( UI22 )
438 *
439 *           If smaller pivot < SMINI, use SMINI
440 *
441             IF( U22ABS.LT.SMINI ) THEN
442                UR22 = SMINI
443                UI22 = ZERO
444                INFO = 1
445             END IF
446             IF( RSWAP( ICMAX ) ) THEN
447                BR2 = B( 11 )
448                BR1 = B( 21 )
449                BI2 = B( 12 )
450                BI1 = B( 22 )
451             ELSE
452                BR1 = B( 11 )
453                BR2 = B( 21 )
454                BI1 = B( 12 )
455                BI2 = B( 22 )
456             END IF
457             BR2 = BR2 - LR21*BR1 + LI21*BI1
458             BI2 = BI2 - LI21*BR1 - LR21*BI1
459             BBND = MAX( ( ABS( BR1 )+ABS( BI1 ) )*
460      $             ( U22ABS*ABS( UR11R )+ABS( UI11R ) ) ),
461      $             ABS( BR2 )+ABS( BI2 ) )
462             IF( BBND.GT.ONE .AND. U22ABS.LT.ONE ) THEN
463                IF( BBND.GE.BIGNUM*U22ABS ) THEN
464                   SCALE = ONE / BBND
465                   BR1 = SCALE*BR1
466                   BI1 = SCALE*BI1
467                   BR2 = SCALE*BR2
468                   BI2 = SCALE*BI2
469                END IF
470             END IF
471 *
472             CALL DLADIV( BR2, BI2, UR22, UI22, XR2, XI2 )
473             XR1 = UR11R*BR1 - UI11R*BI1 - UR12S*XR2 + UI12S*XI2
474             XI1 = UI11R*BR1 + UR11R*BI1 - UI12S*XR2 - UR12S*XI2
475             IF( ZSWAP( ICMAX ) ) THEN
476                X( 11 ) = XR2
477                X( 21 ) = XR1
478                X( 12 ) = XI2
479                X( 22 ) = XI1
480             ELSE
481                X( 11 ) = XR1
482                X( 21 ) = XR2
483                X( 12 ) = XI1
484                X( 22 ) = XI2
485             END IF
486             XNORM = MAXABS( XR1 )+ABS( XI1 ), ABS( XR2 )+ABS( XI2 ) )
487 *
488 *           Further scaling if  norm(A) norm(X) > overflow
489 *
490             IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THEN
491                IF( XNORM.GT.BIGNUM / CMAX ) THEN
492                   TEMP = CMAX / BIGNUM
493                   X( 11 ) = TEMP*X( 11 )
494                   X( 21 ) = TEMP*X( 21 )
495                   X( 12 ) = TEMP*X( 12 )
496                   X( 22 ) = TEMP*X( 22 )
497                   XNORM = TEMP*XNORM
498                   SCALE = TEMP*SCALE
499                END IF
500             END IF
501          END IF
502       END IF
503 *
504       RETURN
505 *
506 *     End of DLALN2
507 *
508       END