// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !! /// <summary> /// QR decomposition - raw Lapack output /// </summary> /// <param name="A">general input matrix A</param> /// <returns>orthonormal / unitary matrix Q and upper triangular /// matrix R packed into single matrix. This is the output of the /// lapack function ?geqrf.</returns> /// <remarks><para>Input matrix A will not be altered. </para> /// <para>The matrix returned is the direct output of the lapack /// function [d,s,c,z]geqrf respectively. This mean that it contains /// the decomposition factors Q and R, but they are cmbined into a /// single matrix for performance reasons. If you need one of the factors, /// you would use the overloaded function /// <see cref="ILNumerics.BuiltInFunctions.ILMath.qr(ILArray<double>,ref ILArray<double>)"/> /// instead, which returns those factors seperately.</para></remarks> public static ILArray <complex> qr(ILArray <complex> A) { if (!A.IsMatrix) { throw new ILArgumentException("qr decomposition: A must be a matrix"); } int m = A.Dimensions[0], n = A.Dimensions[1]; ILArray <complex> ret = (ILArray <complex>)A.Clone(); complex [] tau = new complex [(m < n)?m:n]; int info = 0; Lapack.zgeqrf(m, n, ret.m_data, m, tau, ref info); if (info < 0) { throw new ILArgumentException("qr: an error occoured during decomposition"); } return(ret); }
/// <summary> /// QR decomposition, returning Q and R, optionally 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] (see remarks). </param> /// <param name="economySize">if true, the size of Q and R will /// be [m x m] and [m x n] respectively. However, if m < n, /// the economySize parameter has no effect. </param> /// <returns>Orthonormal real / unitary complex 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>The function returns Q and R such that the equation /// <para>A = Q * R</para> holds with roundoff errors. ('*' /// denotes matrix multiplication.) /// <para>Q and R will be solid ILArray's.</para></remarks> public static ILArray <complex> qr( ILArray <complex> A, ref ILArray <complex> R, 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); return(ILArray <complex> .empty(A.Dimensions)); } 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.zgeqrf(m, n, QArr, m, 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); } 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)]; } } if (info != 0) { throw new ILArgumentException("qr: error in lapack library (???gqr). info=" + info.ToString()); } return(ret); }