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}