Skip to content

Commit

Permalink
Impl complex matrix svd
Browse files Browse the repository at this point in the history
  • Loading branch information
cpmech committed Mar 15, 2024
1 parent 9881224 commit d9a38cb
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ See also:
* [russell_lab/examples](https://github.com/cpmech/russell/tree/main/russell_lab/examples)
* [russell_sparse/examples](https://github.com/cpmech/russell/tree/main/russell_sparse/examples)

**Note:** For the functions dealing with complex numbers, the following line must be added to all derived code:

```rust
use num_complex::Complex64;
```

This line will bring `Complex64` to the scope. For convenience the (russell_lab) macro `cpx!` may be used to allocate complex numbers.

### Compute a singular value decomposition

```rust
Expand Down
11 changes: 11 additions & 0 deletions russell_lab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ _This crate is part of [Russell - Rust Scientific Library](https://github.com/cp
* [Introduction](#introduction)
* [Installation](#debian)
* [Setting Cargo.toml](#cargo)
* [Complex numbers](#complex-numbers)
* [Examples](#examples)
* [About the column major representation](#col-major)
* [Benchmarks](#benchmarks)
Expand Down Expand Up @@ -50,6 +51,16 @@ This crate depends on an efficient BLAS library such as [OpenBLAS](https://githu
russell_lab = "*"
```

## <a name="complex-numbers"></a> Complex numbers

**Note:** For the functions dealing with complex numbers, the following line must be added to all derived code:

```rust
use num_complex::Complex64;
```

This line will bring `Complex64` to the scope. For convenience the (russell_lab) macro `cpx!` may be used to allocate complex numbers.

## <a name="examples"></a> Examples

See also:
Expand Down
30 changes: 30 additions & 0 deletions russell_lab/c_code/interface_blas.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define FN_DGGEV dggev_
#define FN_ZGGEV zggev_
#define FN_DGESVD dgesvd_
#define FN_ZGESVD zgesvd_
#define FN_DGETRF dgetrf_
#define FN_DGETRI dgetri_
#define FN_ZGETRF zgetrf_
Expand All @@ -36,6 +37,7 @@
#define FN_DGGEV LAPACK_dggev
#define FN_ZGGEV LAPACK_zggev
#define FN_DGESVD LAPACK_dgesvd
#define FN_ZGESVD LAPACK_zgesvd
#define FN_DGETRF LAPACK_dgetrf
#define FN_DGETRI LAPACK_dgetri
#define FN_ZGETRF LAPACK_zgetrf
Expand Down Expand Up @@ -310,6 +312,34 @@ void c_dgesvd(int32_t jobu_code,
FN_DGESVD(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork, info);
}

// Computes the singular value decomposition (SVD)
// <https://www.netlib.org/lapack/explore-html/d6/d42/zgesvd_8f.html>
void c_zgesvd(int32_t jobu_code,
int32_t jobvt_code,
const int32_t *m,
const int32_t *n,
COMPLEX64 *a,
const int32_t *lda,
double *s,
COMPLEX64 *u,
const int32_t *ldu,
COMPLEX64 *vh,
const int32_t *ldvt,
COMPLEX64 *work,
const int32_t *lwork,
double *rwork,
int32_t *info) {
const char *jobu = jobu_code == SVD_CODE_A ? "A"
: jobu_code == SVD_CODE_S ? "S"
: jobu_code == SVD_CODE_O ? "O"
: "N";
const char *jobvt = jobvt_code == SVD_CODE_A ? "A"
: jobvt_code == SVD_CODE_S ? "S"
: jobvt_code == SVD_CODE_O ? "O"
: "N";
FN_ZGESVD(jobu, jobvt, m, n, a, lda, s, u, ldu, vh, ldvt, work, lwork, rwork, info);
}

// Computes the LU factorization of a general (m,n) matrix
// <https://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html>
void c_dgetrf(const int32_t *m,
Expand Down
36 changes: 36 additions & 0 deletions russell_lab/examples/temp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use num_complex::Complex64;
use russell_lab::*;

fn main() -> Result<(), StrError> {
// matrix
let data = [
[cpx!(1.0, 1.0), cpx!(2.0, -1.0), cpx!(3.0, 0.0)],
[cpx!(2.0, -1.0), cpx!(4.0, 1.0), cpx!(5.0, -1.0)],
[cpx!(3.0, 0.0), cpx!(5.0, -1.0), cpx!(6.0, 1.0)],
];

let mut a = ComplexMatrix::from(&data);
let a_copy = ComplexMatrix::from(&data);

// allocate output data
let (m, n) = a.dims();
let min_mn = if m < n { m } else { n };
let mut s = Vector::new(min_mn);
let mut u = ComplexMatrix::new(m, m);
let mut vh = ComplexMatrix::new(n, n);

// calculate SVD
complex_mat_svd(&mut s, &mut u, &mut vh, &mut a).unwrap();

// check SVD
let mut usv = ComplexMatrix::new(m, n);
for i in 0..m {
for j in 0..n {
for k in 0..min_mn {
usv.add(i, j, u.get(i, k) * s[k] * vh.get(k, j));
}
}
}
complex_mat_approx_eq(&usv, &a_copy, 1e-14);
Ok(())
}
8 changes: 8 additions & 0 deletions russell_lab/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
//! * Reading writing files ([read_table()]) , linspace ([NumVector::linspace()]), grid generators ([generate2d()]), [generate3d()]), [linear_fitting()], [Stopwatch] and more
//! * Checking results, comparing float point numbers, and verifying the correctness of derivatives; see [crate::check]
//!
//! **Note:** For the functions dealing with complex numbers, the following line must be added to all derived code:
//!
//! ```
//! use num_complex::Complex64;
//! ```
//!
//! This line will bring [num_complex::Complex64] to the scope. For convenience the (russell_lab) macro [crate::cpx!] may be used to allocate complex numbers.
//!
//! # Example - Cholesky factorization
//!
//! ```
Expand Down
Loading

0 comments on commit d9a38cb

Please sign in to comment.