Exemplo n.º 1
0
        //void decompose();
        private void decompose()
        {
            bool    flag;
            int     i, its, j, jj, k, nm = int.MinValue;
            int     l = int.MinValue;
            double  anorm, c, f, g, h, s, scale, x, y, z;
            VecDoub rv1 = new VecDoub(n);

            g = scale = anorm = 0.0;
            for (i = 0; i < n; i++)
            {
                l      = i + 2;
                rv1[i] = scale * g;
                g      = s = scale = 0.0;
                if (i < m)
                {
                    for (k = i; k < m; k++)
                    {
                        scale += Math.Abs(u[k][i]);
                    }
                    if (scale != 0.0)
                    {
                        for (k = i; k < m; k++)
                        {
                            u[k][i] /= scale;
                            s       += u[k][i] * u[k][i];
                        }
                        f       = u[i][i];
                        g       = -NR.SIGN(Math.Sqrt(s), f);
                        h       = f * g - s;
                        u[i][i] = f - g;
                        for (j = l - 1; j < n; j++)
                        {
                            for (s = 0.0, k = i; k < m; k++)
                            {
                                s += u[k][i] * u[k][j];
                            }
                            f = s / h;
                            for (k = i; k < m; k++)
                            {
                                u[k][j] += f * u[k][i];
                            }
                        }
                        for (k = i; k < m; k++)
                        {
                            u[k][i] *= scale;
                        }
                    }
                }
                w[i] = scale * g;
                g    = s = scale = 0.0;
                if (i + 1 <= m && i + 1 != n)
                {
                    for (k = l - 1; k < n; k++)
                    {
                        scale += Math.Abs(u[i][k]);
                    }
                    if (scale != 0.0)
                    {
                        for (k = l - 1; k < n; k++)
                        {
                            u[i][k] /= scale;
                            s       += u[i][k] * u[i][k];
                        }
                        f           = u[i][l - 1];
                        g           = -NR.SIGN(Math.Sqrt(s), f);
                        h           = f * g - s;
                        u[i][l - 1] = f - g;
                        for (k = l - 1; k < n; k++)
                        {
                            rv1[k] = u[i][k] / h;
                        }
                        for (j = l - 1; j < m; j++)
                        {
                            for (s = 0.0, k = l - 1; k < n; k++)
                            {
                                s += u[j][k] * u[i][k];
                            }
                            for (k = l - 1; k < n; k++)
                            {
                                u[j][k] += s * rv1[k];
                            }
                        }
                        for (k = l - 1; k < n; k++)
                        {
                            u[i][k] *= scale;
                        }
                    }
                }
                anorm = Math.Max(anorm, (Math.Abs(w[i]) + Math.Abs(rv1[i])));
            }
            for (i = n - 1; i >= 0; i--)
            {
                if (i < n - 1)
                {
                    if (g != 0.0)
                    {
                        for (j = l; j < n; j++)
                        {
                            v[j][i] = (u[i][j] / u[i][l]) / g;
                        }
                        for (j = l; j < n; j++)
                        {
                            for (s = 0.0, k = l; k < n; k++)
                            {
                                s += u[i][k] * v[k][j];
                            }
                            for (k = l; k < n; k++)
                            {
                                v[k][j] += s * v[k][i];
                            }
                        }
                    }
                    for (j = l; j < n; j++)
                    {
                        v[i][j] = v[j][i] = 0.0;
                    }
                }
                v[i][i] = 1.0;
                g       = rv1[i];
                l       = i;
            }
            for (i = Math.Min(m, n) - 1; i >= 0; i--)
            {
                l = i + 1;
                g = w[i];
                for (j = l; j < n; j++)
                {
                    u[i][j] = 0.0;
                }
                if (g != 0.0)
                {
                    g = 1.0 / g;
                    for (j = l; j < n; j++)
                    {
                        for (s = 0.0, k = l; k < m; k++)
                        {
                            s += u[k][i] * u[k][j];
                        }
                        f = (s / u[i][i]) * g;
                        for (k = i; k < m; k++)
                        {
                            u[k][j] += f * u[k][i];
                        }
                    }
                    for (j = i; j < m; j++)
                    {
                        u[j][i] *= g;
                    }
                }
                else
                {
                    for (j = i; j < m; j++)
                    {
                        u[j][i] = 0.0;
                    }
                }
                ++u[i][i];
            }
            for (k = n - 1; k >= 0; k--)
            {
                for (its = 0; its < 30; its++)
                {
                    flag = true;
                    for (l = k; l >= 0; l--)
                    {
                        nm = l - 1;
                        if (l == 0 || Math.Abs(rv1[l]) <= eps * anorm)
                        {
                            flag = false;
                            break;
                        }
                        if (Math.Abs(w[nm]) <= eps * anorm)
                        {
                            break;
                        }
                    }
                    if (flag)
                    {
                        c = 0.0;
                        s = 1.0;
                        for (i = l; i < k + 1; i++)
                        {
                            f      = s * rv1[i];
                            rv1[i] = c * rv1[i];
                            if (Math.Abs(f) <= eps * anorm)
                            {
                                break;
                            }
                            g    = w[i];
                            h    = pythag(f, g);
                            w[i] = h;
                            h    = 1.0 / h;
                            c    = g * h;
                            s    = -f * h;
                            for (j = 0; j < m; j++)
                            {
                                y        = u[j][nm];
                                z        = u[j][i];
                                u[j][nm] = y * c + z * s;
                                u[j][i]  = z * c - y * s;
                            }
                        }
                    }
                    z = w[k];
                    if (l == k)
                    {
                        if (z < 0.0)
                        {
                            w[k] = -z;
                            for (j = 0; j < n; j++)
                            {
                                v[j][k] = -v[j][k];
                            }
                        }
                        break;
                    }
                    if (its == 29)
                    {
                        throw new Exception("no convergence in 30 svdcmp iterations");
                    }
                    x  = w[l];
                    nm = k - 1;
                    y  = w[nm];
                    g  = rv1[nm];
                    h  = rv1[k];
                    f  = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
                    g  = pythag(f, 1.0);
                    f  = ((x - z) * (x + z) + h * ((y / (f + NR.SIGN(g, f))) - h)) / x;
                    c  = s = 1.0;
                    for (j = l; j <= nm; j++)
                    {
                        i      = j + 1;
                        g      = rv1[i];
                        y      = w[i];
                        h      = s * g;
                        g      = c * g;
                        z      = pythag(f, h);
                        rv1[j] = z;
                        c      = f / z;
                        s      = h / z;
                        f      = x * c + g * s;
                        g      = g * c - x * s;
                        h      = y * s;
                        y     *= c;
                        for (jj = 0; jj < n; jj++)
                        {
                            x        = v[jj][j];
                            z        = v[jj][i];
                            v[jj][j] = x * c + z * s;
                            v[jj][i] = z * c - x * s;
                        }
                        z    = pythag(f, h);
                        w[j] = z;
                        if (z != 0.0)
                        {
                            z = 1.0 / z;
                            c = f * z;
                            s = h * z;
                        }
                        f = c * g + s * y;
                        x = c * y - s * g;
                        for (jj = 0; jj < m; jj++)
                        {
                            y        = u[jj][j];
                            z        = u[jj][i];
                            u[jj][j] = y * c + z * s;
                            u[jj][i] = z * c - y * s;
                        }
                    }
                    rv1[l] = 0.0;
                    rv1[k] = f;
                    w[k]   = x;
                }
            }
        }
