📄 zstedc.c
字号:
lwmin = *n * *n;
/* Computing 2nd power */
i__1 = *n;
lrwmin = *n * 3 + 1 + (*n << 1) * lgn + i__1 * i__1 * 3;
liwmin = *n * 6 + 6 + *n * 5 * lgn;
} else if (icompz == 2) {
lwmin = 1;
/* Computing 2nd power */
i__1 = *n;
lrwmin = (*n << 2) + 1 + (i__1 * i__1 << 1);
liwmin = *n * 5 + 3;
}
}
if (icompz < 0) {
*info = -1;
} else if (*n < 0) {
*info = -2;
} else if (*ldz < 1 || icompz > 0 && *ldz < max(1,*n)) {
*info = -6;
} else if (*lwork < lwmin && ! lquery) {
*info = -8;
} else if (*lrwork < lrwmin && ! lquery) {
*info = -10;
} else if (*liwork < liwmin && ! lquery) {
*info = -12;
}
if (*info == 0) {
work[1].r = (doublereal) lwmin, work[1].i = 0.;
rwork[1] = (doublereal) lrwmin;
iwork[1] = liwmin;
}
if (*info != 0) {
i__1 = -(*info);
xerbla_("ZSTEDC", &i__1);
return 0;
} else if (lquery) {
return 0;
}
/* Quick return if possible */
latime_1.itcnt = 0.;
if (*n == 0) {
return 0;
}
if (*n == 1) {
if (icompz != 0) {
i__1 = z___subscr(1, 1);
z__[i__1].r = 1., z__[i__1].i = 0.;
}
return 0;
}
smlsiz = ilaenv_(&c__9, "ZSTEDC", " ", &c__0, &c__0, &c__0, &c__0, (
ftnlen)6, (ftnlen)1);
/* If the following conditional clause is removed, then the routine
will use the Divide and Conquer routine to compute only the
eigenvalues, which requires (3N + 3N**2) real workspace and
(2 + 5N + 2N lg(N)) integer workspace.
Since on many architectures DSTERF is much faster than any other
algorithm for finding eigenvalues only, it is used here
as the default.
If COMPZ = 'N', use DSTERF to compute the eigenvalues. */
if (icompz == 0) {
dsterf_(n, &d__[1], &e[1], info);
return 0;
}
/* If N is smaller than the minimum divide size (SMLSIZ+1), then
solve the problem with another solver. */
if (*n <= smlsiz) {
if (icompz == 0) {
dsterf_(n, &d__[1], &e[1], info);
return 0;
} else if (icompz == 2) {
zsteqr_("I", n, &d__[1], &e[1], &z__[z_offset], ldz, &rwork[1],
info);
return 0;
} else {
zsteqr_("V", n, &d__[1], &e[1], &z__[z_offset], ldz, &rwork[1],
info);
return 0;
}
}
/* If COMPZ = 'I', we simply call DSTEDC instead. */
if (icompz == 2) {
dlaset_("Full", n, n, &c_b18, &c_b19, &rwork[1], n);
ll = *n * *n + 1;
i__1 = *lrwork - ll + 1;
dstedc_("I", n, &d__[1], &e[1], &rwork[1], n, &rwork[ll], &i__1, &
iwork[1], liwork, info);
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
i__2 = *n;
for (i__ = 1; i__ <= i__2; ++i__) {
i__3 = z___subscr(i__, j);
i__4 = (j - 1) * *n + i__;
z__[i__3].r = rwork[i__4], z__[i__3].i = 0.;
/* L10: */
}
/* L20: */
}
return 0;
}
/* From now on, only option left to be handled is COMPZ = 'V',
i.e. ICOMPZ = 1.
Scale. */
orgnrm = dlanst_("M", n, &d__[1], &e[1]);
if (orgnrm == 0.) {
return 0;
}
eps = dlamch_("Epsilon");
start = 1;
/* while ( START <= N ) */
L30:
if (start <= *n) {
/* Let END be the position of the next subdiagonal entry such that
E( END ) <= TINY or END = N if no such subdiagonal exists. The
matrix identified by the elements between START and END
constitutes an independent sub-problem. */
end = start;
L40:
if (end < *n) {
latime_1.ops += 4;
tiny = eps * sqrt((d__1 = d__[end], abs(d__1))) * sqrt((d__2 =
d__[end + 1], abs(d__2)));
if ((d__1 = e[end], abs(d__1)) > tiny) {
++end;
goto L40;
}
}
/* (Sub) Problem determined. Compute its size and solve it. */
m = end - start + 1;
if (m > smlsiz) {
*info = smlsiz;
/* Scale. */
orgnrm = dlanst_("M", &m, &d__[start], &e[start]);
latime_1.ops = latime_1.ops + (m << 1) - 1;
dlascl_("G", &c__0, &c__0, &orgnrm, &c_b19, &m, &c__1, &d__[start]
, &m, info);
i__1 = m - 1;
i__2 = m - 1;
dlascl_("G", &c__0, &c__0, &orgnrm, &c_b19, &i__1, &c__1, &e[
start], &i__2, info);
zlaed0_(n, &m, &d__[start], &e[start], &z___ref(1, start), ldz, &
work[1], n, &rwork[1], &iwork[1], info);
if (*info > 0) {
*info = (*info / (m + 1) + start - 1) * (*n + 1) + *info % (m
+ 1) + start - 1;
return 0;
}
/* Scale back. */
latime_1.ops += m;
dlascl_("G", &c__0, &c__0, &c_b19, &orgnrm, &m, &c__1, &d__[start]
, &m, info);
} else {
dsteqr_("I", &m, &d__[start], &e[start], &rwork[1], &m, &rwork[m *
m + 1], info);
latime_1.ops += (doublereal) (*n) * 4 * m * m;
zlacrm_(n, &m, &z___ref(1, start), ldz, &rwork[1], &m, &work[1],
n, &rwork[m * m + 1]);
zlacpy_("A", n, &m, &work[1], n, &z___ref(1, start), ldz);
if (*info > 0) {
*info = start * (*n + 1) + end;
return 0;
}
}
start = end + 1;
goto L30;
}
/* endwhile
If the problem split any number of times, then the eigenvalues
will not be properly ordered. Here we permute the eigenvalues
(and the associated eigenvectors) into ascending order. */
if (m != *n) {
/* Use Selection Sort to minimize swaps of eigenvectors */
i__1 = *n;
for (ii = 2; ii <= i__1; ++ii) {
i__ = ii - 1;
k = i__;
p = d__[i__];
i__2 = *n;
for (j = ii; j <= i__2; ++j) {
if (d__[j] < p) {
k = j;
p = d__[j];
}
/* L50: */
}
if (k != i__) {
d__[k] = d__[i__];
d__[i__] = p;
zswap_(n, &z___ref(1, i__), &c__1, &z___ref(1, k), &c__1);
}
/* L60: */
}
}
work[1].r = (doublereal) lwmin, work[1].i = 0.;
rwork[1] = (doublereal) lrwmin;
iwork[1] = liwmin;
return 0;
/* End of ZSTEDC */
} /* zstedc_ */
#undef z___ref
#undef z___subscr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -