Skip to main content

singe_cusolver/eigen/
info.rs

1use std::ptr;
2
3use crate::{
4    context::Context,
5    error::{Error, Result},
6    sys, try_ffi,
7};
8
9#[derive(Debug)]
10pub struct SyevjInfo {
11    handle: sys::syevjInfo_t,
12}
13
14// syevj info handles store solver options and expose mutation only through
15// &mut self, so immutable sharing is allowed.
16unsafe impl Send for SyevjInfo {}
17unsafe impl Sync for SyevjInfo {}
18
19impl SyevjInfo {
20    /// Creates `syevj`, `syevj_batched`, and `sygvj` parameter storage with default values.
21    ///
22    /// The returned [`SyevjInfo`] owns the cuSOLVER parameter handle and destroys
23    /// it when dropped.
24    ///
25    /// # Errors
26    ///
27    /// Returns an error if cuSOLVER cannot allocate the parameter storage or if
28    /// it does not return a valid handle.
29    pub fn create() -> Result<Self> {
30        let mut handle = ptr::null_mut();
31        unsafe {
32            try_ffi!(sys::cusolverDnCreateSyevjInfo(&raw mut handle))?;
33        }
34
35        if handle.is_null() {
36            return Err(Error::NullHandle);
37        }
38
39        Ok(Self { handle })
40    }
41
42    /// Configures the `syevj` tolerance.
43    ///
44    /// # Errors
45    ///
46    /// Returns an error if cuSOLVER rejects the tolerance value.
47    pub fn set_tolerance(&mut self, tolerance: f64) -> Result<()> {
48        unsafe {
49            try_ffi!(sys::cusolverDnXsyevjSetTolerance(self.as_raw(), tolerance,))?;
50        }
51        Ok(())
52    }
53
54    /// Configures the maximum number of `syevj` sweeps.
55    /// The default value is 100.
56    ///
57    /// # Errors
58    ///
59    /// Returns an error if cuSOLVER rejects the sweep count.
60    pub fn set_max_sweeps(&mut self, max_sweeps: i32) -> Result<()> {
61        unsafe {
62            try_ffi!(sys::cusolverDnXsyevjSetMaxSweeps(self.as_raw(), max_sweeps,))?;
63        }
64        Ok(())
65    }
66
67    /// If `sort_eigenvalues` is false, the eigenvalues are not sorted.
68    /// This setting only applies to `syevj_batched`.
69    /// `syevj` and `sygvj` always sort eigenvalues in ascending order.
70    /// By default, eigenvalues are always sorted in ascending order.
71    ///
72    /// # Errors
73    ///
74    /// Returns an error if cuSOLVER rejects the sort setting.
75    pub fn set_sort_eigenvalues(&mut self, sort_eigenvalues: bool) -> Result<()> {
76        unsafe {
77            try_ffi!(sys::cusolverDnXsyevjSetSortEig(
78                self.as_raw(),
79                i32::from(sort_eigenvalues),
80            ))?;
81        }
82        Ok(())
83    }
84
85    /// Returns the residual reported by `syevj` or `sygvj`.
86    /// This accessor does not support `syevj_batched`.
87    /// Calling this after `syevj_batched` returns [`crate::error::Status::NotSupported`].
88    ///
89    /// # Errors
90    ///
91    /// Returns an error if the info handle was used with `syevj_batched`,
92    /// which does not report a residual.
93    pub fn residual(&self, ctx: &Context) -> Result<f64> {
94        ctx.bind()?;
95
96        let mut residual = 0.0;
97        unsafe {
98            try_ffi!(sys::cusolverDnXsyevjGetResidual(
99                ctx.as_raw(),
100                self.as_raw(),
101                &raw mut residual,
102            ))?;
103        }
104        Ok(residual)
105    }
106
107    /// Returns the number of executed `syevj` or `sygvj` sweeps.
108    /// This accessor does not support `syevj_batched`.
109    /// Calling this after `syevj_batched` returns [`crate::error::Status::NotSupported`].
110    ///
111    /// # Errors
112    ///
113    /// Returns an error if the info handle was used with `syevj_batched`,
114    /// which does not report a sweep count.
115    pub fn executed_sweeps(&self, ctx: &Context) -> Result<i32> {
116        ctx.bind()?;
117
118        let mut sweeps = 0;
119        unsafe {
120            try_ffi!(sys::cusolverDnXsyevjGetSweeps(
121                ctx.as_raw(),
122                self.as_raw(),
123                &raw mut sweeps,
124            ))?;
125        }
126        Ok(sweeps)
127    }
128
129    pub fn as_raw(&self) -> sys::syevjInfo_t {
130        self.handle
131    }
132
133    /// Takes ownership of a raw cuSOLVER `syevj` info handle.
134    ///
135    /// # Safety
136    ///
137    /// `handle` must be a valid `syevjInfo_t` created by cuSOLVER. The
138    /// returned wrapper takes ownership and will destroy it with
139    /// `cusolverDnDestroySyevjInfo`; no other owner may destroy or keep using it.
140    pub unsafe fn from_raw(handle: sys::syevjInfo_t) -> Result<Self> {
141        if handle.is_null() {
142            return Err(Error::NullHandle);
143        }
144        Ok(Self { handle })
145    }
146
147    /// Releases ownership and returns the raw cuSOLVER `syevj` info handle.
148    ///
149    /// The caller becomes responsible for destroying the handle.
150    pub fn into_raw(self) -> sys::syevjInfo_t {
151        let handle = self.handle;
152        std::mem::forget(self);
153        handle
154    }
155}
156
157impl Drop for SyevjInfo {
158    fn drop(&mut self) {
159        unsafe {
160            if let Err(err) = try_ffi!(sys::cusolverDnDestroySyevjInfo(self.handle)) {
161                #[cfg(debug_assertions)]
162                eprintln!("failed to destroy cusolver syevj info: {err}");
163            }
164        }
165    }
166}