Esempio n. 1
0
        /// <summary>
        /// QR decomposition with pivoting, possibly economical sized
        /// </summary>
        /// <param name="A">general input matrix A of size [m x n]</param>
        /// <param name="R">output parameter. Upper triangular matrix R as
        /// result of decomposition. Size [m x n] or [min(m,n) x n] depending
        /// on <paramref name="economySize"/> (see remarks). </param>
        /// <param name="economySize"><para>if true, <list type="bullet">
        /// <item>the size of Q and R will be [m x m] and [m x n] respectively.
        /// However, if m &lt; n, the economySize parameter has no effect on
        /// those sizes.</item>
        /// <item>the output parameter E will be returned as row permutation
        /// vector rather than as permutation matrix</item></list></para>
        /// <para>if false, this function acts exactly as its overload
        /// <see cref="ILNumerics.BuiltInFunctions.ILMath.qr(ILArray&lt;double&gt;,ref ILArray&lt;double&gt;,ref ILArray&lt;double&gt;)"/></para>
        /// </param>
        /// <param name="E">permutation matrix from pivoting. Size [m x m].
        /// If this is not null, the permutation matrix/ vector E will be returned.
        /// <para>E is of size [n x n], if <paramref name="economySize"/> is
        /// true, a row vector of length n otherwise</para></param>
        /// <returns>Orthonormal / unitary matrix Q as result of decomposition.
        /// Size [m x m] or [m x min(m,n)], depending on <paramref name="economySize"/>
        /// (see remarks below)</returns>
        /// <remarks><para> If <paramref name="economySize"/> is false, the function
        /// returns Q, R and E such that the equation A * E = Q * R holds except
        /// roundoff errors. </para>
        /// <para>If <paramref name="economySize"/> is true, E will be a permutation
        /// vector and the equation A[null,E] == Q * R holds (except roundoff).</para>
        /// <para>E reflects the pivoting of A done inside LAPACK in order to give R
        /// increasingly diagonal elements.</para>
        /// <para>Q, R and E will be solid ILArray's.</para></remarks>
        public static ILArray <complex> qr(
            ILArray <complex> A,
            ref ILArray <complex> R,
            ref ILArray <complex> E,
            bool economySize)
        {
            if (Object.Equals(R, null))
            {
                return(qr(A));
            }
            int m = A.Dimensions[0];
            int n = A.Dimensions[1];

            if (m < n && economySize)
            {
                return(qr(A, ref R, false));
            }
            ILArray <complex> ret;

            if (m == 0 || n == 0)
            {
                R = new  ILArray <complex> (new  complex [0], m, n);
                E = new  ILArray <complex> (new  complex [0], 1, 0);
                return(ILArray <complex> .empty(A.Dimensions));
            }
            // prepare IPVT
            if (object.Equals(E, null))
            {
                return(qr(A, ref R, economySize));
            }
            if (!economySize)
            {
                E = new  ILArray <complex> (new  complex [n * n], n, n);
            }
            else
            {
                E = new  ILArray <complex> (new  complex [n], 1, n);
            }
            int [] ipvt  = new int[n];
            int    minMN = (m < n)?m:n;
            int    info  = 0;

            complex [] tau = new  complex [minMN];
            complex [] QArr;
            if (m >= n)
            {
                ret = new  ILArray <complex> (
                    new  complex [(economySize)? minMN * m : m * m],
                    m, (economySize)? minMN: m);
            }
            else
            {
                // economySize is always false ... !
                // a temporary array is needed for extraction of the compact lapack Q (?geqrf)
                ret = new  ILArray <complex> (
                    new  complex [m * n], m, n);
            }
            QArr = ret.m_data;
            for (int i = m * n; i-- > 0;)
            {
                QArr[i] = A.GetValue(i);
            }
            Lapack.zgeqp3(m, n, QArr, m, ipvt, tau, ref info);
            if (info != 0)
            {
                throw new ILArgumentException("qr: error inside lapack library (?geqrf). info=" + info.ToString());
            }
            // extract R, Q
            if (economySize)
            {
                R = copyUpperTriangle(QArr, m, n, minMN);
                Lapack.zungqr(m, minMN, tau.Length, QArr, m, tau, ref info);
                // transform E into out typed vector
                for (int i = 0; i < n; i++)
                {
                    E.m_data[i] = ipvt[i] - 1;
                }
            }
            else
            {
                R = copyUpperTriangle(QArr, m, n, m);
                Lapack.zungqr(m, m, tau.Length, QArr, m, tau, ref info);
                if (m < n)
                {
                    ret = ret[":;0:" + (m - 1)];
                }
                // transform E into matrix
                for (int i = 0; i < n; i++)
                {
                    E.m_data[(ipvt[i] - 1) + n * i] = new complex(1.0, 0.0);
                }
            }
            if (info != 0)
            {
                throw new ILArgumentException("qr: error in lapack library (???gqr). info=" + info.ToString());
            }
            return(ret);
        }