예제 #1
0
        /// <summary>
        ///   Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///   A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            var clone = new QrDecompositionF();

            clone.qr    = (Single[, ])qr.Clone();
            clone.Rdiag = (Single[])Rdiag.Clone();
            return(clone);
        }
        /// <summary>
        ///   Construct an eigenvalue decomposition.</summary>
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        /// <param name="assumeSymmetric">
        ///   Defines if the matrix should be assumed as being symmetric
        ///   regardless if it is or not. Default is <see langword="false"/>.</param>
        /// <param name="inPlace">
        ///   Pass <see langword="true"/> to perform the decomposition in place. The matrix
        ///   <paramref name="value"/> will be destroyed in the process, resulting in less
        ///   memory comsumption.</param>
        public EigenvalueDecompositionF(Single[,] value, bool assumeSymmetric, bool inPlace)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if (value.GetLength(0) != value.GetLength(1))
            {
                throw new ArgumentException("Matrix is not a square matrix.", "value");
            }

            n = value.GetLength(1);
            V = new Single[n, n];
            d = new Single[n];
            e = new Single[n];


            this.symmetric = assumeSymmetric;

            if (this.symmetric)
            {
                V = inPlace ? value : (Single[, ])value.Clone();

                // Tridiagonalize.
                this.tred2();

                // Diagonalize.
                this.tql2();
            }
            else
            {
                H = inPlace ? value : (Single[, ])value.Clone();

                ort = new Single[n];

                // Reduce to Hessenberg form.
                this.orthes();

                // Reduce Hessenberg to real Schur form.
                this.hqr2();
            }
        }
예제 #3
0
        /// <summary>
        ///   Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///   A new object that is a copy of this instance.
        /// </returns>
        ///
        public object Clone()
        {
            var svd = new SingularValueDecompositionF();

            svd.m       = m;
            svd.n       = n;
            svd.s       = (Single[])s.Clone();
            svd.si      = (int[])si.Clone();
            svd.swapped = swapped;
            if (u != null)
            {
                svd.u = (Single[, ])u.Clone();
            }
            if (v != null)
            {
                svd.v = (Single[, ])u.Clone();
            }

            return(svd);
        }
예제 #4
0
        /// <summary>
        ///   Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///   A new object that is a copy of this instance.
        /// </returns>
        ///
        public object Clone()
        {
            var clone = new CholeskyDecompositionF();

            clone.L                = (Single[, ])L.Clone();
            clone.D                = (Single[])D.Clone();
            clone.n                = n;
            clone.robust           = robust;
            clone.positiveDefinite = positiveDefinite;
            clone.symmetric        = symmetric;
            return(clone);
        }
        /// <summary>
        ///   Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///   A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            var clone = new EigenvalueDecompositionF();

            clone.d         = (Single[])d.Clone();
            clone.e         = (Single[])e.Clone();
            clone.H         = (Single[, ])H.Clone();
            clone.n         = n;
            clone.ort       = (Single[])ort;
            clone.symmetric = symmetric;
            clone.V         = (Single[, ])V.Clone();
            return(clone);
        }
