コード例 #1
0
        /// <summary>
        /// Decompose matrix A into uper and lower triangular part. Returns permutation matrix also.
        /// </summary>
        /// <param name="A">general input matrix. Size [m x n]</param>
        /// <param name="U">[output] reference to upper triangular matrix. Size [min(m,n) x n]. Must not be null.</param>
        /// <param name="P">[output] reference to permutation matrix. Size [min(m,n) x min(m,n)]. Must not be null.</param>
        /// <returns>lower triangular matrix L of size [m x min(m,n)]</returns>
        /// <remarks>A is decomposed into L and U, so that the equation
        /// <code>ILMath.multiply(L,U) == ILMath.multiply(P,A)</code>
        /// will hold except for round off error.
        /// <para>L and U will be true lower triangular matrices.</para>
        /// <example> <code>
        /// //Let's construct a matrix X:
        /// ILArray&lt;double&gt; X = new ILArray&lt;double&gt;(new double[]{1, 2, 3, 4, 4, 4, 5, 6, 7},3,3).T;
        /// // now X.ToString() will give something like:
        /// // {&lt;Double&gt; 63238509 [3x3] Ref(2)
        /// //(:,:)
        /// // 1,00000  2,00000  3,00000
        /// // 4,00000  4,00000  4,00000
        /// // 5,00000  6,00000  7,00000
        /// //}
        /// // construct references on U and P and call the decomposition
        /// ILArray&lt;double&gt; U = new ILArray&lt;double&gt;.empty();
        /// ILArray&lt;double&gt; P = new ILArray&lt;double&gt;.empty();
        /// ILArray&lt;double&gt; L = ILMath.lu(X, ref U, ref P);
        ///
        /// // L.ToString() is now:
        /// // {&lt;Double&gt; 19634871 [3x3] Phys.
        /// //(:,:)
        /// // 1,00000   0,00000   0,00000
        /// // 0,80000   1,00000   0,00000
        /// // 0,20000  -1,00000   1,00000
        /// //}
        /// // U is now:
        /// //{&lt;Double&gt; 22584602 [3x3] Phys.
        /// //(:,:)
        /// // 5,00000  6,00000  7,00000
        /// // 0,00000  -0,80000  -1,60000
        /// // 0,00000  0,00000  0,00000
        /// //}
        /// // and P is:
        /// //{&lt;Double&gt; 2192437 [3x3] Phys.
        /// //(:,:)
        /// // 0,00000  0,00000  1,00000
        /// // 0,00000  1,00000  0,00000
        /// // 1,00000  0,00000  0,00000
        /// //}
        /// </code>
        /// In order to reflect the pivoting done during the decomposition inside ?getrf, the matrix P may be used on A:
        /// <code>
        /// (ILMath.multiply(P,A) - ILMath.multiply(L,U)).ToString();
        /// // will give:
        /// //{&lt;Double&gt; 59192235 [3x3] Phys.
        /// //(:,:)
        /// // 0,00000  0,00000  0,00000
        /// // 0,00000  0,00000  0,00000
        /// // 0,00000  0,00000  0,00000
        /// //}
        /// </code>
        /// </example>
        /// <para>lu uses the Lapack function ?getrf.</para>
        /// <para>All of the matrices U,L,P returned will be solid ILArrays.</para>
        /// </remarks>
        /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.lu(ILArray&lt;double&gt;)"/>
        /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.lu(ILArray&lt;double&gt;, ref ILArray&lt;double&gt;)"/>
        /// <exception cref="ILNumerics.Exceptions.ILArgumentException"> if input A is not a matrix.</exception>
        public static ILArray <fcomplex> lu(ILArray <fcomplex> A, ref ILArray <fcomplex> U, ref ILArray <fcomplex> P)
        {
            if (!A.IsMatrix)
            {
                throw new ILArgumentSizeException("lu is defined for matrices only!");
            }
            int m = A.Dimensions[0], n = A.Dimensions[1], info = 0, minMN = (m < n)? m : n;
            ILArray <fcomplex> L = (ILArray <fcomplex>)A.Clone();

            int [] pivInd        = ILMemoryPool.Pool.New <int>(minMN);
            Lapack.cgetrf(m, n, L.m_data, m, pivInd, ref info);
            if (info < 0)
            {
                ILMemoryPool.Pool.RegisterObject(pivInd);
                throw new ILArgumentException("lu: illegal parameter error.");
                //} else if (info > 0) {
                //    // singular diagonal entry found
            }
            else
            {
                // completed successfuly
                if (!Object.Equals(U, null))
                {
                    if (!Object.Equals(P, null))
                    {
                        pivInd = perm2indicesForward(pivInd);
                        U      = copyUpperTriangle(L, minMN, n);
                        L      = copyLowerTriangle(L, m, minMN, new fcomplex(1.0f, 0.0f));
                        P      = ILArray <fcomplex> .zeros(minMN, minMN);

                        // construct permutation matrix P
                        for (int r = 0; r < m; r++)
                        {
                            P[r, pivInd[r]] = new fcomplex(1.0f, 0.0f);
                        }
                    }
                    else
                    {
                        pivInd = perm2indicesBackward(pivInd);
                        U      = copyUpperTriangle(L, minMN, n);
                        L      = copyLowerTrianglePerm(L, m, minMN, new fcomplex(1.0f, 0.0f), pivInd);
                    }
                }
            }
            ILMemoryPool.Pool.RegisterObject(pivInd);
            return(L);
        }
