コード例 #1
0
        public override void Transformby(Matrix mat)
        {
            if (mat.IsUnitMatrix())
            {
                return;
            }
            Matrix           mult     = (ECSMatrix * mat);
            MatrixProperties matprops = mult.Properties;

            Radius *= matprops.GetScaleXY();
            base.Transformby(mat);
        }
コード例 #2
0
ファイル: slash.cs プロジェクト: zhufengGNSS/ILNumerics
// DO NOT EDIT INSIDE THIS REGION !! CHANGES WILL BE LOST !!

        /// <summary>
        /// Solve linear equation system
        /// </summary>
        /// <param name="A">Matrix A. Size [n x q]</param>
        /// <param name="B">'rigth hand side' B. Size [n x m]</param>
        /// <returns> solution x solving the equation system: multiply(A, x) = B. Size [n x m]</returns>
        /// <remarks><para>depending on the structure and properties of A, the equation system will be solved in different ways:
        /// <list type="bullet">
        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's!
        /// <example><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix
        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
        /// // now construct a right side and solve the equations:
        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T;
        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved beeing reference arrays! ]]></example></item>
        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
        /// <para>if during the cholesky factorization A was found to be <b>not positive definite</b> - the cholesky factorization is canceled. </para></item>
        /// <item>otherwise, if A is square only, it will be decomposed into upper and lower triangular martices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
        /// </list></para>
        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
        /// <para>For specifiying the rank of A in the unsquare case (q != n), the eps member from <see cref="ILNumerics.Settings.ILSettings"/> class is used.</para></remarks>
        public static ILArray <complex> linsolve(ILArray <complex> A, ILArray <complex> B)
        {
            if (object.Equals(A, null) || object.Equals(B, null))
            {
                throw new ILArgumentException("linsolve: parameter must not be null!");
            }
            MatrixProperties props = MatrixProperties.None;

            if (A.Dimensions[0] == A.Dimensions[1])
            {
                props |= MatrixProperties.Square;
                if (ILMath.istriup(A))
                {
                    props |= MatrixProperties.UpperTriangular;
                    return(linsolve(A, B, ref props));
                }
                if (ILMath.istrilow(A))
                {
                    props |= MatrixProperties.LowerTriangular;
                    return(linsolve(A, B, ref props));
                }
                if (ILMath.ishermitian(A))
                {
                    // give cholesky a try
                    props |= MatrixProperties.Hermitian;
                    props |= MatrixProperties.PositivDefinite;
                    ILArray <complex> ret = linsolve(A, B, ref props);
                    if (!object.Equals(ret, null))
                    {
                        return(ret);
                    }
                    else
                    {
                        props ^= MatrixProperties.PositivDefinite;
                    }
                }
            }
            return(linsolve(A, B, ref props));
        }
