Exemplo n.º 1
0
        /// <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;
        }
Exemplo n.º 2
0
    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];
    }