#![allow(dead_code)]
use crate::Complex64;
use crate::constants::CcBool;
unsafe extern "C" {
pub(crate) fn c_dgesv(
n: *const i32,
nrhs: *const i32,
a: *mut f64,
lda: *const i32,
ipiv: *mut i32,
b: *mut f64,
ldb: *const i32,
info: *mut i32,
);
pub(crate) fn c_dgetrf(m: *const i32, n: *const i32, a: *mut f64, lda: *const i32, ipiv: *mut i32, info: *mut i32);
pub(crate) fn c_dgetri(n: *const i32, a: *mut f64, lda: *const i32, ipiv: *const i32, work: *mut f64, lwork: *const i32, info: *mut i32);
pub(crate) fn c_dpotrf(upper: CcBool, n: *const i32, a: *mut f64, lda: *const i32, info: *mut i32);
pub(crate) fn c_zgetrf(m: *const i32, n: *const i32, a: *mut Complex64, lda: *const i32, ipiv: *mut i32, info: *mut i32);
pub(crate) fn c_zgetri(
n: *const i32,
a: *mut Complex64,
lda: *const i32,
ipiv: *const i32,
work: *mut Complex64,
lwork: *const i32,
info: *mut i32,
);
pub(crate) fn c_zgesv(
n: *const i32,
nrhs: *const i32,
a: *mut Complex64,
lda: *const i32,
ipiv: *mut i32,
b: *mut Complex64,
ldb: *const i32,
info: *mut i32,
);
pub(crate) fn c_zpotrf(upper: CcBool, n: *const i32, a: *mut Complex64, lda: *const i32, info: *mut i32);
pub(crate) fn c_zheev(
calc_v: CcBool,
upper: CcBool,
n: *const i32,
a: *mut Complex64,
lda: *const i32,
w: *mut f64,
work: *mut Complex64,
lwork: *const i32,
rwork: *mut f64,
info: *mut i32,
);
pub(crate) fn c_dsyev(
calc_v: CcBool,
upper: CcBool,
n: *const i32,
a: *mut f64,
lda: *const i32,
w: *mut f64,
work: *mut f64,
lwork: *const i32,
info: *mut i32,
);
pub(crate) fn c_dgeev(
calc_vl: CcBool,
calc_vr: CcBool,
n: *const i32,
a: *mut f64,
lda: *const i32,
wr: *mut f64,
wi: *mut f64,
vl: *mut f64,
ldvl: *const i32,
vr: *mut f64,
ldvr: *const i32,
work: *mut f64,
lwork: *const i32,
info: *mut i32,
);
pub(crate) fn c_dgesvd(
jobu_code: i32,
jobvt_code: i32,
m: *const i32,
n: *const i32,
a: *mut f64,
lda: *const i32,
s: *mut f64,
u: *mut f64,
ldu: *const i32,
vt: *mut f64,
ldvt: *const i32,
work: *mut f64,
lwork: *const i32,
info: *mut i32,
);
}
pub(crate) mod svd_code {
pub const ALL: i32 = 0; pub const SKINNY: i32 = 1; pub const OVERWRITE: i32 = 2; pub const NONE: i32 = 3; }
pub(crate) mod query {
use super::*;
use crate::constants::{C_FALSE, C_TRUE};
#[allow(clippy::too_many_arguments)]
pub(crate) fn dgeev(a: &mut [f64], n: usize, wr: &mut [f64], wi: &mut [f64], vr: Option<&mut [f64]>) -> i32 {
assert_eq!(a.len(), n * n, "reference dgeev: a must be n*n");
assert_eq!(wr.len(), n, "reference dgeev: wr must have n entries");
assert_eq!(wi.len(), n, "reference dgeev: wi must have n entries");
if let Some(v) = &vr {
assert_eq!(v.len(), n * n, "reference dgeev: vr must be n*n when requested");
}
let n_i32 = n as i32;
let ld = n_i32;
let mut info = 0i32;
let (want_vr, ldvr) = match &vr {
Some(_) => (C_TRUE, n_i32),
None => (C_FALSE, 1),
};
let vr_ptr = match vr {
Some(v) => v.as_mut_ptr(),
None => std::ptr::null_mut(),
};
let mut work = vec![0.0f64; 1];
let mut lwork = -1i32;
unsafe {
c_dgeev(
C_FALSE,
want_vr,
&n_i32,
a.as_mut_ptr(),
&ld,
wr.as_mut_ptr(),
wi.as_mut_ptr(),
std::ptr::null_mut(),
&1i32,
vr_ptr,
&ldvr,
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
if info != 0 {
return info;
}
let need = work[0].max(1.0) as usize;
let mut work = vec![0.0f64; need];
lwork = need as i32;
unsafe {
c_dgeev(
C_FALSE,
want_vr,
&n_i32,
a.as_mut_ptr(),
&ld,
wr.as_mut_ptr(),
wi.as_mut_ptr(),
std::ptr::null_mut(),
&1i32,
vr_ptr,
&ldvr,
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
info
}
pub(crate) fn dsyev(a: &mut [f64], n: usize, w: &mut [f64], want_v: bool) -> i32 {
assert_eq!(a.len(), n * n, "reference dsyev: a must be n*n");
assert_eq!(w.len(), n, "reference dsyev: w must have n entries");
let n_i32 = n as i32;
let ld = n_i32;
let mut info = 0i32;
let jobz = if want_v { C_TRUE } else { C_FALSE };
let mut work = vec![0.0f64; 1];
let mut lwork = -1i32;
unsafe {
c_dsyev(
jobz,
C_FALSE,
&n_i32,
a.as_mut_ptr(),
&ld,
w.as_mut_ptr(),
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
if info != 0 {
return info;
}
let need = work[0].max(1.0) as usize;
let mut work = vec![0.0f64; need];
lwork = need as i32;
unsafe {
c_dsyev(
jobz,
C_FALSE,
&n_i32,
a.as_mut_ptr(),
&ld,
w.as_mut_ptr(),
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
info
}
pub(crate) fn zheev(a: &mut [Complex64], n: usize, w: &mut [f64], want_v: bool) -> i32 {
assert_eq!(a.len(), n * n, "reference zheev: a must be n*n");
assert_eq!(w.len(), n, "reference zheev: w must have n entries");
let n_i32 = n as i32;
let ld = n_i32;
let mut info = 0i32;
let jobz = if want_v { C_TRUE } else { C_FALSE };
let mut work = vec![Complex64::new(0.0, 0.0); 1];
let mut rwork = vec![0.0f64; (3 * n).max(1)];
let mut lwork = -1i32;
unsafe {
c_zheev(
jobz,
C_FALSE,
&n_i32,
a.as_mut_ptr(),
&ld,
w.as_mut_ptr(),
work.as_mut_ptr(),
&lwork,
rwork.as_mut_ptr(),
&mut info,
);
}
if info != 0 {
return info;
}
let need = work[0].re.max(1.0) as usize;
let mut work = vec![Complex64::new(0.0, 0.0); need];
lwork = need as i32;
unsafe {
c_zheev(
jobz,
C_FALSE,
&n_i32,
a.as_mut_ptr(),
&ld,
w.as_mut_ptr(),
work.as_mut_ptr(),
&lwork,
rwork.as_mut_ptr(),
&mut info,
);
}
info
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn dgesvd(a: &mut [f64], m: usize, n: usize, s: &mut [f64], u: &mut [f64], vt: &mut [f64]) -> i32 {
let (m_i32, n_i32) = (m as i32, n as i32);
let min_mn = m.min(n);
assert_eq!(a.len(), m * n, "reference dgesvd: a must be m*n");
assert_eq!(u.len(), m * m, "reference dgesvd: u must be m*m");
assert_eq!(vt.len(), n * n, "reference dgesvd: vt must be n*n");
assert_eq!(s.len(), m.min(n), "reference dgesvd: s must be min(m,n)");
let mut info = 0i32;
let mut work = vec![0.0f64; 1];
let mut lwork = -1i32;
unsafe {
c_dgesvd(
svd_code::ALL,
svd_code::ALL,
&m_i32,
&n_i32,
a.as_mut_ptr(),
&m_i32,
s.as_mut_ptr(),
u.as_mut_ptr(),
&m_i32,
vt.as_mut_ptr(),
&n_i32,
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
if info != 0 {
return info;
}
let need = work[0].max(1.0) as usize;
let mut work = vec![0.0f64; need];
lwork = need as i32;
let _ = min_mn;
unsafe {
c_dgesvd(
svd_code::ALL,
svd_code::ALL,
&m_i32,
&n_i32,
a.as_mut_ptr(),
&m_i32,
s.as_mut_ptr(),
u.as_mut_ptr(),
&m_i32,
vt.as_mut_ptr(),
&n_i32,
work.as_mut_ptr(),
&lwork,
&mut info,
);
}
info
}
}