コード例 #3
0
ファイル: eig.cs プロジェクト: wdxa/ILNumerics
 /// <summary>
 /// find eigenvalues  and eigenvectors 
 /// </summary>
 /// <param name="A">input: square matrix, size [n x n]</param>
 /// <param name="V">output (optional): eigenvectors</param>   
 /// <param name="propsA">matrix properties, on input - if specified, 
 /// will be used to choose the proper method of solution. On exit will be 
 /// filled according to the properties of A.</param>
 /// <param name="balance">true: permute A in order to increase the 
 /// numerical stability, false: do not permute A.</param>
 /// <returns>eigenvalues as vector (if V is null) or as diagonoal 
 /// matrix (if V was requested, i.e. not equaled null).</returns>
 /// <remarks><para>The eigenvalues of A are found by use of the 
 /// Lapack functions dgeevx, sgeevx, cgeevx and zgeevx. </para>
 /// <para>The arrays returned will be of complex inner type, 
 /// since no further constraints are set on the structure of 
 /// A (it may be nonsymmetric). Use 
 /// <see cref="ILNumerics.BuiltInFunctions.ILMath.eigSymm(ILArray&lt;double&gt;)"/> 
 /// or <see cref="ILNumerics.BuiltInFunctions.ILMath.eigSymm(ILArray&lt;double&gt;,ref ILArray&lt;double&gt;)"/> 
 /// functions for computing the real eigenvalues of symmetric 
 /// matrices explicitly.</para>
 /// <para>Depending on the parameter <paramref name="balance"/>, 
 /// A will be balanced first. This includes permutations and 
 /// scaling of A in order to improve the conditioning of the 
 /// eigenvalues.</para></remarks>
 /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.eig(ILArray&lt;double&gt;)"/>
 /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.eig(ILArray&lt;double&gt;,ref ILArray&lt;complex&gt;,ref MatrixProperties,bool)"/>
 /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if a 
 /// is not square</exception>
 public static /*!HC:HCClsCmplx*/ ILArray<complex> eig(/*!HC:HCCls1*/ ILArray<double> A, ref /*!HC:HCClsCmplx*/ ILArray<complex> V, ref MatrixProperties propsA, bool balance) {
     if (A.IsEmpty) {
         V = /*!HC:HCClsCmplx*/ ILArray<complex> .empty(A.Dimensions); 
         return /*!HC:HCClsCmplx*/ ILArray<complex> .empty(A.Dimensions); 
     }
     /*!HC:HCClsCmplx*/ ILArray<complex> ret = null;  
     int n = A.Dimensions[0]; 
     bool createVR = (object.Equals(V,null))? false:true; 
     if (n != A.Dimensions[1]) 
         throw new ILArgumentException("eig: matrix A must be square!");
     propsA |= MatrixProperties.Square; 
     if (((propsA & MatrixProperties.Hermitian) != 0 || ILMath.ishermitian(A))) {
         propsA |= MatrixProperties.Hermitian; 
         /*!HC:HCCls1*/ ILArray<double> Vd = null; 
         if (createVR) 
             Vd = /*!HC:HCCls1*/ ILArray<double> .empty(0,0);
         /*!HC:HCCls1*/ ILArray<double> tmpRet = eigSymm(A,ref Vd);
         if (createVR)
             V = /*!HC:HCCls2Cmplx*/ ILMath.tocomplex (Vd); 
         ret = /*!HC:HCCls2Cmplx*/ ILMath.tocomplex (tmpRet);
     } else {
         // nonsymmetric case
         char bal = (balance)? 'B':'N', jobvr;  
         /*!HC:HCCls1*/ ILArray<double> tmpA = (/*!HC:HCCls1*/ ILArray<double> )A.Clone(); 
         /*!HC:HCArr1*/ double [] vr = null;
         /*!HC:HCArr1*/ double [] wr = ILMemoryPool.Pool.New</*!HC:HCArr1*/ double >(n); 
         /*!HC:HCArrWI*/ 
         double[] wi = ILMemoryPool.Pool.New<double>(n); 
         /*!HC:HCArrReal*/ double [] scale  = ILMemoryPool.Pool.New</*!HC:HCArrReal*/ double >(n);
         /*!HC:HCArrReal*/ double [] rconde = ILMemoryPool.Pool.New</*!HC:HCArrReal*/ double >(n); 
         /*!HC:HCArrReal*/ double [] rcondv = ILMemoryPool.Pool.New</*!HC:HCArrReal*/ double >(n); 
         /*!HC:HCArrReal*/ double abnrm = 0; 
         int ldvr, ilo = 0, ihi = 0, info = 0;
         if (createVR) {
             ldvr = n;
             vr = ILMemoryPool.Pool.New</*!HC:HCArr1*/ double >(n * n);
             jobvr = 'V'; 
         } else {
             ldvr = 1; 
             vr = new /*!HC:HCArr1*/ double [1]; 
             jobvr = 'N'; 
         }
         /*!HC:HC?geevx*/
         Lapack.dgeevx(bal,'N',jobvr,'N',n,tmpA.m_data,n,wr,wi,new /*!HC:HCArr1*/ double [1],1,vr,ldvr,ref ilo,ref ihi,scale,ref abnrm,rconde,rcondv,ref info);   
         if (info != 0) 
             throw new ILArgumentException("eig: error in Lapack '?geevx': (" + info + ")");
         // create eigenvalues 
         /*!HC:HCArrCmplx*/ complex [] retArr = ILMemoryPool.Pool.New</*!HC:HCArrCmplx*/ complex >(n); 
         for (int i = 0; i < n; i++) {
             /*!HC:HCSortEVal*/
             retArr[i].real = wr[i]; retArr[i].imag = wi[i]; 
         }
         ret = new /*!HC:HCClsCmplx*/ ILArray<complex> (retArr,n,1);
         if (createVR) {
             #region HCSortEVec
             complex [] VArr = ILMemoryPool.Pool.New< complex >(n * n);
             for (int c = 0; c < n; c++) {
                 if (wi[c] != 0 && wi[c+1] != 0 && c < n-1) {
                     ilo = n * c; ihi = ilo + n;
                     for (int r = 0; r < n; r++) {
                         VArr[ilo].real = vr[ilo];
                         VArr[ilo].imag = vr[ihi];  
                         VArr[ihi].real = vr[ilo];  
                         VArr[ihi].imag = -vr[ihi]; 
                         ilo++; ihi++; 
                     }
                     c++; 
                 } else {
                     ilo = n * c;
                     for (int r = 0; r < n; r++) {
                         VArr[ilo].real = vr[ilo];
                         ilo++; 
                     }
                 }
             }
             V = new ILArray<complex> (VArr,n,n); 
             #endregion HYCALPER
             if (createVR) 
                 ret = ILMath.diag(ret); 
         }
     }
     return ret; 
 }
