📄 bdsvd.cpp
字号:
applyrotationsfromtheright(fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work2, work3, u, utemp);
}
if( ncc>0 )
{
applyrotationsfromtheleft(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work2, work3, c, ctemp);
}
//
// Test convergence
//
if( fabs(e(m-1))<=thresh )
{
e(m-1) = 0;
}
}
else
{
//
// Chase bulge from bottom to top
// Save cosines and sines for later singular vector updates
//
f = (fabs(d(m))-shift)*(extsignbdsqr(double(1), d(m))+shift/d(m));
g = e(m-1);
for(i = m; i >= ll+1; i--)
{
generaterotation(f, g, cosr, sinr, r);
if( i<m )
{
e(i) = r;
}
f = cosr*d(i)+sinr*e(i-1);
e(i-1) = cosr*e(i-1)-sinr*d(i);
g = sinr*d(i-1);
d(i-1) = cosr*d(i-1);
generaterotation(f, g, cosl, sinl, r);
d(i) = r;
f = cosl*e(i-1)+sinl*d(i-1);
d(i-1) = cosl*d(i-1)-sinl*e(i-1);
if( i>ll+1 )
{
g = sinl*e(i-2);
e(i-2) = cosl*e(i-2);
}
work0(i-ll) = cosr;
work1(i-ll) = -sinr;
work2(i-ll) = cosl;
work3(i-ll) = -sinl;
}
e(ll) = f;
//
// Test convergence
//
if( fabs(e(ll))<=thresh )
{
e(ll) = 0;
}
//
// Update singular vectors if desired
//
if( ncvt>0 )
{
applyrotationsfromtheleft(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, work2, work3, vt, vttemp);
}
if( nru>0 )
{
applyrotationsfromtheright(!fwddir, ustart, uend, ll+ustart-1, m+ustart-1, work0, work1, u, utemp);
}
if( ncc>0 )
{
applyrotationsfromtheleft(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, work0, work1, c, ctemp);
}
}
}
//
// QR iteration finished, go back and check convergence
//
continue;
}
//
// All singular values converged, so make them positive
//
for(i = 1; i <= n; i++)
{
if( d(i)<0 )
{
d(i) = -d(i);
//
// Change sign of singular vectors, if desired
//
if( ncvt>0 )
{
ap::vmul(&vt(i+vstart-1, vstart), ap::vlen(vstart,vend), -1);
}
}
}
//
// Sort the singular values into decreasing order (insertion sort on
// singular values, but only one transposition per singular vector)
//
for(i = 1; i <= n-1; i++)
{
//
// Scan for smallest D(I)
//
isub = 1;
smin = d(1);
for(j = 2; j <= n+1-i; j++)
{
if( d(j)<=smin )
{
isub = j;
smin = d(j);
}
}
if( isub!=n+1-i )
{
//
// Swap singular values and vectors
//
d(isub) = d(n+1-i);
d(n+1-i) = smin;
if( ncvt>0 )
{
j = n+1-i;
ap::vmove(&vttemp(vstart), &vt(isub+vstart-1, vstart), ap::vlen(vstart,vend));
ap::vmove(&vt(isub+vstart-1, vstart), &vt(j+vstart-1, vstart), ap::vlen(vstart,vend));
ap::vmove(&vt(j+vstart-1, vstart), &vttemp(vstart), ap::vlen(vstart,vend));
}
if( nru>0 )
{
j = n+1-i;
ap::vmove(utemp.getvector(ustart, uend), u.getcolumn(isub+ustart-1, ustart, uend));
ap::vmove(u.getcolumn(isub+ustart-1, ustart, uend), u.getcolumn(j+ustart-1, ustart, uend));
ap::vmove(u.getcolumn(j+ustart-1, ustart, uend), utemp.getvector(ustart, uend));
}
if( ncc>0 )
{
j = n+1-i;
ap::vmove(&ctemp(cstart), &c(isub+cstart-1, cstart), ap::vlen(cstart,cend));
ap::vmove(&c(isub+cstart-1, cstart), &c(j+cstart-1, cstart), ap::vlen(cstart,cend));
ap::vmove(&c(j+cstart-1, cstart), &ctemp(cstart), ap::vlen(cstart,cend));
}
}
}
return result;
}
double extsignbdsqr(double a, double b)
{
double result;
if( b>=0 )
{
result = fabs(a);
}
else
{
result = -fabs(a);
}
return result;
}
void svd2x2(double f, double g, double h, double& ssmin, double& ssmax)
{
double aas;
double at;
double au;
double c;
double fa;
double fhmn;
double fhmx;
double ga;
double ha;
fa = fabs(f);
ga = fabs(g);
ha = fabs(h);
fhmn = ap::minreal(fa, ha);
fhmx = ap::maxreal(fa, ha);
if( fhmn==0 )
{
ssmin = 0;
if( fhmx==0 )
{
ssmax = ga;
}
else
{
ssmax = ap::maxreal(fhmx, ga)*sqrt(1+ap::sqr(ap::minreal(fhmx, ga)/ap::maxreal(fhmx, ga)));
}
}
else
{
if( ga<fhmx )
{
aas = 1+fhmn/fhmx;
at = (fhmx-fhmn)/fhmx;
au = ap::sqr(ga/fhmx);
c = 2/(sqrt(aas*aas+au)+sqrt(at*at+au));
ssmin = fhmn*c;
ssmax = fhmx/c;
}
else
{
au = fhmx/ga;
if( au==0 )
{
//
// Avoid possible harmful underflow if exponent range
// asymmetric (true SSMIN may not underflow even if
// AU underflows)
//
ssmin = fhmn*fhmx/ga;
ssmax = ga;
}
else
{
aas = 1+fhmn/fhmx;
at = (fhmx-fhmn)/fhmx;
c = 1/(sqrt(1+ap::sqr(aas*au))+sqrt(1+ap::sqr(at*au)));
ssmin = fhmn*c*au;
ssmin = ssmin+ssmin;
ssmax = ga/(c+c);
}
}
}
}
void svdv2x2(double f,
double g,
double h,
double& ssmin,
double& ssmax,
double& snr,
double& csr,
double& snl,
double& csl)
{
bool gasmal;
bool swp;
int pmax;
double a;
double clt;
double crt;
double d;
double fa;
double ft;
double ga;
double gt;
double ha;
double ht;
double l;
double m;
double mm;
double r;
double s;
double slt;
double srt;
double t;
double temp;
double tsign;
double tt;
double v;
ft = f;
fa = fabs(ft);
ht = h;
ha = fabs(h);
//
// PMAX points to the maximum absolute element of matrix
// PMAX = 1 if F largest in absolute values
// PMAX = 2 if G largest in absolute values
// PMAX = 3 if H largest in absolute values
//
pmax = 1;
swp = ha>fa;
if( swp )
{
//
// Now FA .ge. HA
//
pmax = 3;
temp = ft;
ft = ht;
ht = temp;
temp = fa;
fa = ha;
ha = temp;
}
gt = g;
ga = fabs(gt);
if( ga==0 )
{
//
// Diagonal matrix
//
ssmin = ha;
ssmax = fa;
clt = 1;
crt = 1;
slt = 0;
srt = 0;
}
else
{
gasmal = true;
if( ga>fa )
{
pmax = 2;
if( fa/ga<ap::machineepsilon )
{
//
// Case of very large GA
//
gasmal = false;
ssmax = ga;
if( ha>1 )
{
v = ga/ha;
ssmin = fa/v;
}
else
{
v = fa/ga;
ssmin = v*ha;
}
clt = 1;
slt = ht/gt;
srt = 1;
crt = ft/gt;
}
}
if( gasmal )
{
//
// Normal case
//
d = fa-ha;
if( d==fa )
{
l = 1;
}
else
{
l = d/fa;
}
m = gt/ft;
t = 2-l;
mm = m*m;
tt = t*t;
s = sqrt(tt+mm);
if( l==0 )
{
r = fabs(m);
}
else
{
r = sqrt(l*l+mm);
}
a = 0.5*(s+r);
ssmin = ha/a;
ssmax = fa*a;
if( mm==0 )
{
//
// Note that M is very tiny
//
if( l==0 )
{
t = extsignbdsqr(double(2), ft)*extsignbdsqr(double(1), gt);
}
else
{
t = gt/extsignbdsqr(d, ft)+m/t;
}
}
else
{
t = (m/(s+t)+m/(r+l))*(1+a);
}
l = sqrt(t*t+4);
crt = 2/l;
srt = t/l;
clt = (crt+srt*m)/a;
v = ht/ft;
slt = v*srt/a;
}
}
if( swp )
{
csl = srt;
snl = crt;
csr = slt;
snr = clt;
}
else
{
csl = clt;
snl = slt;
csr = crt;
snr = srt;
}
//
// Correct signs of SSMAX and SSMIN
//
if( pmax==1 )
{
tsign = extsignbdsqr(double(1), csr)*extsignbdsqr(double(1), csl)*extsignbdsqr(double(1), f);
}
if( pmax==2 )
{
tsign = extsignbdsqr(double(1), snr)*extsignbdsqr(double(1), csl)*extsignbdsqr(double(1), g);
}
if( pmax==3 )
{
tsign = extsignbdsqr(double(1), snr)*extsignbdsqr(double(1), snl)*extsignbdsqr(double(1), h);
}
ssmax = extsignbdsqr(ssmax, tsign);
ssmin = extsignbdsqr(ssmin, tsign*extsignbdsqr(double(1), f)*extsignbdsqr(double(1), h));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -