use std::ptr;
use crate::{
context::Context,
error::{Error, Result},
sys, try_ffi,
};
#[derive(Debug)]
pub struct GesvdjInfo {
handle: sys::gesvdjInfo_t,
}
unsafe impl Send for GesvdjInfo {}
unsafe impl Sync for GesvdjInfo {}
impl GesvdjInfo {
pub fn create() -> Result<Self> {
let mut handle = ptr::null_mut();
unsafe {
try_ffi!(sys::cusolverDnCreateGesvdjInfo(&raw mut handle))?;
}
if handle.is_null() {
return Err(Error::NullHandle);
}
Ok(Self { handle })
}
pub fn set_tolerance(&mut self, tolerance: f64) -> Result<()> {
unsafe {
try_ffi!(sys::cusolverDnXgesvdjSetTolerance(self.as_raw(), tolerance,))?;
}
Ok(())
}
pub fn set_max_sweeps(&mut self, max_sweeps: i32) -> Result<()> {
unsafe {
try_ffi!(sys::cusolverDnXgesvdjSetMaxSweeps(
self.as_raw(),
max_sweeps,
))?;
}
Ok(())
}
pub fn set_sort_eigenvalues(&mut self, sort_eigenvalues: bool) -> Result<()> {
unsafe {
try_ffi!(sys::cusolverDnXgesvdjSetSortEig(
self.as_raw(),
i32::from(sort_eigenvalues),
))?;
}
Ok(())
}
pub fn residual(&self, ctx: &Context) -> Result<f64> {
ctx.bind()?;
let mut residual = 0.0;
unsafe {
try_ffi!(sys::cusolverDnXgesvdjGetResidual(
ctx.as_raw(),
self.as_raw(),
&raw mut residual,
))?;
}
Ok(residual)
}
pub fn executed_sweeps(&self, ctx: &Context) -> Result<i32> {
ctx.bind()?;
let mut sweeps = 0;
unsafe {
try_ffi!(sys::cusolverDnXgesvdjGetSweeps(
ctx.as_raw(),
self.as_raw(),
&raw mut sweeps,
))?;
}
Ok(sweeps)
}
pub fn as_raw(&self) -> sys::gesvdjInfo_t {
self.handle
}
pub unsafe fn from_raw(handle: sys::gesvdjInfo_t) -> Result<Self> {
if handle.is_null() {
return Err(Error::NullHandle);
}
Ok(Self { handle })
}
pub fn into_raw(self) -> sys::gesvdjInfo_t {
let handle = self.handle;
std::mem::forget(self);
handle
}
}
impl Drop for GesvdjInfo {
fn drop(&mut self) {
unsafe {
if let Err(err) = try_ffi!(sys::cusolverDnDestroyGesvdjInfo(self.handle)) {
#[cfg(debug_assertions)]
eprintln!("failed to destroy cusolver gesvdj info: {err}");
}
}
}
}