コード例 #4
0
 public static uint GetMatrixIndex(MatrixProperties matrixProperties)
 {
     return(matrixProperties.Columns * matrixProperties.Size + matrixProperties.Rows);
 }
コード例 #5
0
ファイル: TESTILLapack.cs プロジェクト: wdxa/ILNumerics
 private void Test_slash(ILArray<double> A, ILArray<double> B, MatrixProperties props, double tol) {
     int errorCode = 0; 
     try {
         ILArray<double> Res = ILMath.linsolve(A,B,ref props); 
         if (ILMath.norm(ILMath.multiply(A, Res) - B) > tol)
             throw new Exception("Test_slash: invalid result (double)");
         ILArray<float> AF = ILMath.tosingle(A); 
         ILArray<float> BF = ILMath.tosingle(B); 
         ILArray<float> ResF = ILMath.linsolve(AF,BF,ref props); 
         if (ILMath.norm(ILMath.multiply(AF, ResF) - BF) > tol)
             throw new Exception("Test_slash: invalid result (float)");
         ILArray<fcomplex> AFc = ILMath.tofcomplex(A); 
         ILArray<fcomplex> BFc = ILMath.tofcomplex(B); 
         ILArray<fcomplex> ResFc = ILMath.linsolve(AFc,BFc,ref props); 
         if (ILMath.norm(ILMath.multiply(AFc, ResFc) - BFc) > tol)
             throw new Exception("Test_slash: invalid result (fcomplex)");
         ILArray<complex> AC = ILMath.tocomplex(A); 
         ILArray<complex> BC = ILMath.tocomplex(B); 
         ILArray<complex> ResC = ILMath.linsolve(AC,BC,ref props); 
         if (ILMath.norm(ILMath.multiply(AC, ResC) - BC) > tol)
             throw new Exception("Test_slash: invalid result (complex)");
         Success("Test_slash: A " + A.Dimensions.ToString() + " * x = B " + B.Dimensions.ToString() + " (" + props.ToString() + ")");
     } catch(Exception e) {
         Error(errorCode,e.Message + " input size:" + A.Dimensions.ToString()); 
     }
 }
