klu_rs/
raw.rs

1use klu_sys::{
2    klu_analyze, klu_defaults, klu_factor, klu_free_numeric, klu_free_symbolic, klu_l_analyze,
3    klu_l_defaults, klu_l_factor, klu_l_free_numeric, klu_l_free_symbolic, klu_l_rcond,
4    klu_l_refactor, klu_l_solve, klu_l_tsolve, klu_rcond, klu_refactor, klu_solve, klu_tsolve,
5    klu_z_factor, klu_z_free_numeric, klu_z_rcond, klu_z_refactor, klu_z_solve, klu_z_tsolve,
6    klu_zl_factor, klu_zl_free_numeric, klu_zl_rcond, klu_zl_refactor, klu_zl_solve, klu_zl_tsolve,
7    KluCommon, KluLCommon, KluLNumeric, KluLSymbolic, KluNumeric, KluSymbolic,
8};
9use num_complex::{Complex64, ComplexFloat};
10
11use crate::raw::sealed::Sealed;
12use std::fmt::Debug;
13use std::ops::{Add, AddAssign, Div, Mul, Sub};
14
15mod sealed {
16    use num_complex::Complex64;
17
18    pub trait Sealed {}
19    impl Sealed for f64 {}
20    impl Sealed for Complex64 {}
21    impl Sealed for i32 {}
22    impl Sealed for i64 {}
23}
24
25/// Values that can be used by the KLU solver.
26/// The functions of this trait are all unsafe because they directly call the underlying C implementation.
27#[allow(clippy::missing_safety_doc)]
28pub trait KluData:
29    Sealed
30    + Copy
31    + PartialEq
32    + Debug
33    + Default
34    + Mul
35    + Sub
36    + Add
37    + AddAssign
38    + Div
39    + ComplexFloat<Real = f64>
40    + 'static
41{
42    unsafe fn klu_solve<I: KluIndex>(
43        symbolic: *mut I::KluSymbolic,
44        numeric: *mut I::KluNumeric,
45        rhs_dimension: I,
46        number_rhs: I,
47        rhs_data: *mut Self,
48        common: *mut I::KluCommon,
49    ) -> bool;
50
51    unsafe fn klu_tsolve<I: KluIndex>(
52        symbolic: *mut I::KluSymbolic,
53        numeric: *mut I::KluNumeric,
54        rhs_dimension: I,
55        number_rhs: I,
56        rhs_data: *mut Self,
57        common: *mut I::KluCommon,
58    ) -> bool;
59
60    unsafe fn klu_factor<I: KluIndex>(
61        colum_offsets: *const I,
62        row_indices: *const I,
63        data: *mut Self,
64        symbolic: *mut I::KluSymbolic,
65        common: *mut I::KluCommon,
66    ) -> *mut I::KluNumeric;
67
68    unsafe fn klu_refactor<I: KluIndex>(
69        colum_offsets: *const I,
70        row_indices: *const I,
71        data: *mut Self,
72        symbolic: *mut I::KluSymbolic,
73        numeric: *mut I::KluNumeric,
74        common: *mut I::KluCommon,
75    ) -> bool;
76
77    unsafe fn klu_free_numeric<I: KluIndex>(
78        numeric: *mut *mut I::KluNumeric,
79        common: *mut I::KluCommon,
80    );
81
82    unsafe fn klu_rcond<I: KluIndex>(
83        symbolic: *mut I::KluSymbolic,
84        numeric: *mut I::KluNumeric,
85        common: *mut I::KluCommon,
86    ) -> bool;
87}
88
89/// Values that can be used by the KLU solver.
90/// The functions of this trait are all unsafe because they directly call the underlying C implementation.
91#[allow(clippy::missing_safety_doc)]
92pub trait KluIndex:
93    PartialEq + PartialOrd + Ord + Debug + Copy + Clone + Eq + Sealed + Add<Output = Self>
94{
95    type KluCommon: Debug;
96    type KluNumeric: Debug;
97    type KluSymbolic: Debug;
98
99    fn from_usize(val: usize) -> Self;
100    fn into_usize(self) -> usize;
101
102    unsafe fn klu_defaults(common: *mut Self::KluCommon) -> Self;
103
104    unsafe fn klu_analyze(
105        dim: Self,
106        colum_offsets: *const Self,
107        row_indices: *const Self,
108        common: *mut Self::KluCommon,
109    ) -> *mut Self::KluSymbolic;
110
111    unsafe fn klu_free_symbolic(
112        symbolic: *mut *mut Self::KluSymbolic,
113        common: *mut Self::KluCommon,
114    );
115
116    unsafe fn klu_factor(
117        colum_offsets: *const Self,
118        row_indices: *const Self,
119        data: *mut f64,
120        symbolic: *mut Self::KluSymbolic,
121        common: *mut Self::KluCommon,
122    ) -> *mut Self::KluNumeric;
123
124    unsafe fn klu_z_factor(
125        colum_offsets: *const Self,
126        row_indices: *const Self,
127        data: *mut f64,
128        symbolic: *mut Self::KluSymbolic,
129        common: *mut Self::KluCommon,
130    ) -> *mut Self::KluNumeric;
131
132    unsafe fn klu_refactor(
133        colum_offsets: *const Self,
134        row_indices: *const Self,
135        data: *mut f64,
136        symbolic: *mut Self::KluSymbolic,
137        numeric: *mut Self::KluNumeric,
138        common: *mut Self::KluCommon,
139    ) -> bool;
140
141    unsafe fn klu_z_refactor(
142        colum_offsets: *const Self,
143        row_indices: *const Self,
144        data: *mut f64,
145        symbolic: *mut Self::KluSymbolic,
146        numeric: *mut Self::KluNumeric,
147        common: *mut Self::KluCommon,
148    ) -> bool;
149
150    unsafe fn klu_solve(
151        symbolic: *mut Self::KluSymbolic,
152        numeric: *mut Self::KluNumeric,
153        rhs_dimension: Self,
154        number_rhs: Self,
155        rhs_data: *mut f64,
156        common: *mut Self::KluCommon,
157    ) -> bool;
158
159    unsafe fn klu_tsolve(
160        symbolic: *mut Self::KluSymbolic,
161        numeric: *mut Self::KluNumeric,
162        rhs_dimension: Self,
163        number_rhs: Self,
164        rhs_data: *mut f64,
165        common: *mut Self::KluCommon,
166    ) -> bool;
167
168    unsafe fn klu_z_solve(
169        symbolic: *mut Self::KluSymbolic,
170        numeric: *mut Self::KluNumeric,
171        rhs_dimension: Self,
172        number_rhs: Self,
173        rhs_data: *mut f64,
174        common: *mut Self::KluCommon,
175    ) -> bool;
176
177    unsafe fn klu_z_tsolve(
178        symbolic: *mut Self::KluSymbolic,
179        numeric: *mut Self::KluNumeric,
180        rhs_dimension: Self,
181        number_rhs: Self,
182        rhs_data: *mut f64,
183        common: *mut Self::KluCommon,
184    ) -> bool;
185
186    unsafe fn klu_free_numeric(numeric: *mut *mut Self::KluNumeric, common: *mut Self::KluCommon);
187
188    unsafe fn klu_z_free_numeric(numeric: *mut *mut Self::KluNumeric, common: *mut Self::KluCommon);
189
190    fn check_status(common: &Self::KluCommon);
191    fn get_rcond(common: &Self::KluCommon) -> f64;
192    fn is_singular(common: &Self::KluCommon) -> bool;
193
194    unsafe fn klu_rcond(
195        symbolic: *mut Self::KluSymbolic,
196        numeric: *mut Self::KluNumeric,
197        common: *mut Self::KluCommon,
198    ) -> bool;
199
200    unsafe fn klu_z_rcond(
201        symbolic: *mut Self::KluSymbolic,
202        numeric: *mut Self::KluNumeric,
203        common: *mut Self::KluCommon,
204    ) -> bool;
205}
206
207impl KluData for f64 {
208    unsafe fn klu_solve<I: KluIndex>(
209        symbolic: *mut <I as KluIndex>::KluSymbolic,
210        numeric: *mut <I as KluIndex>::KluNumeric,
211        rhs_dimension: I,
212        number_rhs: I,
213        rhs_data: *mut Self,
214        common: *mut <I as KluIndex>::KluCommon,
215    ) -> bool {
216        I::klu_solve(
217            symbolic,
218            numeric,
219            rhs_dimension,
220            number_rhs,
221            rhs_data,
222            common,
223        )
224    }
225
226    unsafe fn klu_tsolve<I: KluIndex>(
227        symbolic: *mut I::KluSymbolic,
228        numeric: *mut I::KluNumeric,
229        rhs_dimension: I,
230        number_rhs: I,
231        rhs_data: *mut Self,
232        common: *mut I::KluCommon,
233    ) -> bool {
234        I::klu_tsolve(
235            symbolic,
236            numeric,
237            rhs_dimension,
238            number_rhs,
239            rhs_data,
240            common,
241        )
242    }
243
244    unsafe fn klu_factor<I: KluIndex>(
245        colum_offsets: *const I,
246        row_indices: *const I,
247        data: *mut Self,
248        symbolic: *mut I::KluSymbolic,
249        common: *mut I::KluCommon,
250    ) -> *mut I::KluNumeric {
251        I::klu_factor(colum_offsets, row_indices, data, symbolic, common)
252    }
253
254    unsafe fn klu_refactor<I: KluIndex>(
255        colum_offsets: *const I,
256        row_indices: *const I,
257        data: *mut Self,
258        symbolic: *mut I::KluSymbolic,
259        numeric: *mut I::KluNumeric,
260        common: *mut I::KluCommon,
261    ) -> bool {
262        I::klu_refactor(colum_offsets, row_indices, data, symbolic, numeric, common)
263    }
264
265    unsafe fn klu_free_numeric<I: KluIndex>(
266        numeric: *mut *mut I::KluNumeric,
267        common: *mut I::KluCommon,
268    ) {
269        I::klu_free_numeric(numeric, common)
270    }
271
272    unsafe fn klu_rcond<I: KluIndex>(
273        symbolic: *mut I::KluSymbolic,
274        numeric: *mut I::KluNumeric,
275        common: *mut I::KluCommon,
276    ) -> bool {
277        I::klu_rcond(symbolic, numeric, common)
278    }
279}
280
281impl KluData for Complex64 {
282    unsafe fn klu_solve<I: KluIndex>(
283        symbolic: *mut <I as KluIndex>::KluSymbolic,
284        numeric: *mut <I as KluIndex>::KluNumeric,
285        rhs_dimension: I,
286        number_rhs: I,
287        rhs_data: *mut Self,
288        common: *mut <I as KluIndex>::KluCommon,
289    ) -> bool {
290        I::klu_z_solve(
291            symbolic,
292            numeric,
293            rhs_dimension,
294            number_rhs,
295            rhs_data as *mut f64,
296            common,
297        )
298    }
299
300    unsafe fn klu_tsolve<I: KluIndex>(
301        symbolic: *mut I::KluSymbolic,
302        numeric: *mut I::KluNumeric,
303        rhs_dimension: I,
304        number_rhs: I,
305        rhs_data: *mut Self,
306        common: *mut I::KluCommon,
307    ) -> bool {
308        I::klu_z_tsolve(
309            symbolic,
310            numeric,
311            rhs_dimension,
312            number_rhs,
313            rhs_data as *mut f64,
314            common,
315        )
316    }
317
318    unsafe fn klu_factor<I: KluIndex>(
319        colum_offsets: *const I,
320        row_indices: *const I,
321        data: *mut Self,
322        symbolic: *mut I::KluSymbolic,
323        common: *mut I::KluCommon,
324    ) -> *mut I::KluNumeric {
325        I::klu_z_factor(
326            colum_offsets,
327            row_indices,
328            data as *mut f64,
329            symbolic,
330            common,
331        )
332    }
333
334    unsafe fn klu_refactor<I: KluIndex>(
335        colum_offsets: *const I,
336        row_indices: *const I,
337        data: *mut Self,
338        symbolic: *mut I::KluSymbolic,
339        numeric: *mut I::KluNumeric,
340        common: *mut I::KluCommon,
341    ) -> bool {
342        I::klu_z_refactor(
343            colum_offsets,
344            row_indices,
345            data as *mut f64,
346            symbolic,
347            numeric,
348            common,
349        )
350    }
351
352    unsafe fn klu_free_numeric<I: KluIndex>(
353        numeric: *mut *mut I::KluNumeric,
354        common: *mut I::KluCommon,
355    ) {
356        I::klu_z_free_numeric(numeric, common)
357    }
358
359    unsafe fn klu_rcond<I: KluIndex>(
360        symbolic: *mut I::KluSymbolic,
361        numeric: *mut I::KluNumeric,
362        common: *mut I::KluCommon,
363    ) -> bool {
364        I::klu_z_rcond(symbolic, numeric, common)
365    }
366}
367// targets where c_int != i32 are not supported
368impl KluIndex for i32 {
369    type KluCommon = KluCommon;
370    type KluNumeric = KluNumeric;
371    type KluSymbolic = KluSymbolic;
372
373    fn from_usize(val: usize) -> Self {
374        debug_assert!(val <= Self::MAX as usize);
375        val as Self
376    }
377
378    fn into_usize(self) -> usize {
379        debug_assert!(self >= 0);
380        self as usize
381    }
382
383    unsafe fn klu_defaults(common: *mut Self::KluCommon) -> Self {
384        klu_defaults(common)
385    }
386
387    unsafe fn klu_analyze(
388        dim: Self,
389        colum_offsets: *const Self,
390        row_indices: *const Self,
391        common: *mut Self::KluCommon,
392    ) -> *mut Self::KluSymbolic {
393        klu_analyze(
394            dim,
395            colum_offsets as *mut Self,
396            row_indices as *mut Self,
397            common,
398        )
399    }
400
401    unsafe fn klu_free_symbolic(
402        symbolic: *mut *mut Self::KluSymbolic,
403        common: *mut Self::KluCommon,
404    ) {
405        if klu_free_symbolic(symbolic, common) == 0 {
406            unreachable!("freeing klu symbolic object failed")
407        }
408    }
409
410    unsafe fn klu_factor(
411        colum_offsets: *const Self,
412        row_indices: *const Self,
413        data: *mut f64,
414        symbolic: *mut Self::KluSymbolic,
415        common: *mut Self::KluCommon,
416    ) -> *mut Self::KluNumeric {
417        klu_factor(
418            colum_offsets as *mut Self,
419            row_indices as *mut Self,
420            data,
421            symbolic,
422            common,
423        )
424    }
425
426    unsafe fn klu_z_factor(
427        colum_offsets: *const Self,
428        row_indices: *const Self,
429        data: *mut f64,
430        symbolic: *mut Self::KluSymbolic,
431        common: *mut Self::KluCommon,
432    ) -> *mut Self::KluNumeric {
433        klu_z_factor(
434            colum_offsets as *mut Self,
435            row_indices as *mut Self,
436            data,
437            symbolic,
438            common,
439        )
440    }
441
442    unsafe fn klu_refactor(
443        colum_offsets: *const Self,
444        row_indices: *const Self,
445        data: *mut f64,
446        symbolic: *mut Self::KluSymbolic,
447        numeric: *mut Self::KluNumeric,
448        common: *mut Self::KluCommon,
449    ) -> bool {
450        klu_refactor(
451            colum_offsets as *mut Self,
452            row_indices as *mut Self,
453            data,
454            symbolic,
455            numeric,
456            common,
457        ) != 0
458    }
459
460    unsafe fn klu_z_refactor(
461        colum_offsets: *const Self,
462        row_indices: *const Self,
463        data: *mut f64,
464        symbolic: *mut Self::KluSymbolic,
465        numeric: *mut Self::KluNumeric,
466        common: *mut Self::KluCommon,
467    ) -> bool {
468        klu_z_refactor(
469            colum_offsets as *mut Self,
470            row_indices as *mut Self,
471            data,
472            symbolic,
473            numeric,
474            common,
475        ) != 0
476    }
477
478    unsafe fn klu_solve(
479        symbolic: *mut Self::KluSymbolic,
480        numeric: *mut Self::KluNumeric,
481        rhs_dimension: Self,
482        number_rhs: Self,
483        rhs_data: *mut f64,
484        common: *mut Self::KluCommon,
485    ) -> bool {
486        klu_solve(
487            symbolic,
488            numeric,
489            rhs_dimension,
490            number_rhs,
491            rhs_data,
492            common,
493        ) != 0
494    }
495
496    unsafe fn klu_tsolve(
497        symbolic: *mut Self::KluSymbolic,
498        numeric: *mut Self::KluNumeric,
499        rhs_dimension: Self,
500        number_rhs: Self,
501        rhs_data: *mut f64,
502        common: *mut Self::KluCommon,
503    ) -> bool {
504        klu_tsolve(
505            symbolic,
506            numeric,
507            rhs_dimension,
508            number_rhs,
509            rhs_data,
510            common,
511        ) != 0
512    }
513
514    unsafe fn klu_z_solve(
515        symbolic: *mut Self::KluSymbolic,
516        numeric: *mut Self::KluNumeric,
517        rhs_dimension: Self,
518        number_rhs: Self,
519        rhs_data: *mut f64,
520        common: *mut Self::KluCommon,
521    ) -> bool {
522        klu_z_solve(
523            symbolic,
524            numeric,
525            rhs_dimension,
526            number_rhs,
527            rhs_data,
528            common,
529        ) != 0
530    }
531
532    unsafe fn klu_z_tsolve(
533        symbolic: *mut Self::KluSymbolic,
534        numeric: *mut Self::KluNumeric,
535        rhs_dimension: Self,
536        number_rhs: Self,
537        rhs_data: *mut f64,
538        common: *mut Self::KluCommon,
539    ) -> bool {
540        klu_z_tsolve(
541            symbolic,
542            numeric,
543            rhs_dimension,
544            number_rhs,
545            rhs_data,
546            0,
547            common,
548        ) != 0
549    }
550
551    unsafe fn klu_free_numeric(numeric: *mut *mut Self::KluNumeric, common: *mut Self::KluCommon) {
552        if klu_free_numeric(numeric, common) == 0 {
553            unreachable!("freeing klu numeric object failed")
554        }
555    }
556
557    unsafe fn klu_z_free_numeric(
558        numeric: *mut *mut Self::KluNumeric,
559        common: *mut Self::KluCommon,
560    ) {
561        if klu_z_free_numeric(numeric, common) == 0 {
562            unreachable!("freeing klu numeric object failed")
563        }
564    }
565
566    fn check_status(common: &Self::KluCommon) {
567        match common.status {
568            -2 => unreachable!("KLU error: OUT OF MEMORY"),
569            -3 => unreachable!("KLU error: INVALID"),
570            -4 => unreachable!("KLU error: TOO LARGE"),
571            code @ (Self::MIN..=-5 | -1) => {
572                unreachable!("KLU failed with unkown errorcode {}", code)
573            }
574            _ => (),
575        }
576    }
577
578    fn get_rcond(common: &Self::KluCommon) -> f64 {
579        common.rcond
580    }
581
582    fn is_singular(common: &Self::KluCommon) -> bool {
583        common.status == 1
584    }
585
586    unsafe fn klu_rcond(
587        symbolic: *mut Self::KluSymbolic,
588        numeric: *mut Self::KluNumeric,
589        common: *mut Self::KluCommon,
590    ) -> bool {
591        klu_rcond(symbolic, numeric, common) != 0
592    }
593
594    unsafe fn klu_z_rcond(
595        symbolic: *mut Self::KluSymbolic,
596        numeric: *mut Self::KluNumeric,
597        common: *mut Self::KluCommon,
598    ) -> bool {
599        klu_z_rcond(symbolic, numeric, common) != 0
600    }
601}
602
603// Klu uses conditions to ensure its long is always 64 bit
604impl KluIndex for i64 {
605    type KluCommon = KluLCommon;
606    type KluNumeric = KluLNumeric;
607    type KluSymbolic = KluLSymbolic;
608
609    fn from_usize(val: usize) -> Self {
610        debug_assert!(val < Self::MAX as usize);
611        val as Self
612    }
613
614    fn into_usize(self) -> usize {
615        debug_assert!(self > 0);
616        self as usize
617    }
618
619    unsafe fn klu_defaults(common: *mut Self::KluCommon) -> Self {
620        klu_l_defaults(common)
621    }
622
623    unsafe fn klu_analyze(
624        dim: Self,
625        colum_offsets: *const Self,
626        row_indices: *const Self,
627        common: *mut Self::KluCommon,
628    ) -> *mut Self::KluSymbolic {
629        klu_l_analyze(
630            dim,
631            colum_offsets as *mut Self,
632            row_indices as *mut Self,
633            common,
634        )
635    }
636
637    unsafe fn klu_free_symbolic(
638        symbolic: *mut *mut Self::KluSymbolic,
639        common: *mut Self::KluCommon,
640    ) {
641        if klu_l_free_symbolic(symbolic, common) == 0 {
642            unreachable!("freeing klu numeric object failed")
643        }
644    }
645
646    unsafe fn klu_factor(
647        colum_offsets: *const Self,
648        row_indices: *const Self,
649        data: *mut f64,
650        symbolic: *mut Self::KluSymbolic,
651        common: *mut Self::KluCommon,
652    ) -> *mut Self::KluNumeric {
653        klu_l_factor(
654            colum_offsets as *mut Self,
655            row_indices as *mut Self,
656            data,
657            symbolic,
658            common,
659        )
660    }
661
662    unsafe fn klu_z_factor(
663        colum_offsets: *const Self,
664        row_indices: *const Self,
665        data: *mut f64,
666        symbolic: *mut Self::KluSymbolic,
667        common: *mut Self::KluCommon,
668    ) -> *mut Self::KluNumeric {
669        klu_zl_factor(
670            colum_offsets as *mut Self,
671            row_indices as *mut Self,
672            data,
673            symbolic,
674            common,
675        )
676    }
677
678    unsafe fn klu_refactor(
679        colum_offsets: *const Self,
680        row_indices: *const Self,
681        data: *mut f64,
682        symbolic: *mut Self::KluSymbolic,
683        numeric: *mut Self::KluNumeric,
684        common: *mut Self::KluCommon,
685    ) -> bool {
686        klu_l_refactor(
687            colum_offsets as *mut Self,
688            row_indices as *mut Self,
689            data,
690            symbolic,
691            numeric,
692            common,
693        ) != 0
694    }
695
696    unsafe fn klu_z_refactor(
697        colum_offsets: *const Self,
698        row_indices: *const Self,
699        data: *mut f64,
700        symbolic: *mut Self::KluSymbolic,
701        numeric: *mut Self::KluNumeric,
702        common: *mut Self::KluCommon,
703    ) -> bool {
704        klu_zl_refactor(
705            colum_offsets as *mut Self,
706            row_indices as *mut Self,
707            data,
708            symbolic,
709            numeric,
710            common,
711        ) != 0
712    }
713
714    unsafe fn klu_solve(
715        symbolic: *mut Self::KluSymbolic,
716        numeric: *mut Self::KluNumeric,
717        rhs_dimension: Self,
718        number_rhs: Self,
719        rhs_data: *mut f64,
720        common: *mut Self::KluCommon,
721    ) -> bool {
722        klu_l_solve(
723            symbolic,
724            numeric,
725            rhs_dimension,
726            number_rhs,
727            rhs_data,
728            common,
729        ) != 0
730    }
731
732    unsafe fn klu_tsolve(
733        symbolic: *mut Self::KluSymbolic,
734        numeric: *mut Self::KluNumeric,
735        rhs_dimension: Self,
736        number_rhs: Self,
737        rhs_data: *mut f64,
738        common: *mut Self::KluCommon,
739    ) -> bool {
740        klu_l_tsolve(
741            symbolic,
742            numeric,
743            rhs_dimension,
744            number_rhs,
745            rhs_data,
746            common,
747        ) != 0
748    }
749
750    unsafe fn klu_z_solve(
751        symbolic: *mut Self::KluSymbolic,
752        numeric: *mut Self::KluNumeric,
753        rhs_dimension: Self,
754        number_rhs: Self,
755        rhs_data: *mut f64,
756        common: *mut Self::KluCommon,
757    ) -> bool {
758        klu_zl_solve(
759            symbolic,
760            numeric,
761            rhs_dimension,
762            number_rhs,
763            rhs_data,
764            common,
765        ) != 0
766    }
767
768    unsafe fn klu_z_tsolve(
769        symbolic: *mut Self::KluSymbolic,
770        numeric: *mut Self::KluNumeric,
771        rhs_dimension: Self,
772        number_rhs: Self,
773        rhs_data: *mut f64,
774        common: *mut Self::KluCommon,
775    ) -> bool {
776        klu_zl_tsolve(
777            symbolic,
778            numeric,
779            rhs_dimension,
780            number_rhs,
781            rhs_data,
782            0,
783            common,
784        ) != 0
785    }
786
787    unsafe fn klu_free_numeric(numeric: *mut *mut Self::KluNumeric, common: *mut Self::KluCommon) {
788        if klu_l_free_numeric(numeric, common) == 0 {
789            unreachable!("freeing klu numeric object failed")
790        }
791    }
792
793    unsafe fn klu_z_free_numeric(
794        numeric: *mut *mut Self::KluNumeric,
795        common: *mut Self::KluCommon,
796    ) {
797        if klu_zl_free_numeric(numeric, common) == 0 {
798            unreachable!("freeing klu numeric object failed")
799        }
800    }
801
802    fn check_status(common: &Self::KluCommon) {
803        match common.status {
804            0 => (),
805            -1 => unreachable!("KLU failed with unkown errorcode -1"),
806            -2 => unreachable!("KLU error: OUT OF MEMORY"),
807            -3 => unreachable!("KLU error: INVALID"),
808            -4 => unreachable!("KLU error: TOO LARGE"),
809            code @ Self::MIN..=-5 => unreachable!("KLU failed with unkown errorcode {}", code),
810            1 => unreachable!("Singular matrix!"),
811            code => unreachable!("Unkown warning {code}"),
812        }
813    }
814
815    fn get_rcond(common: &Self::KluCommon) -> f64 {
816        common.rcond
817    }
818
819    fn is_singular(common: &Self::KluCommon) -> bool {
820        common.status == 1
821    }
822
823    unsafe fn klu_rcond(
824        symbolic: *mut Self::KluSymbolic,
825        numeric: *mut Self::KluNumeric,
826        common: *mut Self::KluCommon,
827    ) -> bool {
828        klu_l_rcond(symbolic, numeric, common) != 0
829    }
830
831    unsafe fn klu_z_rcond(
832        symbolic: *mut Self::KluSymbolic,
833        numeric: *mut Self::KluNumeric,
834        common: *mut Self::KluCommon,
835    ) -> bool {
836        klu_zl_rcond(symbolic, numeric, common) != 0
837    }
838}