📄 svd.java
字号:
// kase = 4 if e(p-1) is negligible (convergence).
for (k = p - 2; k >= -1; k--) {
if (k == -1) {
break;
}
if (Math.abs(e[k]) <=
tiny + eps * (Math.abs(s[k]) + Math.abs(s[k + 1]))) {
e[k] = 0.0;
break;
}
}
if (k == p - 2) {
kase = 4;
} else {
int ks;
for (ks = p - 1; ks >= k; ks--) {
if (ks == k) {
break;
}
double t = (ks != p ? Math.abs(e[ks]) : 0.) +
(ks != k + 1 ? Math.abs(e[ks - 1]) : 0.);
if (Math.abs(s[ks]) <= tiny + eps * t) {
s[ks] = 0.0;
break;
}
}
if (ks == k) {
kase = 3;
} else if (ks == p - 1) {
kase = 1;
} else {
kase = 2;
k = ks;
}
}
k++;
// Perform the task indicated by kase.
switch (kase) {
// Deflate negligible s(p).
case 1: {
double f = e[p - 2];
e[p - 2] = 0.0;
for (int j = p - 2; j >= k; j--) {
double t = hypot(s[j], f);
double cs = s[j] / t;
double sn = f / t;
s[j] = t;
if (j != k) {
f = -sn * e[j - 1];
e[j - 1] = cs * e[j - 1];
}
if (wantv) {
for (int i = 0; i < n; i++) {
t = cs * V[i][j] + sn * V[i][p - 1];
V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1];
V[i][j] = t;
}
}
}
}
break;
// Split at negligible s(k).
case 2: {
double f = e[k - 1];
e[k - 1] = 0.0;
for (int j = k; j < p; j++) {
double t = hypot(s[j], f);
double cs = s[j] / t;
double sn = f / t;
s[j] = t;
f = -sn * e[j];
e[j] = cs * e[j];
if (wantu) {
for (int i = 0; i < m; i++) {
t = cs * U[i][j] + sn * U[i][k - 1];
U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1];
U[i][j] = t;
}
}
}
}
break;
// Perform one qr step.
case 3: {
// Calculate the shift.
double scale = Math.max(Math.max(Math.max(Math.max(
Math.abs(s[p - 1]), Math.abs(s[p - 2])), Math.abs(e[p - 2])),
Math.abs(s[k])), Math.abs(e[k]));
double sp = s[p - 1] / scale;
double spm1 = s[p - 2] / scale;
double epm1 = e[p - 2] / scale;
double sk = s[k] / scale;
double ek = e[k] / scale;
double b = ( (spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0;
double c = (sp * epm1) * (sp * epm1);
double shift = 0.0;
if ( (b != 0.0) | (c != 0.0)) {
shift = Math.sqrt(b * b + c);
if (b < 0.0) {
shift = -shift;
}
shift = c / (b + shift);
}
double f = (sk + sp) * (sk - sp) + shift;
double g = sk * ek;
// Chase zeros.
for (int j = k; j < p - 1; j++) {
double t = hypot(f, g);
double cs = f / t;
double sn = g / t;
if (j != k) {
e[j - 1] = t;
}
f = cs * s[j] + sn * e[j];
e[j] = cs * e[j] - sn * s[j];
g = sn * s[j + 1];
s[j + 1] = cs * s[j + 1];
if (wantv) {
for (int i = 0; i < n; i++) {
t = cs * V[i][j] + sn * V[i][j + 1];
V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1];
V[i][j] = t;
}
}
t = hypot(f, g);
cs = f / t;
sn = g / t;
s[j] = t;
f = cs * e[j] + sn * s[j + 1];
s[j + 1] = -sn * e[j] + cs * s[j + 1];
g = sn * e[j + 1];
e[j + 1] = cs * e[j + 1];
if (wantu && (j < m - 1)) {
for (int i = 0; i < m; i++) {
t = cs * U[i][j] + sn * U[i][j + 1];
U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1];
U[i][j] = t;
}
}
}
e[p - 2] = f;
iter = iter + 1;
}
break;
// Convergence.
case 4: {
// Make the singular values positive.
if (s[k] <= 0.0) {
s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
if (wantv) {
for (int i = 0; i <= pp; i++) {
V[i][k] = -V[i][k];
}
}
}
// Order the singular values.
while (k < pp) {
if (s[k] >= s[k + 1]) {
break;
}
double t = s[k];
s[k] = s[k + 1];
s[k + 1] = t;
if (wantv && (k < n - 1)) {
for (int i = 0; i < n; i++) {
t = V[i][k + 1];
V[i][k + 1] = V[i][k];
V[i][k] = t;
}
}
if (wantu && (k < m - 1)) {
for (int i = 0; i < m; i++) {
t = U[i][k + 1];
U[i][k + 1] = U[i][k];
U[i][k] = t;
}
}
k++;
}
iter = 0;
p--;
}
break;
}
}
}
/** Return the left singular vectors
@return U
*/
public DoubleDenseMatrix getLeftMatrix() {
DoubleDenseMatrix ddm;
double[][] newMatrix;
int rows, columns, i, j;
rows = m;
columns = Math.min(dimension, n);
newMatrix = new double[rows][columns];
for (i = 0; i < rows; i++)
for (j = 0; j < columns; j++)
newMatrix[i][j] = U[i][j];
ddm = new DoubleFlatDenseMatrix(newMatrix);
return ddm;
}
/** Return the right singular vectors
@return V
*/
public DoubleDenseMatrix getRightMatrix() {
DoubleDenseMatrix ddm;
double[][] newMatrix;
int i, j, len;
len = Math.min(dimension, n);
newMatrix = new double[len][n];
for (i = 0; i < len; i++)
for (j = 0; j < n; j++)
newMatrix[i][j] = V[i][j];
ddm = new DoubleFlatDenseMatrix(newMatrix);
return ddm;
}
/** Return the one-dimensional array of singular values
@return diagonal of S.
*/
public double[] getSingularValues() {
int len, i;
double sv[];
len = Math.min(dimension, s.length);
sv = new double[len];
for (i = 0; i < len; i++)
sv[i] = s[i];
return sv;
}
/** Return the diagonal matrix of singular values
@return S
*/
public DoubleDenseMatrix getMiddleMatrix() {
int i, len;
len = Math.min(dimension, s.length);
DoubleDenseMatrix x = new DoubleFlatDenseMatrix(len, len);
for (i = 0; i < len; i++)
x.setDouble(i, i, this.s[i]);
return x;
}
/** sqrt(a^2 + b^2) without under/overflow. **/
private double hypot(double a, double b) {
double r;
if (Math.abs(a) > Math.abs(b)) {
r = b / a;
r = Math.abs(a) * Math.sqrt(1 + r * r);
} else if (b != 0) {
r = a / b;
r = Math.abs(b) * Math.sqrt(1 + r * r);
} else {
r = 0.0;
}
return r;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -