Пример #1
0
        /// <summary>
        /// singular value decomposition
        /// </summary>
        /// <param name="X">matrix X. The elements of X will not be altered.</param>
        /// <param name="U">(return value) left singular vectors of X as columns of matrix U.
        /// If this parameter is set, it must be not null. It might be an empty array. On return
        /// it will be set to a physical array accordingly.</param>
        /// <param name="V">right singular vectors of X as rows of matrix V.
        /// If this parameter is set, it must be not null. It might be an empty array. On return
        /// it will be set to a physical array accordingly.</param>
        /// <param name="small">if true: return only first min(M,N) columns of U and S will be
        /// of size [min(M,N),min(M,N)]</param>
        /// <param name="discardFiniteTest">if true: the matrix given will not be checked for infinte or NaN values. If such elements
        /// are contained nevertheless, this may result in failing convergence or error. In worst case
        /// the function may hang inside the Lapack lib. Use with care! </param>
        /// <returns>singluar values as diagonal matrix of same size as X</returns>
        /// <remarks>the right singular vectors V will be returned as reference array.</remarks>
        public static /*!HC:outClsS*/ ILArray <double> svd(/*!HC:inCls1*/ ILArray <double> X, ref /*!HC:outClsU*/ ILArray <double> U, ref /*!HC:outClsV*/ ILArray <double> V, bool small, bool discardFiniteTest)
        {
            if (!X.IsMatrix)
            {
                throw new ILArgumentSizeException("svd is defined for matrices only!");
            }
            // early exit for small matrices
            if (X.Dimensions[1] < 4 && X.Dimensions[0] == X.Dimensions[1])
            {
                switch (X.Dimensions[0])
                {
                case 1:
                    if (!Object.Equals(U, null))
                    {
                        U = (/*!HC:outArrU*/ double )1.0;
                    }
                    if (!Object.Equals(V, null))
                    {
                        V = (/*!HC:outArrV*/ double )1.0;
                    }
                    return(new /*!HC:outClsS*/ ILArray <double> (ILMath.abs(X)));
                    //case 2:
                    //    return -1;
                    //case 3:
                    //    return -1;
                }
            }
            if (!discardFiniteTest && !all(all(isfinite(X))))
            {
                throw new ILArgumentException("svd: input must have only finite elements!");
            }
            if (Lapack == null)
            {
                throw new ILMathException("No Lapack package available.");
            }
            // parameter evaluation
            int M = X.Dimensions[0]; int N = X.Dimensions[1];
            int minMN = (M < N) ? M : N;
            int LDU = M; int LDVT = N;
            int LDA = M;

            /*!HC:outArrS*/ double [] dS = new /*!HC:outArrS*/ double [minMN];
            char jobz = (small) ? 'S' : 'A';

            /*!HC:outArrU*/ double [] dU  = null;
            /*!HC:outArrV*/ double [] dVT = null;
            int info = 0;

            if (!Object.Equals(U, null) || !Object.Equals(V, null))
            {
                // need to return U and VT
                if (small)
                {
                    dU  = new /*!HC:outArrU*/ double  [M * minMN];
                    dVT = new /*!HC:outArrV*/ double [N * minMN];
                }
                else
                {
                    dU  = new /*!HC:outArrU*/ double [M * M];
                    dVT = new /*!HC:outArrV*/ double [N * N];
                }
            }
            else
            {
                jobz = 'N';
            }

            // must create copy of input !
            /*!HC:inArr1*/ double [] dInput = new /*!HC:inArr1*/ double [X.m_data.Length];
            System.Array.Copy(X.m_data, dInput, X.m_data.Length);
            /*!HC:lapack_dgesdd*/
            Lapack.dgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
            if (info < 0)
            {
                throw new ILArgumentException("ILMath.svd: the " + (-info).ToString() + "th argument was invalid.");
            }
            if (info > 0)
            {
                throw new ILArgumentException("svd was not converging!");
            }
            /*!HC:outClsS*/ ILArray <double> ret = null;

            if (info == 0)
            {
                // success
                if (!Object.Equals(U, null) || !Object.Equals(V, null))
                {
                    if (small)
                    {
                        ret = /*!HC:outClsS*/ ILArray <double> .zeros(minMN, minMN);
                    }
                    else
                    {
                        ret = /*!HC:outClsS*/ ILArray <double> .zeros(M, N);
                    }
                    for (int i = 0; i < minMN; i++)
                    {
                        ret.SetValue(dS[i], i, i);
                    }
                    if (!Object.Equals(U, null))
                    {
                        U = new /*!HC:outClsU*/ ILArray <double> (dU, M, dU.Length / M);
                    }
                    if (!Object.Equals(V, null))
                    {
                        /*!HC:complxConj*/
                        V = new  ILArray <double> (dVT, N, dVT.Length / N).T;
                    }
                }
                else
                {
                    ret = new /*!HC:outClsS*/ ILArray <double> (dS, minMN, 1);
                }
            }
            return(ret);
        }
