/// <summary> /// Calculates the eigenvalues and optionally the eigenvectors of a symmetric matrix. Does not check if the matrix is /// symmetric. /// </summary> /// <param name="order">The number of rows/columns of the original symmetric matrix.</param> /// <param name="matrix"> /// The original matrix in full column major format. Will be overwritten. /// </param> /// <param name="calcEigenvectors"> /// If true, both eigenvalues and eigenvectors will be computed. Else only eigenvalues will be computed. /// </param> /// <returns>An object holding the eigensystem of the matrix.</returns> public static SymmetricEigensystemFull Create(int order, double[] matrix, bool calcEigenvectors) { EigensystemJob job = calcEigenvectors ? EigensystemJob.EigenvaluesAndEigenVectors : EigensystemJob.OnlyEigenvalues; int leadingDimA = order; var eigenvalues = new double[order]; // symmetric matrices have as many eigenvalues as their size LapackEigensystems.Dsyev(job, StoredTriangle.Upper, order, matrix, 0, leadingDimA, eigenvalues, 0); if (calcEigenvectors) { // The original matrix is overwritten by the eigenvectors var eigenvectors = Matrix.CreateFromArray(matrix, order, order); return(new SymmetricEigensystemFull(order, Vector.CreateFromArray(eigenvalues), eigenvectors)); } else { return(new SymmetricEigensystemFull(order, Vector.CreateFromArray(eigenvalues), null)); } }
/// <summary> /// Calculates the eigenvalues and optionally the left and right eigenvectors of a square matrix. Does not check if the /// matrix is square. /// </summary> /// <param name="order">The number of rows/columns of the original square matrix.</param> /// <param name="matrix"> /// The original matrix in full column major format. Will be overwritten. /// </param> /// <param name="calcLeftEigenvectors"> /// If true, left eigenvectors will be computed, in addition to eigenvalues and possibly right eigenvectors. /// Else left eigenvectors will not be computed. /// </param> /// <param name="calcRightEigenvectors"> /// If true, right eigenvectors will be computed, in addition to eigenvalues and possibly left eigenvectors. /// Else right eigenvectors will not be computed. /// </param> /// <returns>An object holding the eigensystem of the matrix.</returns> public static NonSymmetricEigensystemFull Create( int order, double[] matrix, bool calcLeftEigenvectors, bool calcRightEigenvectors) { // Prepare LAPACK input int leadingDimA = order; // There as many eigenvalues as the order of the matrix, but some the complex eigenvalues come in conjugate pairs. var eigenvaluesReal = new double[order]; var eigenvaluesImaginary = new double[order]; EigensystemJob jobLeft; double[] eigenvectorsLeft; int leadingDimEigenvectorsLeft; if (calcLeftEigenvectors) { jobLeft = EigensystemJob.EigenvaluesAndEigenVectors; eigenvectorsLeft = new double[order * order]; leadingDimEigenvectorsLeft = order; } else { jobLeft = EigensystemJob.OnlyEigenvalues; eigenvectorsLeft = new double[1]; leadingDimEigenvectorsLeft = 1; } EigensystemJob jobRight; double[] eigenvectorsRight; int leadingDimEigenvectorsRight; if (calcRightEigenvectors) { jobRight = EigensystemJob.EigenvaluesAndEigenVectors; eigenvectorsRight = new double[order * order]; leadingDimEigenvectorsRight = order; } else { jobRight = EigensystemJob.OnlyEigenvalues; eigenvectorsRight = new double[1]; leadingDimEigenvectorsRight = 1; } // Call Lapack LapackEigensystems.Dgeev(jobLeft, jobRight, order, matrix, 0, leadingDimA, eigenvaluesReal, 0, eigenvaluesImaginary, 0, eigenvectorsLeft, 0, leadingDimEigenvectorsLeft, eigenvectorsRight, 0, leadingDimEigenvectorsRight); // Repack LAPACK output into usable classes if (!calcLeftEigenvectors) { eigenvectorsLeft = null; } if (!calcRightEigenvectors) { eigenvectorsRight = null; } return(new NonSymmetricEigensystemFull( order, eigenvaluesReal, eigenvaluesImaginary, eigenvectorsLeft, eigenvectorsRight)); }