예제 #6
0
        /// <summary>
        ///   Constructs a new singular value decomposition.
        /// </summary>
        ///
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        /// <param name="computeLeftSingularVectors">
        ///   Pass <see langword="true"/> if the left singular vector matrix U
        ///   should be computed. Pass <see langword="false"/> otherwise. Default
        ///   is <see langword="true"/>.</param>
        /// <param name="computeRightSingularVectors">
        ///   Pass <see langword="true"/> if the right singular vector matrix V
        ///   should be computed. Pass <see langword="false"/> otherwise. Default
        ///   is <see langword="true"/>.</param>
        /// <param name="autoTranspose">
        ///   Pass <see langword="true"/> to automatically transpose the value matrix in
        ///   case JAMA's assumptions about the dimensionality of the matrix are violated.
        ///   Pass <see langword="false"/> otherwise. Default is <see langword="false"/>.</param>
        /// <param name="inPlace">
        ///   Pass <see langword="true"/> to perform the decomposition in place. The matrix
        ///   <paramref name="value"/> will be destroyed in the process, resulting in less
        ///   memory comsumption.</param>
        ///
        public unsafe SingularValueDecompositionF(Single[,] value,
                                                  bool computeLeftSingularVectors, bool computeRightSingularVectors, bool autoTranspose, bool inPlace)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            Single[,] a;
            m = value.GetLength(0); // rows
            n = value.GetLength(1); // cols

            if (m == 0 || n == 0)
            {
                throw new ArgumentException("Matrix does not have any rows or columns.", "value");
            }



            if (m < n)              // Check if we are violating JAMA's assumption
            {
                if (!autoTranspose) // Yes, check if we should correct it
                {
                    // Warning! This routine is not guaranteed to work when A has less rows
                    //  than columns. If this is the case, you should compute SVD on the
                    //  transpose of A and then swap the left and right eigenvectors.

                    // However, as the solution found can still be useful, the exception below
                    // will not be thrown, and only a warning will be output in the trace.

                    // throw new ArgumentException("Matrix should have more rows than columns.");

                    System.Diagnostics.Trace.WriteLine(
                        "WARNING: Computing SVD on a matrix with more columns than rows.");

                    // Proceed anyway
                    a = inPlace ? value : (Single[, ])value.Clone();
                }
                else
                {
                    // Transposing and swapping
                    a       = value.Transpose(inPlace && m == n);
                    m       = value.GetLength(1);
                    n       = value.GetLength(0);
                    swapped = true;

                    bool aux = computeLeftSingularVectors;
                    computeLeftSingularVectors  = computeRightSingularVectors;
                    computeRightSingularVectors = aux;
                }
            }
            else
            {
                // Input matrix is ok
                a = inPlace ? value : (Single[, ])value.Clone();
            }


            int nu = System.Math.Min(m, n);
            int ni = System.Math.Min(m + 1, n);

            s = new Single[ni];
            u = new Single[m, nu];
            v = new Single[n, n];
            Single[] e     = new Single[n];
            Single[] work  = new Single[m];
            bool     wantu = computeLeftSingularVectors;
            bool     wantv = computeRightSingularVectors;

            fixed(Single *U = u)
            fixed(Single * V = v)
            fixed(Single * A = a)
            {
                // Will store ordered sequence of indices after sorting.
                si = new int[ni]; for (int i = 0; i < ni; i++)
                {
                    si[i] = i;
                }


                // Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e.
                int nct = System.Math.Min(m - 1, n);
                int nrt = System.Math.Max(0, System.Math.Min(n - 2, m));

                for (int k = 0; k < System.Math.Max(nct, nrt); k++)
                {
                    if (k < nct)
                    {
                        // Compute the transformation for the k-th column and place the k-th diagonal in s[k].
                        // Compute 2-norm of k-th column without under/overflow.
                        s[k] = 0;
                        for (int i = k; i < m; i++)
                        {
                            s[k] = Accord.Math.Tools.Hypotenuse(s[k], a[i, k]);
                        }

                        if (s[k] != 0)
                        {
                            if (a[k, k] < 0)
                            {
                                s[k] = -s[k];
                            }

                            for (int i = k; i < m; i++)
                            {
                                a[i, k] /= s[k];
                            }

                            a[k, k] += 1;
                        }

                        s[k] = -s[k];
                    }

                    for (int j = k + 1; j < n; j++)
                    {
                        Single *ptr_ak = A + k * n + k; // A[k,k]
                        Single *ptr_aj = A + k * n + j; // A[k,j]

                        if ((k < nct) & (s[k] != 0))
                        {
                            // Apply the transformation.
                            Single  t  = 0;
                            Single *ak = ptr_ak;
                            Single *aj = ptr_aj;

                            for (int i = k; i < m; i++)
                            {
                                t  += (*ak) * (*aj);
                                ak += n; aj += n;
                            }

                            t  = -t / *ptr_ak;
                            ak = ptr_ak;
                            aj = ptr_aj;

                            for (int i = k; i < m; i++)
                            {
                                *aj += t * (*ak);
                                ak += n; aj += n;
                            }
                        }

                        // Place the k-th row of A into e for the subsequent calculation of the row transformation.
                        e[j] = *ptr_aj;
                    }


                    if (wantu & (k < nct))
                    {
                        // Place the transformation in U for subsequent back
                        // multiplication.
                        for (int i = k; i < m; i++)
                        {
                            u[i, k] = a[i, k];
                        }
                    }

                    if (k < nrt)
                    {
                        // Compute the k-th row transformation and place the k-th super-diagonal in e[k].
                        // Compute 2-norm without under/overflow.
                        e[k] = 0;
                        for (int i = k + 1; i < n; i++)
                        {
                            e[k] = Accord.Math.Tools.Hypotenuse(e[k], e[i]);
                        }

                        if (e[k] != 0)
                        {
                            if (e[k + 1] < 0)
                            {
                                e[k] = -e[k];
                            }

                            for (int i = k + 1; i < n; i++)
                            {
                                e[i] /= e[k];
                            }

                            e[k + 1] += 1;
                        }

                        e[k] = -e[k];
                        if ((k + 1 < m) & (e[k] != 0))
                        {
                            // Apply the transformation.
                            for (int i = k + 1; i < m; i++)
                            {
                                work[i] = 0;
                            }

                            int k1 = k + 1;
                            for (int i = k1; i < m; i++)
                            {
                                Single *ai = A + (i * n) + k1;
                                for (int j = k1; j < n; j++, ai++)
                                {
                                    work[i] += e[j] * (*ai);
                                }
                            }

                            for (int j = k1; j < n; j++)
                            {
                                Single  t  = -e[j] / e[k1];
                                Single *aj = A + (k1 * n) + j;
                                for (int i = k1; i < m; i++, aj += n)
                                {
                                    *aj += t * work[i];
                                }
                            }
                        }

                        if (wantv)
                        {
                            // Place the transformation in V for subsequent back multiplication.
                            for (int i = k + 1; i < n; i++)
                            {
                                v[i, k] = e[i];
                            }
                        }
                    }
                }

                // Set up the final bidiagonal matrix or order p.
                int p = System.Math.Min(n, m + 1);

                if (nct < n)
                {
                    s[nct] = a[nct, nct];
                }
                if (m < p)
                {
                    s[p - 1] = 0;
                }
                if (nrt + 1 < p)
                {
                    e[nrt] = a[nrt, p - 1];
                }
                e[p - 1] = 0;

                // If required, generate U.
                if (wantu)
                {
                    for (int j = nct; j < nu; j++)
                    {
                        for (int i = 0; i < m; i++)
                        {
                            u[i, j] = 0;
                        }
                        u[j, j] = 1;
                    }

                    for (int k = nct - 1; k >= 0; k--)
                    {
                        if (s[k] != 0)
                        {
                            Single *ptr_uk = U + k * nu + k; // u[k,k]

                            Single *uk, uj;
                            for (int j = k + 1; j < nu; j++)
                            {
                                Single *ptr_uj = U + k * nu + j; // u[k,j]

                                Single t = 0;
                                uk = ptr_uk;
                                uj = ptr_uj;

                                for (int i = k; i < m; i++)
                                {
                                    t  += *uk * *uj;
                                    uk += nu; uj += nu;
                                }

                                t = -t / *ptr_uk;

                                uk = ptr_uk; uj = ptr_uj;
                                for (int i = k; i < m; i++)
                                {
                                    *uj += t * (*uk);
                                    uk += nu; uj += nu;
                                }
                            }

                            uk = ptr_uk;
                            for (int i = k; i < m; i++)
                            {
                                *uk = -(*uk);
                                uk += nu;
                            }

                            u[k, k] = 1 + u[k, k];
                            for (int i = 0; i < k - 1; i++)
                            {
                                u[i, k] = 0;
                            }
                        }
                        else
                        {
                            for (int i = 0; i < m; i++)
                            {
                                u[i, k] = 0;
                            }
                            u[k, k] = 1;
                        }
                    }
                }

                // If required, generate V.
                if (wantv)
                {
                    for (int k = n - 1; k >= 0; k--)
                    {
                        if ((k < nrt) & (e[k] != 0))
                        {
                            // TODO: The following is a pseudo correction to make SVD
                            //  work on matrices with n > m (less rows than columns).

                            // For the proper correction, compute the decomposition of the
                            //  transpose of A and swap the left and right eigenvectors

                            // Original line:
                            //   for (int j = k + 1; j < nu; j++)
                            // Pseudo correction:
                            //   for (int j = k + 1; j < n; j++)

                            for (int j = k + 1; j < n; j++)           // pseudo-correction
                            {
                                Single *ptr_vk = V + (k + 1) * n + k; // v[k + 1, k]
                                Single *ptr_vj = V + (k + 1) * n + j; // v[k + 1, j]

                                Single  t  = 0;
                                Single *vk = ptr_vk;
                                Single *vj = ptr_vj;

                                for (int i = k + 1; i < n; i++)
                                {
                                    t  += *vk * *vj;
                                    vk += n; vj += n;
                                }

                                t = -t / *ptr_vk;

                                vk = ptr_vk; vj = ptr_vj;
                                for (int i = k + 1; i < n; i++)
                                {
                                    *vj += t * (*vk);
                                    vk += n; vj += n;
                                }
                            }
                        }

                        for (int i = 0; i < n; i++)
                        {
                            v[i, k] = 0;
                        }
                        v[k, k] = 1;
                    }
                }

                // Main iteration loop for the singular values.
                int pp   = p - 1;
                int iter = 0;

                while (p > 0)
                {
                    int k, kase;

                    // Here is where a test for too many iterations would go.

                    // This section of the program inspects for
                    // negligible elements in the s and e arrays.  On
                    // completion the variables kase and k are set as follows.

                    // kase = 1     if s(p) and e[k-1] are negligible and k<p
                    // kase = 2     if s(k) is negligible and k<p
                    // kase = 3     if e[k-1] is negligible, k<p, and
                    //              s(k), ..., s(p) are not negligible (qr step).
                    // kase = 4     if e(p-1) is negligible (convergence).

                    for (k = p - 2; k >= -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;
                            break;
                        }
                    }

                    if (k == p - 2)
                    {
                        kase = 4;
                    }
                    else
                    {
                        int ks;
                        for (ks = p - 1; ks >= k; ks--)
                        {
                            if (ks == k)
                            {
                                break;
                            }

                            Single t = (ks != p ? System.Math.Abs(e[ks]) : 0) +
                                       (ks != k + 1 ? System.Math.Abs(e[ks - 1]) : 0);
                            if (System.Math.Abs(s[ks]) <= tiny + eps * t)
                            {
                                s[ks] = 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:
                    {
                        Single f = e[p - 2];
                        e[p - 2] = 0;
                        for (int j = p - 2; j >= k; j--)
                        {
                            Single t  = Accord.Math.Tools.Hypotenuse(s[j], f);
                            Single cs = s[j] / t;
                            Single 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:
                    {
                        Single f = e[k - 1];
                        e[k - 1] = 0;
                        for (int j = k; j < p; j++)
                        {
                            Single t  = Accord.Math.Tools.Hypotenuse(s[j], f);
                            Single cs = s[j] / t;
                            Single 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.
                        Single 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]));
                        Single sp    = s[p - 1] / scale;
                        Single spm1  = s[p - 2] / scale;
                        Single epm1  = e[p - 2] / scale;
                        Single sk    = s[k] / scale;
                        Single ek    = e[k] / scale;
                        Single b     = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;
                        Single c     = (sp * epm1) * (sp * epm1);
                        double shift = 0;

                        if ((b != 0) | (c != 0))
                        {
                            if (b < 0)
                            {
                                shift = -System.Math.Sqrt(b * b + c);
                            }
                            else
                            {
                                shift = System.Math.Sqrt(b * b + c);
                            }

                            shift = c / (b + shift);
                        }

                        Single f = (sk + sp) * (sk - sp) + (Single)shift;
                        Single g = sk * ek;

                        // Chase zeros.
                        for (int j = k; j < p - 1; j++)
                        {
                            Single t  = Accord.Math.Tools.Hypotenuse(f, g);
                            Single cs = f / t;
                            Single 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(Single *ptr_vj = &v[0, j])
                                    {
                                        Single *vj  = ptr_vj;
                                        Single *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;*/

                                            Single vij  = *vj;
                                            Single 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))
                            {
                                fixed(Single *ptr_uj = &u[0, j])
                                {
                                    Single *uj  = ptr_uj;
                                    Single *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;*/

                                        Single uij  = *uj;
                                        Single 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)
                        {
                            s[k] = (s[k] < 0 ? -s[k] : 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;
                            }

                            Single t = s[k];
                            s[k]     = s[k + 1];
                            s[k + 1] = t;

                            int ti = si[k];
                            si[k]     = si[k + 1];
                            si[k + 1] = ti;

                            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)
            {
                Single[,] temp = this.u;
                this.u         = this.v;
                this.v         = temp;
            }
        }
예제 #7
0
        /// <summary>Constructs a QR decomposition.</summary>
        /// <param name="value">The matrix A to be decomposed.</param>
        /// <param name="transpose">True if the decomposition should be performed on
        /// the transpose of A rather than A itself, false otherwise. Default is false.</param>
        public QrDecompositionF(Single[,] value, bool transpose)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if ((!transpose && value.GetLength(0) < value.GetLength(1)) ||
                (transpose && value.GetLength(1) < value.GetLength(0)))
            {
                throw new ArgumentException("Matrix has more columns than rows.", "value");
            }

            this.qr = transpose ? value.Transpose() : (Single[, ])value.Clone();

            int rows = qr.GetLength(0);
            int cols = qr.GetLength(1);

            this.Rdiag = new Single[cols];

            for (int k = 0; k < cols; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                Single nrm = 0;
                for (int i = k; i < rows; i++)
                {
                    nrm = Tools.Hypotenuse(nrm, qr[i, k]);
                }

                if (nrm != 0)
                {
                    // Form k-th Householder vector.
                    if (qr[k, k] < 0)
                    {
                        nrm = -nrm;
                    }

                    for (int i = k; i < rows; i++)
                    {
                        qr[i, k] /= nrm;
                    }

                    qr[k, k] += 1;

                    // Apply transformation to remaining columns.
                    for (int j = k + 1; j < cols; j++)
                    {
                        Single s = 0;

                        for (int i = k; i < rows; i++)
                        {
                            s += qr[i, k] * qr[i, j];
                        }

                        s = -s / qr[k, k];

                        for (int i = k; i < rows; i++)
                        {
                            qr[i, j] += s * qr[i, k];
                        }
                    }
                }

                this.Rdiag[k] = -nrm;
            }
        }
예제 #8
0
        /// <summary>Least squares solution of <c>A * X = B</c></summary>
        /// <param name="value">Right-hand-side matrix with as many rows as <c>A</c> and any number of columns.</param>
        /// <returns>A matrix that minimized the two norm of <c>Q * R * X - B</c>.</returns>
        /// <exception cref="T:System.ArgumentException">Matrix row dimensions must be the same.</exception>
        /// <exception cref="T:System.InvalidOperationException">Matrix is rank deficient.</exception>
        public Single[,] Solve(Single[,] value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if (value.GetLength(0) != qr.GetLength(0))
            {
                throw new ArgumentException("Matrix row dimensions must agree.");
            }

            if (!this.FullRank)
            {
                throw new InvalidOperationException("Matrix is rank deficient.");
            }

            // Copy right hand side
            int count = value.GetLength(1);
            var X     = (Single[, ])value.Clone();
            int m     = qr.GetLength(0);
            int n     = qr.GetLength(1);

            // Compute Y = transpose(Q)*B
            for (int k = 0; k < n; k++)
            {
                for (int j = 0; j < count; j++)
                {
                    Single s = 0;

                    for (int i = k; i < m; i++)
                    {
                        s += qr[i, k] * X[i, j];
                    }

                    s = -s / qr[k, k];

                    for (int i = k; i < m; i++)
                    {
                        X[i, j] += s * qr[i, k];
                    }
                }
            }

            // Solve R*X = Y;
            for (int k = n - 1; k >= 0; k--)
            {
                for (int j = 0; j < count; j++)
                {
                    X[k, j] /= Rdiag[k];
                }

                for (int i = 0; i < k; i++)
                {
                    for (int j = 0; j < count; j++)
                    {
                        X[i, j] -= X[k, j] * qr[i, k];
                    }
                }
            }

            var r = new Single[n, count];

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < count; j++)
                {
                    r[i, j] = X[i, j];
                }
            }

            return(r);
        }
예제 #9
0
        /// <summary>
        ///   Constructs a new LU decomposition.
        /// </summary>
        /// <param name="value">The matrix A to be decomposed.</param>
        /// <param name="transpose">True if the decomposition should be performed on
        /// the transpose of A rather than A itself, false otherwise. Default is false.</param>
        /// <param name="inPlace">True if the decomposition should be performed over the
        /// <paramref name="value"/> matrix rather than on a copy of it. If true, the
        /// matrix will be destroyed during the decomposition. Default is false.</param>
        ///
        public LuDecompositionF(Single[,] value, bool transpose, bool inPlace)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if (transpose)
            {
                this.lu = value.Transpose(inPlace);
            }
            else
            {
                this.lu = inPlace ? value : (Single[, ])value.Clone();
            }

            this.rows      = lu.GetLength(0);
            this.cols      = lu.GetLength(1);
            this.pivotSign = 1;

            this.pivotVector = new int[rows];
            for (int i = 0; i < rows; i++)
            {
                pivotVector[i] = i;
            }

            var LUcolj = new Single[rows];


            unsafe
            {
                fixed(Single *LU = lu)
                {
                    // Outer loop.
                    for (int j = 0; j < cols; j++)
                    {
                        // Make a copy of the j-th column to localize references.
                        for (int i = 0; i < rows; i++)
                        {
                            LUcolj[i] = lu[i, j];
                        }

                        // Apply previous transformations.
                        for (int i = 0; i < rows; i++)
                        {
                            Single s = 0;

                            // Most of the time is spent in
                            // the following dot product:
                            int     kmax   = Math.Min(i, j);
                            Single *LUrowi = &LU[i * cols];
                            for (int k = 0; k < kmax; k++)
                            {
                                s += LUrowi[k] * LUcolj[k];
                            }

                            LUrowi[j] = LUcolj[i] -= s;
                        }

                        // Find pivot and exchange if necessary.
                        int p = j;
                        for (int i = j + 1; i < rows; i++)
                        {
                            if (Math.Abs(LUcolj[i]) > Math.Abs(LUcolj[p]))
                            {
                                p = i;
                            }
                        }

                        if (p != j)
                        {
                            for (int k = 0; k < cols; k++)
                            {
                                var t = lu[p, k];
                                lu[p, k] = lu[j, k];
                                lu[j, k] = t;
                            }

                            int v = pivotVector[p];
                            pivotVector[p] = pivotVector[j];
                            pivotVector[j] = v;

                            pivotSign = -pivotSign;
                        }

                        // Compute multipliers.
                        if (j < rows && lu[j, j] != 0)
                        {
                            for (int i = j + 1; i < rows; i++)
                            {
                                lu[i, j] /= lu[j, j];
                            }
                        }
                    }
                }
            }
        }
예제 #10
0
        /// <summary>Solves a set of equation systems of type <c>A * X = B</c>.</summary>
        /// <param name="value">Right hand side matrix with as many rows as <c>A</c> and any number of columns.</param>
        /// <returns>Matrix <c>X</c> so that <c>L * L' * X = B</c>.</returns>
        /// <exception cref="T:System.ArgumentException">Matrix dimensions do not match.</exception>
        /// <exception cref="T:System.NonSymmetricMatrixException">Matrix is not symmetric.</exception>
        /// <exception cref="T:System.NonPositiveDefiniteMatrixException">Matrix is not positive-definite.</exception>
        /// <param name="inPlace">True to compute the solving in place, false otherwise.</param>
        ///
        public Single[,] Solve(Single[,] value, bool inPlace)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (value.GetLength(0) != n)
            {
                throw new ArgumentException("Argument matrix should have the same number of rows as the decomposed matrix.", "value");
            }

            if (!symmetric)
            {
                throw new NonSymmetricMatrixException("Decomposed matrix is not symmetric.");
            }

            if (!robust && !positiveDefinite)
            {
                throw new NonPositiveDefiniteMatrixException("Decomposed matrix is not positive definite.");
            }


            int count = value.GetLength(1);

            Single[,] B = inPlace ? value : (Single[, ])value.Clone();


            // Solve L*Y = B;
            for (int k = 0; k < n; k++)
            {
                for (int j = 0; j < count; j++)
                {
                    for (int i = 0; i < k; i++)
                    {
                        B[k, j] -= B[i, j] * L[k, i];
                    }

                    B[k, j] /= L[k, k];
                }
            }

            if (robust)
            {
                for (int k = 0; k < n; k++)
                {
                    for (int j = 0; j < count; j++)
                    {
                        B[k, j] /= D[k];
                    }
                }
            }

            // Solve L'*X = Y;
            for (int k = n - 1; k >= 0; k--)
            {
                for (int j = 0; j < count; j++)
                {
                    for (int i = k + 1; i < n; i++)
                    {
                        B[k, j] -= B[i, j] * L[i, k];
                    }

                    B[k, j] /= L[k, k];
                }
            }

            return(B);
        }