Exemplo n.º 2
0
        private bool sing;        // Indicates whether A is singular.

        public QRdcmp(MatDoub a)
        {
            n = a.nrows();
            MatDoub qt = new MatDoub(n, n);
            MatDoub r  = new MatDoub(a);

            sing = (false);
            int     i, j, k;
            VecDoub c = new VecDoub(n);
            VecDoub d = new VecDoub(n);
            double  scale, sigma, sum, tau;

            for (k = 0; k < n - 1; k++)
            {
                scale = 0.0;
                for (i = k; i < n; i++)
                {
                    scale = Math.Max(scale, Math.Abs(r[i][k]));
                }
                if (scale == 0.0)
                { // Singular case.
                    sing = true;
                    c[k] = d[k] = 0.0;
                }
                else
                { // Form Qk and Qk A.
                    for (i = k; i < n; i++)
                    {
                        r[i][k] /= scale;
                    }

                    for (sum = 0.0, i = k; i < n; i++)
                    {
                        sum += r[i][k] * r[i][k];
                    }

                    sigma    = NR.SIGN(Math.Sqrt(sum), r[k][k]);
                    r[k][k] += sigma;
                    c[k]     = sigma * r[k][k];
                    d[k]     = -scale * sigma;

                    for (j = k + 1; j < n; j++)
                    {
                        for (sum = 0.0, i = k; i < n; i++)
                        {
                            sum += r[i][k] * r[i][j];
                        }
                        tau = sum / c[k];
                        for (i = k; i < n; i++)
                        {
                            r[i][j] -= tau * r[i][k];
                        }
                    }
                }
            }
            d[n - 1] = r[n - 1][n - 1];
            if (d[n - 1] == 0.0)
            {
                sing = true;
            }

            ///////////////////////////
            for (i = 0; i < n; i++)
            { // Form QT explicitly.
                for (j = 0; j < n; j++)
                {
                    qt[i][j] = 0.0;
                }
                qt[i][i] = 1.0;
            }
            for (k = 0; k < n - 1; k++)
            {
                if (c[k] != 0.0)
                {
                    for (j = 0; j < n; j++)
                    {
                        sum = 0.0;
                        for (i = k; i < n; i++)
                        {
                            sum += r[i][k] * qt[i][j];
                        }
                        sum /= c[k];
                        for (i = k; i < n; i++)
                        {
                            qt[i][j] -= sum * r[i][k];
                        }
                    }
                }
            }
            for (i = 0; i < n; i++)
            { // Form R explicitly.
                r[i][i] = d[i];
                for (j = 0; j < i; j++)
                {
                    r[i][j] = 0.0;
                }
            }
        }