1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
use lapacke; use num_traits::Zero; use crate::error::*; use crate::layout::MatrixLayout; use crate::types::*; use crate::svddc::UVTFlag; use super::{SVDOutput, into_result}; pub trait SVDDC_: Scalar { unsafe fn svddc(l: MatrixLayout, jobz: UVTFlag, a: &mut [Self]) -> Result<SVDOutput<Self>>; } macro_rules! impl_svdd { ($scalar:ty, $gesdd:path) => { impl SVDDC_ for $scalar { unsafe fn svddc( l: MatrixLayout, jobz: UVTFlag, mut a: &mut [Self], ) -> Result<SVDOutput<Self>> { let (m, n) = l.size(); let k = m.min(n); let lda = l.lda(); let (ucol, vtrow) = match jobz { UVTFlag::Full => (m, n), UVTFlag::Some => (k, k), UVTFlag::None => (1, 1), }; let mut s = vec![Self::Real::zero(); k.max(1) as usize]; let mut u = vec![Self::zero(); (m * ucol).max(1) as usize]; let ldu = l.resized(m, ucol).lda(); let mut vt = vec![Self::zero(); (vtrow * n).max(1) as usize]; let ldvt = l.resized(vtrow, n).lda(); let info = $gesdd( l.lapacke_layout(), jobz as u8, m, n, &mut a, lda, &mut s, &mut u, ldu, &mut vt, ldvt, ); into_result( info, SVDOutput { s: s, u: if jobz == UVTFlag::None { None } else { Some(u) }, vt: if jobz == UVTFlag::None { None } else { Some(vt) }, }, ) } } }; } impl_svdd!(f32, lapacke::sgesdd); impl_svdd!(f64, lapacke::dgesdd); impl_svdd!(c32, lapacke::cgesdd); impl_svdd!(c64, lapacke::zgesdd);