use crate::rocblas::Handle;
use crate::rocblas::ffi as rocblas_ffi;
use crate::rocsolver::bindings;
use crate::rocsolver::error::{Error, Result};
use crate::rocsolver::types::{Complex32, Complex64, Svect, Workmode};
type RocblasHandle = rocblas_ffi::rocblas_handle;
type RocblasStatus = rocblas_ffi::rocblas_status;
#[inline]
fn cast_handle(handle: RocblasHandle) -> bindings::rocblas_handle {
handle as bindings::rocblas_handle
}
pub trait GesvdType: Sized + Copy {
type RealType: Copy;
unsafe fn gesvd(
handle: RocblasHandle,
left_svect: bindings::rocblas_svect,
right_svect: bindings::rocblas_svect,
m: i32,
n: i32,
A: *mut Self,
lda: i32,
S: *mut Self::RealType,
U: *mut Self,
ldu: i32,
V: *mut Self,
ldv: i32,
E: *mut Self::RealType,
fast_alg: bindings::rocblas_workmode,
info: *mut i32,
) -> RocblasStatus;
}
impl GesvdType for f32 {
type RealType = f32;
unsafe fn gesvd(
handle: RocblasHandle,
left_svect: bindings::rocblas_svect,
right_svect: bindings::rocblas_svect,
m: i32,
n: i32,
A: *mut Self,
lda: i32,
S: *mut Self::RealType,
U: *mut Self,
ldu: i32,
V: *mut Self,
ldv: i32,
E: *mut Self::RealType,
fast_alg: bindings::rocblas_workmode,
info: *mut i32,
) -> RocblasStatus {
bindings::rocsolver_sgesvd(
cast_handle(handle),
left_svect,
right_svect,
m,
n,
A,
lda,
S,
U,
ldu,
V,
ldv,
E,
fast_alg,
info,
)
}
}
impl GesvdType for f64 {
type RealType = f64;
unsafe fn gesvd(
handle: RocblasHandle,
left_svect: bindings::rocblas_svect,
right_svect: bindings::rocblas_svect,
m: i32,
n: i32,
A: *mut Self,
lda: i32,
S: *mut Self::RealType,
U: *mut Self,
ldu: i32,
V: *mut Self,
ldv: i32,
E: *mut Self::RealType,
fast_alg: bindings::rocblas_workmode,
info: *mut i32,
) -> RocblasStatus {
bindings::rocsolver_dgesvd(
cast_handle(handle),
left_svect,
right_svect,
m,
n,
A,
lda,
S,
U,
ldu,
V,
ldv,
E,
fast_alg,
info,
)
}
}
impl GesvdType for Complex32 {
type RealType = f32;
unsafe fn gesvd(
handle: RocblasHandle,
left_svect: bindings::rocblas_svect,
right_svect: bindings::rocblas_svect,
m: i32,
n: i32,
A: *mut Self,
lda: i32,
S: *mut Self::RealType,
U: *mut Self,
ldu: i32,
V: *mut Self,
ldv: i32,
E: *mut Self::RealType,
fast_alg: bindings::rocblas_workmode,
info: *mut i32,
) -> RocblasStatus {
bindings::rocsolver_cgesvd(
cast_handle(handle),
left_svect,
right_svect,
m,
n,
A,
lda,
S,
U,
ldu,
V,
ldv,
E,
fast_alg,
info,
)
}
}
impl GesvdType for Complex64 {
type RealType = f64;
unsafe fn gesvd(
handle: RocblasHandle,
left_svect: bindings::rocblas_svect,
right_svect: bindings::rocblas_svect,
m: i32,
n: i32,
A: *mut Self,
lda: i32,
S: *mut Self::RealType,
U: *mut Self,
ldu: i32,
V: *mut Self,
ldv: i32,
E: *mut Self::RealType,
fast_alg: bindings::rocblas_workmode,
info: *mut i32,
) -> RocblasStatus {
bindings::rocsolver_zgesvd(
cast_handle(handle),
left_svect,
right_svect,
m,
n,
A,
lda,
S,
U,
ldu,
V,
ldv,
E,
fast_alg,
info,
)
}
}
#[inline]
pub fn gesvd<T: GesvdType>(
handle: &Handle,
left_svect: Svect,
right_svect: Svect,
m: i32,
n: i32,
A: *mut T,
lda: i32,
S: *mut T::RealType,
U: *mut T,
ldu: i32,
V: *mut T,
ldv: i32,
E: *mut T::RealType,
fast_alg: Workmode,
info: *mut i32,
) -> Result<()> {
let status = unsafe {
T::gesvd(
handle.as_raw(),
left_svect.into(),
right_svect.into(),
m,
n,
A,
lda,
S,
U,
ldu,
V,
ldv,
E,
fast_alg.into(),
info,
)
};
Error::from_status(status)
}