/// <summary> ///Computes all the eigenvalues and eigenvectors of /// a real symmetric band matrix A. /// </summary> /// <param name="A">The real symmetric band matrix A.</param> /// <param name="EigenVects">The eigenvectors.</param> /// <returns>The eigenvalues.</returns> public Matrix GetEigenvalues(SymmetricBandMatrix A, out Matrix EigenVects) { if (this._dsbev == null) this._dsbev = new DSBEV(); this.CheckDimensions(A); Matrix SymmetricBand = A.GetSymmetricBandPackedMatrix(); double[] SymmetricBandData = SymmetricBand.Data; EigenVects = new Matrix(A.RowCount, A.ColumnCount); double[] EigenVectsData = EigenVects.Data; Matrix EigenVals = new Matrix(A.RowCount, 1); double[] EigenValsData = EigenVals.Data; int Info = 0; double[] Work = new double[3 * A.RowCount - 2]; _dsbev.Run("V", "U", A.RowCount, A.UpperBandWidth, ref SymmetricBandData, 0, SymmetricBand.RowCount, ref EigenValsData, 0, ref EigenVectsData, 0, A.RowCount, ref Work, 0, ref Info); #region Error /// = 0: successful exit /// .LT. 0: if INFO = -i, the i-th argument had an illegal value /// .GT. 0: if INFO = i, the algorithm failed to converge; i /// off-diagonal elements of an intermediate tridiagonal /// form did not converge to zero. if (Info < 0) { string infoSTg = Math.Abs(Info).ToString(); throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value"); } else if (Info > 0) { string infoSTg = Math.Abs(Info).ToString(); throw new Exception("The algorithm failed to converge."); } #endregion return EigenVals; }
private void lapackeigsys(int numevals, int num, double[] a, bool packed, bool upper, double[] lowevals, double[] lowevecs) { // The inputs char jobz = 'V'; // Compute eigenvalues and eigenvectors char range = 'I'; // the IL-th through IU-th eigenvalues will be found. char uplo = (upper ? 'U' : 'L'); // If not packed, then it makes no difference if up or down. int n = num; // The order of the matrix A. N >= 0. int lda = num; // The leading dimension of the array A. // This is not needed for packed, since packed is really a vector, so no LDA double vl = 0.0; // Not referenced if RANGE = 'A' or 'I'. double vu = 0.0; // Not referenced if RANGE = 'A' or 'I'. int il = 1; // lowest eigenvalue thru the int iu = numevals; // numevals eigenvalues are found. /* indices (in ascending order) of the smallest and largest eigenvalues to be returned. 1 <= IL <= IU <= N, if N > 0; */ char slamchchar = 'S'; double abstol = 2 * Double.Epsilon; // 2 * slamch_(&slamchchar); /* The absolute error tolerance for the eigenvalues. ABSTOL + EPS * max( |a|,|b| ) , Eigenvalues will be computed most accurately when ABSTOL is set to twice the underflow threshold 2*SLAMCH('S'), not zero. */ int ldz = num; // The leading dimension of the array int lwork = 8 * num; // The length of the arr WORK. LWORK >= max(1,8*N). // This is not needed for packed, since it assumes LWORK = 8*N // now the outputs int m; /* Output: The total number of eigenvalues found. 0 <= M <= N. If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. */ double[] w = new double[num]; // malloc(sizeof(double)*num); /* (output) On normal exit, the first M elements contain the selected eigenvalues in ascending order. However, we must allocate extra space?*/ // double *z = new double[num*numevals]; // This is what we use lowevecs for. Not so for W, since that has // num elements, not numevals. We have to copy over those values. /* (output) If JOBZ = 'V', then if INFO = 0, the first M columns of Z contain the orthonormal eigenvectors of the matrix A corresponding to the selected eigenvalues, with the i-th column of Z holding the eigenvector associated with W(i). */ double[] work = new double[lwork]; // On exit, if INFO = 0, WORK(1) returns the optimal LWORK. int[] iwork = new int[5 * num]; // dimension (5*N) int[] ifail = new int[num]; /* If JOBZ = 'V', then if INFO = 0, the first M elements of IFAIL are zero. If INFO > 0, then IFAIL contains the indices of the eigenvectors that failed to converge. */ int info = 0; /* = 0: successful exit < 0: if INFO = -i, i-th argument had illegal value > 0: if INFO = i, i eigenvectors failed to converge Their indices are stored in array IFAIL. */ // Compute! -- LAPACK driver routine (version 2.0) -- September 30, 1994 if (packed) { DotNumerics.LinearAlgebra.CSLapack.DSBEV dsbev_ = new DotNumerics.LinearAlgebra.CSLapack.DSBEV(); dspevx_(jobz, range, uplo, n, a, /*-*/ vl, vu, il, iu, abstol, m, w, lowevecs, ldz, work, /*---*/ iwork, ifail, info); // dspevx_.Run(jobz, "", } else dsyevx_(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, lowevecs, ldz, work, lwork, iwork, ifail, info); // Done! if (info != 0) { string err = "Errors in lapackeigsys with " + (packed ? "sspevx_" : "ssyevx_") + "!!! info: " + info + "\n"; if (info < 0) { err += "The " + info + "'th argument had an illegal value!\n"; } else { err += info + " eigenvectors failed to converge! They were:\n"; for (int i = 0; i < num; i++) { if (ifail[i] != 0) { err += "Index number:" + ifail[i] + "\n"; } } } throw new InvalidOperationException(err); } // We didn't use lowevals as the input for the routine // since it expects num elements in lowevals, instead of numevals. for (int i = 0; i < numevals; i++) lowevals[i] = w[i]; }