/// <summary> /// find all eigenvalues of symmetric (hermitian) matrix /// </summary> /// <param name="A">input matrix, Size [n x n], symmetric (hermitian for complex A) </param> /// <returns>array of size [n,1] with eigenvalues of A.</returns> /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para> /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks> /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception> public static /*!HC:HCCls1*/ ILArray<double> eigSymm (/*!HC:HCCls1*/ ILArray<double> A) { if (A.IsEmpty) { return /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); } int n = A.Dimensions[0]; if (n != A.Dimensions[1]) throw new ILArgumentException("eigSymm: input matrix A must be square and symmetric/hermitian."); /*!HC:HCCls1*/ ILArray<double> ret = null; int m = 0,info = 0; /*!HC:HCCls1*/ ILArray<double> tmpA = A.copyUpperTriangle(n); /*!HC:HCClsReal*/ ILArray<double> w = new /*!HC:HCClsReal*/ ILArray<double> (new /*!HC:HCArrReal*/ double [n],1,n); /*!HC:HCArr1*/ double [] z = new /*!HC:HCArr1*/ double [1]; ; int [] isuppz = new int[2 * n]; /*!HC:lapack_???evr*/ Lapack.dsyevr ('N','A','U',n,tmpA.m_data,n,0,0,0,0,0,ref m,w.m_data,z,1,isuppz,ref info); ret = /*!HC:HCClsConv3*/ /**/ (w); return ret; } /// <summary> /// find all eigenvalues and -vectors of symmetric (hermitian) matrix /// </summary> /// <param name="A">input matrix, Size [n x n], symmetric (hermitian for complex A) </param> /// <param name="V">output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param> /// <returns>diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns> /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para> /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks> /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square.</exception> public static /*!HC:HCCls1*/ ILArray<double> eigSymm (/*!HC:HCCls1*/ ILArray<double> A, ref /*!HC:HCCls1*/ ILArray<double> V) { if (A.IsEmpty) { V = /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); return /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); } int n = A.Dimensions[0]; if (n != A.Dimensions[1]) throw new ILArgumentException("eigSymm: input matrix A must be square and symmetric/hermitian."); /*!HC:HCCls1*/ ILArray<double> ret = null; int m = 0,ldz = 0,info = 0; /*!HC:HCCls1*/ ILArray<double> tmpA = A.copyUpperTriangle(n); /*!HC:HCClsReal*/ ILArray<double> w = new /*!HC:HCClsReal*/ ILArray<double> (new /*!HC:HCArrReal*/ double [n],n,1); /*!HC:HCArr1*/ double [] z; char jobz; if (object.Equals(V,null)) { z = new /*!HC:HCArr1*/ double [1]; jobz = 'N'; ldz = 1; } else { z = new /*!HC:HCArr1*/ double [n * n]; jobz = 'V'; ldz = n; } int [] isuppz = new int[2 * n]; /*!HC:lapack_???evr*/ Lapack.dsyevr (jobz,'A','U',n,tmpA.m_data,n,1,n,0,0,0,ref m,w.m_data,z,ldz,isuppz,ref info); if (info != 0) throw new ILException("eigSymm: error returned from lapack: " + info); if (jobz == 'V') { V = new /*!HC:HCCls1*/ ILArray<double> (z,n,n); V = V[null,ILMath.vector(0,m-1)]; ret = ILMath.diag(/*!HC:HCClsConv3*/ /**/ (w)); } else { ret = /*!HC:HCClsConv3*/ /**/ (w); } return ret; } /// <summary> /// find some eigenvalues and -vectors of symmetric (hermitian) matrix /// </summary> /// <param name="A">input matrix, Size [n x n], symmetric (hermitian for complex A) </param> /// <param name="V">output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param> /// <param name="rangeStart">specify the lowest limit for the range of eigenvalues to be queried.</param> /// <param name="rangeEnd">specify the upper limit for the range of eigenvalues to be queried.</param> /// <returns>diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns> /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para> /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks> /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> < <paramref name="rangeStart"/></exception> public static /*!HC:HCCls1*/ ILArray<double> eigSymm (/*!HC:HCCls1*/ ILArray<double> A, ref /*!HC:HCCls1*/ ILArray<double> V, int rangeStart, int rangeEnd) { if (A.IsEmpty) { V = /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); return /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); } int n = A.Dimensions[0]; if (n != A.Dimensions[1]) throw new ILArgumentException("eigSymm: input matrix A must be square and symmetric/hermitian."); /*!HC:HCCls1*/ ILArray<double> ret = null; int m = 0,ldz = 0,info = 0; if (rangeEnd < rangeStart || rangeStart < 1) throw new ILArgumentException("eigSymm: invalid range of eigenvalues requested"); /*!HC:HCCls1*/ ILArray<double> tmpA = A.copyUpperTriangle(n); /*!HC:HCClsReal*/ ILArray<double> w = new /*!HC:HCClsReal*/ ILArray<double> (new /*!HC:HCArrReal*/ double [n],1,n); /*!HC:HCArr1*/ double [] z; char jobz; if (object.Equals(V,null)) { z = new /*!HC:HCArr1*/ double [1]; jobz = 'N'; ldz = 1; } else { z = new /*!HC:HCArr1*/ double [n * n]; jobz = 'V'; ldz = n; } int [] isuppz = new int[2 * n]; /*!HC:lapack_???evr*/ Lapack.dsyevr (jobz,'I','U',n,tmpA.m_data,n,0,0,rangeStart,rangeEnd,0,ref m,w.m_data,z,ldz,isuppz,ref info); ret = ILMath.diag(/*!HC:HCClsConv3*/ /**/ (w)); if (jobz == 'V') { V = new /*!HC:HCCls1*/ ILArray<double> (z,n,n); V = V[null,ILMath.vector(0,m-1)]; } return ret; }
/// <summary> /// find some eigenvalues and -vectors of symmetric (hermitian) matrix /// </summary> /// <param name="A">input matrix, Size [n x n], symmetric (hermitian for complex A) </param> /// <param name="V">output: n eigenvectors as columns. Size [n x n]. If V is null on input, the eigenvectors will not be computed and V is not changed. </param> /// <param name="rangeStart">The eigenvalues will be returned by increasing size. This will determine the number of the first eigenvalue to be returned.</param> /// <param name="rangeEnd">Determine the number of the last eigenvalue to be returned.</param> /// <returns>diagonal matrix of size [n,n] with eigenvalues of A on the main diagonal.</returns> /// <remarks><para>For computation the Lapack functions dsyevr, ssyevr, chesvr and zheesv are used. </para> /// <para>Since A is symmetric, the eigenvalues will always be real. Therefore the return value will be of the same inner type as A.</para></remarks> /// <exception cref="ILNumerics.Exceptions.ILArgumentException">if A is not square or <paramref name="rangeEnd"/> < <paramref name="rangeStart"/> or if either one is <= 0.</exception> public static /*!HC:HCCls1*/ ILArray<double> eigSymm (/*!HC:HCCls1*/ ILArray<double> A, ref /*!HC:HCCls1*/ ILArray<double> V, /*!HC:HCArrReal*/ double rangeStart, /*!HC:HCArrReal*/ double rangeEnd) { if (A.IsEmpty) { V = /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); return /*!HC:HCCls1*/ ILArray<double> .empty(A.Dimensions); } int n = A.Dimensions[0]; if (n != A.Dimensions[1]) throw new ILArgumentException("eigSymm: input matrix A must be square and symmetric/hermitian."); /*!HC:HCCls1*/ ILArray<double> ret = null; int m = 0,ldz = 0,info = 0; if (rangeStart > rangeEnd) throw new ILArgumentException("eigSymm: invalid range of eigenvalues requested"); /*!HC:HCCls1*/ ILArray<double> tmpA = A.copyUpperTriangle(n); /*!HC:HCClsReal*/ ILArray<double> w = new /*!HC:HCClsReal*/ ILArray<double> (new /*!HC:HCArrReal*/ double [n],1,n); /*!HC:HCArr1*/ double [] z; char jobz; if (object.Equals(V,null)) { z = new /*!HC:HCArr1*/ double [1]; jobz = 'N'; ldz = 1; } else { z = new /*!HC:HCArr1*/ double [n * n]; jobz = 'V'; ldz = n; } int [] isuppz = new int[2 * n]; /*!HC:lapack_???evr*/ Lapack.dsyevr (jobz,'V','U',n,tmpA.m_data,n,rangeStart,rangeEnd,0,0,0, ref m,w.m_data,z,ldz,isuppz,ref info); ret = ILMath.diag(/*!HC:HCClsConv3*/ /**/ (w)); if (jobz == 'V') { V = new /*!HC:HCCls1*/ ILArray<double> (z,n,n); V = V[null,ILMath.vector(0,m-1)]; }
/// <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<double>)"/> /// or <see cref="ILNumerics.BuiltInFunctions.ILMath.eigSymm(ILArray<double>,ref ILArray<double>)"/> /// 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<double>)"/> /// <seealso cref="ILNumerics.BuiltInFunctions.ILMath.eig(ILArray<double>,ref ILArray<complex>,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; }