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