コード例 #6
0
ファイル: TESTILLapack.cs プロジェクト: wdxa/ILNumerics
 private void Test_slashMatrProp() {
     int errorCode = 0; 
     try {
         
         // construct 4 x 4 matrix, symmetric, positiv definite
         ILArray<double> A = ILMath.randn(4,4);
         A = A + A.T;                  // <- construct symmetry
         A.Diagonal = ILMath.abs(A.Diagonal * 100); // <- construct pos.def.
         
         // now construct a right side and solve the equations: 
         ILArray<double> B = new double[] {1.0,2.0,3.0,4.0}; 
         MatrixProperties prop = new MatrixProperties(); 
         prop |= MatrixProperties.Hermitian; 
         prop |= MatrixProperties.PositivDefinite; 
         ILArray<double> x = ILMath.linsolve(A,B.T,ref prop); 
         //[test: if A was not symm.,pos.def. linsolve returnes null]
         System.Diagnostics.Debug.Assert(!Object.Equals(x,null)); 
         ILArray<double> bTest = ILMath.multiply(A,x);
         ILArray<double> err = ILMath.norm(bTest - B.T); 
     } catch (Exception e) {
         Error(errorCode,e.Message); 
     }
 }
コード例 #7
0
ファイル: slash.cs プロジェクト: wdxa/ILNumerics
 /// <summary>
 /// Solve linear equation system
 /// </summary>
 /// <param name="A">Matrix A. Size [n x q]</param>
 /// <param name="B">'rigth hand side' B. Size [n x m]</param>
 /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. This flag should be tested on return, in order to verify the reliability of the solution.</param>
 /// <returns>the solution x solving multiply(A,x) = B. Size [n x m]</returns>
 /// <remarks><para>depending on the <paramref name="props"/> parameter the equation system will be solved differently for special structures of A:
 /// <list type="bullet">
 /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's! 
 /// <example><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix 
 /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
 /// // now construct a right side and solve the equations: 
 /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T; 
 /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved beeing reference arrays! ]]></example></item>
 /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
 /// <para>if during the cholesky factorization A was found to be <b>not positive definite</b> - the corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
 /// <item>otherwise if A is square only, it will be decomposed into upper and lower triangular matrices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
 /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
 /// </list></para>
 /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
 /// <para>For specifiying the rank of A in the unsquare case (q != n), the eps member from <see cref="ILNumerics.Settings.ILSettings"/> class is used.</para></remarks>
 public static  ILArray<complex> linsolve( ILArray<complex> A,  ILArray<complex> B, ref MatrixProperties props) {
     if (object.Equals(A,null)) 
         throw new ILArgumentException("linsolve: input argument A must not be null!"); 
     if (object.Equals(B,null))
         throw new ILArgumentException("linsolve: input argument B must not be null!"); 
     if (A.IsEmpty || B.IsEmpty)
         return  ILArray<complex> .empty(A.Dimensions); 
     if (A.Dimensions[0] != B.Dimensions[0])
         throw new ILArgumentException("linsolve: number of rows for matrix A must match number of rows for RHS!");
     int info = 0, m = A.Dimensions[0]; 
     ILArray<complex> ret; 
     if (m == A.Dimensions[1]) {
         props |= MatrixProperties.Square; 
         if ((props & MatrixProperties.LowerTriangular) != 0) {
             ret = solveLowerTriangularSystem(A,B,ref info); 
             if (info > 0)
                 props |= MatrixProperties.Singular; 
             return ret;
         } 
         if ((props & MatrixProperties.UpperTriangular) != 0) {
             ret = solveUpperTriangularSystem(A,B, ref info); 
             if (info > 0)
                 props |= MatrixProperties.Singular; 
            return ret; 
         } 
         if ((props & MatrixProperties.Hermitian) != 0) {
             ILArray<complex> cholFact = A.copyUpperTriangle(m);
             Lapack.zpotrf ('U', m, cholFact.m_data, m, ref info); 
             if (info > 0) {
                 props ^= MatrixProperties.Hermitian; 
                 return null; 
             }  else {
                 // solve 
                 ret = ( ILArray<complex> )B.Clone(); 
                 Lapack.zpotrs ('U',m,B.Dimensions[1],cholFact.m_data,m,ret.m_data,m,ref info);   
                 return ret; 
             } 
         } else {
             // attempt complete (expensive) LU factorization 
             ILArray<complex> L = ( ILArray<complex> )A.Clone();  
             int [] pivInd = new int[m]; 
             Lapack.zgetrf (m, m, L.m_data, m, pivInd ,ref info); 
             if (info > 0)
                 props |= MatrixProperties.Singular; 
             ret = ( ILArray<complex> )B.Clone(); 
             Lapack.zgetrs ('N',m,B.Dimensions[1],L.m_data,m,pivInd,ret.m_data,m,ref info); 
             if (info < 0) 
                 throw new ILArgumentException("linsolve: failed to solve via lapack dgetrs");
             return ret; 
         }
     } else {
         // under- / overdetermined system
         int n = A.Dimensions[1], rank = 0, minMN = (m < n)? m:n, maxMN = (m > n)? m:n;
         int nrhs = B.Dimensions[1];
         if (B.Dimensions[0] != m) 
             throw new ILArgumentException("linsolve: right hand side matrix B must match input A!"); 
         ILArray<complex> tmpA = ( ILArray<complex> )A.Clone();
         if (m < n) {
             ret = new  ILArray<complex> (new  complex [n * nrhs],n,nrhs);
             ret["0:"+(m-1)+";:"] = B;
         } else {
             ret = ( ILArray<complex> )B.Clone();
         }
         int [] JPVT = new int [n]; 
         Lapack.zgelsy (m, n, B.Dimensions[1], tmpA.m_data, m, ret.m_data, 
                             maxMN, JPVT,  ILMath.MachineParameterDouble.eps ,
                             ref rank, ref info); 
         if (n < m) {
             ret = ret[ILMath.vector(0,n-1),null];
         }
         if (rank < minMN)
             props |= MatrixProperties.RankDeficient; 
         return ret; 
     }
 }
