File:  [local] / rpl / lapack / lapack / dtrsyl.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Jan 26 15:22:46 2010 UTC (14 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Initial revision

    1:       SUBROUTINE DTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C,
    2:      $                   LDC, SCALE, 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          TRANA, TRANB
   11:       INTEGER            INFO, ISGN, LDA, LDB, LDC, M, N
   12:       DOUBLE PRECISION   SCALE
   13: *     ..
   14: *     .. Array Arguments ..
   15:       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), C( LDC, * )
   16: *     ..
   17: *
   18: *  Purpose
   19: *  =======
   20: *
   21: *  DTRSYL solves the real Sylvester matrix equation:
   22: *
   23: *     op(A)*X + X*op(B) = scale*C or
   24: *     op(A)*X - X*op(B) = scale*C,
   25: *
   26: *  where op(A) = A or A**T, and  A and B are both upper quasi-
   27: *  triangular. A is M-by-M and B is N-by-N; the right hand side C and
   28: *  the solution X are M-by-N; and scale is an output scale factor, set
   29: *  <= 1 to avoid overflow in X.
   30: *
   31: *  A and B must be in Schur canonical form (as returned by DHSEQR), that
   32: *  is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks;
   33: *  each 2-by-2 diagonal block has its diagonal elements equal and its
   34: *  off-diagonal elements of opposite sign.
   35: *
   36: *  Arguments
   37: *  =========
   38: *
   39: *  TRANA   (input) CHARACTER*1
   40: *          Specifies the option op(A):
   41: *          = 'N': op(A) = A    (No transpose)
   42: *          = 'T': op(A) = A**T (Transpose)
   43: *          = 'C': op(A) = A**H (Conjugate transpose = Transpose)
   44: *
   45: *  TRANB   (input) CHARACTER*1
   46: *          Specifies the option op(B):
   47: *          = 'N': op(B) = B    (No transpose)
   48: *          = 'T': op(B) = B**T (Transpose)
   49: *          = 'C': op(B) = B**H (Conjugate transpose = Transpose)
   50: *
   51: *  ISGN    (input) INTEGER
   52: *          Specifies the sign in the equation:
   53: *          = +1: solve op(A)*X + X*op(B) = scale*C
   54: *          = -1: solve op(A)*X - X*op(B) = scale*C
   55: *
   56: *  M       (input) INTEGER
   57: *          The order of the matrix A, and the number of rows in the
   58: *          matrices X and C. M >= 0.
   59: *
   60: *  N       (input) INTEGER
   61: *          The order of the matrix B, and the number of columns in the
   62: *          matrices X and C. N >= 0.
   63: *
   64: *  A       (input) DOUBLE PRECISION array, dimension (LDA,M)
   65: *          The upper quasi-triangular matrix A, in Schur canonical form.
   66: *
   67: *  LDA     (input) INTEGER
   68: *          The leading dimension of the array A. LDA >= max(1,M).
   69: *
   70: *  B       (input) DOUBLE PRECISION array, dimension (LDB,N)
   71: *          The upper quasi-triangular matrix B, in Schur canonical form.
   72: *
   73: *  LDB     (input) INTEGER
   74: *          The leading dimension of the array B. LDB >= max(1,N).
   75: *
   76: *  C       (input/output) DOUBLE PRECISION array, dimension (LDC,N)
   77: *          On entry, the M-by-N right hand side matrix C.
   78: *          On exit, C is overwritten by the solution matrix X.
   79: *
   80: *  LDC     (input) INTEGER
   81: *          The leading dimension of the array C. LDC >= max(1,M)
   82: *
   83: *  SCALE   (output) DOUBLE PRECISION
   84: *          The scale factor, scale, set <= 1 to avoid overflow in X.
   85: *
   86: *  INFO    (output) INTEGER
   87: *          = 0: successful exit
   88: *          < 0: if INFO = -i, the i-th argument had an illegal value
   89: *          = 1: A and B have common or very close eigenvalues; perturbed
   90: *               values were used to solve the equation (but the matrices
   91: *               A and B are unchanged).
   92: *
   93: *  =====================================================================
   94: *
   95: *     .. Parameters ..
   96:       DOUBLE PRECISION   ZERO, ONE
   97:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
   98: *     ..
   99: *     .. Local Scalars ..
  100:       LOGICAL            NOTRNA, NOTRNB
  101:       INTEGER            IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXT
  102:       DOUBLE PRECISION   A11, BIGNUM, DA11, DB, EPS, SCALOC, SGN, SMIN,
  103:      $                   SMLNUM, SUML, SUMR, XNORM
  104: *     ..
  105: *     .. Local Arrays ..
  106:       DOUBLE PRECISION   DUM( 1 ), VEC( 2, 2 ), X( 2, 2 )
  107: *     ..
  108: *     .. External Functions ..
  109:       LOGICAL            LSAME
  110:       DOUBLE PRECISION   DDOT, DLAMCH, DLANGE
  111:       EXTERNAL           LSAME, DDOT, DLAMCH, DLANGE
  112: *     ..
  113: *     .. External Subroutines ..
  114:       EXTERNAL           DLABAD, DLALN2, DLASY2, DSCAL, XERBLA
  115: *     ..
  116: *     .. Intrinsic Functions ..
  117:       INTRINSIC          ABS, DBLE, MAX, MIN
  118: *     ..
  119: *     .. Executable Statements ..
  120: *
  121: *     Decode and Test input parameters
  122: *
  123:       NOTRNA = LSAME( TRANA, 'N' )
  124:       NOTRNB = LSAME( TRANB, 'N' )
  125: *
  126:       INFO = 0
  127:       IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND. .NOT.
  128:      $    LSAME( TRANA, 'C' ) ) THEN
  129:          INFO = -1
  130:       ELSE IF( .NOT.NOTRNB .AND. .NOT.LSAME( TRANB, 'T' ) .AND. .NOT.
  131:      $         LSAME( TRANB, 'C' ) ) THEN
  132:          INFO = -2
  133:       ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THEN
  134:          INFO = -3
  135:       ELSE IF( M.LT.0 ) THEN
  136:          INFO = -4
  137:       ELSE IF( N.LT.0 ) THEN
  138:          INFO = -5
  139:       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
  140:          INFO = -7
  141:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
  142:          INFO = -9
  143:       ELSE IF( LDC.LT.MAX( 1, M ) ) THEN
  144:          INFO = -11
  145:       END IF
  146:       IF( INFO.NE.0 ) THEN
  147:          CALL XERBLA( 'DTRSYL', -INFO )
  148:          RETURN
  149:       END IF
  150: *
  151: *     Quick return if possible
  152: *
  153:       SCALE = ONE
  154:       IF( M.EQ.0 .OR. N.EQ.0 )
  155:      $   RETURN
  156: *
  157: *     Set constants to control overflow
  158: *
  159:       EPS = DLAMCH( 'P' )
  160:       SMLNUM = DLAMCH( 'S' )
  161:       BIGNUM = ONE / SMLNUM
  162:       CALL DLABAD( SMLNUM, BIGNUM )
  163:       SMLNUM = SMLNUM*DBLE( M*N ) / EPS
  164:       BIGNUM = ONE / SMLNUM
  165: *
  166:       SMIN = MAX( SMLNUM, EPS*DLANGE( 'M', M, M, A, LDA, DUM ),
  167:      $       EPS*DLANGE( 'M', N, N, B, LDB, DUM ) )
  168: *
  169:       SGN = ISGN
  170: *
  171:       IF( NOTRNA .AND. NOTRNB ) THEN
  172: *
  173: *        Solve    A*X + ISGN*X*B = scale*C.
  174: *
  175: *        The (K,L)th block of X is determined starting from
  176: *        bottom-left corner column by column by
  177: *
  178: *         A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
  179: *
  180: *        Where
  181: *                  M                         L-1
  182: *        R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)].
  183: *                I=K+1                       J=1
  184: *
  185: *        Start column loop (index = L)
  186: *        L1 (L2) : column index of the first (first) row of X(K,L).
  187: *
  188:          LNEXT = 1
  189:          DO 60 L = 1, N
  190:             IF( L.LT.LNEXT )
  191:      $         GO TO 60
  192:             IF( L.EQ.N ) THEN
  193:                L1 = L
  194:                L2 = L
  195:             ELSE
  196:                IF( B( L+1, L ).NE.ZERO ) THEN
  197:                   L1 = L
  198:                   L2 = L + 1
  199:                   LNEXT = L + 2
  200:                ELSE
  201:                   L1 = L
  202:                   L2 = L
  203:                   LNEXT = L + 1
  204:                END IF
  205:             END IF
  206: *
  207: *           Start row loop (index = K)
  208: *           K1 (K2): row index of the first (last) row of X(K,L).
  209: *
  210:             KNEXT = M
  211:             DO 50 K = M, 1, -1
  212:                IF( K.GT.KNEXT )
  213:      $            GO TO 50
  214:                IF( K.EQ.1 ) THEN
  215:                   K1 = K
  216:                   K2 = K
  217:                ELSE
  218:                   IF( A( K, K-1 ).NE.ZERO ) THEN
  219:                      K1 = K - 1
  220:                      K2 = K
  221:                      KNEXT = K - 2
  222:                   ELSE
  223:                      K1 = K
  224:                      K2 = K
  225:                      KNEXT = K - 1
  226:                   END IF
  227:                END IF
  228: *
  229:                IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
  230:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  231:      $                   C( MIN( K1+1, M ), L1 ), 1 )
  232:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  233:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  234:                   SCALOC = ONE
  235: *
  236:                   A11 = A( K1, K1 ) + SGN*B( L1, L1 )
  237:                   DA11 = ABS( A11 )
  238:                   IF( DA11.LE.SMIN ) THEN
  239:                      A11 = SMIN
  240:                      DA11 = SMIN
  241:                      INFO = 1
  242:                   END IF
  243:                   DB = ABS( VEC( 1, 1 ) )
  244:                   IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
  245:                      IF( DB.GT.BIGNUM*DA11 )
  246:      $                  SCALOC = ONE / DB
  247:                   END IF
  248:                   X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
  249: *
  250:                   IF( SCALOC.NE.ONE ) THEN
  251:                      DO 10 J = 1, N
  252:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  253:    10                CONTINUE
  254:                      SCALE = SCALE*SCALOC
  255:                   END IF
  256:                   C( K1, L1 ) = X( 1, 1 )
  257: *
  258:                ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
  259: *
  260:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  261:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  262:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  263:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  264: *
  265:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  266:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  267:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
  268:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  269: *
  270:                   CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),
  271:      $                         LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
  272:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  273:                   IF( IERR.NE.0 )
  274:      $               INFO = 1
  275: *
  276:                   IF( SCALOC.NE.ONE ) THEN
  277:                      DO 20 J = 1, N
  278:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  279:    20                CONTINUE
  280:                      SCALE = SCALE*SCALOC
  281:                   END IF
  282:                   C( K1, L1 ) = X( 1, 1 )
  283:                   C( K2, L1 ) = X( 2, 1 )
  284: *
  285:                ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
  286: *
  287:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  288:      $                   C( MIN( K1+1, M ), L1 ), 1 )
  289:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  290:                   VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
  291: *
  292:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  293:      $                   C( MIN( K1+1, M ), L2 ), 1 )
  294:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
  295:                   VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
  296: *
  297:                   CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),
  298:      $                         LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
  299:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  300:                   IF( IERR.NE.0 )
  301:      $               INFO = 1
  302: *
  303:                   IF( SCALOC.NE.ONE ) THEN
  304:                      DO 30 J = 1, N
  305:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  306:    30                CONTINUE
  307:                      SCALE = SCALE*SCALOC
  308:                   END IF
  309:                   C( K1, L1 ) = X( 1, 1 )
  310:                   C( K1, L2 ) = X( 2, 1 )
  311: *
  312:                ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
  313: *
  314:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  315:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  316:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  317:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  318: *
  319:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  320:      $                   C( MIN( K2+1, M ), L2 ), 1 )
  321:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
  322:                   VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
  323: *
  324:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  325:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  326:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
  327:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  328: *
  329:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  330:      $                   C( MIN( K2+1, M ), L2 ), 1 )
  331:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )
  332:                   VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
  333: *
  334:                   CALL DLASY2( .FALSE., .FALSE., ISGN, 2, 2,
  335:      $                         A( K1, K1 ), LDA, B( L1, L1 ), LDB, VEC,
  336:      $                         2, SCALOC, X, 2, XNORM, IERR )
  337:                   IF( IERR.NE.0 )
  338:      $               INFO = 1
  339: *
  340:                   IF( SCALOC.NE.ONE ) THEN
  341:                      DO 40 J = 1, N
  342:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  343:    40                CONTINUE
  344:                      SCALE = SCALE*SCALOC
  345:                   END IF
  346:                   C( K1, L1 ) = X( 1, 1 )
  347:                   C( K1, L2 ) = X( 1, 2 )
  348:                   C( K2, L1 ) = X( 2, 1 )
  349:                   C( K2, L2 ) = X( 2, 2 )
  350:                END IF
  351: *
  352:    50       CONTINUE
  353: *
  354:    60    CONTINUE
  355: *
  356:       ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN
  357: *
  358: *        Solve    A' *X + ISGN*X*B = scale*C.
  359: *
  360: *        The (K,L)th block of X is determined starting from
  361: *        upper-left corner column by column by
  362: *
  363: *          A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L)
  364: *
  365: *        Where
  366: *                   K-1                        L-1
  367: *          R(K,L) = SUM [A(I,K)'*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)]
  368: *                   I=1                        J=1
  369: *
  370: *        Start column loop (index = L)
  371: *        L1 (L2): column index of the first (last) row of X(K,L)
  372: *
  373:          LNEXT = 1
  374:          DO 120 L = 1, N
  375:             IF( L.LT.LNEXT )
  376:      $         GO TO 120
  377:             IF( L.EQ.N ) THEN
  378:                L1 = L
  379:                L2 = L
  380:             ELSE
  381:                IF( B( L+1, L ).NE.ZERO ) THEN
  382:                   L1 = L
  383:                   L2 = L + 1
  384:                   LNEXT = L + 2
  385:                ELSE
  386:                   L1 = L
  387:                   L2 = L
  388:                   LNEXT = L + 1
  389:                END IF
  390:             END IF
  391: *
  392: *           Start row loop (index = K)
  393: *           K1 (K2): row index of the first (last) row of X(K,L)
  394: *
  395:             KNEXT = 1
  396:             DO 110 K = 1, M
  397:                IF( K.LT.KNEXT )
  398:      $            GO TO 110
  399:                IF( K.EQ.M ) THEN
  400:                   K1 = K
  401:                   K2 = K
  402:                ELSE
  403:                   IF( A( K+1, K ).NE.ZERO ) THEN
  404:                      K1 = K
  405:                      K2 = K + 1
  406:                      KNEXT = K + 2
  407:                   ELSE
  408:                      K1 = K
  409:                      K2 = K
  410:                      KNEXT = K + 1
  411:                   END IF
  412:                END IF
  413: *
  414:                IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
  415:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  416:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  417:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  418:                   SCALOC = ONE
  419: *
  420:                   A11 = A( K1, K1 ) + SGN*B( L1, L1 )
  421:                   DA11 = ABS( A11 )
  422:                   IF( DA11.LE.SMIN ) THEN
  423:                      A11 = SMIN
  424:                      DA11 = SMIN
  425:                      INFO = 1
  426:                   END IF
  427:                   DB = ABS( VEC( 1, 1 ) )
  428:                   IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
  429:                      IF( DB.GT.BIGNUM*DA11 )
  430:      $                  SCALOC = ONE / DB
  431:                   END IF
  432:                   X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
  433: *
  434:                   IF( SCALOC.NE.ONE ) THEN
  435:                      DO 70 J = 1, N
  436:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  437:    70                CONTINUE
  438:                      SCALE = SCALE*SCALOC
  439:                   END IF
  440:                   C( K1, L1 ) = X( 1, 1 )
  441: *
  442:                ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
  443: *
  444:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  445:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  446:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  447: *
  448:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
  449:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
  450:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  451: *
  452:                   CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),
  453:      $                         LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
  454:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  455:                   IF( IERR.NE.0 )
  456:      $               INFO = 1
  457: *
  458:                   IF( SCALOC.NE.ONE ) THEN
  459:                      DO 80 J = 1, N
  460:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  461:    80                CONTINUE
  462:                      SCALE = SCALE*SCALOC
  463:                   END IF
  464:                   C( K1, L1 ) = X( 1, 1 )
  465:                   C( K2, L1 ) = X( 2, 1 )
  466: *
  467:                ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
  468: *
  469:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  470:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  471:                   VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
  472: *
  473:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
  474:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
  475:                   VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
  476: *
  477:                   CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ),
  478:      $                         LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
  479:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  480:                   IF( IERR.NE.0 )
  481:      $               INFO = 1
  482: *
  483:                   IF( SCALOC.NE.ONE ) THEN
  484:                      DO 90 J = 1, N
  485:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  486:    90                CONTINUE
  487:                      SCALE = SCALE*SCALOC
  488:                   END IF
  489:                   C( K1, L1 ) = X( 1, 1 )
  490:                   C( K1, L2 ) = X( 2, 1 )
  491: *
  492:                ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
  493: *
  494:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  495:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 )
  496:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  497: *
  498:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
  499:                   SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 )
  500:                   VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
  501: *
  502:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
  503:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 )
  504:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  505: *
  506:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )
  507:                   SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 )
  508:                   VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
  509: *
  510:                   CALL DLASY2( .TRUE., .FALSE., ISGN, 2, 2, A( K1, K1 ),
  511:      $                         LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
  512:      $                         2, XNORM, IERR )
  513:                   IF( IERR.NE.0 )
  514:      $               INFO = 1
  515: *
  516:                   IF( SCALOC.NE.ONE ) THEN
  517:                      DO 100 J = 1, N
  518:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  519:   100                CONTINUE
  520:                      SCALE = SCALE*SCALOC
  521:                   END IF
  522:                   C( K1, L1 ) = X( 1, 1 )
  523:                   C( K1, L2 ) = X( 1, 2 )
  524:                   C( K2, L1 ) = X( 2, 1 )
  525:                   C( K2, L2 ) = X( 2, 2 )
  526:                END IF
  527: *
  528:   110       CONTINUE
  529:   120    CONTINUE
  530: *
  531:       ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN
  532: *
  533: *        Solve    A'*X + ISGN*X*B' = scale*C.
  534: *
  535: *        The (K,L)th block of X is determined starting from
  536: *        top-right corner column by column by
  537: *
  538: *           A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)
  539: *
  540: *        Where
  541: *                     K-1                          N
  542: *            R(K,L) = SUM [A(I,K)'*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].
  543: *                     I=1                        J=L+1
  544: *
  545: *        Start column loop (index = L)
  546: *        L1 (L2): column index of the first (last) row of X(K,L)
  547: *
  548:          LNEXT = N
  549:          DO 180 L = N, 1, -1
  550:             IF( L.GT.LNEXT )
  551:      $         GO TO 180
  552:             IF( L.EQ.1 ) THEN
  553:                L1 = L
  554:                L2 = L
  555:             ELSE
  556:                IF( B( L, L-1 ).NE.ZERO ) THEN
  557:                   L1 = L - 1
  558:                   L2 = L
  559:                   LNEXT = L - 2
  560:                ELSE
  561:                   L1 = L
  562:                   L2 = L
  563:                   LNEXT = L - 1
  564:                END IF
  565:             END IF
  566: *
  567: *           Start row loop (index = K)
  568: *           K1 (K2): row index of the first (last) row of X(K,L)
  569: *
  570:             KNEXT = 1
  571:             DO 170 K = 1, M
  572:                IF( K.LT.KNEXT )
  573:      $            GO TO 170
  574:                IF( K.EQ.M ) THEN
  575:                   K1 = K
  576:                   K2 = K
  577:                ELSE
  578:                   IF( A( K+1, K ).NE.ZERO ) THEN
  579:                      K1 = K
  580:                      K2 = K + 1
  581:                      KNEXT = K + 2
  582:                   ELSE
  583:                      K1 = K
  584:                      K2 = K
  585:                      KNEXT = K + 1
  586:                   END IF
  587:                END IF
  588: *
  589:                IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
  590:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  591:                   SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,
  592:      $                   B( L1, MIN( L1+1, N ) ), LDB )
  593:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  594:                   SCALOC = ONE
  595: *
  596:                   A11 = A( K1, K1 ) + SGN*B( L1, L1 )
  597:                   DA11 = ABS( A11 )
  598:                   IF( DA11.LE.SMIN ) THEN
  599:                      A11 = SMIN
  600:                      DA11 = SMIN
  601:                      INFO = 1
  602:                   END IF
  603:                   DB = ABS( VEC( 1, 1 ) )
  604:                   IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
  605:                      IF( DB.GT.BIGNUM*DA11 )
  606:      $                  SCALOC = ONE / DB
  607:                   END IF
  608:                   X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
  609: *
  610:                   IF( SCALOC.NE.ONE ) THEN
  611:                      DO 130 J = 1, N
  612:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  613:   130                CONTINUE
  614:                      SCALE = SCALE*SCALOC
  615:                   END IF
  616:                   C( K1, L1 ) = X( 1, 1 )
  617: *
  618:                ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
  619: *
  620:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  621:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  622:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  623:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  624: *
  625:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
  626:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  627:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  628:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  629: *
  630:                   CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ),
  631:      $                         LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
  632:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  633:                   IF( IERR.NE.0 )
  634:      $               INFO = 1
  635: *
  636:                   IF( SCALOC.NE.ONE ) THEN
  637:                      DO 140 J = 1, N
  638:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  639:   140                CONTINUE
  640:                      SCALE = SCALE*SCALOC
  641:                   END IF
  642:                   C( K1, L1 ) = X( 1, 1 )
  643:                   C( K2, L1 ) = X( 2, 1 )
  644: *
  645:                ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
  646: *
  647:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  648:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  649:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  650:                   VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
  651: *
  652:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
  653:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  654:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  655:                   VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
  656: *
  657:                   CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),
  658:      $                         LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
  659:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  660:                   IF( IERR.NE.0 )
  661:      $               INFO = 1
  662: *
  663:                   IF( SCALOC.NE.ONE ) THEN
  664:                      DO 150 J = 1, N
  665:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  666:   150                CONTINUE
  667:                      SCALE = SCALE*SCALOC
  668:                   END IF
  669:                   C( K1, L1 ) = X( 1, 1 )
  670:                   C( K1, L2 ) = X( 2, 1 )
  671: *
  672:                ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
  673: *
  674:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 )
  675:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  676:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  677:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  678: *
  679:                   SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 )
  680:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  681:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  682:                   VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
  683: *
  684:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 )
  685:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  686:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  687:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  688: *
  689:                   SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 )
  690:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  691:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  692:                   VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
  693: *
  694:                   CALL DLASY2( .TRUE., .TRUE., ISGN, 2, 2, A( K1, K1 ),
  695:      $                         LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
  696:      $                         2, XNORM, IERR )
  697:                   IF( IERR.NE.0 )
  698:      $               INFO = 1
  699: *
  700:                   IF( SCALOC.NE.ONE ) THEN
  701:                      DO 160 J = 1, N
  702:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  703:   160                CONTINUE
  704:                      SCALE = SCALE*SCALOC
  705:                   END IF
  706:                   C( K1, L1 ) = X( 1, 1 )
  707:                   C( K1, L2 ) = X( 1, 2 )
  708:                   C( K2, L1 ) = X( 2, 1 )
  709:                   C( K2, L2 ) = X( 2, 2 )
  710:                END IF
  711: *
  712:   170       CONTINUE
  713:   180    CONTINUE
  714: *
  715:       ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN
  716: *
  717: *        Solve    A*X + ISGN*X*B' = scale*C.
  718: *
  719: *        The (K,L)th block of X is determined starting from
  720: *        bottom-right corner column by column by
  721: *
  722: *            A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L)
  723: *
  724: *        Where
  725: *                      M                          N
  726: *            R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)'].
  727: *                    I=K+1                      J=L+1
  728: *
  729: *        Start column loop (index = L)
  730: *        L1 (L2): column index of the first (last) row of X(K,L)
  731: *
  732:          LNEXT = N
  733:          DO 240 L = N, 1, -1
  734:             IF( L.GT.LNEXT )
  735:      $         GO TO 240
  736:             IF( L.EQ.1 ) THEN
  737:                L1 = L
  738:                L2 = L
  739:             ELSE
  740:                IF( B( L, L-1 ).NE.ZERO ) THEN
  741:                   L1 = L - 1
  742:                   L2 = L
  743:                   LNEXT = L - 2
  744:                ELSE
  745:                   L1 = L
  746:                   L2 = L
  747:                   LNEXT = L - 1
  748:                END IF
  749:             END IF
  750: *
  751: *           Start row loop (index = K)
  752: *           K1 (K2): row index of the first (last) row of X(K,L)
  753: *
  754:             KNEXT = M
  755:             DO 230 K = M, 1, -1
  756:                IF( K.GT.KNEXT )
  757:      $            GO TO 230
  758:                IF( K.EQ.1 ) THEN
  759:                   K1 = K
  760:                   K2 = K
  761:                ELSE
  762:                   IF( A( K, K-1 ).NE.ZERO ) THEN
  763:                      K1 = K - 1
  764:                      K2 = K
  765:                      KNEXT = K - 2
  766:                   ELSE
  767:                      K1 = K
  768:                      K2 = K
  769:                      KNEXT = K - 1
  770:                   END IF
  771:                END IF
  772: *
  773:                IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN
  774:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  775:      $                   C( MIN( K1+1, M ), L1 ), 1 )
  776:                   SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC,
  777:      $                   B( L1, MIN( L1+1, N ) ), LDB )
  778:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  779:                   SCALOC = ONE
  780: *
  781:                   A11 = A( K1, K1 ) + SGN*B( L1, L1 )
  782:                   DA11 = ABS( A11 )
  783:                   IF( DA11.LE.SMIN ) THEN
  784:                      A11 = SMIN
  785:                      DA11 = SMIN
  786:                      INFO = 1
  787:                   END IF
  788:                   DB = ABS( VEC( 1, 1 ) )
  789:                   IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN
  790:                      IF( DB.GT.BIGNUM*DA11 )
  791:      $                  SCALOC = ONE / DB
  792:                   END IF
  793:                   X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11
  794: *
  795:                   IF( SCALOC.NE.ONE ) THEN
  796:                      DO 190 J = 1, N
  797:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  798:   190                CONTINUE
  799:                      SCALE = SCALE*SCALOC
  800:                   END IF
  801:                   C( K1, L1 ) = X( 1, 1 )
  802: *
  803:                ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN
  804: *
  805:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  806:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  807:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  808:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  809:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  810: *
  811:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  812:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  813:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  814:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  815:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  816: *
  817:                   CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ),
  818:      $                         LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ),
  819:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  820:                   IF( IERR.NE.0 )
  821:      $               INFO = 1
  822: *
  823:                   IF( SCALOC.NE.ONE ) THEN
  824:                      DO 200 J = 1, N
  825:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  826:   200                CONTINUE
  827:                      SCALE = SCALE*SCALOC
  828:                   END IF
  829:                   C( K1, L1 ) = X( 1, 1 )
  830:                   C( K2, L1 ) = X( 2, 1 )
  831: *
  832:                ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN
  833: *
  834:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  835:      $                   C( MIN( K1+1, M ), L1 ), 1 )
  836:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  837:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  838:                   VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) )
  839: *
  840:                   SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA,
  841:      $                   C( MIN( K1+1, M ), L2 ), 1 )
  842:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  843:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  844:                   VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) )
  845: *
  846:                   CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ),
  847:      $                         LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ),
  848:      $                         ZERO, X, 2, SCALOC, XNORM, IERR )
  849:                   IF( IERR.NE.0 )
  850:      $               INFO = 1
  851: *
  852:                   IF( SCALOC.NE.ONE ) THEN
  853:                      DO 210 J = 1, N
  854:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  855:   210                CONTINUE
  856:                      SCALE = SCALE*SCALOC
  857:                   END IF
  858:                   C( K1, L1 ) = X( 1, 1 )
  859:                   C( K1, L2 ) = X( 2, 1 )
  860: *
  861:                ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN
  862: *
  863:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  864:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  865:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  866:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  867:                   VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR )
  868: *
  869:                   SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA,
  870:      $                   C( MIN( K2+1, M ), L2 ), 1 )
  871:                   SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC,
  872:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  873:                   VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR )
  874: *
  875:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  876:      $                   C( MIN( K2+1, M ), L1 ), 1 )
  877:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  878:      $                   B( L1, MIN( L2+1, N ) ), LDB )
  879:                   VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR )
  880: *
  881:                   SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA,
  882:      $                   C( MIN( K2+1, M ), L2 ), 1 )
  883:                   SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC,
  884:      $                   B( L2, MIN( L2+1, N ) ), LDB )
  885:                   VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR )
  886: *
  887:                   CALL DLASY2( .FALSE., .TRUE., ISGN, 2, 2, A( K1, K1 ),
  888:      $                         LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X,
  889:      $                         2, XNORM, IERR )
  890:                   IF( IERR.NE.0 )
  891:      $               INFO = 1
  892: *
  893:                   IF( SCALOC.NE.ONE ) THEN
  894:                      DO 220 J = 1, N
  895:                         CALL DSCAL( M, SCALOC, C( 1, J ), 1 )
  896:   220                CONTINUE
  897:                      SCALE = SCALE*SCALOC
  898:                   END IF
  899:                   C( K1, L1 ) = X( 1, 1 )
  900:                   C( K1, L2 ) = X( 1, 2 )
  901:                   C( K2, L1 ) = X( 2, 1 )
  902:                   C( K2, L2 ) = X( 2, 2 )
  903:                END IF
  904: *
  905:   230       CONTINUE
  906:   240    CONTINUE
  907: *
  908:       END IF
  909: *
  910:       RETURN
  911: *
  912: *     End of DTRSYL
  913: *
  914:       END

CVSweb interface <joel.bertrand@systella.fr>