claed0.c
Go to the documentation of this file.
00001 /* claed0.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static integer c__9 = 9;
00019 static integer c__0 = 0;
00020 static integer c__2 = 2;
00021 static integer c__1 = 1;
00022 
00023 /* Subroutine */ int claed0_(integer *qsiz, integer *n, real *d__, real *e, 
00024         complex *q, integer *ldq, complex *qstore, integer *ldqs, real *rwork, 
00025          integer *iwork, integer *info)
00026 {
00027     /* System generated locals */
00028     integer q_dim1, q_offset, qstore_dim1, qstore_offset, i__1, i__2;
00029     real r__1;
00030 
00031     /* Builtin functions */
00032     double log(doublereal);
00033     integer pow_ii(integer *, integer *);
00034 
00035     /* Local variables */
00036     integer i__, j, k, ll, iq, lgn, msd2, smm1, spm1, spm2;
00037     real temp;
00038     integer curr, iperm;
00039     extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, 
00040             complex *, integer *);
00041     integer indxq, iwrem;
00042     extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 
00043             integer *);
00044     integer iqptr;
00045     extern /* Subroutine */ int claed7_(integer *, integer *, integer *, 
00046             integer *, integer *, integer *, real *, complex *, integer *, 
00047             real *, integer *, real *, integer *, integer *, integer *, 
00048             integer *, integer *, real *, complex *, real *, integer *, 
00049             integer *);
00050     integer tlvls;
00051     extern /* Subroutine */ int clacrm_(integer *, integer *, complex *, 
00052             integer *, real *, integer *, complex *, integer *, real *);
00053     integer igivcl;
00054     extern /* Subroutine */ int xerbla_(char *, integer *);
00055     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
00056             integer *, integer *);
00057     integer igivnm, submat, curprb, subpbs, igivpt, curlvl, matsiz, iprmpt, 
00058             smlsiz;
00059     extern /* Subroutine */ int ssteqr_(char *, integer *, real *, real *, 
00060             real *, integer *, real *, integer *);
00061 
00062 
00063 /*  -- LAPACK routine (version 3.2) -- */
00064 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00065 /*     November 2006 */
00066 
00067 /*     .. Scalar Arguments .. */
00068 /*     .. */
00069 /*     .. Array Arguments .. */
00070 /*     .. */
00071 
00072 /*  Purpose */
00073 /*  ======= */
00074 
00075 /*  Using the divide and conquer method, CLAED0 computes all eigenvalues */
00076 /*  of a symmetric tridiagonal matrix which is one diagonal block of */
00077 /*  those from reducing a dense or band Hermitian matrix and */
00078 /*  corresponding eigenvectors of the dense or band matrix. */
00079 
00080 /*  Arguments */
00081 /*  ========= */
00082 
00083 /*  QSIZ   (input) INTEGER */
00084 /*         The dimension of the unitary matrix used to reduce */
00085 /*         the full matrix to tridiagonal form.  QSIZ >= N if ICOMPQ = 1. */
00086 
00087 /*  N      (input) INTEGER */
00088 /*         The dimension of the symmetric tridiagonal matrix.  N >= 0. */
00089 
00090 /*  D      (input/output) REAL array, dimension (N) */
00091 /*         On entry, the diagonal elements of the tridiagonal matrix. */
00092 /*         On exit, the eigenvalues in ascending order. */
00093 
00094 /*  E      (input/output) REAL array, dimension (N-1) */
00095 /*         On entry, the off-diagonal elements of the tridiagonal matrix. */
00096 /*         On exit, E has been destroyed. */
00097 
00098 /*  Q      (input/output) COMPLEX array, dimension (LDQ,N) */
00099 /*         On entry, Q must contain an QSIZ x N matrix whose columns */
00100 /*         unitarily orthonormal. It is a part of the unitary matrix */
00101 /*         that reduces the full dense Hermitian matrix to a */
00102 /*         (reducible) symmetric tridiagonal matrix. */
00103 
00104 /*  LDQ    (input) INTEGER */
00105 /*         The leading dimension of the array Q.  LDQ >= max(1,N). */
00106 
00107 /*  IWORK  (workspace) INTEGER array, */
00108 /*         the dimension of IWORK must be at least */
00109 /*                      6 + 6*N + 5*N*lg N */
00110 /*                      ( lg( N ) = smallest integer k */
00111 /*                                  such that 2^k >= N ) */
00112 
00113 /*  RWORK  (workspace) REAL array, */
00114 /*                               dimension (1 + 3*N + 2*N*lg N + 3*N**2) */
00115 /*                        ( lg( N ) = smallest integer k */
00116 /*                                    such that 2^k >= N ) */
00117 
00118 /*  QSTORE (workspace) COMPLEX array, dimension (LDQS, N) */
00119 /*         Used to store parts of */
00120 /*         the eigenvector matrix when the updating matrix multiplies */
00121 /*         take place. */
00122 
00123 /*  LDQS   (input) INTEGER */
00124 /*         The leading dimension of the array QSTORE. */
00125 /*         LDQS >= max(1,N). */
00126 
00127 /*  INFO   (output) INTEGER */
00128 /*          = 0:  successful exit. */
00129 /*          < 0:  if INFO = -i, the i-th argument had an illegal value. */
00130 /*          > 0:  The algorithm failed to compute an eigenvalue while */
00131 /*                working on the submatrix lying in rows and columns */
00132 /*                INFO/(N+1) through mod(INFO,N+1). */
00133 
00134 /*  ===================================================================== */
00135 
00136 /*  Warning:      N could be as big as QSIZ! */
00137 
00138 /*     .. Parameters .. */
00139 /*     .. */
00140 /*     .. Local Scalars .. */
00141 /*     .. */
00142 /*     .. External Subroutines .. */
00143 /*     .. */
00144 /*     .. External Functions .. */
00145 /*     .. */
00146 /*     .. Intrinsic Functions .. */
00147 /*     .. */
00148 /*     .. Executable Statements .. */
00149 
00150 /*     Test the input parameters. */
00151 
00152     /* Parameter adjustments */
00153     --d__;
00154     --e;
00155     q_dim1 = *ldq;
00156     q_offset = 1 + q_dim1;
00157     q -= q_offset;
00158     qstore_dim1 = *ldqs;
00159     qstore_offset = 1 + qstore_dim1;
00160     qstore -= qstore_offset;
00161     --rwork;
00162     --iwork;
00163 
00164     /* Function Body */
00165     *info = 0;
00166 
00167 /*     IF( ICOMPQ .LT. 0 .OR. ICOMPQ .GT. 2 ) THEN */
00168 /*        INFO = -1 */
00169 /*     ELSE IF( ( ICOMPQ .EQ. 1 ) .AND. ( QSIZ .LT. MAX( 0, N ) ) ) */
00170 /*    $        THEN */
00171     if (*qsiz < max(0,*n)) {
00172         *info = -1;
00173     } else if (*n < 0) {
00174         *info = -2;
00175     } else if (*ldq < max(1,*n)) {
00176         *info = -6;
00177     } else if (*ldqs < max(1,*n)) {
00178         *info = -8;
00179     }
00180     if (*info != 0) {
00181         i__1 = -(*info);
00182         xerbla_("CLAED0", &i__1);
00183         return 0;
00184     }
00185 
00186 /*     Quick return if possible */
00187 
00188     if (*n == 0) {
00189         return 0;
00190     }
00191 
00192     smlsiz = ilaenv_(&c__9, "CLAED0", " ", &c__0, &c__0, &c__0, &c__0);
00193 
00194 /*     Determine the size and placement of the submatrices, and save in */
00195 /*     the leading elements of IWORK. */
00196 
00197     iwork[1] = *n;
00198     subpbs = 1;
00199     tlvls = 0;
00200 L10:
00201     if (iwork[subpbs] > smlsiz) {
00202         for (j = subpbs; j >= 1; --j) {
00203             iwork[j * 2] = (iwork[j] + 1) / 2;
00204             iwork[(j << 1) - 1] = iwork[j] / 2;
00205 /* L20: */
00206         }
00207         ++tlvls;
00208         subpbs <<= 1;
00209         goto L10;
00210     }
00211     i__1 = subpbs;
00212     for (j = 2; j <= i__1; ++j) {
00213         iwork[j] += iwork[j - 1];
00214 /* L30: */
00215     }
00216 
00217 /*     Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1 */
00218 /*     using rank-1 modifications (cuts). */
00219 
00220     spm1 = subpbs - 1;
00221     i__1 = spm1;
00222     for (i__ = 1; i__ <= i__1; ++i__) {
00223         submat = iwork[i__] + 1;
00224         smm1 = submat - 1;
00225         d__[smm1] -= (r__1 = e[smm1], dabs(r__1));
00226         d__[submat] -= (r__1 = e[smm1], dabs(r__1));
00227 /* L40: */
00228     }
00229 
00230     indxq = (*n << 2) + 3;
00231 
00232 /*     Set up workspaces for eigenvalues only/accumulate new vectors */
00233 /*     routine */
00234 
00235     temp = log((real) (*n)) / log(2.f);
00236     lgn = (integer) temp;
00237     if (pow_ii(&c__2, &lgn) < *n) {
00238         ++lgn;
00239     }
00240     if (pow_ii(&c__2, &lgn) < *n) {
00241         ++lgn;
00242     }
00243     iprmpt = indxq + *n + 1;
00244     iperm = iprmpt + *n * lgn;
00245     iqptr = iperm + *n * lgn;
00246     igivpt = iqptr + *n + 2;
00247     igivcl = igivpt + *n * lgn;
00248 
00249     igivnm = 1;
00250     iq = igivnm + (*n << 1) * lgn;
00251 /* Computing 2nd power */
00252     i__1 = *n;
00253     iwrem = iq + i__1 * i__1 + 1;
00254 /*     Initialize pointers */
00255     i__1 = subpbs;
00256     for (i__ = 0; i__ <= i__1; ++i__) {
00257         iwork[iprmpt + i__] = 1;
00258         iwork[igivpt + i__] = 1;
00259 /* L50: */
00260     }
00261     iwork[iqptr] = 1;
00262 
00263 /*     Solve each submatrix eigenproblem at the bottom of the divide and */
00264 /*     conquer tree. */
00265 
00266     curr = 0;
00267     i__1 = spm1;
00268     for (i__ = 0; i__ <= i__1; ++i__) {
00269         if (i__ == 0) {
00270             submat = 1;
00271             matsiz = iwork[1];
00272         } else {
00273             submat = iwork[i__] + 1;
00274             matsiz = iwork[i__ + 1] - iwork[i__];
00275         }
00276         ll = iq - 1 + iwork[iqptr + curr];
00277         ssteqr_("I", &matsiz, &d__[submat], &e[submat], &rwork[ll], &matsiz, &
00278                 rwork[1], info);
00279         clacrm_(qsiz, &matsiz, &q[submat * q_dim1 + 1], ldq, &rwork[ll], &
00280                 matsiz, &qstore[submat * qstore_dim1 + 1], ldqs, &rwork[iwrem]
00281 );
00282 /* Computing 2nd power */
00283         i__2 = matsiz;
00284         iwork[iqptr + curr + 1] = iwork[iqptr + curr] + i__2 * i__2;
00285         ++curr;
00286         if (*info > 0) {
00287             *info = submat * (*n + 1) + submat + matsiz - 1;
00288             return 0;
00289         }
00290         k = 1;
00291         i__2 = iwork[i__ + 1];
00292         for (j = submat; j <= i__2; ++j) {
00293             iwork[indxq + j] = k;
00294             ++k;
00295 /* L60: */
00296         }
00297 /* L70: */
00298     }
00299 
00300 /*     Successively merge eigensystems of adjacent submatrices */
00301 /*     into eigensystem for the corresponding larger matrix. */
00302 
00303 /*     while ( SUBPBS > 1 ) */
00304 
00305     curlvl = 1;
00306 L80:
00307     if (subpbs > 1) {
00308         spm2 = subpbs - 2;
00309         i__1 = spm2;
00310         for (i__ = 0; i__ <= i__1; i__ += 2) {
00311             if (i__ == 0) {
00312                 submat = 1;
00313                 matsiz = iwork[2];
00314                 msd2 = iwork[1];
00315                 curprb = 0;
00316             } else {
00317                 submat = iwork[i__] + 1;
00318                 matsiz = iwork[i__ + 2] - iwork[i__];
00319                 msd2 = matsiz / 2;
00320                 ++curprb;
00321             }
00322 
00323 /*     Merge lower order eigensystems (of size MSD2 and MATSIZ - MSD2) */
00324 /*     into an eigensystem of size MATSIZ.  CLAED7 handles the case */
00325 /*     when the eigenvectors of a full or band Hermitian matrix (which */
00326 /*     was reduced to tridiagonal form) are desired. */
00327 
00328 /*     I am free to use Q as a valuable working space until Loop 150. */
00329 
00330             claed7_(&matsiz, &msd2, qsiz, &tlvls, &curlvl, &curprb, &d__[
00331                     submat], &qstore[submat * qstore_dim1 + 1], ldqs, &e[
00332                     submat + msd2 - 1], &iwork[indxq + submat], &rwork[iq], &
00333                     iwork[iqptr], &iwork[iprmpt], &iwork[iperm], &iwork[
00334                     igivpt], &iwork[igivcl], &rwork[igivnm], &q[submat * 
00335                     q_dim1 + 1], &rwork[iwrem], &iwork[subpbs + 1], info);
00336             if (*info > 0) {
00337                 *info = submat * (*n + 1) + submat + matsiz - 1;
00338                 return 0;
00339             }
00340             iwork[i__ / 2 + 1] = iwork[i__ + 2];
00341 /* L90: */
00342         }
00343         subpbs /= 2;
00344         ++curlvl;
00345         goto L80;
00346     }
00347 
00348 /*     end while */
00349 
00350 /*     Re-merge the eigenvalues/vectors which were deflated at the final */
00351 /*     merge step. */
00352 
00353     i__1 = *n;
00354     for (i__ = 1; i__ <= i__1; ++i__) {
00355         j = iwork[indxq + i__];
00356         rwork[i__] = d__[j];
00357         ccopy_(qsiz, &qstore[j * qstore_dim1 + 1], &c__1, &q[i__ * q_dim1 + 1]
00358 , &c__1);
00359 /* L100: */
00360     }
00361     scopy_(n, &rwork[1], &c__1, &d__[1], &c__1);
00362 
00363     return 0;
00364 
00365 /*     End of CLAED0 */
00366 
00367 } /* claed0_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:30