コード例 #8
0
ファイル: slash.cs プロジェクト: zhufengGNSS/ILNumerics
        /// <summary>
        /// Solve linear equation system
        /// </summary>
        /// <param name="A">Matrix A. Size [n x q]</param>
        /// <param name="B">'rigth hand side' B. Size [n x m]</param>
        /// <param name="props">Matrix properties. If defined, no checks are made for the structure of A. If the matrix A was found to be (close to or) singular, the 'MatrixProperties.Singular' flag in props will be set. This flag should be tested on return, in order to verify the reliability of the solution.</param>
        /// <returns>the solution x solving multiply(A,x) = B. Size [n x m]</returns>
        /// <remarks><para>depending on the <paramref name="props"/> parameter the equation system will be solved differently for special structures of A:
        /// <list type="bullet">
        /// <item>If A is square (q == n) and an <b>upper or lower triangular</b> matrix, the system will directly be solved via backward- or forward substitution. Therefore the Lapack function ?trtrs will be used, whenever the memory layout of A is suitable. This may be the case even for reference ILArray's!
        /// <example><![CDATA[ILArray<double> A = ILMath.randn(4); // construct 4 x 4 matrix
        /// A = A.T; // A is a reference array now! The transpose is fast and does not consume much memory
        /// // now construct a right side and solve the equations:
        /// ILArray<double> B = new ILArray<double> (1.0,2.0,3.0).T;
        /// ILMath.linsolve(A,B); // ... will be carried out via Lapack, even for all arrays involved beeing reference arrays! ]]></example></item>
        /// <item><para>if A is square and symmetric or hermitian, A will be decomposed into a triangular equation system using cholesky factorization and Lapack. The system is than solved using performant Lapack routines.</para>
        /// <para>if during the cholesky factorization A was found to be <b>not positive definite</b> - the corresponding flag in props will be cleaned and <c>null</c> will be returned.</para></item>
        /// <item>otherwise if A is square only, it will be decomposed into upper and lower triangular matrices using LU decomposition and Lapack. The triangular system is than solved using performant Lapack routines.</item>
        /// <item>otherwise, if A is of size [q x n] and q != n, the system is solved using QR decomposition. A may be rank deficient. The solution is computed by use of the Lapack routine '?gelsy' and may be a reference array.</item>
        /// </list></para>
        /// <para>Compatibility with Matlab<sup>(R)</sup>: If A is square, the algorithm used follows the same logic as Matlab up to Rel 14, with the exception of Hessenberg matrices wich are solved via LU factorization here. The un-squared case is handled differently. A direct Lapack driver function (?gelsy) is used here. Therefore the solutions might differ! However, the solution will of course fullfill the equation A * x = B without round off errrors. </para>
        /// <para>For specifiying the rank of A in the unsquare case (q != n), the eps member from <see cref="ILNumerics.Settings.ILSettings"/> class is used.</para></remarks>
        public static ILArray <complex> linsolve(ILArray <complex> A, ILArray <complex> B, ref MatrixProperties props)
        {
            if (object.Equals(A, null))
            {
                throw new ILArgumentException("linsolve: input argument A must not be null!");
            }
            if (object.Equals(B, null))
            {
                throw new ILArgumentException("linsolve: input argument B must not be null!");
            }
            if (A.IsEmpty || B.IsEmpty)
            {
                return(ILArray <complex> .empty(A.Dimensions));
            }
            if (A.Dimensions[0] != B.Dimensions[0])
            {
                throw new ILArgumentException("linsolve: number of rows for matrix A must match number of rows for RHS!");
            }
            int info = 0, m = A.Dimensions[0];
            ILArray <complex> ret;

            if (m == A.Dimensions[1])
            {
                props |= MatrixProperties.Square;
                if ((props & MatrixProperties.LowerTriangular) != 0)
                {
                    ret = solveLowerTriangularSystem(A, B, ref info);
                    if (info > 0)
                    {
                        props |= MatrixProperties.Singular;
                    }
                    return(ret);
                }
                if ((props & MatrixProperties.UpperTriangular) != 0)
                {
                    ret = solveUpperTriangularSystem(A, B, ref info);
                    if (info > 0)
                    {
                        props |= MatrixProperties.Singular;
                    }
                    return(ret);
                }
                if ((props & MatrixProperties.Hermitian) != 0)
                {
                    ILArray <complex> cholFact = A.copyUpperTriangle(m);
                    Lapack.zpotrf('U', m, cholFact.m_data, m, ref info);
                    if (info > 0)
                    {
                        props ^= MatrixProperties.Hermitian;
                        return(null);
                    }
                    else
                    {
                        // solve
                        ret = (ILArray <complex>)B.Clone();
                        Lapack.zpotrs('U', m, B.Dimensions[1], cholFact.m_data, m, ret.m_data, m, ref info);
                        return(ret);
                    }
                }
                else
                {
                    // attempt complete (expensive) LU factorization
                    ILArray <complex> L      = (ILArray <complex>)A.Clone();
                    int []            pivInd = new int[m];
                    Lapack.zgetrf(m, m, L.m_data, m, pivInd, ref info);
                    if (info > 0)
                    {
                        props |= MatrixProperties.Singular;
                    }
                    ret = (ILArray <complex>)B.Clone();
                    Lapack.zgetrs('N', m, B.Dimensions[1], L.m_data, m, pivInd, ret.m_data, m, ref info);
                    if (info < 0)
                    {
                        throw new ILArgumentException("linsolve: failed to solve via lapack dgetrs");
                    }
                    return(ret);
                }
            }
            else
            {
                // under- / overdetermined system
                int n = A.Dimensions[1], rank = 0, minMN = (m < n)? m:n, maxMN = (m > n)? m:n;
                int nrhs = B.Dimensions[1];
                if (B.Dimensions[0] != m)
                {
                    throw new ILArgumentException("linsolve: right hand side matrix B must match input A!");
                }
                ILArray <complex> tmpA = (ILArray <complex>)A.Clone();
                if (m < n)
                {
                    ret = new  ILArray <complex> (new  complex [n * nrhs], n, nrhs);
                    ret["0:" + (m - 1) + ";:"] = B;
                }
                else
                {
                    ret = (ILArray <complex>)B.Clone();
                }
                int [] JPVT = new int [n];
                Lapack.zgelsy(m, n, B.Dimensions[1], tmpA.m_data, m, ret.m_data,
                              maxMN, JPVT, ILMath.MachineParameterDouble.eps,
                              ref rank, ref info);
                if (n < m)
                {
                    ret = ret[ILMath.vector(0, n - 1), null];
                }
                if (rank < minMN)
                {
                    props |= MatrixProperties.RankDeficient;
                }
                return(ret);
            }
        }