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 real c_b23 = 1.f;
9 static real c_b24 = 0.f;
10 static integer c__1 = 1;
12 /* Subroutine */ int slaed0_(integer *icompq, integer *qsiz, integer *n, real
13 *d__, real *e, real *q, integer *ldq, real *qstore, integer *ldqs,
14 real *work, integer *iwork, integer *info)
16 /* System generated locals */
17 integer q_dim1, q_offset, qstore_dim1, qstore_offset, i__1, i__2;
20 /* Builtin functions */
21 double log(doublereal);
22 integer pow_ii(integer *, integer *);
25 integer i__, j, k, iq, lgn, msd2, smm1, spm1, spm2;
28 extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *,
29 integer *, real *, real *, integer *, real *, integer *, real *,
31 integer iperm, indxq, iwrem;
32 extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *,
35 extern /* Subroutine */ int slaed1_(integer *, real *, real *, integer *,
36 integer *, real *, integer *, real *, integer *, integer *),
37 slaed7_(integer *, integer *, integer *, integer *, integer *,
38 integer *, real *, real *, integer *, integer *, real *, integer *
39 , real *, integer *, integer *, integer *, integer *, integer *,
40 real *, real *, integer *, integer *);
42 extern /* Subroutine */ int xerbla_(char *, integer *);
43 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
44 integer *, integer *);
45 integer igivnm, submat;
46 extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *,
47 integer *, real *, integer *);
48 integer curprb, subpbs, igivpt, curlvl, matsiz, iprmpt, smlsiz;
49 extern /* Subroutine */ int ssteqr_(char *, integer *, real *, real *,
50 real *, integer *, real *, integer *);
53 /* -- LAPACK routine (version 3.1) -- */
54 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
57 /* .. Scalar Arguments .. */
59 /* .. Array Arguments .. */
65 /* SLAED0 computes all eigenvalues and corresponding eigenvectors of a */
66 /* symmetric tridiagonal matrix using the divide and conquer method. */
71 /* ICOMPQ (input) INTEGER */
72 /* = 0: Compute eigenvalues only. */
73 /* = 1: Compute eigenvectors of original dense symmetric matrix */
74 /* also. On entry, Q contains the orthogonal matrix used */
75 /* to reduce the original matrix to tridiagonal form. */
76 /* = 2: Compute eigenvalues and eigenvectors of tridiagonal */
79 /* QSIZ (input) INTEGER */
80 /* The dimension of the orthogonal matrix used to reduce */
81 /* the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1. */
83 /* N (input) INTEGER */
84 /* The dimension of the symmetric tridiagonal matrix. N >= 0. */
86 /* D (input/output) REAL array, dimension (N) */
87 /* On entry, the main diagonal of the tridiagonal matrix. */
88 /* On exit, its eigenvalues. */
90 /* E (input) REAL array, dimension (N-1) */
91 /* The off-diagonal elements of the tridiagonal matrix. */
92 /* On exit, E has been destroyed. */
94 /* Q (input/output) REAL array, dimension (LDQ, N) */
95 /* On entry, Q must contain an N-by-N orthogonal matrix. */
96 /* If ICOMPQ = 0 Q is not referenced. */
97 /* If ICOMPQ = 1 On entry, Q is a subset of the columns of the */
98 /* orthogonal matrix used to reduce the full */
99 /* matrix to tridiagonal form corresponding to */
100 /* the subset of the full matrix which is being */
101 /* decomposed at this time. */
102 /* If ICOMPQ = 2 On entry, Q will be the identity matrix. */
103 /* On exit, Q contains the eigenvectors of the */
104 /* tridiagonal matrix. */
106 /* LDQ (input) INTEGER */
107 /* The leading dimension of the array Q. If eigenvectors are */
108 /* desired, then LDQ >= max(1,N). In any case, LDQ >= 1. */
110 /* QSTORE (workspace) REAL array, dimension (LDQS, N) */
111 /* Referenced only when ICOMPQ = 1. Used to store parts of */
112 /* the eigenvector matrix when the updating matrix multiplies */
115 /* LDQS (input) INTEGER */
116 /* The leading dimension of the array QSTORE. If ICOMPQ = 1, */
117 /* then LDQS >= max(1,N). In any case, LDQS >= 1. */
119 /* WORK (workspace) REAL array, */
120 /* If ICOMPQ = 0 or 1, the dimension of WORK must be at least */
121 /* 1 + 3*N + 2*N*lg N + 2*N**2 */
122 /* ( lg( N ) = smallest integer k */
123 /* such that 2^k >= N ) */
124 /* If ICOMPQ = 2, the dimension of WORK must be at least */
127 /* IWORK (workspace) INTEGER array, */
128 /* If ICOMPQ = 0 or 1, the dimension of IWORK must be at least */
129 /* 6 + 6*N + 5*N*lg N. */
130 /* ( lg( N ) = smallest integer k */
131 /* such that 2^k >= N ) */
132 /* If ICOMPQ = 2, the dimension of IWORK must be at least */
135 /* INFO (output) INTEGER */
136 /* = 0: successful exit. */
137 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
138 /* > 0: The algorithm failed to compute an eigenvalue while */
139 /* working on the submatrix lying in rows and columns */
140 /* INFO/(N+1) through mod(INFO,N+1). */
142 /* Further Details */
143 /* =============== */
145 /* Based on contributions by */
146 /* Jeff Rutter, Computer Science Division, University of California */
147 /* at Berkeley, USA */
149 /* ===================================================================== */
151 /* .. Parameters .. */
153 /* .. Local Scalars .. */
155 /* .. External Subroutines .. */
157 /* .. External Functions .. */
159 /* .. Intrinsic Functions .. */
161 /* .. Executable Statements .. */
163 /* Test the input parameters. */
165 /* Parameter adjustments */
169 q_offset = 1 + q_dim1;
172 qstore_offset = 1 + qstore_dim1;
173 qstore -= qstore_offset;
180 if (*icompq < 0 || *icompq > 2) {
182 } else if (*icompq == 1 && *qsiz < max(0,*n)) {
186 } else if (*ldq < max(1,*n)) {
188 } else if (*ldqs < max(1,*n)) {
193 xerbla_("SLAED0", &i__1);
197 /* Quick return if possible */
203 smlsiz = ilaenv_(&c__9, "SLAED0", " ", &c__0, &c__0, &c__0, &c__0);
205 /* Determine the size and placement of the submatrices, and save in */
206 /* the leading elements of IWORK. */
212 if (iwork[subpbs] > smlsiz) {
213 for (j = subpbs; j >= 1; --j) {
214 iwork[j * 2] = (iwork[j] + 1) / 2;
215 iwork[(j << 1) - 1] = iwork[j] / 2;
223 for (j = 2; j <= i__1; ++j) {
224 iwork[j] += iwork[j - 1];
228 /* Divide the matrix into SUBPBS submatrices of size at most SMLSIZ+1 */
229 /* using rank-1 modifications (cuts). */
233 for (i__ = 1; i__ <= i__1; ++i__) {
234 submat = iwork[i__] + 1;
236 d__[smm1] -= (r__1 = e[smm1], dabs(r__1));
237 d__[submat] -= (r__1 = e[smm1], dabs(r__1));
241 indxq = (*n << 2) + 3;
244 /* Set up workspaces for eigenvalues only/accumulate new vectors */
247 temp = log((real) (*n)) / log(2.f);
248 lgn = (integer) temp;
249 if (pow_ii(&c__2, &lgn) < *n) {
252 if (pow_ii(&c__2, &lgn) < *n) {
255 iprmpt = indxq + *n + 1;
256 iperm = iprmpt + *n * lgn;
257 iqptr = iperm + *n * lgn;
258 igivpt = iqptr + *n + 2;
259 igivcl = igivpt + *n * lgn;
262 iq = igivnm + (*n << 1) * lgn;
263 /* Computing 2nd power */
265 iwrem = iq + i__1 * i__1 + 1;
267 /* Initialize pointers */
270 for (i__ = 0; i__ <= i__1; ++i__) {
271 iwork[iprmpt + i__] = 1;
272 iwork[igivpt + i__] = 1;
278 /* Solve each submatrix eigenproblem at the bottom of the divide and */
283 for (i__ = 0; i__ <= i__1; ++i__) {
288 submat = iwork[i__] + 1;
289 matsiz = iwork[i__ + 1] - iwork[i__];
292 ssteqr_("I", &matsiz, &d__[submat], &e[submat], &q[submat +
293 submat * q_dim1], ldq, &work[1], info);
298 ssteqr_("I", &matsiz, &d__[submat], &e[submat], &work[iq - 1 +
299 iwork[iqptr + curr]], &matsiz, &work[1], info);
304 sgemm_("N", "N", qsiz, &matsiz, &matsiz, &c_b23, &q[submat *
305 q_dim1 + 1], ldq, &work[iq - 1 + iwork[iqptr + curr]],
306 &matsiz, &c_b24, &qstore[submat * qstore_dim1 + 1],
309 /* Computing 2nd power */
311 iwork[iqptr + curr + 1] = iwork[iqptr + curr] + i__2 * i__2;
315 i__2 = iwork[i__ + 1];
316 for (j = submat; j <= i__2; ++j) {
317 iwork[indxq + j] = k;
324 /* Successively merge eigensystems of adjacent submatrices */
325 /* into eigensystem for the corresponding larger matrix. */
327 /* while ( SUBPBS > 1 ) */
334 for (i__ = 0; i__ <= i__1; i__ += 2) {
341 submat = iwork[i__] + 1;
342 matsiz = iwork[i__ + 2] - iwork[i__];
347 /* Merge lower order eigensystems (of size MSD2 and MATSIZ - MSD2) */
348 /* into an eigensystem of size MATSIZ. */
349 /* SLAED1 is used only for the full eigensystem of a tridiagonal */
351 /* SLAED7 handles the cases in which eigenvalues only or eigenvalues */
352 /* and eigenvectors of a full symmetric matrix (which was reduced to */
353 /* tridiagonal form) are desired. */
356 slaed1_(&matsiz, &d__[submat], &q[submat + submat * q_dim1],
357 ldq, &iwork[indxq + submat], &e[submat + msd2 - 1], &
358 msd2, &work[1], &iwork[subpbs + 1], info);
360 slaed7_(icompq, &matsiz, qsiz, &tlvls, &curlvl, &curprb, &d__[
361 submat], &qstore[submat * qstore_dim1 + 1], ldqs, &
362 iwork[indxq + submat], &e[submat + msd2 - 1], &msd2, &
363 work[iq], &iwork[iqptr], &iwork[iprmpt], &iwork[iperm]
364 , &iwork[igivpt], &iwork[igivcl], &work[igivnm], &
365 work[iwrem], &iwork[subpbs + 1], info);
370 iwork[i__ / 2 + 1] = iwork[i__ + 2];
380 /* Re-merge the eigenvalues/vectors which were deflated at the final */
385 for (i__ = 1; i__ <= i__1; ++i__) {
386 j = iwork[indxq + i__];
388 scopy_(qsiz, &qstore[j * qstore_dim1 + 1], &c__1, &q[i__ * q_dim1
392 scopy_(n, &work[1], &c__1, &d__[1], &c__1);
393 } else if (*icompq == 2) {
395 for (i__ = 1; i__ <= i__1; ++i__) {
396 j = iwork[indxq + i__];
398 scopy_(n, &q[j * q_dim1 + 1], &c__1, &work[*n * i__ + 1], &c__1);
401 scopy_(n, &work[1], &c__1, &d__[1], &c__1);
402 slacpy_("A", n, n, &work[*n + 1], n, &q[q_offset], ldq);
405 for (i__ = 1; i__ <= i__1; ++i__) {
406 j = iwork[indxq + i__];
410 scopy_(n, &work[1], &c__1, &d__[1], &c__1);
415 *info = submat * (*n + 1) + submat + matsiz - 1;