예제 #11
0
        /// <summary>
        ///   Construct an eigenvalue decomposition.</summary>
        ///
        /// <param name="value">
        ///   The matrix to be decomposed.</param>
        /// <param name="assumeSymmetric">
        ///   Defines if the matrix should be assumed as being symmetric
        ///   regardless if it is or not. Default is <see langword="false"/>.</param>
        /// <param name="inPlace">
        ///   Pass <see langword="true"/> to perform the decomposition in place. The matrix
        ///   <paramref name="value"/> will be destroyed in the process, resulting in less
        ///   memory comsumption.</param>
        /// <param name="sort">
        ///   Pass <see langword="true"/> to sort the eigenvalues and eigenvectors at the end
        ///   of the decomposition.</param>
        ///
        public EigenvalueDecompositionF(Single[,] value, bool assumeSymmetric,
                                        bool inPlace = false, bool sort = false)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value", "Matrix cannot be null.");
            }

            if (value.GetLength(0) != value.GetLength(1))
            {
                throw new ArgumentException("Matrix is not a square matrix.", "value");
            }

            n = value.GetLength(1);
            V = new Single[n, n];
            d = new Single[n];
            e = new Single[n];


            this.symmetric = assumeSymmetric;

            if (this.symmetric)
            {
                V = inPlace ? value : (Single[, ])value.Clone();

                // Tridiagonalize.
                this.tred2();

                // Diagonalize.
                this.tql2();
            }
            else
            {
                H = inPlace ? value : (Single[, ])value.Clone();

                ort = new Single[n];

                // Reduce to Hessenberg form.
                this.orthes();

                // Reduce Hessenberg to real Schur form.
                this.hqr2();
            }

            if (sort)
            {
                // Sort eigenvalues and vectors in descending order
                var idx = Vector.Range(n);
                Array.Sort(idx, (i, j) =>
                {
                    if (Math.Abs(d[i]) == Math.Abs(d[j]))
                    {
                        return(-Math.Abs(e[i]).CompareTo(Math.Abs(e[j])));
                    }
                    return(-Math.Abs(d[i]).CompareTo(Math.Abs(d[j])));
                });

                this.d = this.d.Get(idx);
                this.e = this.e.Get(idx);
                this.V = this.V.Get(null, idx);
            }
        }