📄 zsvdc.c
字号:
L120:
if (wantv)
for (i = l+1; i < *p; ++i) {
i__1 = i + l * *ldv; /* index [i,l] */
v[i__1].r = e[i].r, v[i__1].i = e[i].i;
}
}
/* set up the final bidiagonal matrix or order m. */
m = min(*p-1, *n);
if (nct < *p) {
i__1 = nct * (*ldx+1); /* index [nct,nct] */
s[nct].r = x[i__1].r, s[nct].i = x[i__1].i;
}
if (*n-1 < m) {
s[m].r = 0., s[m].i = 0.;
}
if (nrt < m) {
i__1 = nrt + m * *ldx; /* index [nrt,m] */
e[nrt].r = x[i__1].r, e[nrt].i = x[i__1].i;
}
e[m].r = 0., e[m].i = 0.;
/* if required, generate u. */
if (wantu)
for (j = nct; j < ncu; ++j) {
for (i = 0; i < *n; ++i) {
i__1 = i + j * *ldu; /* index [i,j] */
u[i__1].r = 0., u[i__1].i = 0.;
}
i__1 = j + j * *ldu; /* index [j,j] */
u[i__1].r = 1., u[i__1].i = 0.;
}
if (wantu)
for (l = nct-1; l >= 0; --l) {
if (s[l].r == 0. && s[l].i == 0.) {
for (i = 0; i < *n; ++i) {
i__1 = i + l * *ldu; /* index [i,l] */
u[i__1].r = 0., u[i__1].i = 0.;
}
i__1 = l + l * *ldu; /* index [l,l] */
u[i__1].r = 1., u[i__1].i = 0.;
continue; /* next l */
}
i__1 = *n - l;
i__2 = l + l * *ldu; /* index [l,l] */
for (j = l+1; j < ncu; ++j) {
zdotc_(&t, &i__1, &u[i__2], &c__1, &u[l+j* *ldu], &c__1);
t.r = -t.r, t.i = -t.i;
z_div(&t, &t, &u[i__2]);
zaxpy_(&i__1, &t, &u[i__2], &c__1, &u[l+j* *ldu], &c__1);
}
zscal_(&i__1, &c_m1, &u[i__2], &c__1);
u[i__2].r += 1.;
for (i = 0; i < l; ++i) {
i__1 = i + l * *ldu; /* index [i,l] */
u[i__1].r = 0., u[i__1].i = 0.;
}
}
/* if it is required, generate v. */
if (wantv)
for (l = *p-1; l >= 0; --l) {
if (l < nrt && (e[l].r != 0. || e[l].i != 0.))
for (j = l+1; j < *p; ++j) {
i__1 = *p - l - 1;
i__2 = l+1 + l * *ldv; /* index [l+1,l] */
zdotc_(&t, &i__1, &v[i__2], &c__1, &v[l+1 +j* *ldv], &c__1);
t.r = -t.r, t.i = -t.i;
z_div(&t, &t, &v[i__2]);
zaxpy_(&i__1, &t, &v[i__2], &c__1, &v[l+1 +j* *ldv], &c__1);
}
for (i = 0; i < *p; ++i) {
i__1 = i + l * *ldv; /* index [i,l] */
v[i__1].r = 0., v[i__1].i = 0.;
}
i__1 = l + l * *ldv; /* index [l,l] */
v[i__1].r = 1., v[i__1].i = 0.;
}
/* transform s and e so that they are double precision. */
for (i = 0; i <= m; ++i) {
if (s[i].r != 0. || s[i].i != 0.) {
t.r = z_abs(&s[i]), t.i = 0.;
z_div(&r, &s[i], &t);
s[i].r = t.r, s[i].i = t.i;
if (i < m) {
z_div(&e[i], &e[i], &r);
}
if (wantu) {
zscal_(n, &r, &u[i* *ldu], &c__1);
}
}
if (i == m) {
break; /* last i */
}
if (e[i].r == 0. && e[i].i == 0.) {
continue; /* next i */
}
t.r = z_abs(&e[i]), t.i = 0.;
z_div(&r, &t, &e[i]);
e[i].r = t.r, e[i].i = t.i;
z__1.r = s[i+1].r * r.r - s[i+1].i * r.i,
z__1.i = s[i+1].r * r.i + s[i+1].i * r.r;
s[i+1].r = z__1.r, s[i+1].i = z__1.i;
if (wantv) {
zscal_(p, &r, &v[(i+1)* *ldv], &c__1);
}
}
/* main iteration loop for the singular values. */
mm = m;
iter = 0;
/* quit if all the singular values have been found. */
L400:
if (m == -1) {
return; /* exit from zsvdc */
}
/* if too many iterations have been performed, set */
/* flag and return. */
if (iter >= maxit) {
*info = m+1;
return; /* exit from zsvdc */
}
/* this section of the program inspects for */
/* negligible elements in the s and e arrays. on */
/* completion the variables kase and l are set as follows. */
/* kase = 1 if s(m) and e(l-1) are negligible and l.lt.m */
/* kase = 2 if s(l) is negligible and l.lt.m */
/* kase = 3 if e(l-1) is negligible, l.lt.m, and */
/* s(l), ..., s(m) are not negligible (qr step). */
/* kase = 4 if e(m-1) is negligible (convergence). */
for (l = m; l > 0; --l) {
test = z_abs(&s[l-1]) + z_abs(&s[l]);
ztest = test + z_abs(&e[l-1]);
if (fsm_ieee_doubles_equal(&ztest, &test)) {
/* WAS: if (ztest == test) { */
e[l-1].r = 0., e[l-1].i = 0.;
break; /* last l */
}
}
if (l == m) { /* kase = 4 */ /* convergence. */
/* make the singular value positive */
if (s[l].r < 0.) {
s[l].r = -s[l].r, s[l].i = -s[l].i;
if (wantv) {
zscal_(p, &c_m1, &v[l* *ldv], &c__1);
}
}
/* order the singular value. */
while (l != mm && s[l].r < s[l+1].r) {
t.r = s[l].r, t.i = s[l].i;
s[l].r = s[l+1].r, s[l].i = s[l+1].i;
s[l+1].r = t.r, s[l+1].i = t.i;
if (wantv && l < *p-1) {
zswap_(p, &v[l* *ldv], &c__1, &v[(l+1)* *ldv], &c__1);
}
if (wantu && l < *n-1) {
zswap_(n, &u[l* *ldu], &c__1, &u[(l+1)* *ldu], &c__1);
}
++l;
}
iter = 0;
--m;
goto L400;
}
for (ls = m; ls >= l; --ls) {
test = 0.;
if (ls != m) {
test += z_abs(&e[ls]);
}
if (ls != l) {
test += z_abs(&e[ls-1]);
}
ztest = test + z_abs(&s[ls]);
if (fsm_ieee_doubles_equal(&ztest, &test)) {
/* WAS: if (ztest == test) { */
s[ls].r = 0., s[ls].i = 0.;
break; /* last ls */
}
}
if (ls == l-1) { /* kase = 3 */ /* perform one qr step. */
/* calculate the shift. */
scale = z_abs(&s[m]),
scale = max(scale, z_abs(&s[m-1])),
scale = max(scale, z_abs(&e[m-1])),
scale = max(scale, z_abs(&s[l])),
scale = max(scale, z_abs(&e[l]));
sm = s[m].r / scale;
smm1 = s[m-1].r / scale;
emm1 = e[m-1].r / scale;
sl = s[l].r / scale;
el = e[l].r / scale;
b = ((smm1+sm) * (smm1-sm) + emm1*emm1) / 2.;
c = sm * emm1; c *= c;
shift = 0.;
if (b != 0. || c != 0.) {
shift = sqrt(b*b + c);
if (b < 0.) {
shift = -shift;
}
shift = c / (b + shift);
}
f = (sl + sm) * (sl - sm) + shift;
g = sl * el;
/* chase zeros. */
for (k = l; k < m; ++k) {
drotg_(&f, &g, &cs, &sn);
if (k != l) {
e[k-1].r = f, e[k-1].i = 0.;
}
f = cs * s[k].r + sn * e[k].r;
e[k].r = cs * e[k].r - sn * s[k].r,
e[k].i = cs * e[k].i - sn * s[k].i;
g = sn * s[k+1].r;
s[k+1].r *= cs, s[k+1].i *= cs;
if (wantv) {
zdrot_(p, &v[k* *ldv], &c__1, &v[(k+1)* *ldv], &c__1, &cs, &sn);
}
drotg_(&f, &g, &cs, &sn);
s[k].r = f, s[k].i = 0.;
f = cs * e[k].r + sn * s[k+1].r;
s[k+1].r = -sn * e[k].r + cs * s[k+1].r,
s[k+1].i = -sn * e[k].i + cs * s[k+1].i;
g = sn * e[k+1].r;
e[k+1].r *= cs, e[k+1].i *= cs;
if (wantu && k < *n-1) {
zdrot_(n, &u[k* *ldu], &c__1, &u[(k+1)* *ldu], &c__1, &cs, &sn);
}
}
e[m-1].r = f, e[m-1].i = 0.;
++iter;
}
else if (ls == m) { /* kase = 1 */ /* deflate negligible s(m). */
f = e[m-1].r;
e[m-1].r = 0., e[m-1].i = 0.;
for (k = m-1; k >= l; --k) {
t1 = s[k].r;
drotg_(&t1, &f, &cs, &sn);
s[k].r = t1, s[k].i = 0.;
if (k != l) {
f = -sn * e[k-1].r;
e[k-1].r *= cs, e[k-1].i *= cs;
}
if (wantv) {
zdrot_(p, &v[k* *ldv], &c__1, &v[m* *ldv], &c__1, &cs, &sn);
}
}
}
else { /* kase = 2 */ /* split at negligible s(l). */
/* l = ls + 1; */
f = e[ls].r;
e[ls].r = 0., e[ls].i = 0.;
for (k = ls+1; k <= m; ++k) {
t1 = s[k].r;
drotg_(&t1, &f, &cs, &sn);
s[k].r = t1, s[k].i = 0.;
f = -sn * e[k].r;
e[k].r *= cs, e[k].i *= cs;
if (wantu) {
zdrot_(n, &u[k* *ldu], &c__1, &u[ls* *ldu], &c__1, &cs, &sn);
}
}
}
goto L400;
} /* zsvdc_ */
int fsm_ieee_doubles_equal(const double *x, const double *y)
{
return *x == *y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -