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

    1:       SUBROUTINE DLAED0( ICOMPQ, QSIZ, N, D, E, Q, LDQ, QSTORE, LDQS,
    2:      $                   WORK, IWORK, 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:       INTEGER            ICOMPQ, INFO, LDQ, LDQS, N, QSIZ
   11: *     ..
   12: *     .. Array Arguments ..
   13:       INTEGER            IWORK( * )
   14:       DOUBLE PRECISION   D( * ), E( * ), Q( LDQ, * ), QSTORE( LDQS, * ),
   15:      $                   WORK( * )
   16: *     ..
   17: *
   18: *  Purpose
   19: *  =======
   20: *
   21: *  DLAED0 computes all eigenvalues and corresponding eigenvectors of a
   22: *  symmetric tridiagonal matrix using the divide and conquer method.
   23: *
   24: *  Arguments
   25: *  =========
   26: *
   27: *  ICOMPQ  (input) INTEGER
   28: *          = 0:  Compute eigenvalues only.
   29: *          = 1:  Compute eigenvectors of original dense symmetric matrix
   30: *                also.  On entry, Q contains the orthogonal matrix used
   31: *                to reduce the original matrix to tridiagonal form.
   32: *          = 2:  Compute eigenvalues and eigenvectors of tridiagonal
   33: *                matrix.
   34: *
   35: *  QSIZ   (input) INTEGER
   36: *         The dimension of the orthogonal matrix used to reduce
   37: *         the full matrix to tridiagonal form.  QSIZ >= N if ICOMPQ = 1.
   38: *
   39: *  N      (input) INTEGER
   40: *         The dimension of the symmetric tridiagonal matrix.  N >= 0.
   41: *
   42: *  D      (input/output) DOUBLE PRECISION array, dimension (N)
   43: *         On entry, the main diagonal of the tridiagonal matrix.
   44: *         On exit, its eigenvalues.
   45: *
   46: *  E      (input) DOUBLE PRECISION array, dimension (N-1)
   47: *         The off-diagonal elements of the tridiagonal matrix.
   48: *         On exit, E has been destroyed.
   49: *
   50: *  Q      (input/output) DOUBLE PRECISION array, dimension (LDQ, N)
   51: *         On entry, Q must contain an N-by-N orthogonal matrix.
   52: *         If ICOMPQ = 0    Q is not referenced.
   53: *         If ICOMPQ = 1    On entry, Q is a subset of the columns of the
   54: *                          orthogonal matrix used to reduce the full
   55: *                          matrix to tridiagonal form corresponding to
   56: *                          the subset of the full matrix which is being
   57: *                          decomposed at this time.
   58: *         If ICOMPQ = 2    On entry, Q will be the identity matrix.
   59: *                          On exit, Q contains the eigenvectors of the
   60: *                          tridiagonal matrix.
   61: *
   62: *  LDQ    (input) INTEGER
   63: *         The leading dimension of the array Q.  If eigenvectors are
   64: *         desired, then  LDQ >= max(1,N).  In any case,  LDQ >= 1.
   65: *
   66: *  QSTORE (workspace) DOUBLE PRECISION array, dimension (LDQS, N)
   67: *         Referenced only when ICOMPQ = 1.  Used to store parts of
   68: *         the eigenvector matrix when the updating matrix multiplies
   69: *         take place.
   70: *
   71: *  LDQS   (input) INTEGER
   72: *         The leading dimension of the array QSTORE.  If ICOMPQ = 1,
   73: *         then  LDQS >= max(1,N).  In any case,  LDQS >= 1.
   74: *
   75: *  WORK   (workspace) DOUBLE PRECISION array,
   76: *         If ICOMPQ = 0 or 1, the dimension of WORK must be at least
   77: *                     1 + 3*N + 2*N*lg N + 2*N**2
   78: *                     ( lg( N ) = smallest integer k
   79: *                                 such that 2^k >= N )
   80: *         If ICOMPQ = 2, the dimension of WORK must be at least
   81: *                     4*N + N**2.
   82: *
   83: *  IWORK  (workspace) INTEGER array,
   84: *         If ICOMPQ = 0 or 1, the dimension of IWORK must be at least
   85: *                        6 + 6*N + 5*N*lg N.
   86: *                        ( lg( N ) = smallest integer k
   87: *                                    such that 2^k >= N )
   88: *         If ICOMPQ = 2, the dimension of IWORK must be at least
   89: *                        3 + 5*N.
   90: *
   91: *  INFO   (output) INTEGER
   92: *          = 0:  successful exit.
   93: *          < 0:  if INFO = -i, the i-th argument had an illegal value.
   94: *          > 0:  The algorithm failed to compute an eigenvalue while
   95: *                working on the submatrix lying in rows and columns
   96: *                INFO/(N+1) through mod(INFO,N+1).
   97: *
   98: *  Further Details
   99: *  ===============
  100: *
  101: *  Based on contributions by
  102: *     Jeff Rutter, Computer Science Division, University of California
  103: *     at Berkeley, USA
  104: *
  105: *  =====================================================================
  106: *
  107: *     .. Parameters ..
  108:       DOUBLE PRECISION   ZERO, ONE, TWO
  109:       PARAMETER          ( ZERO = 0.D0, ONE = 1.D0, TWO = 2.D0 )
  110: *     ..
  111: *     .. Local Scalars ..
  112:       INTEGER            CURLVL, CURPRB, CURR, I, IGIVCL, IGIVNM,
  113:      $                   IGIVPT, INDXQ, IPERM, IPRMPT, IQ, IQPTR, IWREM,
  114:      $                   J, K, LGN, MATSIZ, MSD2, SMLSIZ, SMM1, SPM1,
  115:      $                   SPM2, SUBMAT, SUBPBS, TLVLS
  116:       DOUBLE PRECISION   TEMP
  117: *     ..
  118: *     .. External Subroutines ..
  119:       EXTERNAL           DCOPY, DGEMM, DLACPY, DLAED1, DLAED7, DSTEQR,
  120:      $                   XERBLA
  121: *     ..
  122: *     .. External Functions ..
  123:       INTEGER            ILAENV
  124:       EXTERNAL           ILAENV
  125: *     ..
  126: *     .. Intrinsic Functions ..
  127:       INTRINSIC          ABS, DBLE, INT, LOG, MAX
  128: *     ..
  129: *     .. Executable Statements ..
  130: *
  131: *     Test the input parameters.
  132: *
  133:       INFO = 0
  134: *
  135:       IF( ICOMPQ.LT.0 .OR. ICOMPQ.GT.2 ) THEN
  136:          INFO = -1
  137:       ELSE IF( ( ICOMPQ.EQ.1 ) .AND. ( QSIZ.LT.MAX( 0, N ) ) ) THEN
  138:          INFO = -2
  139:       ELSE IF( N.LT.0 ) THEN
  140:          INFO = -3
  141:       ELSE IF( LDQ.LT.MAX( 1, N ) ) THEN
  142:          INFO = -7
  143:       ELSE IF( LDQS.LT.MAX( 1, N ) ) THEN
  144:          INFO = -9
  145:       END IF
  146:       IF( INFO.NE.0 ) THEN
  147:          CALL XERBLA( 'DLAED0', -INFO )
  148:          RETURN
  149:       END IF
  150: *
  151: *     Quick return if possible
  152: *
  153:       IF( N.EQ.0 )
  154:      $   RETURN
  155: *
  156:       SMLSIZ = ILAENV( 9, 'DLAED0', ' ', 0, 0, 0, 0 )
  157: *
  158: *     Determine the size and placement of the submatrices, and save in
  159: *     the leading elements of IWORK.
  160: *
  161:       IWORK( 1 ) = N
  162:       SUBPBS = 1
  163:       TLVLS = 0
  164:    10 CONTINUE
  165:       IF( IWORK( SUBPBS ).GT.SMLSIZ ) THEN
  166:          DO 20 J = SUBPBS, 1, -1
  167:             IWORK( 2*J ) = ( IWORK( J )+1 ) / 2
  168:             IWORK( 2*J-1 ) = IWORK( J ) / 2
  169:    20    CONTINUE
  170:          TLVLS = TLVLS + 1
  171:          SUBPBS = 2*SUBPBS
  172:          GO TO 10
  173:       END IF
  174:       DO 30 J = 2, SUBPBS
  175:          IWORK( J ) = IWORK( J ) + IWORK( J-1 )
  176:    30 CONTINUE
  177: *
  178: *     Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1
  179: *     using rank-1 modifications (cuts).
  180: *
  181:       SPM1 = SUBPBS - 1
  182:       DO 40 I = 1, SPM1
  183:          SUBMAT = IWORK( I ) + 1
  184:          SMM1 = SUBMAT - 1
  185:          D( SMM1 ) = D( SMM1 ) - ABS( E( SMM1 ) )
  186:          D( SUBMAT ) = D( SUBMAT ) - ABS( E( SMM1 ) )
  187:    40 CONTINUE
  188: *
  189:       INDXQ = 4*N + 3
  190:       IF( ICOMPQ.NE.2 ) THEN
  191: *
  192: *        Set up workspaces for eigenvalues only/accumulate new vectors
  193: *        routine
  194: *
  195:          TEMP = LOG( DBLE( N ) ) / LOG( TWO )
  196:          LGN = INT( TEMP )
  197:          IF( 2**LGN.LT.N )
  198:      $      LGN = LGN + 1
  199:          IF( 2**LGN.LT.N )
  200:      $      LGN = LGN + 1
  201:          IPRMPT = INDXQ + N + 1
  202:          IPERM = IPRMPT + N*LGN
  203:          IQPTR = IPERM + N*LGN
  204:          IGIVPT = IQPTR + N + 2
  205:          IGIVCL = IGIVPT + N*LGN
  206: *
  207:          IGIVNM = 1
  208:          IQ = IGIVNM + 2*N*LGN
  209:          IWREM = IQ + N**2 + 1
  210: *
  211: *        Initialize pointers
  212: *
  213:          DO 50 I = 0, SUBPBS
  214:             IWORK( IPRMPT+I ) = 1
  215:             IWORK( IGIVPT+I ) = 1
  216:    50    CONTINUE
  217:          IWORK( IQPTR ) = 1
  218:       END IF
  219: *
  220: *     Solve each submatrix eigenproblem at the bottom of the divide and
  221: *     conquer tree.
  222: *
  223:       CURR = 0
  224:       DO 70 I = 0, SPM1
  225:          IF( I.EQ.0 ) THEN
  226:             SUBMAT = 1
  227:             MATSIZ = IWORK( 1 )
  228:          ELSE
  229:             SUBMAT = IWORK( I ) + 1
  230:             MATSIZ = IWORK( I+1 ) - IWORK( I )
  231:          END IF
  232:          IF( ICOMPQ.EQ.2 ) THEN
  233:             CALL DSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
  234:      $                   Q( SUBMAT, SUBMAT ), LDQ, WORK, INFO )
  235:             IF( INFO.NE.0 )
  236:      $         GO TO 130
  237:          ELSE
  238:             CALL DSTEQR( 'I', MATSIZ, D( SUBMAT ), E( SUBMAT ),
  239:      $                   WORK( IQ-1+IWORK( IQPTR+CURR ) ), MATSIZ, WORK,
  240:      $                   INFO )
  241:             IF( INFO.NE.0 )
  242:      $         GO TO 130
  243:             IF( ICOMPQ.EQ.1 ) THEN
  244:                CALL DGEMM( 'N', 'N', QSIZ, MATSIZ, MATSIZ, ONE,
  245:      $                     Q( 1, SUBMAT ), LDQ, WORK( IQ-1+IWORK( IQPTR+
  246:      $                     CURR ) ), MATSIZ, ZERO, QSTORE( 1, SUBMAT ),
  247:      $                     LDQS )
  248:             END IF
  249:             IWORK( IQPTR+CURR+1 ) = IWORK( IQPTR+CURR ) + MATSIZ**2
  250:             CURR = CURR + 1
  251:          END IF
  252:          K = 1
  253:          DO 60 J = SUBMAT, IWORK( I+1 )
  254:             IWORK( INDXQ+J ) = K
  255:             K = K + 1
  256:    60    CONTINUE
  257:    70 CONTINUE
  258: *
  259: *     Successively merge eigensystems of adjacent submatrices
  260: *     into eigensystem for the corresponding larger matrix.
  261: *
  262: *     while ( SUBPBS > 1 )
  263: *
  264:       CURLVL = 1
  265:    80 CONTINUE
  266:       IF( SUBPBS.GT.1 ) THEN
  267:          SPM2 = SUBPBS - 2
  268:          DO 90 I = 0, SPM2, 2
  269:             IF( I.EQ.0 ) THEN
  270:                SUBMAT = 1
  271:                MATSIZ = IWORK( 2 )
  272:                MSD2 = IWORK( 1 )
  273:                CURPRB = 0
  274:             ELSE
  275:                SUBMAT = IWORK( I ) + 1
  276:                MATSIZ = IWORK( I+2 ) - IWORK( I )
  277:                MSD2 = MATSIZ / 2
  278:                CURPRB = CURPRB + 1
  279:             END IF
  280: *
  281: *     Merge lower order eigensystems (of size MSD2 and MATSIZ - MSD2)
  282: *     into an eigensystem of size MATSIZ.
  283: *     DLAED1 is used only for the full eigensystem of a tridiagonal
  284: *     matrix.
  285: *     DLAED7 handles the cases in which eigenvalues only or eigenvalues
  286: *     and eigenvectors of a full symmetric matrix (which was reduced to
  287: *     tridiagonal form) are desired.
  288: *
  289:             IF( ICOMPQ.EQ.2 ) THEN
  290:                CALL DLAED1( MATSIZ, D( SUBMAT ), Q( SUBMAT, SUBMAT ),
  291:      $                      LDQ, IWORK( INDXQ+SUBMAT ),
  292:      $                      E( SUBMAT+MSD2-1 ), MSD2, WORK,
  293:      $                      IWORK( SUBPBS+1 ), INFO )
  294:             ELSE
  295:                CALL DLAED7( ICOMPQ, MATSIZ, QSIZ, TLVLS, CURLVL, CURPRB,
  296:      $                      D( SUBMAT ), QSTORE( 1, SUBMAT ), LDQS,
  297:      $                      IWORK( INDXQ+SUBMAT ), E( SUBMAT+MSD2-1 ),
  298:      $                      MSD2, WORK( IQ ), IWORK( IQPTR ),
  299:      $                      IWORK( IPRMPT ), IWORK( IPERM ),
  300:      $                      IWORK( IGIVPT ), IWORK( IGIVCL ),
  301:      $                      WORK( IGIVNM ), WORK( IWREM ),
  302:      $                      IWORK( SUBPBS+1 ), INFO )
  303:             END IF
  304:             IF( INFO.NE.0 )
  305:      $         GO TO 130
  306:             IWORK( I / 2+1 ) = IWORK( I+2 )
  307:    90    CONTINUE
  308:          SUBPBS = SUBPBS / 2
  309:          CURLVL = CURLVL + 1
  310:          GO TO 80
  311:       END IF
  312: *
  313: *     end while
  314: *
  315: *     Re-merge the eigenvalues/vectors which were deflated at the final
  316: *     merge step.
  317: *
  318:       IF( ICOMPQ.EQ.1 ) THEN
  319:          DO 100 I = 1, N
  320:             J = IWORK( INDXQ+I )
  321:             WORK( I ) = D( J )
  322:             CALL DCOPY( QSIZ, QSTORE( 1, J ), 1, Q( 1, I ), 1 )
  323:   100    CONTINUE
  324:          CALL DCOPY( N, WORK, 1, D, 1 )
  325:       ELSE IF( ICOMPQ.EQ.2 ) THEN
  326:          DO 110 I = 1, N
  327:             J = IWORK( INDXQ+I )
  328:             WORK( I ) = D( J )
  329:             CALL DCOPY( N, Q( 1, J ), 1, WORK( N*I+1 ), 1 )
  330:   110    CONTINUE
  331:          CALL DCOPY( N, WORK, 1, D, 1 )
  332:          CALL DLACPY( 'A', N, N, WORK( N+1 ), N, Q, LDQ )
  333:       ELSE
  334:          DO 120 I = 1, N
  335:             J = IWORK( INDXQ+I )
  336:             WORK( I ) = D( J )
  337:   120    CONTINUE
  338:          CALL DCOPY( N, WORK, 1, D, 1 )
  339:       END IF
  340:       GO TO 140
  341: *
  342:   130 CONTINUE
  343:       INFO = SUBMAT*( N+1 ) + SUBMAT + MATSIZ - 1
  344: *
  345:   140 CONTINUE
  346:       RETURN
  347: *
  348: *     End of DLAED0
  349: *
  350:       END

CVSweb interface <joel.bertrand@systella.fr>