using System.Collections;
namespace VisualMath.Accord.Math.Decompositions
{
using System;
///
= -1; k--)
{
if (k == -1)
break;
if (System.Math.Abs(e[k]) <=
tiny + eps * (System.Math.Abs(s[k]) + System.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 ? System.Math.Abs(e[ks]) : 0.0) +
(ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0.0);
if (System.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 = Accord.Math.Tools.Hypotenuse(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 = Accord.Math.Tools.Hypotenuse(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 = System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Max(System.Math.Abs(s[p - 1]), System.Math.Abs(s[p - 2])), System.Math.Abs(e[p - 2])), System.Math.Abs(s[k])), System.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))
{
if (b < 0.0)
shift = -System.Math.Sqrt(b * b + c);
else
shift = System.Math.Sqrt(b * b + c);
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 = Accord.Math.Tools.Hypotenuse(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)
{
unsafe
{
fixed (double* ptr_vj = &v[0, j])
{
double* vj = ptr_vj;
double* vj1 = ptr_vj + 1;
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;*/
double vij = *vj;
double vij1 = *vj1;
t = cs * vij + sn * vij1;
*vj1 = -sn * vij + cs * vij1;
*vj = t;
vj += n; vj1 += n;
}
}
}
}
t = Accord.Math.Tools.Hypotenuse(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))
{
unsafe
{
fixed (double* ptr_uj = &u[0, j])
{
double* uj = ptr_uj;
double* uj1 = ptr_uj + 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;*/
double uij = *uj;
double uij1 = *uj1;
t = cs * uij + sn * uij1;
*uj1 = -sn * uij + cs * uij1;
*uj = t;
uj += nu; uj1 += nu;
}
}
}
}
}
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;
}
}
// If we are violating JAMA's assumption about
// the input dimension, we need to swap u and v.
if (swapped)
{
double[,] temp = this.u;
this.u = this.v;
this.v = temp;
}
}
///