- Notifications
You must be signed in to change notification settings - Fork 197
linalg: Eigenvalues and Eigenvectors #816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 27 commits
7d390f7 430c89c 7645a45 6ce5172 2d58c68 15b73fc b5f7f21 892308f 1ebf374 f9279b3 56d89a8 f13e75d 34bb7d7 cdef45f fe1c89e 65099e3 0e13fe5 d0f385a acd93b9 36c8d5a e6aa0f5 17ebed2 bac3187 4f503f7 34284cb f232a76 d19425a cc95fc4 18b95af 1fb2ba9 f5303bf 66f1f17 5501b83 59f3b34 d433869 File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| | @@ -687,6 +687,8 @@ Expert (`Pure`) interface: | |||||
| | ||||||
| `overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. | ||||||
| | ||||||
| `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||
| | ||||||
| ### Return value | ||||||
| | ||||||
| For a full-rank matrix, returns an array value that represents the solution to the linear system of equations. | ||||||
| | @@ -899,6 +901,180 @@ Exceptions trigger an `error stop`. | |||||
| {!example/linalg/example_determinant2.f90!} | ||||||
| ``` | ||||||
| | ||||||
| ## `eig` - Eigenvalues and Eigenvectors of a Square Matrix | ||||||
| | ||||||
| ### Status | ||||||
| | ||||||
| Experimental | ||||||
| | ||||||
| ### Description | ||||||
| | ||||||
| This subroutine computes the solution to the eigenproblem \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), where \( A \) is a square, full-rank, `real` or `complex` matrix. | ||||||
| | ||||||
| Result array `lambda` returns the eigenvalues of \( A \). The user can request eigenvectors to be returned: if provided, on output `left` will contain the left eigenvectors, `right` the right eigenvectors of \( A \). | ||||||
| Both `left` and `right` are rank-2 arrays, where eigenvectors are stored as columns. | ||||||
| The solver is based on LAPACK's `*GEEV` backends. | ||||||
| | ||||||
| ### Syntax | ||||||
| | ||||||
| `call ` [[stdlib_linalg(module):eig(interface)]] `(a, lambda [, right] [,left] [,overwrite_a] [,err])` | ||||||
| | ||||||
| ### Arguments | ||||||
| | ||||||
| `a` : `real` or `complex` square array containing the coefficient matrix. If `overwrite_a=.false.`, it is an `intent(in)` argument. Otherwise, it is an `intent(inout)` argument and is destroyed by the call. | ||||||
| | ||||||
| `lambda`: Shall be a `complex` or `real` rank-1 array of the same kind as `a`, containing the eigenvalues, or their `real` component only. It is an `intent(out)` argument. | ||||||
| | ||||||
| `right` (optional): Shall be a `complex` rank-2 array of the same size and kind as `a`, containing the right eigenvectors of `a`. It is an `intent(out)` argument. | ||||||
| | ||||||
| `left` (optional): Shall be a `complex` rank-2 array of the same size and kind as `a`, containing the left eigenvectors of `a`. It is an `intent(out)` argument. | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
| ||||||
| | ||||||
| `overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
What is the default value (.true. or .false.)? | ||||||
| | ||||||
| `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||
| | ||||||
| ### Return value | ||||||
| | ||||||
| Raises `LINALG_ERROR` if the calculation did not converge. | ||||||
| Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. | ||||||
| Raises `LINALG_VALUE_ERROR` if the `real` component is only requested, but the eigenvalues have non-trivial imaginary parts. | ||||||
| If `err` is not present, exceptions trigger an `error stop`. | ||||||
| | ||||||
| ### Example | ||||||
| | ||||||
| ```fortran | ||||||
| {!example/linalg/example_eig.f90!} | ||||||
| ``` | ||||||
| | ||||||
| ## `eigh` - Eigenvalues and Eigenvectors of a Real symmetric or Complex Hermitian Square Matrix | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
| ||||||
| | ||||||
| ### Status | ||||||
| | ||||||
| Experimental | ||||||
| | ||||||
| ### Description | ||||||
| | ||||||
| This subroutine computes the solution to the eigendecomposition \( A \cdot \bar{v} - \lambda \cdot \bar{v} \), | ||||||
| where \( A \) is a square, full-rank, `real` symmetric \( A = A^T \) or `complex` Hermitian \( A = A^H \) matrix. | ||||||
| | ||||||
| Result array `lambda` returns the `real` eigenvalues of \( A \). The user can request the orthogonal eigenvectors | ||||||
| to be returned: on output `vectors` may contain the matrix of eigenvectors, returned as a columns. | ||||||
| ||||||
| | ||||||
| Normally, only the lower triangular part of \( A \) is accessed. On input, `logical` flag `upper_a` | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggested change
| ||||||
| allows the user to request what triangular part of the matrix should be used. | ||||||
| | ||||||
| The solver is based on LAPACK's `*SYEV` and `*HEEV` backends. | ||||||
| | ||||||
| ### Syntax | ||||||
| | ||||||
| `call ` [[stdlib_linalg(module):eigh(interface)]] `(a, lambda [, vectors] [, upper_a] [, overwrite_a] [,err])` | ||||||
| | ||||||
| ### Arguments | ||||||
| | ||||||
| `a` : `real` or `complex` square array containing the coefficient matrix. It is an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call. | ||||||
| | ||||||
| `lambda`: Shall be a `complex` rank-1 array of the same precision as `a`, containing the eigenvalues. It is an `intent(out)` argument. | ||||||
| | ||||||
| `vectors` (optional): Shall be a rank-2 array of the same type, size and kind as `a`, containing the eigenvectors of `a`. It is an `intent(out)` argument. | ||||||
| | ||||||
| `upper_a` (optional): Shall be an input `logical` flag. if `.true.`, the upper triangular part of `a` will be accessed. Otherwise, the lower triangular part will be accessed. It is an `intent(in)` argument. | ||||||
perazz marked this conversation as resolved. Outdated Show resolved Hide resolved | ||||||
| | ||||||
| `overwrite_a` (optional): Shall be an input `logical` flag. If `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument. | ||||||
| | ||||||
| `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||
| | ||||||
| ### Return value | ||||||
| | ||||||
| Raises `LINALG_ERROR` if the calculation did not converge. | ||||||
| Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. | ||||||
| If `err` is not present, exceptions trigger an `error stop`. | ||||||
| | ||||||
| ### Example | ||||||
| | ||||||
| ```fortran | ||||||
| {!example/linalg/example_eigh.f90!} | ||||||
| ``` | ||||||
| | ||||||
| ## `eigvals` - Eigenvalues of a Square Matrix | ||||||
| | ||||||
| ### Status | ||||||
| | ||||||
| Experimental | ||||||
| | ||||||
| ### Description | ||||||
| | ||||||
| This function returns the eigenvalues to matrix \( A \): a square, full-rank, `real` or `complex` matrix. | ||||||
| The eigenvalues are solutions to the eigenproblem \( A \cdot \bar{v} - \lambda \cdot \bar{v} \). | ||||||
| | ||||||
| Result array `lambda` is `complex`, and returns the eigenvalues of \( A \). | ||||||
| The solver is based on LAPACK's `*GEEV` backends. | ||||||
| | ||||||
| ### Syntax | ||||||
| | ||||||
| `lambda = ` [[stdlib_linalg(module):eigvals(interface)]] `(a, [,err])` | ||||||
| | ||||||
| ### Arguments | ||||||
| | ||||||
| `a` : `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. | ||||||
perazz marked this conversation as resolved. Outdated Show resolved Hide resolved | ||||||
| | ||||||
| `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||
| | ||||||
| ### Return value | ||||||
| | ||||||
| Returns a `complex` array containing the eigenvalues of `a`. | ||||||
| | ||||||
| Raises `LINALG_ERROR` if the calculation did not converge. | ||||||
| Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. | ||||||
| If `err` is not present, exceptions trigger an `error stop`. | ||||||
| | ||||||
| | ||||||
| ### Example | ||||||
| | ||||||
| ```fortran | ||||||
| {!example/linalg/example_eigvals.f90!} | ||||||
| ``` | ||||||
| | ||||||
| ## `eigvalsh` - Eigenvalues of a Real Symmetric or Complex Hermitian Square Matrix | ||||||
| | ||||||
| ### Status | ||||||
| | ||||||
| Experimental | ||||||
| | ||||||
| ### Description | ||||||
| | ||||||
| This function returns the eigenvalues to matrix \( A \): a where \( A \) is a square, full-rank, | ||||||
| `real` symmetric \( A = A^T \) or `complex` Hermitian \( A = A^H \) matrix. | ||||||
| The eigenvalues are solutions to the eigenproblem \( A \cdot \bar{v} - \lambda \cdot \bar{v} \). | ||||||
| | ||||||
| Result array `lambda` is `real`, and returns the eigenvalues of \( A \). | ||||||
| The solver is based on LAPACK's `*SYEV` and `*HEEV` backends. | ||||||
| | ||||||
| ### Syntax | ||||||
| | ||||||
| `lambda = ` [[stdlib_linalg(module):eigvalsh(interface)]] `(a, [, upper_a] [,err])` | ||||||
| | ||||||
| ### Arguments | ||||||
| | ||||||
| `a` : `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. | ||||||
perazz marked this conversation as resolved. Outdated Show resolved Hide resolved | ||||||
| | ||||||
| `upper_a` (optional): Shall be an input logical flag. if `.true.`, the upper triangular part of `a` will be used accessed. Otherwise, the lower triangular part will be accessed (default). It is an `intent(in)` argument. | ||||||
perazz marked this conversation as resolved. Outdated Show resolved Hide resolved | ||||||
| | ||||||
| `err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||
| | ||||||
| ### Return value | ||||||
| | ||||||
| Returns a `real` array containing the eigenvalues of `a`. | ||||||
| | ||||||
| Raises `LINALG_ERROR` if the calculation did not converge. | ||||||
| Raises `LINALG_VALUE_ERROR` if any matrix or arrays have invalid/incompatible sizes. | ||||||
| If `err` is not present, exceptions trigger an `error stop`. | ||||||
| | ||||||
| ### Example | ||||||
| | ||||||
| ```fortran | ||||||
| {!example/linalg/example_eigvalsh.f90!} | ||||||
| ``` | ||||||
| | ||||||
| ## `svd` - Compute the singular value decomposition of a rank-2 array (matrix). | ||||||
| | ||||||
| ### Status | ||||||
| | @@ -989,4 +1165,3 @@ Exceptions trigger an `error stop`, unless argument `err` is present. | |||||
| ```fortran | ||||||
| {!example/linalg/example_svdvals.f90!} | ||||||
| ``` | ||||||
| | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| ! Eigendecomposition of a real square matrix | ||
| program example_eig | ||
| use stdlib_linalg, only: eig | ||
| implicit none | ||
| | ||
| integer :: i | ||
| real, allocatable :: A(:,:) | ||
| complex, allocatable :: lambda(:),vectors(:,:) | ||
| | ||
| ! Decomposition of this square matrix | ||
| ! NB Fortran is column-major -> transpose input | ||
| A = transpose(reshape( [ [2, 2, 4], & | ||
| [1, 3, 5], & | ||
| [2, 3, 4] ], [3,3] )) | ||
| | ||
| ! Get eigenvalues and right eigenvectors | ||
| allocate(lambda(3),vectors(3,3)) | ||
| | ||
| call eig(A, lambda, right=vectors) | ||
| | ||
| do i=1,3 | ||
| print *, 'eigenvalue ',i,': ',lambda(i) | ||
| print *, 'eigenvector ',i,': ',vectors(:,i) | ||
| end do | ||
| | ||
| end program example_eig |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| ! Eigendecomposition of a real symmetric matrix | ||
| program example_eigh | ||
| use stdlib_linalg, only: eigh | ||
| implicit none | ||
| | ||
| integer :: i | ||
| real, allocatable :: A(:,:),lambda(:),v(:,:) | ||
perazz marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| complex, allocatable :: cA(:,:),cv(:,:) | ||
| | ||
| ! Decomposition of this symmetric matrix | ||
| ! NB Fortran is column-major -> transpose input | ||
| A = transpose(reshape( [ [2, 1, 4], & | ||
| [1, 3, 5], & | ||
| [4, 5, 4] ], [3,3] )) | ||
| | ||
| ! Note: real symmetric matrices have real (orthogonal) eigenvalues and eigenvectors | ||
| allocate(lambda(3),v(3,3)) | ||
| call eigh(A, lambda, vectors=v) | ||
| | ||
| print *, 'Real matrix' | ||
| do i=1,3 | ||
| print *, 'eigenvalue ',i,': ',lambda(i) | ||
| print *, 'eigenvector ',i,': ',v(:,i) | ||
| end do | ||
| | ||
| ! Complex hermitian matrices have real (orthogonal) eigenvalues and complex eigenvectors | ||
| cA = A | ||
| | ||
| allocate(cv(3,3)) | ||
| call eigh(cA, lambda, vectors=cv) | ||
| | ||
| print *, 'Complex matrix' | ||
| do i=1,3 | ||
| print *, 'eigenvalue ',i,': ',lambda(i) | ||
| print *, 'eigenvector ',i,': ',cv(:,i) | ||
| end do | ||
| | ||
| end program example_eigh | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| ! Eigenvalues of a general real / complex matrix | ||
| program example_eigvals | ||
| use stdlib_linalg, only: eigvals | ||
| implicit none | ||
| | ||
| integer :: i | ||
| real, allocatable :: A(:,:),lambda(:) | ||
| complex, allocatable :: cA(:,:),clambda(:) | ||
| | ||
| ! NB Fortran is column-major -> transpose input | ||
| A = transpose(reshape( [ [2, 8, 4], & | ||
| [1, 3, 5], & | ||
| [9, 5,-2] ], [3,3] )) | ||
| | ||
| ! Note: real symmetric matrix | ||
| lambda = eigvals(A) | ||
| print *, 'Real matrix eigenvalues: ',lambda | ||
| | ||
| ! Complex general matrix | ||
| cA = cmplx(A, -2*A) | ||
| clambda = eigvals(cA) | ||
| print *, 'Complex matrix eigenvalues: ',clambda | ||
| | ||
| end program example_eigvals |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| ! Eigenvalues of a real symmetric / complex hermitian matrix | ||
| program example_eigvalsh | ||
| use stdlib_linalg, only: eigvalsh | ||
| implicit none | ||
| | ||
| integer :: i | ||
| real, allocatable :: A(:,:),lambda(:) | ||
| complex, allocatable :: cA(:,:) | ||
| | ||
| ! Decomposition of this symmetric matrix | ||
| ! NB Fortran is column-major -> transpose input | ||
| A = transpose(reshape( [ [2, 1, 4], & | ||
| [1, 3, 5], & | ||
| [4, 5, 4] ], [3,3] )) | ||
| | ||
| ! Note: real symmetric matrices have real (orthogonal) eigenvalues and eigenvectors | ||
| lambda = eigvalsh(A) | ||
| print *, 'Symmetric matrix eigenvalues: ',lambda | ||
| | ||
| ! Complex hermitian matrices have real (orthogonal) eigenvalues and complex eigenvectors | ||
| cA = A | ||
| lambda = eigvalsh(cA) | ||
| print *, 'Hermitian matrix eigenvalues: ',lambda | ||
| | ||
| end program example_eigvalsh |
Uh oh!
There was an error while loading. Please reload this page.