コード例 #2
0
        /// <summary>
        /// Determinant of square matrix
        /// </summary>
        /// <param name="A">square input matrix</param>
        /// <returns>determinant of A</returns>
        /// <remarks><para>The determinant is computed by decomposing A into upper and lower triangular part. Therefore LAPACK function ?getrf is used. <br />
        /// Due to the properties of determinants, det(a) is the same as det(L) * det(U),where det(L) can easily be extracted from the permutation indices returned from LU decomposition. det(U) - with U beeing an upper triangular matrix - equals the product of the diagonal elements.</para>
        /// <para>For scalar A, a plain copy of A is returned.</para></remarks>
        /// <example>Creating a nonsingular 4x4 (double) matrix and it's determinant
        /// <code>ILArray&lt;double&gt; A = ILMath.counter(1.0,1.0,4,4);
        ///A[1] = 0.0;  // make A nonsingular
        ///A[14] = 0.0; //(same as: A[2,3] = 0.0;)
        /// // A is now:
        /// //&lt;Double&gt; [4,4]
        /// //(:,:) 1e+001 *
        /// // 0,10000   0,50000   0,90000   1,30000
        /// // 0,00000   0,60000   1,00000   1,40000
        /// // 0,30000   0,70000   1,10000   0,00000
        /// // 0,40000   0,80000   1,20000   1,60000
        ///
        ///ILMath.det(A) gives:
        /// //&lt;Double&gt; -360
        ///</code></example>
        ///<exception cref="ILNumerics.Exceptions.ILArgumentException">if A is empty or not a square matrix</exception>
        public static ILArray <fcomplex> det(ILArray <fcomplex> A)
        {
            if (A.IsScalar)
            {
                return(A.C);
            }
            if (A.IsEmpty)
            {
                throw new ILArgumentException("det: A must be a matrix");
            }
            int m = A.Dimensions[0];

            if (m != A.Dimensions[1])
            {
                throw new ILArgumentException("det: matrix A must be square");
            }

            ILArray <fcomplex> L = A.C;

            int [] pivInd = new int[m];
            int    info   = 0;

            Lapack.cgetrf(m, m, L.m_data, m, pivInd, ref info);
            if (info < 0)
            {
                throw new ILArgumentException("det: illegal parameter error.");
            }
            // determine pivoting: number of exchanges
            fcomplex retA = new fcomplex(1.0f, 0.0f);

            for (int i = 0; i < m;)
            {
                retA *= L.m_data[i * m + i];
                if (pivInd[i] != ++i)
                {
                    retA *= -1.0f;
                }
            }
            L.Dispose();
            return(new  ILArray <fcomplex> (retA));
        }