Пример #2
0
        /// <summary>
        /// singular value decomposition 
        /// </summary>
        /// <param name="X">matrix X. The elements of X will not be altered.</param>
        /// <param name="U">(return value) left singular vectors of X as columns of matrix U. 
        /// If this parameter is set, it must be not null. It might be an empty array. On return
        /// it will be set to a physical array accordingly.</param>
        /// <param name="V">right singular vectors of X as rows of matrix V.
        /// If this parameter is set, it must be not null. It might be an empty array. On return
        /// it will be set to a physical array accordingly.</param>
        /// <param name="small">if true: return only first min(M,N) columns of U and S will be 
        /// of size [min(M,N),min(M,N)]</param>
        /// <param name="discardFiniteTest">if true: the matrix given will not be checked for infinte or NaN values. If such elements 
        /// are contained nevertheless, this may result in failing convergence or error. In worst case 
        /// the function may hang inside the Lapack lib. Use with care! </param>
        /// <returns>singluar values as diagonal matrix of same size as X</returns>
        /// <remarks>the right singular vectors V will be returned as reference array.</remarks>
        public static /*!HC:outClsS*/ ILArray<double> svd(/*!HC:inCls1*/ ILArray<double> X, ref /*!HC:outClsU*/ ILArray<double> U, ref /*!HC:outClsV*/ ILArray<double> V, bool small, bool discardFiniteTest) {
            if (!X.IsMatrix)
                throw new ILArgumentSizeException("svd is defined for matrices only!");
            // early exit for small matrices
            if (X.Dimensions[1] < 4 && X.Dimensions[0] == X.Dimensions[1]) { 
                switch (X.Dimensions[0]) {
                    case 1: 
                        if (!Object.Equals(U,null))
                            U = (/*!HC:outArrU*/ double ) 1.0; 
                        if (!Object.Equals(V,null))
                            V = (/*!HC:outArrV*/ double ) 1.0; 
                        return new /*!HC:outClsS*/ ILArray<double> ( ILMath.abs(X)); 
                    //case 2:
                    //    return -1; 
                    //case 3: 
                    //    return -1; 
                }
            }
            if (!discardFiniteTest && !all(all(isfinite( X )))) 
                throw new ILArgumentException("svd: input must have only finite elements!");
            if (Lapack == null)
                throw new ILMathException("No Lapack package available.");
            // parameter evaluation
            int M = X.Dimensions[0]; int N = X.Dimensions[1];
            int minMN = (M < N) ? M : N;
            int LDU = M; int LDVT = N;
            int LDA = M;
            /*!HC:outArrS*/ double [] dS = new /*!HC:outArrS*/ double [minMN];
            char jobz = (small) ? 'S' : 'A';
            /*!HC:outArrU*/ double [] dU = null;
            /*!HC:outArrV*/ double [] dVT = null;
            int info = 0;
            if (!Object.Equals(U, null) || !Object.Equals(V, null)) {
                // need to return U and VT 
                if (small) {
                    dU = new /*!HC:outArrU*/ double  [M * minMN];
                    dVT = new /*!HC:outArrV*/ double [N * minMN];
                } else {
                    dU = new /*!HC:outArrU*/ double [M * M];
                    dVT = new /*!HC:outArrV*/ double [N * N];
                }
            } else {
                jobz = 'N';
            }

            if (X.IsReference) {
                X.Detach();
            }
            // must create copy of input ! 
            /*!HC:inArr1*/ double [] dInput = new /*!HC:inArr1*/ double [X.m_data.Length]; 
            System.Array.Copy(X.m_data, dInput, X.m_data.Length);
            /*!HC:lapack_dgesdd*/
            Lapack.dgesdd(jobz, M, N, dInput, LDA, dS, dU, LDU, dVT, LDVT, ref info);
            if (info < 0) 
                throw new ILArgumentException ("ILMath.svd: the " + (-info).ToString() +"th argument was invalid.");
            if (info > 0)
                throw new ILArgumentException("svd was not converging!");
            /*!HC:outClsS*/ ILArray<double> ret = null; 
            if (info == 0) {
                // success
                if (!Object.Equals(U, null) || !Object.Equals(V, null)) {
                    if (small) {
                        ret = /*!HC:outClsS*/ ILArray<double> .zeros(minMN,minMN);
                    } else {
                        ret = /*!HC:outClsS*/ ILArray<double> .zeros(M, N);
                    }
                    for (int i = 0; i < minMN; i++) {
                        ret.SetValue(dS[i],i,i); 
                    }
                    if (!Object.Equals(U, null))
                        U = new /*!HC:outClsU*/ ILArray<double> (dU,M,dU.Length / M);
                    if (!Object.Equals(V, null)) {
                        /*!HC:complxConj*/
                        V = new  ILArray<double> (dVT,N,dVT.Length / N).T;  
                    }
                } else {
                    ret = new /*!HC:outClsS*/ ILArray<double> (dS,minMN,1); 
                }
            }
            return ret;
        }