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

    1:       SUBROUTINE DSBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,
    2:      $                   WORK, INFO )
    3: *
    4: *  -- LAPACK routine (version 3.2) --
    5: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
    6: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
    7: *     November 2006
    8: *
    9: *     .. Scalar Arguments ..
   10:       CHARACTER          UPLO, VECT
   11:       INTEGER            INFO, KD, LDAB, LDQ, N
   12: *     ..
   13: *     .. Array Arguments ..
   14:       DOUBLE PRECISION   AB( LDAB, * ), D( * ), E( * ), Q( LDQ, * ),
   15:      $                   WORK( * )
   16: *     ..
   17: *
   18: *  Purpose
   19: *  =======
   20: *
   21: *  DSBTRD reduces a real symmetric band matrix A to symmetric
   22: *  tridiagonal form T by an orthogonal similarity transformation:
   23: *  Q**T * A * Q = T.
   24: *
   25: *  Arguments
   26: *  =========
   27: *
   28: *  VECT    (input) CHARACTER*1
   29: *          = 'N':  do not form Q;
   30: *          = 'V':  form Q;
   31: *          = 'U':  update a matrix X, by forming X*Q.
   32: *
   33: *  UPLO    (input) CHARACTER*1
   34: *          = 'U':  Upper triangle of A is stored;
   35: *          = 'L':  Lower triangle of A is stored.
   36: *
   37: *  N       (input) INTEGER
   38: *          The order of the matrix A.  N >= 0.
   39: *
   40: *  KD      (input) INTEGER
   41: *          The number of superdiagonals of the matrix A if UPLO = 'U',
   42: *          or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
   43: *
   44: *  AB      (input/output) DOUBLE PRECISION array, dimension (LDAB,N)
   45: *          On entry, the upper or lower triangle of the symmetric band
   46: *          matrix A, stored in the first KD+1 rows of the array.  The
   47: *          j-th column of A is stored in the j-th column of the array AB
   48: *          as follows:
   49: *          if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
   50: *          if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).
   51: *          On exit, the diagonal elements of AB are overwritten by the
   52: *          diagonal elements of the tridiagonal matrix T; if KD > 0, the
   53: *          elements on the first superdiagonal (if UPLO = 'U') or the
   54: *          first subdiagonal (if UPLO = 'L') are overwritten by the
   55: *          off-diagonal elements of T; the rest of AB is overwritten by
   56: *          values generated during the reduction.
   57: *
   58: *  LDAB    (input) INTEGER
   59: *          The leading dimension of the array AB.  LDAB >= KD+1.
   60: *
   61: *  D       (output) DOUBLE PRECISION array, dimension (N)
   62: *          The diagonal elements of the tridiagonal matrix T.
   63: *
   64: *  E       (output) DOUBLE PRECISION array, dimension (N-1)
   65: *          The off-diagonal elements of the tridiagonal matrix T:
   66: *          E(i) = T(i,i+1) if UPLO = 'U'; E(i) = T(i+1,i) if UPLO = 'L'.
   67: *
   68: *  Q       (input/output) DOUBLE PRECISION array, dimension (LDQ,N)
   69: *          On entry, if VECT = 'U', then Q must contain an N-by-N
   70: *          matrix X; if VECT = 'N' or 'V', then Q need not be set.
   71: *
   72: *          On exit:
   73: *          if VECT = 'V', Q contains the N-by-N orthogonal matrix Q;
   74: *          if VECT = 'U', Q contains the product X*Q;
   75: *          if VECT = 'N', the array Q is not referenced.
   76: *
   77: *  LDQ     (input) INTEGER
   78: *          The leading dimension of the array Q.
   79: *          LDQ >= 1, and LDQ >= N if VECT = 'V' or 'U'.
   80: *
   81: *  WORK    (workspace) DOUBLE PRECISION array, dimension (N)
   82: *
   83: *  INFO    (output) INTEGER
   84: *          = 0:  successful exit
   85: *          < 0:  if INFO = -i, the i-th argument had an illegal value
   86: *
   87: *  Further Details
   88: *  ===============
   89: *
   90: *  Modified by Linda Kaufman, Bell Labs.
   91: *
   92: *  =====================================================================
   93: *
   94: *     .. Parameters ..
   95:       DOUBLE PRECISION   ZERO, ONE
   96:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
   97: *     ..
   98: *     .. Local Scalars ..
   99:       LOGICAL            INITQ, UPPER, WANTQ
  100:       INTEGER            I, I2, IBL, INCA, INCX, IQAEND, IQB, IQEND, J,
  101:      $                   J1, J1END, J1INC, J2, JEND, JIN, JINC, K, KD1,
  102:      $                   KDM1, KDN, L, LAST, LEND, NQ, NR, NRT
  103:       DOUBLE PRECISION   TEMP
  104: *     ..
  105: *     .. External Subroutines ..
  106:       EXTERNAL           DLAR2V, DLARGV, DLARTG, DLARTV, DLASET, DROT,
  107:      $                   XERBLA
  108: *     ..
  109: *     .. Intrinsic Functions ..
  110:       INTRINSIC          MAX, MIN
  111: *     ..
  112: *     .. External Functions ..
  113:       LOGICAL            LSAME
  114:       EXTERNAL           LSAME
  115: *     ..
  116: *     .. Executable Statements ..
  117: *
  118: *     Test the input parameters
  119: *
  120:       INITQ = LSAME( VECT, 'V' )
  121:       WANTQ = INITQ .OR. LSAME( VECT, 'U' )
  122:       UPPER = LSAME( UPLO, 'U' )
  123:       KD1 = KD + 1
  124:       KDM1 = KD - 1
  125:       INCX = LDAB - 1
  126:       IQEND = 1
  127: *
  128:       INFO = 0
  129:       IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
  130:          INFO = -1
  131:       ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
  132:          INFO = -2
  133:       ELSE IF( N.LT.0 ) THEN
  134:          INFO = -3
  135:       ELSE IF( KD.LT.0 ) THEN
  136:          INFO = -4
  137:       ELSE IF( LDAB.LT.KD1 ) THEN
  138:          INFO = -6
  139:       ELSE IF( LDQ.LT.MAX( 1, N ) .AND. WANTQ ) THEN
  140:          INFO = -10
  141:       END IF
  142:       IF( INFO.NE.0 ) THEN
  143:          CALL XERBLA( 'DSBTRD', -INFO )
  144:          RETURN
  145:       END IF
  146: *
  147: *     Quick return if possible
  148: *
  149:       IF( N.EQ.0 )
  150:      $   RETURN
  151: *
  152: *     Initialize Q to the unit matrix, if needed
  153: *
  154:       IF( INITQ )
  155:      $   CALL DLASET( 'Full', N, N, ZERO, ONE, Q, LDQ )
  156: *
  157: *     Wherever possible, plane rotations are generated and applied in
  158: *     vector operations of length NR over the index set J1:J2:KD1.
  159: *
  160: *     The cosines and sines of the plane rotations are stored in the
  161: *     arrays D and WORK.
  162: *
  163:       INCA = KD1*LDAB
  164:       KDN = MIN( N-1, KD )
  165:       IF( UPPER ) THEN
  166: *
  167:          IF( KD.GT.1 ) THEN
  168: *
  169: *           Reduce to tridiagonal form, working with upper triangle
  170: *
  171:             NR = 0
  172:             J1 = KDN + 2
  173:             J2 = 1
  174: *
  175:             DO 90 I = 1, N - 2
  176: *
  177: *              Reduce i-th row of matrix to tridiagonal form
  178: *
  179:                DO 80 K = KDN + 1, 2, -1
  180:                   J1 = J1 + KDN
  181:                   J2 = J2 + KDN
  182: *
  183:                   IF( NR.GT.0 ) THEN
  184: *
  185: *                    generate plane rotations to annihilate nonzero
  186: *                    elements which have been created outside the band
  187: *
  188:                      CALL DLARGV( NR, AB( 1, J1-1 ), INCA, WORK( J1 ),
  189:      $                            KD1, D( J1 ), KD1 )
  190: *
  191: *                    apply rotations from the right
  192: *
  193: *
  194: *                    Dependent on the the number of diagonals either
  195: *                    DLARTV or DROT is used
  196: *
  197:                      IF( NR.GE.2*KD-1 ) THEN
  198:                         DO 10 L = 1, KD - 1
  199:                            CALL DLARTV( NR, AB( L+1, J1-1 ), INCA,
  200:      $                                  AB( L, J1 ), INCA, D( J1 ),
  201:      $                                  WORK( J1 ), KD1 )
  202:    10                   CONTINUE
  203: *
  204:                      ELSE
  205:                         JEND = J1 + ( NR-1 )*KD1
  206:                         DO 20 JINC = J1, JEND, KD1
  207:                            CALL DROT( KDM1, AB( 2, JINC-1 ), 1,
  208:      $                                AB( 1, JINC ), 1, D( JINC ),
  209:      $                                WORK( JINC ) )
  210:    20                   CONTINUE
  211:                      END IF
  212:                   END IF
  213: *
  214: *
  215:                   IF( K.GT.2 ) THEN
  216:                      IF( K.LE.N-I+1 ) THEN
  217: *
  218: *                       generate plane rotation to annihilate a(i,i+k-1)
  219: *                       within the band
  220: *
  221:                         CALL DLARTG( AB( KD-K+3, I+K-2 ),
  222:      $                               AB( KD-K+2, I+K-1 ), D( I+K-1 ),
  223:      $                               WORK( I+K-1 ), TEMP )
  224:                         AB( KD-K+3, I+K-2 ) = TEMP
  225: *
  226: *                       apply rotation from the right
  227: *
  228:                         CALL DROT( K-3, AB( KD-K+4, I+K-2 ), 1,
  229:      $                             AB( KD-K+3, I+K-1 ), 1, D( I+K-1 ),
  230:      $                             WORK( I+K-1 ) )
  231:                      END IF
  232:                      NR = NR + 1
  233:                      J1 = J1 - KDN - 1
  234:                   END IF
  235: *
  236: *                 apply plane rotations from both sides to diagonal
  237: *                 blocks
  238: *
  239:                   IF( NR.GT.0 )
  240:      $               CALL DLAR2V( NR, AB( KD1, J1-1 ), AB( KD1, J1 ),
  241:      $                            AB( KD, J1 ), INCA, D( J1 ),
  242:      $                            WORK( J1 ), KD1 )
  243: *
  244: *                 apply plane rotations from the left
  245: *
  246:                   IF( NR.GT.0 ) THEN
  247:                      IF( 2*KD-1.LT.NR ) THEN
  248: *
  249: *                    Dependent on the the number of diagonals either
  250: *                    DLARTV or DROT is used
  251: *
  252:                         DO 30 L = 1, KD - 1
  253:                            IF( J2+L.GT.N ) THEN
  254:                               NRT = NR - 1
  255:                            ELSE
  256:                               NRT = NR
  257:                            END IF
  258:                            IF( NRT.GT.0 )
  259:      $                        CALL DLARTV( NRT, AB( KD-L, J1+L ), INCA,
  260:      $                                     AB( KD-L+1, J1+L ), INCA,
  261:      $                                     D( J1 ), WORK( J1 ), KD1 )
  262:    30                   CONTINUE
  263:                      ELSE
  264:                         J1END = J1 + KD1*( NR-2 )
  265:                         IF( J1END.GE.J1 ) THEN
  266:                            DO 40 JIN = J1, J1END, KD1
  267:                               CALL DROT( KD-1, AB( KD-1, JIN+1 ), INCX,
  268:      $                                   AB( KD, JIN+1 ), INCX,
  269:      $                                   D( JIN ), WORK( JIN ) )
  270:    40                      CONTINUE
  271:                         END IF
  272:                         LEND = MIN( KDM1, N-J2 )
  273:                         LAST = J1END + KD1
  274:                         IF( LEND.GT.0 )
  275:      $                     CALL DROT( LEND, AB( KD-1, LAST+1 ), INCX,
  276:      $                                AB( KD, LAST+1 ), INCX, D( LAST ),
  277:      $                                WORK( LAST ) )
  278:                      END IF
  279:                   END IF
  280: *
  281:                   IF( WANTQ ) THEN
  282: *
  283: *                    accumulate product of plane rotations in Q
  284: *
  285:                      IF( INITQ ) THEN
  286: *
  287: *                 take advantage of the fact that Q was
  288: *                 initially the Identity matrix
  289: *
  290:                         IQEND = MAX( IQEND, J2 )
  291:                         I2 = MAX( 0, K-3 )
  292:                         IQAEND = 1 + I*KD
  293:                         IF( K.EQ.2 )
  294:      $                     IQAEND = IQAEND + KD
  295:                         IQAEND = MIN( IQAEND, IQEND )
  296:                         DO 50 J = J1, J2, KD1
  297:                            IBL = I - I2 / KDM1
  298:                            I2 = I2 + 1
  299:                            IQB = MAX( 1, J-IBL )
  300:                            NQ = 1 + IQAEND - IQB
  301:                            IQAEND = MIN( IQAEND+KD, IQEND )
  302:                            CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
  303:      $                                1, D( J ), WORK( J ) )
  304:    50                   CONTINUE
  305:                      ELSE
  306: *
  307:                         DO 60 J = J1, J2, KD1
  308:                            CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
  309:      $                                D( J ), WORK( J ) )
  310:    60                   CONTINUE
  311:                      END IF
  312: *
  313:                   END IF
  314: *
  315:                   IF( J2+KDN.GT.N ) THEN
  316: *
  317: *                    adjust J2 to keep within the bounds of the matrix
  318: *
  319:                      NR = NR - 1
  320:                      J2 = J2 - KDN - 1
  321:                   END IF
  322: *
  323:                   DO 70 J = J1, J2, KD1
  324: *
  325: *                    create nonzero element a(j-1,j+kd) outside the band
  326: *                    and store it in WORK
  327: *
  328:                      WORK( J+KD ) = WORK( J )*AB( 1, J+KD )
  329:                      AB( 1, J+KD ) = D( J )*AB( 1, J+KD )
  330:    70             CONTINUE
  331:    80          CONTINUE
  332:    90       CONTINUE
  333:          END IF
  334: *
  335:          IF( KD.GT.0 ) THEN
  336: *
  337: *           copy off-diagonal elements to E
  338: *
  339:             DO 100 I = 1, N - 1
  340:                E( I ) = AB( KD, I+1 )
  341:   100       CONTINUE
  342:          ELSE
  343: *
  344: *           set E to zero if original matrix was diagonal
  345: *
  346:             DO 110 I = 1, N - 1
  347:                E( I ) = ZERO
  348:   110       CONTINUE
  349:          END IF
  350: *
  351: *        copy diagonal elements to D
  352: *
  353:          DO 120 I = 1, N
  354:             D( I ) = AB( KD1, I )
  355:   120    CONTINUE
  356: *
  357:       ELSE
  358: *
  359:          IF( KD.GT.1 ) THEN
  360: *
  361: *           Reduce to tridiagonal form, working with lower triangle
  362: *
  363:             NR = 0
  364:             J1 = KDN + 2
  365:             J2 = 1
  366: *
  367:             DO 210 I = 1, N - 2
  368: *
  369: *              Reduce i-th column of matrix to tridiagonal form
  370: *
  371:                DO 200 K = KDN + 1, 2, -1
  372:                   J1 = J1 + KDN
  373:                   J2 = J2 + KDN
  374: *
  375:                   IF( NR.GT.0 ) THEN
  376: *
  377: *                    generate plane rotations to annihilate nonzero
  378: *                    elements which have been created outside the band
  379: *
  380:                      CALL DLARGV( NR, AB( KD1, J1-KD1 ), INCA,
  381:      $                            WORK( J1 ), KD1, D( J1 ), KD1 )
  382: *
  383: *                    apply plane rotations from one side
  384: *
  385: *
  386: *                    Dependent on the the number of diagonals either
  387: *                    DLARTV or DROT is used
  388: *
  389:                      IF( NR.GT.2*KD-1 ) THEN
  390:                         DO 130 L = 1, KD - 1
  391:                            CALL DLARTV( NR, AB( KD1-L, J1-KD1+L ), INCA,
  392:      $                                  AB( KD1-L+1, J1-KD1+L ), INCA,
  393:      $                                  D( J1 ), WORK( J1 ), KD1 )
  394:   130                   CONTINUE
  395:                      ELSE
  396:                         JEND = J1 + KD1*( NR-1 )
  397:                         DO 140 JINC = J1, JEND, KD1
  398:                            CALL DROT( KDM1, AB( KD, JINC-KD ), INCX,
  399:      $                                AB( KD1, JINC-KD ), INCX,
  400:      $                                D( JINC ), WORK( JINC ) )
  401:   140                   CONTINUE
  402:                      END IF
  403: *
  404:                   END IF
  405: *
  406:                   IF( K.GT.2 ) THEN
  407:                      IF( K.LE.N-I+1 ) THEN
  408: *
  409: *                       generate plane rotation to annihilate a(i+k-1,i)
  410: *                       within the band
  411: *
  412:                         CALL DLARTG( AB( K-1, I ), AB( K, I ),
  413:      $                               D( I+K-1 ), WORK( I+K-1 ), TEMP )
  414:                         AB( K-1, I ) = TEMP
  415: *
  416: *                       apply rotation from the left
  417: *
  418:                         CALL DROT( K-3, AB( K-2, I+1 ), LDAB-1,
  419:      $                             AB( K-1, I+1 ), LDAB-1, D( I+K-1 ),
  420:      $                             WORK( I+K-1 ) )
  421:                      END IF
  422:                      NR = NR + 1
  423:                      J1 = J1 - KDN - 1
  424:                   END IF
  425: *
  426: *                 apply plane rotations from both sides to diagonal
  427: *                 blocks
  428: *
  429:                   IF( NR.GT.0 )
  430:      $               CALL DLAR2V( NR, AB( 1, J1-1 ), AB( 1, J1 ),
  431:      $                            AB( 2, J1-1 ), INCA, D( J1 ),
  432:      $                            WORK( J1 ), KD1 )
  433: *
  434: *                 apply plane rotations from the right
  435: *
  436: *
  437: *                    Dependent on the the number of diagonals either
  438: *                    DLARTV or DROT is used
  439: *
  440:                   IF( NR.GT.0 ) THEN
  441:                      IF( NR.GT.2*KD-1 ) THEN
  442:                         DO 150 L = 1, KD - 1
  443:                            IF( J2+L.GT.N ) THEN
  444:                               NRT = NR - 1
  445:                            ELSE
  446:                               NRT = NR
  447:                            END IF
  448:                            IF( NRT.GT.0 )
  449:      $                        CALL DLARTV( NRT, AB( L+2, J1-1 ), INCA,
  450:      $                                     AB( L+1, J1 ), INCA, D( J1 ),
  451:      $                                     WORK( J1 ), KD1 )
  452:   150                   CONTINUE
  453:                      ELSE
  454:                         J1END = J1 + KD1*( NR-2 )
  455:                         IF( J1END.GE.J1 ) THEN
  456:                            DO 160 J1INC = J1, J1END, KD1
  457:                               CALL DROT( KDM1, AB( 3, J1INC-1 ), 1,
  458:      $                                   AB( 2, J1INC ), 1, D( J1INC ),
  459:      $                                   WORK( J1INC ) )
  460:   160                      CONTINUE
  461:                         END IF
  462:                         LEND = MIN( KDM1, N-J2 )
  463:                         LAST = J1END + KD1
  464:                         IF( LEND.GT.0 )
  465:      $                     CALL DROT( LEND, AB( 3, LAST-1 ), 1,
  466:      $                                AB( 2, LAST ), 1, D( LAST ),
  467:      $                                WORK( LAST ) )
  468:                      END IF
  469:                   END IF
  470: *
  471: *
  472: *
  473:                   IF( WANTQ ) THEN
  474: *
  475: *                    accumulate product of plane rotations in Q
  476: *
  477:                      IF( INITQ ) THEN
  478: *
  479: *                 take advantage of the fact that Q was
  480: *                 initially the Identity matrix
  481: *
  482:                         IQEND = MAX( IQEND, J2 )
  483:                         I2 = MAX( 0, K-3 )
  484:                         IQAEND = 1 + I*KD
  485:                         IF( K.EQ.2 )
  486:      $                     IQAEND = IQAEND + KD
  487:                         IQAEND = MIN( IQAEND, IQEND )
  488:                         DO 170 J = J1, J2, KD1
  489:                            IBL = I - I2 / KDM1
  490:                            I2 = I2 + 1
  491:                            IQB = MAX( 1, J-IBL )
  492:                            NQ = 1 + IQAEND - IQB
  493:                            IQAEND = MIN( IQAEND+KD, IQEND )
  494:                            CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
  495:      $                                1, D( J ), WORK( J ) )
  496:   170                   CONTINUE
  497:                      ELSE
  498: *
  499:                         DO 180 J = J1, J2, KD1
  500:                            CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
  501:      $                                D( J ), WORK( J ) )
  502:   180                   CONTINUE
  503:                      END IF
  504:                   END IF
  505: *
  506:                   IF( J2+KDN.GT.N ) THEN
  507: *
  508: *                    adjust J2 to keep within the bounds of the matrix
  509: *
  510:                      NR = NR - 1
  511:                      J2 = J2 - KDN - 1
  512:                   END IF
  513: *
  514:                   DO 190 J = J1, J2, KD1
  515: *
  516: *                    create nonzero element a(j+kd,j-1) outside the
  517: *                    band and store it in WORK
  518: *
  519:                      WORK( J+KD ) = WORK( J )*AB( KD1, J )
  520:                      AB( KD1, J ) = D( J )*AB( KD1, J )
  521:   190             CONTINUE
  522:   200          CONTINUE
  523:   210       CONTINUE
  524:          END IF
  525: *
  526:          IF( KD.GT.0 ) THEN
  527: *
  528: *           copy off-diagonal elements to E
  529: *
  530:             DO 220 I = 1, N - 1
  531:                E( I ) = AB( 2, I )
  532:   220       CONTINUE
  533:          ELSE
  534: *
  535: *           set E to zero if original matrix was diagonal
  536: *
  537:             DO 230 I = 1, N - 1
  538:                E( I ) = ZERO
  539:   230       CONTINUE
  540:          END IF
  541: *
  542: *        copy diagonal elements to D
  543: *
  544:          DO 240 I = 1, N
  545:             D( I ) = AB( 1, I )
  546:   240    CONTINUE
  547:       END IF
  548: *
  549:       RETURN
  550: *
  551: *     End of DSBTRD
  552: *
  553:       END

CVSweb interface <joel.bertrand@systella.fr>