rlst_suitesparse/umfpack/
real.rs1use std::ffi::c_void;
2use std::ptr;
3use std::sync::Arc;
4
5use rlst::sparse::csr_mat::CsrMatrix;
6use rlst::{Array, DynArray, MutableRawAccessArrayImpl, RawAccessArrayImpl, rlst_dynamic_array};
7
8use super::csc::CscMatrix;
9use super::sys;
10use super::{
11 UMFPACK_A, UmfpackError, UmfpackFactorizationStatus, UmfpackFactorize, UmfpackResult,
12 array_data, array_data_mut, factorization_status,
13};
14
15struct UmfpackRealSymbolic {
16 raw: *mut c_void,
17 matrix: Arc<CscMatrix<f64>>,
18}
19
20impl UmfpackFactorize for CsrMatrix<f64> {
21 type Numeric = UmfpackNumeric;
22
23 fn factorize(&self) -> UmfpackResult<Self::Numeric> {
24 UmfpackRealSymbolic::analyze(self)?.factorize()
25 }
26}
27
28impl UmfpackRealSymbolic {
29 fn analyze(matrix: &CsrMatrix<f64>) -> UmfpackResult<Self> {
30 let matrix = Arc::new(CscMatrix::from_csr(matrix)?);
31 let mut raw = ptr::null_mut();
32 let status = unsafe {
33 sys::umfpack_dl_symbolic(
34 matrix.rows_i64()?,
35 matrix.columns_i64()?,
36 matrix.column_pointers.as_ptr(),
37 matrix.row_indices.as_ptr(),
38 matrix.values.as_ptr(),
39 &mut raw,
40 ptr::null(),
41 ptr::null_mut(),
42 )
43 };
44
45 if status != 0 {
46 if !raw.is_null() {
47 unsafe { sys::umfpack_dl_free_symbolic(&mut raw) };
48 }
49 return Err(UmfpackError::NativeFailure {
50 operation: "symbolic analysis",
51 status,
52 });
53 }
54 if raw.is_null() {
55 return Err(UmfpackError::NullHandle("symbolic analysis"));
56 }
57
58 Ok(Self { raw, matrix })
59 }
60
61 fn factorize(&self) -> UmfpackResult<UmfpackNumeric> {
62 let mut raw = ptr::null_mut();
63 let status = unsafe {
64 sys::umfpack_dl_numeric(
65 self.matrix.column_pointers.as_ptr(),
66 self.matrix.row_indices.as_ptr(),
67 self.matrix.values.as_ptr(),
68 self.raw,
69 &mut raw,
70 ptr::null(),
71 ptr::null_mut(),
72 )
73 };
74
75 if status < 0 {
76 if !raw.is_null() {
77 unsafe { sys::umfpack_dl_free_numeric(&mut raw) };
78 }
79 return Err(UmfpackError::NativeFailure {
80 operation: "numeric factorization",
81 status,
82 });
83 }
84 if raw.is_null() {
85 return Err(UmfpackError::NullHandle("numeric factorization"));
86 }
87
88 Ok(UmfpackNumeric {
89 raw,
90 matrix: Arc::clone(&self.matrix),
91 status: factorization_status(status),
92 })
93 }
94}
95
96impl Drop for UmfpackRealSymbolic {
97 fn drop(&mut self) {
98 if !self.raw.is_null() {
99 unsafe { sys::umfpack_dl_free_symbolic(&mut self.raw) };
100 }
101 }
102}
103
104pub struct UmfpackNumeric {
106 raw: *mut c_void,
107 matrix: Arc<CscMatrix<f64>>,
108 status: UmfpackFactorizationStatus,
109}
110
111impl UmfpackNumeric {
112 pub fn status(&self) -> UmfpackFactorizationStatus {
115 self.status
116 }
117
118 pub fn solve<ArrayImpl>(&self, rhs: &Array<ArrayImpl, 1>) -> UmfpackResult<DynArray<f64, 1>>
122 where
123 ArrayImpl: RawAccessArrayImpl<f64, 1>,
124 {
125 let mut solution = rlst_dynamic_array!(f64, [self.matrix.rows]);
126 self.solve_into(rhs, &mut solution)?;
127 Ok(solution)
128 }
129
130 pub fn solve_into<RhsArrayImpl, SolutionArrayImpl>(
136 &self,
137 rhs: &Array<RhsArrayImpl, 1>,
138 solution: &mut Array<SolutionArrayImpl, 1>,
139 ) -> UmfpackResult<()>
140 where
141 RhsArrayImpl: RawAccessArrayImpl<f64, 1>,
142 SolutionArrayImpl: MutableRawAccessArrayImpl<f64, 1>,
143 {
144 let rhs = array_data(rhs, "right-hand side")?;
145 let solution = array_data_mut(solution, "solution")?;
146 self.validate_vector_len(rhs.len())?;
147 self.validate_vector_len(solution.len())?;
148
149 let status = unsafe {
150 sys::umfpack_dl_solve(
151 UMFPACK_A,
152 self.matrix.column_pointers.as_ptr(),
153 self.matrix.row_indices.as_ptr(),
154 self.matrix.values.as_ptr(),
155 solution.as_mut_ptr(),
156 rhs.as_ptr(),
157 self.raw,
158 ptr::null(),
159 ptr::null_mut(),
160 )
161 };
162
163 if status == 0 {
164 Ok(())
165 } else {
166 Err(UmfpackError::NativeFailure {
167 operation: "solve",
168 status,
169 })
170 }
171 }
172
173 fn validate_vector_len(&self, actual: usize) -> UmfpackResult<()> {
174 if actual == self.matrix.rows {
175 Ok(())
176 } else {
177 Err(UmfpackError::DimensionMismatch {
178 expected: self.matrix.rows,
179 actual,
180 })
181 }
182 }
183}
184
185impl Drop for UmfpackNumeric {
186 fn drop(&mut self) {
187 if !self.raw.is_null() {
188 unsafe { sys::umfpack_dl_free_numeric(&mut self.raw) };
189 }
190 }
191}