File:  [local] / rpl / lapack / lapack / dlaln2.f
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Fri Aug 6 15:32:27 2010 UTC (13 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Cohérence

    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' - w D) X = s B   with possible scaling ("s") and
   23: *  perturbation of A.  (A' 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( 4, 4 )
  151:       DOUBLE PRECISION   CI( 2, 2 ), CIV( 4 ), CR( 2, 2 ), 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          ABS, MAX
  162: *     ..
  163: *     .. Equivalences ..
  164:       EQUIVALENCE        ( CI( 1, 1 ), CIV( 1 ) ),
  165:      $                   ( CR( 1, 1 ), CRV( 1 ) )
  166: *     ..
  167: *     .. Data statements ..
  168:       DATA               ZSWAP / .FALSE., .FALSE., .TRUE., .TRUE. /
  169:       DATA               RSWAP / .FALSE., .TRUE., .FALSE., .TRUE. /
  170:       DATA               IPIVOT / 1, 2, 3, 4, 2, 1, 4, 3, 3, 4, 1, 2, 4,
  171:      $                   3, 2, 1 /
  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( 1, 1 ) - 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( 1, 1 ) )
  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( 1, 1 ) = ( B( 1, 1 )*SCALE ) / CSR
  221:             XNORM = ABS( X( 1, 1 ) )
  222:          ELSE
  223: *
  224: *           Complex 1x1 system (w is complex)
  225: *
  226: *           C = ca A - w D
  227: *
  228:             CSR = CA*A( 1, 1 ) - 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( 1, 1 ) ) + ABS( B( 1, 2 ) )
  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( 1, 1 ), SCALE*B( 1, 2 ), CSR, CSI,
  252:      $                   X( 1, 1 ), X( 1, 2 ) )
  253:             XNORM = ABS( X( 1, 1 ) ) + ABS( X( 1, 2 ) )
  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' - w D )
  261: *
  262:          CR( 1, 1 ) = CA*A( 1, 1 ) - WR*D1
  263:          CR( 2, 2 ) = CA*A( 2, 2 ) - WR*D2
  264:          IF( LTRANS ) THEN
  265:             CR( 1, 2 ) = CA*A( 2, 1 )
  266:             CR( 2, 1 ) = CA*A( 1, 2 )
  267:          ELSE
  268:             CR( 2, 1 ) = CA*A( 2, 1 )
  269:             CR( 1, 2 ) = CA*A( 1, 2 )
  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 = 1, 4
  282:                IF( ABS( 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 = MAX( ABS( B( 1, 1 ) ), ABS( B( 2, 1 ) ) )
  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( 1, 1 ) = TEMP*B( 1, 1 )
  298:                X( 2, 1 ) = TEMP*B( 2, 1 )
  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:             IF( ABS( UR22 ).LT.SMINI ) THEN
  317:                UR22 = SMINI
  318:                INFO = 1
  319:             END IF
  320:             IF( RSWAP( ICMAX ) ) THEN
  321:                BR1 = B( 2, 1 )
  322:                BR2 = B( 1, 1 )
  323:             ELSE
  324:                BR1 = B( 1, 1 )
  325:                BR2 = B( 2, 1 )
  326:             END IF
  327:             BR2 = BR2 - LR21*BR1
  328:             BBND = MAX( ABS( 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( 1, 1 ) = XR2
  338:                X( 2, 1 ) = XR1
  339:             ELSE
  340:                X( 1, 1 ) = XR1
  341:                X( 2, 1 ) = XR2
  342:             END IF
  343:             XNORM = MAX( ABS( 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( 1, 1 ) = TEMP*X( 1, 1 )
  351:                   X( 2, 1 ) = TEMP*X( 2, 1 )
  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( 1, 1 ) = -WI*D1
  363:             CI( 2, 1 ) = ZERO
  364:             CI( 1, 2 ) = ZERO
  365:             CI( 2, 2 ) = -WI*D2
  366:             CMAX = ZERO
  367:             ICMAX = 0
  368: *
  369:             DO 20 J = 1, 4
  370:                IF( ABS( 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 = MAX( ABS( B( 1, 1 ) )+ABS( B( 1, 2 ) ),
  380:      $                 ABS( B( 2, 1 ) )+ABS( B( 2, 2 ) ) )
  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( 1, 1 ) = TEMP*B( 1, 1 )
  387:                X( 2, 1 ) = TEMP*B( 2, 1 )
  388:                X( 1, 2 ) = TEMP*B( 1, 2 )
  389:                X( 2, 2 ) = TEMP*B( 2, 2 )
  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:                IF( ABS( 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( 1, 1 )
  448:                BR1 = B( 2, 1 )
  449:                BI2 = B( 1, 2 )
  450:                BI1 = B( 2, 2 )
  451:             ELSE
  452:                BR1 = B( 1, 1 )
  453:                BR2 = B( 2, 1 )
  454:                BI1 = B( 1, 2 )
  455:                BI2 = B( 2, 2 )
  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( 1, 1 ) = XR2
  477:                X( 2, 1 ) = XR1
  478:                X( 1, 2 ) = XI2
  479:                X( 2, 2 ) = XI1
  480:             ELSE
  481:                X( 1, 1 ) = XR1
  482:                X( 2, 1 ) = XR2
  483:                X( 1, 2 ) = XI1
  484:                X( 2, 2 ) = XI2
  485:             END IF
  486:             XNORM = MAX( ABS( 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( 1, 1 ) = TEMP*X( 1, 1 )
  494:                   X( 2, 1 ) = TEMP*X( 2, 1 )
  495:                   X( 1, 2 ) = TEMP*X( 1, 2 )
  496:                   X( 2, 2 ) = TEMP*X( 2, 2 )
  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

CVSweb interface <joel.bertrand@systella.fr>