3 /* Table of constant values */
5 static integer c__9 = 9;
6 static integer c__0 = 0;
7 static integer c__2 = 2;
8 static doublereal c_b23 = 1.;
9 static doublereal c_b24 = 0.;
10 static integer c__1 = 1;
12 /* Subroutine */ int dlaed0_(integer *icompq, integer *qsiz, integer *n,
13 doublereal *d__, doublereal *e, doublereal *q, integer *ldq,
14 doublereal *qstore, integer *ldqs, doublereal *work, integer *iwork,
17 /* System generated locals */
18 integer q_dim1, q_offset, qstore_dim1, qstore_offset, i__1, i__2;
21 /* Builtin functions */
22 double log(doublereal);
23 integer pow_ii(integer *, integer *);
26 integer i__, j, k, iq, lgn, msd2, smm1, spm1, spm2;
29 extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *,
30 integer *, doublereal *, doublereal *, integer *, doublereal *,
31 integer *, doublereal *, doublereal *, integer *);
33 extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *,
34 doublereal *, integer *);
36 extern /* Subroutine */ int dlaed1_(integer *, doublereal *, doublereal *,
37 integer *, integer *, doublereal *, integer *, doublereal *,
38 integer *, integer *);
40 extern /* Subroutine */ int dlaed7_(integer *, integer *, integer *,
41 integer *, integer *, integer *, doublereal *, doublereal *,
42 integer *, integer *, doublereal *, integer *, doublereal *,
43 integer *, integer *, integer *, integer *, integer *, doublereal
44 *, doublereal *, integer *, integer *);
46 extern /* Subroutine */ int dlacpy_(char *, integer *, integer *,
47 doublereal *, integer *, doublereal *, integer *);
49 extern /* Subroutine */ int xerbla_(char *, integer *);
50 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
51 integer *, integer *);
52 integer igivnm, submat, curprb, subpbs, igivpt;
53 extern /* Subroutine */ int dsteqr_(char *, integer *, doublereal *,
54 doublereal *, doublereal *, integer *, doublereal *, integer *);
55 integer curlvl, matsiz, iprmpt, smlsiz;
58 /* -- LAPACK routine (version 3.1) -- */
59 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
62 /* .. Scalar Arguments .. */
64 /* .. Array Arguments .. */
70 /* DLAED0 computes all eigenvalues and corresponding eigenvectors of a */
71 /* symmetric tridiagonal matrix using the divide and conquer method. */
76 /* ICOMPQ (input) INTEGER */
77 /* = 0: Compute eigenvalues only. */
78 /* = 1: Compute eigenvectors of original dense symmetric matrix */
79 /* also. On entry, Q contains the orthogonal matrix used */
80 /* to reduce the original matrix to tridiagonal form. */
81 /* = 2: Compute eigenvalues and eigenvectors of tridiagonal */
84 /* QSIZ (input) INTEGER */
85 /* The dimension of the orthogonal matrix used to reduce */
86 /* the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1. */
88 /* N (input) INTEGER */
89 /* The dimension of the symmetric tridiagonal matrix. N >= 0. */
91 /* D (input/output) DOUBLE PRECISION array, dimension (N) */
92 /* On entry, the main diagonal of the tridiagonal matrix. */
93 /* On exit, its eigenvalues. */
95 /* E (input) DOUBLE PRECISION array, dimension (N-1) */
96 /* The off-diagonal elements of the tridiagonal matrix. */
97 /* On exit, E has been destroyed. */
99 /* Q (input/output) DOUBLE PRECISION array, dimension (LDQ, N) */
100 /* On entry, Q must contain an N-by-N orthogonal matrix. */
101 /* If ICOMPQ = 0 Q is not referenced. */
102 /* If ICOMPQ = 1 On entry, Q is a subset of the columns of the */
103 /* orthogonal matrix used to reduce the full */
104 /* matrix to tridiagonal form corresponding to */
105 /* the subset of the full matrix which is being */
106 /* decomposed at this time. */
107 /* If ICOMPQ = 2 On entry, Q will be the identity matrix. */
108 /* On exit, Q contains the eigenvectors of the */
109 /* tridiagonal matrix. */
111 /* LDQ (input) INTEGER */
112 /* The leading dimension of the array Q. If eigenvectors are */
113 /* desired, then LDQ >= max(1,N). In any case, LDQ >= 1. */
115 /* QSTORE (workspace) DOUBLE PRECISION array, dimension (LDQS, N) */
116 /* Referenced only when ICOMPQ = 1. Used to store parts of */
117 /* the eigenvector matrix when the updating matrix multiplies */
120 /* LDQS (input) INTEGER */
121 /* The leading dimension of the array QSTORE. If ICOMPQ = 1, */
122 /* then LDQS >= max(1,N). In any case, LDQS >= 1. */
124 /* WORK (workspace) DOUBLE PRECISION array, */
125 /* If ICOMPQ = 0 or 1, the dimension of WORK must be at least */
126 /* 1 + 3*N + 2*N*lg N + 2*N**2 */
127 /* ( lg( N ) = smallest integer k */
128 /* such that 2^k >= N ) */
129 /* If ICOMPQ = 2, the dimension of WORK must be at least */
132 /* IWORK (workspace) INTEGER array, */
133 /* If ICOMPQ = 0 or 1, the dimension of IWORK must be at least */
134 /* 6 + 6*N + 5*N*lg N. */
135 /* ( lg( N ) = smallest integer k */
136 /* such that 2^k >= N ) */
137 /* If ICOMPQ = 2, the dimension of IWORK must be at least */
140 /* INFO (output) INTEGER */
141 /* = 0: successful exit. */
142 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
143 /* > 0: The algorithm failed to compute an eigenvalue while */
144 /* working on the submatrix lying in rows and columns */
145 /* INFO/(N+1) through mod(INFO,N+1). */
147 /* Further Details */
148 /* =============== */
150 /* Based on contributions by */
151 /* Jeff Rutter, Computer Science Division, University of California */
152 /* at Berkeley, USA */
154 /* ===================================================================== */
156 /* .. Parameters .. */
158 /* .. Local Scalars .. */
160 /* .. External Subroutines .. */
162 /* .. External Functions .. */
164 /* .. Intrinsic Functions .. */
166 /* .. Executable Statements .. */
168 /* Test the input parameters. */
170 /* Parameter adjustments */
174 q_offset = 1 + q_dim1;
177 qstore_offset = 1 + qstore_dim1;
178 qstore -= qstore_offset;
185 if (*icompq < 0 || *icompq > 2) {
187 } else if (*icompq == 1 && *qsiz < max(0,*n)) {
191 } else if (*ldq < max(1,*n)) {
193 } else if (*ldqs < max(1,*n)) {
198 xerbla_("DLAED0", &i__1);
202 /* Quick return if possible */
208 smlsiz = ilaenv_(&c__9, "DLAED0", " ", &c__0, &c__0, &c__0, &c__0);
210 /* Determine the size and placement of the submatrices, and save in */
211 /* the leading elements of IWORK. */
217 if (iwork[subpbs] > smlsiz) {
218 for (j = subpbs; j >= 1; --j) {
219 iwork[j * 2] = (iwork[j] + 1) / 2;
220 iwork[(j << 1) - 1] = iwork[j] / 2;
228 for (j = 2; j <= i__1; ++j) {
229 iwork[j] += iwork[j - 1];
233 /* Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1 */
234 /* using rank-1 modifications (cuts). */
238 for (i__ = 1; i__ <= i__1; ++i__) {
239 submat = iwork[i__] + 1;
241 d__[smm1] -= (d__1 = e[smm1], abs(d__1));
242 d__[submat] -= (d__1 = e[smm1], abs(d__1));
246 indxq = (*n << 2) + 3;
249 /* Set up workspaces for eigenvalues only/accumulate new vectors */
252 temp = log((doublereal) (*n)) / log(2.);
253 lgn = (integer) temp;
254 if (pow_ii(&c__2, &lgn) < *n) {
257 if (pow_ii(&c__2, &lgn) < *n) {
260 iprmpt = indxq + *n + 1;
261 iperm = iprmpt + *n * lgn;
262 iqptr = iperm + *n * lgn;
263 igivpt = iqptr + *n + 2;
264 igivcl = igivpt + *n * lgn;
267 iq = igivnm + (*n << 1) * lgn;
268 /* Computing 2nd power */
270 iwrem = iq + i__1 * i__1 + 1;
272 /* Initialize pointers */
275 for (i__ = 0; i__ <= i__1; ++i__) {
276 iwork[iprmpt + i__] = 1;
277 iwork[igivpt + i__] = 1;
283 /* Solve each submatrix eigenproblem at the bottom of the divide and */
288 for (i__ = 0; i__ <= i__1; ++i__) {
293 submat = iwork[i__] + 1;
294 matsiz = iwork[i__ + 1] - iwork[i__];
297 dsteqr_("I", &matsiz, &d__[submat], &e[submat], &q[submat +
298 submat * q_dim1], ldq, &work[1], info);
303 dsteqr_("I", &matsiz, &d__[submat], &e[submat], &work[iq - 1 +
304 iwork[iqptr + curr]], &matsiz, &work[1], info);
309 dgemm_("N", "N", qsiz, &matsiz, &matsiz, &c_b23, &q[submat *
310 q_dim1 + 1], ldq, &work[iq - 1 + iwork[iqptr + curr]],
311 &matsiz, &c_b24, &qstore[submat * qstore_dim1 + 1],
314 /* Computing 2nd power */
316 iwork[iqptr + curr + 1] = iwork[iqptr + curr] + i__2 * i__2;
320 i__2 = iwork[i__ + 1];
321 for (j = submat; j <= i__2; ++j) {
322 iwork[indxq + j] = k;
329 /* Successively merge eigensystems of adjacent submatrices */
330 /* into eigensystem for the corresponding larger matrix. */
332 /* while ( SUBPBS > 1 ) */
339 for (i__ = 0; i__ <= i__1; i__ += 2) {
346 submat = iwork[i__] + 1;
347 matsiz = iwork[i__ + 2] - iwork[i__];
352 /* Merge lower order eigensystems (of size MSD2 and MATSIZ - MSD2) */
353 /* into an eigensystem of size MATSIZ. */
354 /* DLAED1 is used only for the full eigensystem of a tridiagonal */
356 /* DLAED7 handles the cases in which eigenvalues only or eigenvalues */
357 /* and eigenvectors of a full symmetric matrix (which was reduced to */
358 /* tridiagonal form) are desired. */
361 dlaed1_(&matsiz, &d__[submat], &q[submat + submat * q_dim1],
362 ldq, &iwork[indxq + submat], &e[submat + msd2 - 1], &
363 msd2, &work[1], &iwork[subpbs + 1], info);
365 dlaed7_(icompq, &matsiz, qsiz, &tlvls, &curlvl, &curprb, &d__[
366 submat], &qstore[submat * qstore_dim1 + 1], ldqs, &
367 iwork[indxq + submat], &e[submat + msd2 - 1], &msd2, &
368 work[iq], &iwork[iqptr], &iwork[iprmpt], &iwork[iperm]
369 , &iwork[igivpt], &iwork[igivcl], &work[igivnm], &
370 work[iwrem], &iwork[subpbs + 1], info);
375 iwork[i__ / 2 + 1] = iwork[i__ + 2];
385 /* Re-merge the eigenvalues/vectors which were deflated at the final */
390 for (i__ = 1; i__ <= i__1; ++i__) {
391 j = iwork[indxq + i__];
393 dcopy_(qsiz, &qstore[j * qstore_dim1 + 1], &c__1, &q[i__ * q_dim1
397 dcopy_(n, &work[1], &c__1, &d__[1], &c__1);
398 } else if (*icompq == 2) {
400 for (i__ = 1; i__ <= i__1; ++i__) {
401 j = iwork[indxq + i__];
403 dcopy_(n, &q[j * q_dim1 + 1], &c__1, &work[*n * i__ + 1], &c__1);
406 dcopy_(n, &work[1], &c__1, &d__[1], &c__1);
407 dlacpy_("A", n, n, &work[*n + 1], n, &q[q_offset], ldq);
410 for (i__ = 1; i__ <= i__1; ++i__) {
411 j = iwork[indxq + i__];
415 dcopy_(n, &work[1], &c__1, &d__[1], &c__1);
420 *info = submat * (*n + 1) + submat + matsiz - 1;