internal void Dgeev(EigensystemJob jobLeft, EigensystemJob jobRight, int orderA, double[] matrixA, int offsetA, int leadingDimA, double[] eigvaluesReal, int offsetEigvaluesReal, double[] eigvaluesImaginary, int offsetEigvaluesImaginary, double[] eigvectorsLeft, int offsetEigvectorsLeft, int leadingDimEigvectorsLeft, double[] eigvectorsRight, int offsetEigvectorsRight, int leadingDimEigvectorsRight) { int info = DefaultInfo; QueryWorkspaceAndExecute((work, offsetWork, lWork) => Provider.Dgeev(jobLeft.Translate(), jobRight.Translate(), orderA, ref matrixA, offsetA, leadingDimA, ref eigvaluesReal, offsetEigvaluesReal, ref eigvaluesImaginary, offsetEigvaluesImaginary, ref eigvectorsLeft, offsetEigvectorsLeft, leadingDimEigvectorsLeft, ref eigvectorsRight, offsetEigvectorsRight, leadingDimEigvectorsRight, ref work, offsetWork, lWork, ref info)); if (info > 0) { throw new LapackException($"The QR algorithm failed to compute all the eigenvalues, and no eigenvectors have " + $"been computed. Elements {info+1:N} of the eigenvalues arrays (real and imaginary) contain eigenvalues which" + "have converged"); } else if (info < 0) { ProcessNegativeInfo(info); } }
/// <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)); } }
internal void Dsyev(EigensystemJob job, StoredTriangle triangle, int orderA, double[] matrixA, int offsetA, int leadingDimA, double[] eigenvalues, int offsetEigenvalues) { int info = DefaultInfo; QueryWorkspaceAndExecute((work, offsetWork, lWork) => Provider.Dsyev( job.Translate(), triangle.Translate(), orderA, ref matrixA, offsetA, leadingDimA, ref eigenvalues, offsetEigenvalues, ref work, offsetWork, lWork, ref info)); if (info > 0) { throw new LapackException($"The algorithm failed to converge. There were {info} elements of an intermediate" + " tridiagonal form which did not converge to zero"); } else if (info < 0) { ProcessNegativeInfo(info); } }
internal static string Translate(this EigensystemJob job) => (job == EigensystemJob.OnlyEigenvalues) ? "N" : "V";