1use crate::internal_prelude_sp::*;
3pub mod bicgstab;
5pub mod conjugate_gradient;
7pub mod eigen;
9pub mod lsmr;
11mod operator_impl;
12mod self_adjoint_eigen;
13mod svd;
14#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
16pub enum InitialGuessStatus {
17 Zero,
19 #[default]
21 MaybeNonZero,
22}
23#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
25pub struct IdentityPrecond {
26 pub dim: usize,
28}
29pub trait LinOp<T: ComplexField>: Sync + core::fmt::Debug {
31 fn apply_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq;
34 fn nrows(&self) -> usize;
36 fn ncols(&self) -> usize;
38 fn apply(
40 &self,
41 out: MatMut<'_, T>,
42 rhs: MatRef<'_, T>,
43 par: Par,
44 stack: &mut MemStack,
45 );
46 fn conj_apply(
48 &self,
49 out: MatMut<'_, T>,
50 rhs: MatRef<'_, T>,
51 par: Par,
52 stack: &mut MemStack,
53 );
54}
55impl<T: ComplexField> LinOp<T> for IdentityPrecond {
56 #[inline]
57 #[track_caller]
58 fn apply_scratch(&self, _rhs_ncols: usize, _par: Par) -> StackReq {
59 StackReq::EMPTY
60 }
61
62 #[inline]
63 fn nrows(&self) -> usize {
64 self.dim
65 }
66
67 #[inline]
68 fn ncols(&self) -> usize {
69 self.dim
70 }
71
72 #[inline]
73 #[track_caller]
74 fn apply(
75 &self,
76 out: MatMut<'_, T>,
77 rhs: MatRef<'_, T>,
78 _par: Par,
79 _stack: &mut MemStack,
80 ) {
81 { out }.copy_from(rhs);
82 }
83
84 #[inline]
85 #[track_caller]
86 fn conj_apply(
87 &self,
88 out: MatMut<'_, T>,
89 rhs: MatRef<'_, T>,
90 _par: Par,
91 _stack: &mut MemStack,
92 ) {
93 { out }.copy_from(rhs);
94 }
95}
96impl<T: ComplexField> BiLinOp<T> for IdentityPrecond {
97 #[inline]
98 fn transpose_apply_scratch(
99 &self,
100 _rhs_ncols: usize,
101 _par: Par,
102 ) -> StackReq {
103 StackReq::EMPTY
104 }
105
106 #[inline]
107 #[track_caller]
108 fn transpose_apply(
109 &self,
110 out: MatMut<'_, T>,
111 rhs: MatRef<'_, T>,
112 _par: Par,
113 _stack: &mut MemStack,
114 ) {
115 { out }.copy_from(rhs);
116 }
117
118 #[inline]
119 #[track_caller]
120 fn adjoint_apply(
121 &self,
122 out: MatMut<'_, T>,
123 rhs: MatRef<'_, T>,
124 _par: Par,
125 _stack: &mut MemStack,
126 ) {
127 { out }.copy_from(rhs);
128 }
129}
130impl<T: ComplexField> Precond<T> for IdentityPrecond {
131 fn apply_in_place_scratch(&self, _rhs_ncols: usize, _par: Par) -> StackReq {
132 StackReq::EMPTY
133 }
134
135 fn apply_in_place(
136 &self,
137 _rhs: MatMut<'_, T>,
138 _par: Par,
139 _stack: &mut MemStack,
140 ) {
141 }
142
143 fn conj_apply_in_place(
144 &self,
145 _rhs: MatMut<'_, T>,
146 _par: Par,
147 _stack: &mut MemStack,
148 ) {
149 }
150}
151impl<T: ComplexField> BiPrecond<T> for IdentityPrecond {
152 fn transpose_apply_in_place_scratch(
153 &self,
154 _rhs_ncols: usize,
155 _par: Par,
156 ) -> StackReq {
157 StackReq::EMPTY
158 }
159
160 fn transpose_apply_in_place(
161 &self,
162 _rhs: MatMut<'_, T>,
163 _par: Par,
164 _stack: &mut MemStack,
165 ) {
166 }
167
168 fn adjoint_apply_in_place(
169 &self,
170 _rhs: MatMut<'_, T>,
171 _par: Par,
172 _stack: &mut MemStack,
173 ) {
174 }
175}
176pub trait BiLinOp<T: ComplexField>: LinOp<T> {
178 fn transpose_apply_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq;
181 fn transpose_apply(
183 &self,
184 out: MatMut<'_, T>,
185 rhs: MatRef<'_, T>,
186 par: Par,
187 stack: &mut MemStack,
188 );
189 fn adjoint_apply(
191 &self,
192 out: MatMut<'_, T>,
193 rhs: MatRef<'_, T>,
194 par: Par,
195 stack: &mut MemStack,
196 );
197}
198pub trait Precond<T: ComplexField>: LinOp<T> {
202 fn apply_in_place_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq {
205 temp_mat_scratch::<T>(self.nrows(), rhs_ncols)
206 .and(self.apply_scratch(rhs_ncols, par))
207 }
208 #[track_caller]
210 fn apply_in_place(
211 &self,
212 rhs: MatMut<'_, T>,
213 par: Par,
214 stack: &mut MemStack,
215 ) {
216 let (mut tmp, stack) = unsafe {
217 temp_mat_uninit::<T, _, _>(self.nrows(), rhs.ncols(), stack)
218 };
219 let mut tmp = tmp.as_mat_mut();
220 self.apply(tmp.rb_mut(), rhs.rb(), par, stack);
221 { rhs }.copy_from(&tmp);
222 }
223 #[track_caller]
225 fn conj_apply_in_place(
226 &self,
227 rhs: MatMut<'_, T>,
228 par: Par,
229 stack: &mut MemStack,
230 ) {
231 let (mut tmp, stack) = unsafe {
232 temp_mat_uninit::<T, _, _>(self.nrows(), rhs.ncols(), stack)
233 };
234 let mut tmp = tmp.as_mat_mut();
235 self.conj_apply(tmp.rb_mut(), rhs.rb(), par, stack);
236 { rhs }.copy_from(&tmp);
237 }
238}
239pub trait BiPrecond<T: ComplexField>: Precond<T> + BiLinOp<T> {
244 fn transpose_apply_in_place_scratch(
247 &self,
248 rhs_ncols: usize,
249 par: Par,
250 ) -> StackReq {
251 temp_mat_scratch::<T>(self.nrows(), rhs_ncols)
252 .and(self.transpose_apply_scratch(rhs_ncols, par))
253 }
254 #[track_caller]
256 fn transpose_apply_in_place(
257 &self,
258 rhs: MatMut<'_, T>,
259 par: Par,
260 stack: &mut MemStack,
261 ) {
262 let (mut tmp, stack) = unsafe {
263 temp_mat_uninit::<T, _, _>(self.nrows(), rhs.ncols(), stack)
264 };
265 let mut tmp = tmp.as_mat_mut();
266 self.transpose_apply(tmp.rb_mut(), rhs.rb(), par, stack);
267 { rhs }.copy_from(&tmp);
268 }
269 #[track_caller]
271 fn adjoint_apply_in_place(
272 &self,
273 rhs: MatMut<'_, T>,
274 par: Par,
275 stack: &mut MemStack,
276 ) {
277 let (mut tmp, stack) = unsafe {
278 temp_mat_uninit::<T, _, _>(self.nrows(), rhs.ncols(), stack)
279 };
280 let mut tmp = tmp.as_mat_mut();
281 self.adjoint_apply(tmp.rb_mut(), rhs.rb(), par, stack);
282 { rhs }.copy_from(&tmp);
283 }
284}
285impl<T: ComplexField, M: Sized + LinOp<T>> LinOp<T> for &M {
286 #[inline]
287 #[track_caller]
288 fn apply_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq {
289 (**self).apply_scratch(rhs_ncols, par)
290 }
291
292 #[inline]
293 fn nrows(&self) -> usize {
294 (**self).nrows()
295 }
296
297 #[inline]
298 fn ncols(&self) -> usize {
299 (**self).ncols()
300 }
301
302 #[inline]
303 #[track_caller]
304 fn apply(
305 &self,
306 out: MatMut<'_, T>,
307 rhs: MatRef<'_, T>,
308 par: Par,
309 stack: &mut MemStack,
310 ) {
311 (**self).apply(out, rhs, par, stack)
312 }
313
314 #[inline]
315 #[track_caller]
316 fn conj_apply(
317 &self,
318 out: MatMut<'_, T>,
319 rhs: MatRef<'_, T>,
320 par: Par,
321 stack: &mut MemStack,
322 ) {
323 (**self).conj_apply(out, rhs, par, stack)
324 }
325}
326impl<T: ComplexField, M: Sized + BiLinOp<T>> BiLinOp<T> for &M {
327 #[inline]
328 #[track_caller]
329 fn transpose_apply_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq {
330 (**self).transpose_apply_scratch(rhs_ncols, par)
331 }
332
333 #[inline]
334 #[track_caller]
335 fn transpose_apply(
336 &self,
337 out: MatMut<'_, T>,
338 rhs: MatRef<'_, T>,
339 par: Par,
340 stack: &mut MemStack,
341 ) {
342 (**self).transpose_apply(out, rhs, par, stack)
343 }
344
345 #[inline]
346 #[track_caller]
347 fn adjoint_apply(
348 &self,
349 out: MatMut<'_, T>,
350 rhs: MatRef<'_, T>,
351 par: Par,
352 stack: &mut MemStack,
353 ) {
354 (**self).adjoint_apply(out, rhs, par, stack)
355 }
356}
357impl<T: ComplexField, M: Sized + Precond<T>> Precond<T> for &M {
358 fn apply_in_place_scratch(&self, rhs_ncols: usize, par: Par) -> StackReq {
359 (**self).apply_in_place_scratch(rhs_ncols, par)
360 }
361
362 fn apply_in_place(
363 &self,
364 rhs: MatMut<'_, T>,
365 par: Par,
366 stack: &mut MemStack,
367 ) {
368 (**self).apply_in_place(rhs, par, stack);
369 }
370
371 fn conj_apply_in_place(
372 &self,
373 rhs: MatMut<'_, T>,
374 par: Par,
375 stack: &mut MemStack,
376 ) {
377 (**self).conj_apply_in_place(rhs, par, stack);
378 }
379}
380impl<T: ComplexField, M: Sized + BiPrecond<T>> BiPrecond<T> for &M {
381 fn transpose_apply_in_place_scratch(
382 &self,
383 rhs_ncols: usize,
384 par: Par,
385 ) -> StackReq {
386 (**self).transpose_apply_in_place_scratch(rhs_ncols, par)
387 }
388
389 fn transpose_apply_in_place(
390 &self,
391 rhs: MatMut<'_, T>,
392 par: Par,
393 stack: &mut MemStack,
394 ) {
395 (**self).transpose_apply_in_place(rhs, par, stack);
396 }
397
398 fn adjoint_apply_in_place(
399 &self,
400 rhs: MatMut<'_, T>,
401 par: Par,
402 stack: &mut MemStack,
403 ) {
404 (**self).adjoint_apply_in_place(rhs, par, stack);
405 }
406}