-
Notifications
You must be signed in to change notification settings - Fork 189
linalg: Singular Value Decomposition #808
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
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
42aa3e5
add `svd`
perazz e1d49d8
base implementation
perazz f5adf8f
1d matrix shape
perazz 64adda4
cleanup
perazz 036c574
add test programs
perazz 4a90c09
tests: replace with `testdrive`
perazz 063b421
create `submodule`
perazz 6abe7df
document `svd` and interface
perazz 194f4a1
document `svdvals` and interface
perazz 9de160b
remove `goto`
perazz cf40f75
add example
perazz 32784cd
add `svdvals` example
perazz bb47ba5
specs: `svd`, `svdvals`
perazz 3b365aa
fix
perazz ba5e5e7
remove complex qp test
perazz 6556e8b
restore `qp` subroutine (test still unactive)
perazz 9c2f133
restore all, avoid `real128` complex parameter math
perazz 88a49bb
Merge branch 'master' into svd
perazz cf15eb1
clearer `logical` flags
perazz 980a555
Update doc/specs/stdlib_linalg.md
perazz 28ae2cb
Update doc/specs/stdlib_linalg.md
perazz 69458ad
Update doc/specs/stdlib_linalg.md
perazz b579d98
rename `svd` examples
perazz 8387797
fix intent in docs
perazz e0d800c
Update doc/specs/stdlib_linalg.md
perazz 6e5a7ce
Merge branch 'svd' of github.com:perazz/stdlib into svd
perazz 8f35e98
format -> character parameter
perazz 173f1ee
Merge branch 'master' into svd
perazz bdffb4f
matrix -> rank-2 array
perazz 9f51efe
Merge branch 'svd' of github.com:perazz/stdlib into svd
perazz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -898,3 +898,95 @@ Exceptions trigger an `error stop`. | |||||||||||
```fortran | ||||||||||||
{!example/linalg/example_determinant2.f90!} | ||||||||||||
``` | ||||||||||||
|
||||||||||||
## `svd` - Compute the singular value decomposition of a rank-2 array (matrix). | ||||||||||||
|
||||||||||||
### Status | ||||||||||||
|
||||||||||||
Experimental | ||||||||||||
|
||||||||||||
### Description | ||||||||||||
|
||||||||||||
This subroutine computes the singular value decomposition of a `real` or `complex` rank-2 array (matrix) \( A = U \cdot S \cdot \V^T \). | ||||||||||||
The solver is based on LAPACK's `*GESDD` backends. | ||||||||||||
|
||||||||||||
Result vector `s` returns the array of singular values on the diagonal of \( S \). | ||||||||||||
If requested, `u` contains the left singular vectors, as columns of \( U \). | ||||||||||||
If requested, `vt` contains the right singular vectors, as rows of \( V^T \). | ||||||||||||
|
||||||||||||
### Syntax | ||||||||||||
|
||||||||||||
`call ` [[stdlib_linalg(module):svd(interface)]] `(a, s, [, u, vt, overwrite_a, full_matrices, err])` | ||||||||||||
|
||||||||||||
### Class | ||||||||||||
Subroutine | ||||||||||||
|
||||||||||||
### Arguments | ||||||||||||
|
||||||||||||
`a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix of size `[m,n]`. It is an `intent(inout)` argument, but returns unchanged unless `overwrite_a=.true.`. | ||||||||||||
|
||||||||||||
`s`: Shall be a rank-1 `real` array, returning the list of `k = min(m,n)` singular values. It is an `intent(out)` argument. | ||||||||||||
|
||||||||||||
`u` (optional): Shall be a rank-2 array of same kind as `a`, returning the left singular vectors of `a` as columns. Its size should be `[m,m]` unless `full_matrices=.false.`, in which case, it can be `[m,min(m,n)]`. It is an `intent(out)` argument. | ||||||||||||
|
||||||||||||
`vt` (optional): Shall be a rank-2 array of same kind as `a`, returning the right singular vectors of `a` as rows. Its size should be `[n,n]` unless `full_matrices=.false.`, in which case, it can be `[min(m,n),n]`. It is an `intent(out)` argument. | ||||||||||||
|
||||||||||||
`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. By default, `overwrite_a=.false.`. It is an `intent(in)` argument. | ||||||||||||
|
||||||||||||
`full_matrices` (optional): Shall be an input `logical` flag. If `.true.` (default), matrices `u` and `vt` shall be full-sized. Otherwise, their secondary dimension can be resized to `min(m,n)`. See `u`, `v` for details. | ||||||||||||
|
||||||||||||
`err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||||||||
|
||||||||||||
### Return values | ||||||||||||
|
||||||||||||
Returns an array `s` that contains the list of singular values of matrix `a`. | ||||||||||||
If requested, returns a rank-2 array `u` that contains the left singular vectors of `a` along its columns. | ||||||||||||
If requested, returns a rank-2 array `vt` that contains the right singular vectors of `a` along its rows. | ||||||||||||
|
||||||||||||
Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. | ||||||||||||
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. What is the value if there is no issue? |
||||||||||||
Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. | ||||||||||||
Exceptions trigger an `error stop`, unless argument `err` is present. | ||||||||||||
|
||||||||||||
### Example | ||||||||||||
|
||||||||||||
```fortran | ||||||||||||
{!example/linalg/example_svd.f90!} | ||||||||||||
``` | ||||||||||||
|
||||||||||||
## `svdvals` - Compute the singular values of a rank-2 array (matrix). | ||||||||||||
|
||||||||||||
### Status | ||||||||||||
|
||||||||||||
Experimental | ||||||||||||
|
||||||||||||
### Description | ||||||||||||
|
||||||||||||
This subroutine computes the singular values of a `real` or `complex` rank-2 array (matrix) from its singular | ||||||||||||
value decomposition \( A = U \cdot S \cdot \V^T \). The solver is based on LAPACK's `*GESDD` backends. | ||||||||||||
|
||||||||||||
Result vector `s` returns the array of singular values on the diagonal of \( S \). | ||||||||||||
|
||||||||||||
### Syntax | ||||||||||||
|
||||||||||||
`s = ` [[stdlib_linalg(module):svdvals(interface)]] `(a [, err])` | ||||||||||||
|
||||||||||||
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
|
||||||||||||
### Arguments | ||||||||||||
|
||||||||||||
`a`: Shall be a rank-2 `real` or `complex` array containing the coefficient matrix of size `[m,n]`. It is an `intent(in)` argument. | ||||||||||||
|
||||||||||||
`err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. | ||||||||||||
|
||||||||||||
### Return values | ||||||||||||
|
||||||||||||
Returns an array `s` that contains the list of singular values of matrix `a`. | ||||||||||||
|
||||||||||||
Raises `LINALG_ERROR` if the underlying Singular Value Decomposition process did not converge. | ||||||||||||
Raises `LINALG_VALUE_ERROR` if the matrix or any of the output arrays invalid/incompatible sizes. | ||||||||||||
Exceptions trigger an `error stop`, unless argument `err` is present. | ||||||||||||
|
||||||||||||
### Example | ||||||||||||
|
||||||||||||
```fortran | ||||||||||||
{!example/linalg/example_svdvals.f90!} | ||||||||||||
``` | ||||||||||||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
! Singular Value Decomposition | ||
program example_svd | ||
use stdlib_linalg_constants, only: dp | ||
use stdlib_linalg, only: svd | ||
implicit none | ||
|
||
real(dp), allocatable :: A(:,:),s(:),u(:,:),vt(:,:) | ||
character(*), parameter :: fmt = "(a,*(1x,f12.8))" | ||
|
||
! We want to find the singular value decomposition of matrix: | ||
! | ||
! A = [ 3 2 2] | ||
! [ 2 3 -2] | ||
! | ||
A = transpose(reshape([ 3, 2, 2, & | ||
2, 3,-2], [3,2])) | ||
|
||
! Prepare arrays | ||
allocate(s(2),u(2,2),vt(3,3)) | ||
|
||
! Get singular value decomposition | ||
call svd(A,s,u,vt) | ||
|
||
! Singular values: [5, 3] | ||
print fmt, ' ' | ||
print fmt, 'S = ',s | ||
print fmt, ' ' | ||
|
||
! Left vectors (may be flipped): | ||
! [Ã2/2 Ã2/2] | ||
! U = [Ã2/2 -Ã2/2] | ||
! | ||
print fmt, ' ' | ||
print fmt, 'U = ',u(1,:) | ||
print fmt, ' ',u(2,:) | ||
|
||
|
||
! Right vectors (may be flipped): | ||
! [Ã2/2 Ã2/2 0] | ||
! V = [1/Ã18 -1/Ã18 4/Ã18] | ||
! [ 2/3 -2/3 -1/3] | ||
! | ||
print fmt, ' ' | ||
print fmt, ' ',vt(1,:) | ||
print fmt, 'VT= ',vt(2,:) | ||
print fmt, ' ',vt(3,:) | ||
print fmt, ' ' | ||
|
||
|
||
end program example_svd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
! Singular Values | ||
program example_svdvals | ||
use stdlib_linalg_constants, only: dp | ||
use stdlib_linalg, only: svdvals | ||
implicit none | ||
|
||
real(dp), allocatable :: A(:,:),s(:) | ||
character(*), parameter :: fmt="(a,*(1x,f12.8))" | ||
|
||
! We want to find the singular values of matrix: | ||
! | ||
! A = [ 3 2 2] | ||
! [ 2 3 -2] | ||
! | ||
A = transpose(reshape([ 3, 2, 2, & | ||
2, 3,-2], [3,2])) | ||
|
||
! Get singular values | ||
s = svdvals(A) | ||
|
||
! Singular values: [5, 3] | ||
print fmt, ' ' | ||
print fmt, 'S = ',s | ||
print fmt, ' ' | ||
|
||
end program example_svdvals |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.