Skip to main content

cddlib_rs/
backend.rs

1// Internal backend bindings and numeric backends.
2//
3// This module owns the `CddNumber` trait and all backend-specific FFI glue.
4
5use std::ffi::c_void;
6use std::mem;
7use std::os::raw::c_long;
8use std::sync::Once;
9
10#[cfg(any(feature = "gmp", feature = "gmprational"))]
11use std::mem::MaybeUninit;
12
13use crate::NumberType;
14
15use cddlib_sys as sys;
16
17#[cfg(feature = "gmp")]
18pub struct CddFloat {
19    inner: sys::gmpfloat::mytype,
20}
21
22#[cfg(feature = "gmprational")]
23pub struct CddRational {
24    inner: sys::gmprational::mytype,
25}
26
27#[cfg(feature = "f64")]
28pub type DefaultNumber = f64;
29
30#[cfg(all(not(feature = "f64"), feature = "gmprational"))]
31pub type DefaultNumber = CddRational;
32
33#[cfg(all(not(feature = "f64"), not(feature = "gmprational"), feature = "gmp"))]
34pub type DefaultNumber = CddFloat;
35
36mod sealed {
37    pub trait Sealed {}
38}
39
40pub trait CddNumber: sealed::Sealed + 'static {
41    const MYTYPE_SIZE: usize;
42    const DEFAULT_NUMBER_TYPE: NumberType;
43
44    fn ensure_initialized();
45
46    #[doc(hidden)]
47    fn dd_no_error() -> u32;
48
49    #[doc(hidden)]
50    unsafe fn dd_create_matrix(rows: c_long, cols: c_long) -> *mut c_void;
51
52    #[doc(hidden)]
53    unsafe fn dd_copy_matrix(matrix: *mut c_void) -> *mut c_void;
54
55    #[doc(hidden)]
56    unsafe fn dd_free_matrix(matrix: *mut c_void);
57
58    #[doc(hidden)]
59    unsafe fn dd_matrix_append_to(dst: *mut *mut c_void, src: *mut c_void) -> i32;
60
61    #[doc(hidden)]
62    unsafe fn dd_append_matrix(a: *mut c_void, b: *mut c_void) -> *mut c_void;
63
64    #[doc(hidden)]
65    unsafe fn dd_matrix_row_remove(matrix: *mut *mut c_void, row: c_long) -> i32;
66
67    #[doc(hidden)]
68    unsafe fn dd_initialize_arow(cols: c_long, out: *mut *mut c_void);
69
70    #[doc(hidden)]
71    unsafe fn dd_free_arow(cols: c_long, arow: *mut c_void);
72
73    #[doc(hidden)]
74    unsafe fn dd_redundant(
75        matrix: *mut c_void,
76        row: c_long,
77        cert: *mut c_void,
78        err: *mut u32,
79    ) -> i32;
80
81    #[doc(hidden)]
82    unsafe fn dd_redundant_rows(matrix: *mut c_void, err: *mut u32) -> *mut libc::c_ulong;
83
84    #[doc(hidden)]
85    unsafe fn dd_matrix_canonicalize(
86        matrix: *mut *mut c_void,
87        impl_lin: *mut *mut libc::c_ulong,
88        redset: *mut *mut libc::c_ulong,
89        newpos: *mut *mut c_long,
90        err: *mut u32,
91    ) -> i32;
92
93    #[doc(hidden)]
94    unsafe fn set_groundsize(set: *mut libc::c_ulong) -> c_long;
95
96    #[doc(hidden)]
97    unsafe fn set_member(elem: c_long, set: *mut libc::c_ulong) -> i32;
98
99    #[doc(hidden)]
100    unsafe fn set_free(set: *mut libc::c_ulong);
101
102    #[doc(hidden)]
103    unsafe fn dd_matrix2poly(matrix: *mut c_void, err: *mut u32) -> *mut c_void;
104
105    #[doc(hidden)]
106    unsafe fn dd_free_polyhedra(poly: *mut c_void);
107
108    #[doc(hidden)]
109    unsafe fn dd_copy_inequalities(poly: *mut c_void) -> *mut c_void;
110
111    #[doc(hidden)]
112    unsafe fn dd_copy_generators(poly: *mut c_void) -> *mut c_void;
113
114    #[doc(hidden)]
115    unsafe fn dd_copy_adjacency(poly: *mut c_void) -> *mut c_void;
116
117    #[doc(hidden)]
118    unsafe fn dd_copy_input_adjacency(poly: *mut c_void) -> *mut c_void;
119
120    #[doc(hidden)]
121    unsafe fn dd_copy_incidence(poly: *mut c_void) -> *mut c_void;
122
123    #[doc(hidden)]
124    unsafe fn dd_copy_input_incidence(poly: *mut c_void) -> *mut c_void;
125
126    #[doc(hidden)]
127    unsafe fn dd_append_matrix2poly(poly: *mut *mut c_void, rows: *mut c_void) -> i32;
128
129    #[doc(hidden)]
130    unsafe fn dd_free_set_family(family: *mut c_void);
131
132    #[doc(hidden)]
133    unsafe fn dd_matrix2lp(matrix: *mut c_void, err: *mut u32) -> *mut c_void;
134
135    #[doc(hidden)]
136    unsafe fn dd_free_lp_data(lp: *mut c_void);
137
138    #[doc(hidden)]
139    unsafe fn dd_lp_solve_dual_simplex(lp: *mut c_void, err: *mut u32) -> i32;
140
141    #[doc(hidden)]
142    unsafe fn lp_status_raw(lp: *mut c_void) -> u32;
143
144    #[doc(hidden)]
145    unsafe fn dd_copy_lp_solution(lp: *mut c_void) -> *mut c_void;
146
147    #[doc(hidden)]
148    unsafe fn dd_free_lp_solution(sol: *mut c_void);
149
150    #[doc(hidden)]
151    unsafe fn lp_solution_optvalue_ptr(sol: *mut c_void) -> *const c_void;
152
153    #[doc(hidden)]
154    unsafe fn write_mytype_real(target: *mut c_void, value: f64);
155
156    #[doc(hidden)]
157    unsafe fn write_mytype_int(target: *mut c_void, value: c_long);
158
159    #[doc(hidden)]
160    unsafe fn read_mytype_real(source: *const c_void) -> f64;
161
162    #[doc(hidden)]
163    unsafe fn write_mytype(target: *mut c_void, value: &Self);
164
165    #[doc(hidden)]
166    unsafe fn read_mytype(source: *const c_void) -> Self;
167}
168
169#[cfg(feature = "f64")]
170impl sealed::Sealed for f64 {}
171
172#[cfg(feature = "f64")]
173impl CddNumber for f64 {
174    const MYTYPE_SIZE: usize = mem::size_of::<sys::f64::mytype>();
175    const DEFAULT_NUMBER_TYPE: NumberType = NumberType::Real;
176
177    fn ensure_initialized() {
178        static INIT: Once = Once::new();
179        INIT.call_once(|| unsafe {
180            sys::f64::dd_set_global_constants();
181        });
182    }
183
184    fn dd_no_error() -> u32 {
185        sys::f64::dd_ErrorType_dd_NoError
186    }
187
188    unsafe fn dd_create_matrix(rows: c_long, cols: c_long) -> *mut c_void {
189        unsafe { sys::f64::dd_CreateMatrix(rows, cols).cast() }
190    }
191
192    unsafe fn dd_copy_matrix(matrix: *mut c_void) -> *mut c_void {
193        unsafe { sys::f64::dd_CopyMatrix(matrix.cast()).cast() }
194    }
195
196    unsafe fn dd_free_matrix(matrix: *mut c_void) {
197        unsafe {
198            sys::f64::dd_FreeMatrix(matrix.cast());
199        }
200    }
201
202    unsafe fn dd_matrix_append_to(dst: *mut *mut c_void, src: *mut c_void) -> i32 {
203        unsafe { sys::f64::dd_MatrixAppendTo(dst.cast(), src.cast()) }
204    }
205
206    unsafe fn dd_append_matrix(a: *mut c_void, b: *mut c_void) -> *mut c_void {
207        unsafe { sys::f64::dd_AppendMatrix(a.cast(), b.cast()).cast() }
208    }
209
210    unsafe fn dd_matrix_row_remove(matrix: *mut *mut c_void, row: c_long) -> i32 {
211        unsafe { sys::f64::dd_MatrixRowRemove(matrix.cast(), row) }
212    }
213
214    unsafe fn dd_initialize_arow(cols: c_long, out: *mut *mut c_void) {
215        unsafe {
216            sys::f64::dd_InitializeArow(cols, out.cast());
217        }
218    }
219
220    unsafe fn dd_free_arow(cols: c_long, arow: *mut c_void) {
221        unsafe {
222            sys::f64::dd_FreeArow(cols, arow.cast());
223        }
224    }
225
226    unsafe fn dd_redundant(
227        matrix: *mut c_void,
228        row: c_long,
229        cert: *mut c_void,
230        err: *mut u32,
231    ) -> i32 {
232        unsafe { sys::f64::dd_Redundant(matrix.cast(), row, cert.cast(), err.cast()) }
233    }
234
235    unsafe fn dd_redundant_rows(matrix: *mut c_void, err: *mut u32) -> *mut libc::c_ulong {
236        unsafe { sys::f64::dd_RedundantRows(matrix.cast(), err.cast()).cast() }
237    }
238
239    unsafe fn dd_matrix_canonicalize(
240        matrix: *mut *mut c_void,
241        impl_lin: *mut *mut libc::c_ulong,
242        redset: *mut *mut libc::c_ulong,
243        newpos: *mut *mut c_long,
244        err: *mut u32,
245    ) -> i32 {
246        unsafe {
247            sys::f64::dd_MatrixCanonicalize(
248                matrix.cast(),
249                impl_lin.cast(),
250                redset.cast(),
251                newpos.cast(),
252                err.cast(),
253            )
254        }
255    }
256
257    unsafe fn set_groundsize(set: *mut libc::c_ulong) -> c_long {
258        unsafe { sys::f64::set_groundsize(set.cast()) }
259    }
260
261    unsafe fn set_member(elem: c_long, set: *mut libc::c_ulong) -> i32 {
262        unsafe { sys::f64::set_member(elem, set.cast()) }
263    }
264
265    unsafe fn set_free(set: *mut libc::c_ulong) {
266        unsafe {
267            sys::f64::set_free(set.cast());
268        }
269    }
270
271    unsafe fn dd_matrix2poly(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
272        unsafe { sys::f64::dd_DDMatrix2Poly(matrix.cast(), err.cast()).cast() }
273    }
274
275    unsafe fn dd_free_polyhedra(poly: *mut c_void) {
276        unsafe {
277            sys::f64::dd_FreePolyhedra(poly.cast());
278        }
279    }
280
281    unsafe fn dd_copy_inequalities(poly: *mut c_void) -> *mut c_void {
282        unsafe { sys::f64::dd_CopyInequalities(poly.cast()).cast() }
283    }
284
285    unsafe fn dd_copy_generators(poly: *mut c_void) -> *mut c_void {
286        unsafe { sys::f64::dd_CopyGenerators(poly.cast()).cast() }
287    }
288
289    unsafe fn dd_copy_adjacency(poly: *mut c_void) -> *mut c_void {
290        unsafe { sys::f64::dd_CopyAdjacency(poly.cast()).cast() }
291    }
292
293    unsafe fn dd_copy_input_adjacency(poly: *mut c_void) -> *mut c_void {
294        unsafe { sys::f64::dd_CopyInputAdjacency(poly.cast()).cast() }
295    }
296
297    unsafe fn dd_copy_incidence(poly: *mut c_void) -> *mut c_void {
298        unsafe { sys::f64::dd_CopyIncidence(poly.cast()).cast() }
299    }
300
301    unsafe fn dd_copy_input_incidence(poly: *mut c_void) -> *mut c_void {
302        unsafe { sys::f64::dd_CopyInputIncidence(poly.cast()).cast() }
303    }
304
305    unsafe fn dd_append_matrix2poly(poly: *mut *mut c_void, rows: *mut c_void) -> i32 {
306        unsafe { sys::f64::dd_AppendMatrix2Poly(poly.cast(), rows.cast()) }
307    }
308
309    unsafe fn dd_free_set_family(family: *mut c_void) {
310        unsafe {
311            sys::f64::dd_FreeSetFamily(family.cast());
312        }
313    }
314
315    unsafe fn dd_matrix2lp(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
316        unsafe { sys::f64::dd_Matrix2LP(matrix.cast(), err.cast()).cast() }
317    }
318
319    unsafe fn dd_free_lp_data(lp: *mut c_void) {
320        unsafe {
321            sys::f64::dd_FreeLPData(lp.cast());
322        }
323    }
324
325    unsafe fn dd_lp_solve_dual_simplex(lp: *mut c_void, err: *mut u32) -> i32 {
326        unsafe {
327            sys::f64::dd_LPSolve(
328                lp.cast(),
329                sys::f64::dd_LPSolverType_dd_DualSimplex,
330                err.cast(),
331            )
332        }
333    }
334
335    unsafe fn lp_status_raw(lp: *mut c_void) -> u32 {
336        unsafe { (*lp.cast::<sys::f64::dd_lpdata>()).LPS }
337    }
338
339    unsafe fn dd_copy_lp_solution(lp: *mut c_void) -> *mut c_void {
340        unsafe { sys::f64::dd_CopyLPSolution(lp.cast()).cast() }
341    }
342
343    unsafe fn dd_free_lp_solution(sol: *mut c_void) {
344        unsafe {
345            sys::f64::dd_FreeLPSolution(sol.cast());
346        }
347    }
348
349    unsafe fn lp_solution_optvalue_ptr(sol: *mut c_void) -> *const c_void {
350        unsafe {
351            let sol = sol.cast::<sys::f64::dd_lpsolution>();
352            (&(*sol).optvalue as *const sys::f64::mytype).cast()
353        }
354    }
355
356    unsafe fn write_mytype_real(target: *mut c_void, value: f64) {
357        unsafe {
358            (*target.cast::<sys::f64::mytype>())[0] = value;
359        }
360    }
361
362    unsafe fn write_mytype_int(target: *mut c_void, value: c_long) {
363        unsafe {
364            (*target.cast::<sys::f64::mytype>())[0] = value as f64;
365        }
366    }
367
368    unsafe fn read_mytype_real(source: *const c_void) -> f64 {
369        unsafe { (*source.cast::<sys::f64::mytype>())[0] }
370    }
371
372    unsafe fn write_mytype(target: *mut c_void, value: &Self) {
373        unsafe {
374            Self::write_mytype_real(target, *value);
375        }
376    }
377
378    unsafe fn read_mytype(source: *const c_void) -> Self {
379        unsafe { Self::read_mytype_real(source) }
380    }
381}
382
383#[cfg(feature = "gmp")]
384impl sealed::Sealed for CddFloat {}
385
386#[cfg(feature = "gmp")]
387impl CddNumber for CddFloat {
388    const MYTYPE_SIZE: usize = mem::size_of::<sys::gmpfloat::mytype>();
389    const DEFAULT_NUMBER_TYPE: NumberType = NumberType::Real;
390
391    fn ensure_initialized() {
392        static INIT: Once = Once::new();
393        INIT.call_once(|| unsafe {
394            sys::gmpfloat::dd_set_global_constants();
395        });
396    }
397
398    fn dd_no_error() -> u32 {
399        sys::gmpfloat::dd_ErrorType_dd_NoError
400    }
401
402    unsafe fn dd_create_matrix(rows: c_long, cols: c_long) -> *mut c_void {
403        unsafe { sys::gmpfloat::dd_CreateMatrix(rows, cols).cast() }
404    }
405
406    unsafe fn dd_copy_matrix(matrix: *mut c_void) -> *mut c_void {
407        unsafe { sys::gmpfloat::dd_CopyMatrix(matrix.cast()).cast() }
408    }
409
410    unsafe fn dd_free_matrix(matrix: *mut c_void) {
411        unsafe {
412            sys::gmpfloat::dd_FreeMatrix(matrix.cast());
413        }
414    }
415
416    unsafe fn dd_matrix_append_to(dst: *mut *mut c_void, src: *mut c_void) -> i32 {
417        unsafe { sys::gmpfloat::dd_MatrixAppendTo(dst.cast(), src.cast()) }
418    }
419
420    unsafe fn dd_append_matrix(a: *mut c_void, b: *mut c_void) -> *mut c_void {
421        unsafe { sys::gmpfloat::dd_AppendMatrix(a.cast(), b.cast()).cast() }
422    }
423
424    unsafe fn dd_matrix_row_remove(matrix: *mut *mut c_void, row: c_long) -> i32 {
425        unsafe { sys::gmpfloat::dd_MatrixRowRemove(matrix.cast(), row) }
426    }
427
428    unsafe fn dd_initialize_arow(cols: c_long, out: *mut *mut c_void) {
429        unsafe {
430            sys::gmpfloat::dd_InitializeArow(cols, out.cast());
431        }
432    }
433
434    unsafe fn dd_free_arow(cols: c_long, arow: *mut c_void) {
435        unsafe {
436            sys::gmpfloat::dd_FreeArow(cols, arow.cast());
437        }
438    }
439
440    unsafe fn dd_redundant(
441        matrix: *mut c_void,
442        row: c_long,
443        cert: *mut c_void,
444        err: *mut u32,
445    ) -> i32 {
446        unsafe { sys::gmpfloat::dd_Redundant(matrix.cast(), row, cert.cast(), err.cast()) }
447    }
448
449    unsafe fn dd_redundant_rows(matrix: *mut c_void, err: *mut u32) -> *mut libc::c_ulong {
450        unsafe { sys::gmpfloat::dd_RedundantRows(matrix.cast(), err.cast()).cast() }
451    }
452
453    unsafe fn dd_matrix_canonicalize(
454        matrix: *mut *mut c_void,
455        impl_lin: *mut *mut libc::c_ulong,
456        redset: *mut *mut libc::c_ulong,
457        newpos: *mut *mut c_long,
458        err: *mut u32,
459    ) -> i32 {
460        unsafe {
461            sys::gmpfloat::dd_MatrixCanonicalize(
462                matrix.cast(),
463                impl_lin.cast(),
464                redset.cast(),
465                newpos.cast(),
466                err.cast(),
467            )
468        }
469    }
470
471    unsafe fn set_groundsize(set: *mut libc::c_ulong) -> c_long {
472        unsafe { sys::gmpfloat::set_groundsize(set.cast()) }
473    }
474
475    unsafe fn set_member(elem: c_long, set: *mut libc::c_ulong) -> i32 {
476        unsafe { sys::gmpfloat::set_member(elem, set.cast()) }
477    }
478
479    unsafe fn set_free(set: *mut libc::c_ulong) {
480        unsafe {
481            sys::gmpfloat::set_free(set.cast());
482        }
483    }
484
485    unsafe fn dd_matrix2poly(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
486        unsafe { sys::gmpfloat::dd_DDMatrix2Poly(matrix.cast(), err.cast()).cast() }
487    }
488
489    unsafe fn dd_free_polyhedra(poly: *mut c_void) {
490        unsafe {
491            sys::gmpfloat::dd_FreePolyhedra(poly.cast());
492        }
493    }
494
495    unsafe fn dd_copy_inequalities(poly: *mut c_void) -> *mut c_void {
496        unsafe { sys::gmpfloat::dd_CopyInequalities(poly.cast()).cast() }
497    }
498
499    unsafe fn dd_copy_generators(poly: *mut c_void) -> *mut c_void {
500        unsafe { sys::gmpfloat::dd_CopyGenerators(poly.cast()).cast() }
501    }
502
503    unsafe fn dd_copy_adjacency(poly: *mut c_void) -> *mut c_void {
504        unsafe { sys::gmpfloat::dd_CopyAdjacency(poly.cast()).cast() }
505    }
506
507    unsafe fn dd_copy_input_adjacency(poly: *mut c_void) -> *mut c_void {
508        unsafe { sys::gmpfloat::dd_CopyInputAdjacency(poly.cast()).cast() }
509    }
510
511    unsafe fn dd_copy_incidence(poly: *mut c_void) -> *mut c_void {
512        unsafe { sys::gmpfloat::dd_CopyIncidence(poly.cast()).cast() }
513    }
514
515    unsafe fn dd_copy_input_incidence(poly: *mut c_void) -> *mut c_void {
516        unsafe { sys::gmpfloat::dd_CopyInputIncidence(poly.cast()).cast() }
517    }
518
519    unsafe fn dd_append_matrix2poly(poly: *mut *mut c_void, rows: *mut c_void) -> i32 {
520        unsafe { sys::gmpfloat::dd_AppendMatrix2Poly(poly.cast(), rows.cast()) }
521    }
522
523    unsafe fn dd_free_set_family(family: *mut c_void) {
524        unsafe {
525            sys::gmpfloat::dd_FreeSetFamily(family.cast());
526        }
527    }
528
529    unsafe fn dd_matrix2lp(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
530        unsafe { sys::gmpfloat::dd_Matrix2LP(matrix.cast(), err.cast()).cast() }
531    }
532
533    unsafe fn dd_free_lp_data(lp: *mut c_void) {
534        unsafe {
535            sys::gmpfloat::dd_FreeLPData(lp.cast());
536        }
537    }
538
539    unsafe fn dd_lp_solve_dual_simplex(lp: *mut c_void, err: *mut u32) -> i32 {
540        unsafe {
541            sys::gmpfloat::dd_LPSolve(
542                lp.cast(),
543                sys::gmpfloat::dd_LPSolverType_dd_DualSimplex,
544                err.cast(),
545            )
546        }
547    }
548
549    unsafe fn lp_status_raw(lp: *mut c_void) -> u32 {
550        unsafe { (*lp.cast::<sys::gmpfloat::dd_lpdata>()).LPS }
551    }
552
553    unsafe fn dd_copy_lp_solution(lp: *mut c_void) -> *mut c_void {
554        unsafe { sys::gmpfloat::dd_CopyLPSolution(lp.cast()).cast() }
555    }
556
557    unsafe fn dd_free_lp_solution(sol: *mut c_void) {
558        unsafe {
559            sys::gmpfloat::dd_FreeLPSolution(sol.cast());
560        }
561    }
562
563    unsafe fn lp_solution_optvalue_ptr(sol: *mut c_void) -> *const c_void {
564        unsafe {
565            let sol = sol.cast::<sys::gmpfloat::dd_lpsolution>();
566            (&(*sol).optvalue as *const sys::gmpfloat::mytype).cast()
567        }
568    }
569
570    unsafe fn write_mytype_real(target: *mut c_void, value: f64) {
571        unsafe {
572            sys::gmpfloat::__gmpf_set_d(target.cast(), value);
573        }
574    }
575
576    unsafe fn write_mytype_int(target: *mut c_void, value: c_long) {
577        unsafe {
578            sys::gmpfloat::__gmpf_set_si(target.cast(), value);
579        }
580    }
581
582    unsafe fn read_mytype_real(source: *const c_void) -> f64 {
583        unsafe { sys::gmpfloat::__gmpf_get_d(source.cast()) }
584    }
585
586    unsafe fn write_mytype(target: *mut c_void, value: &Self) {
587        unsafe {
588            sys::gmpfloat::__gmpf_set(target.cast(), value.inner.as_ptr());
589        }
590    }
591
592    unsafe fn read_mytype(source: *const c_void) -> Self {
593        unsafe {
594            Self::ensure_initialized();
595            let mut inner = MaybeUninit::<sys::gmpfloat::mytype>::uninit();
596            sys::gmpfloat::__gmpf_init(inner.as_mut_ptr().cast());
597            sys::gmpfloat::__gmpf_set(inner.as_mut_ptr().cast(), source.cast());
598            CddFloat {
599                inner: inner.assume_init(),
600            }
601        }
602    }
603}
604
605#[cfg(feature = "gmprational")]
606impl sealed::Sealed for CddRational {}
607
608#[cfg(feature = "gmprational")]
609impl CddNumber for CddRational {
610    const MYTYPE_SIZE: usize = mem::size_of::<sys::gmprational::mytype>();
611    const DEFAULT_NUMBER_TYPE: NumberType = NumberType::Rational;
612
613    fn ensure_initialized() {
614        static INIT: Once = Once::new();
615        INIT.call_once(|| unsafe {
616            sys::gmprational::dd_set_global_constants();
617        });
618    }
619
620    fn dd_no_error() -> u32 {
621        sys::gmprational::dd_ErrorType_dd_NoError
622    }
623
624    unsafe fn dd_create_matrix(rows: c_long, cols: c_long) -> *mut c_void {
625        unsafe { sys::gmprational::dd_CreateMatrix(rows, cols).cast() }
626    }
627
628    unsafe fn dd_copy_matrix(matrix: *mut c_void) -> *mut c_void {
629        unsafe { sys::gmprational::dd_CopyMatrix(matrix.cast()).cast() }
630    }
631
632    unsafe fn dd_free_matrix(matrix: *mut c_void) {
633        unsafe {
634            sys::gmprational::dd_FreeMatrix(matrix.cast());
635        }
636    }
637
638    unsafe fn dd_matrix_append_to(dst: *mut *mut c_void, src: *mut c_void) -> i32 {
639        unsafe { sys::gmprational::dd_MatrixAppendTo(dst.cast(), src.cast()) }
640    }
641
642    unsafe fn dd_append_matrix(a: *mut c_void, b: *mut c_void) -> *mut c_void {
643        unsafe { sys::gmprational::dd_AppendMatrix(a.cast(), b.cast()).cast() }
644    }
645
646    unsafe fn dd_matrix_row_remove(matrix: *mut *mut c_void, row: c_long) -> i32 {
647        unsafe { sys::gmprational::dd_MatrixRowRemove(matrix.cast(), row) }
648    }
649
650    unsafe fn dd_initialize_arow(cols: c_long, out: *mut *mut c_void) {
651        unsafe {
652            sys::gmprational::dd_InitializeArow(cols, out.cast());
653        }
654    }
655
656    unsafe fn dd_free_arow(cols: c_long, arow: *mut c_void) {
657        unsafe {
658            sys::gmprational::dd_FreeArow(cols, arow.cast());
659        }
660    }
661
662    unsafe fn dd_redundant(
663        matrix: *mut c_void,
664        row: c_long,
665        cert: *mut c_void,
666        err: *mut u32,
667    ) -> i32 {
668        unsafe { sys::gmprational::dd_Redundant(matrix.cast(), row, cert.cast(), err.cast()) }
669    }
670
671    unsafe fn dd_redundant_rows(matrix: *mut c_void, err: *mut u32) -> *mut libc::c_ulong {
672        unsafe { sys::gmprational::dd_RedundantRows(matrix.cast(), err.cast()).cast() }
673    }
674
675    unsafe fn dd_matrix_canonicalize(
676        matrix: *mut *mut c_void,
677        impl_lin: *mut *mut libc::c_ulong,
678        redset: *mut *mut libc::c_ulong,
679        newpos: *mut *mut c_long,
680        err: *mut u32,
681    ) -> i32 {
682        unsafe {
683            sys::gmprational::dd_MatrixCanonicalize(
684                matrix.cast(),
685                impl_lin.cast(),
686                redset.cast(),
687                newpos.cast(),
688                err.cast(),
689            )
690        }
691    }
692
693    unsafe fn set_groundsize(set: *mut libc::c_ulong) -> c_long {
694        unsafe { sys::gmprational::set_groundsize(set.cast()) }
695    }
696
697    unsafe fn set_member(elem: c_long, set: *mut libc::c_ulong) -> i32 {
698        unsafe { sys::gmprational::set_member(elem, set.cast()) }
699    }
700
701    unsafe fn set_free(set: *mut libc::c_ulong) {
702        unsafe {
703            sys::gmprational::set_free(set.cast());
704        }
705    }
706
707    unsafe fn dd_matrix2poly(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
708        unsafe { sys::gmprational::dd_DDMatrix2Poly(matrix.cast(), err.cast()).cast() }
709    }
710
711    unsafe fn dd_free_polyhedra(poly: *mut c_void) {
712        unsafe {
713            sys::gmprational::dd_FreePolyhedra(poly.cast());
714        }
715    }
716
717    unsafe fn dd_copy_inequalities(poly: *mut c_void) -> *mut c_void {
718        unsafe { sys::gmprational::dd_CopyInequalities(poly.cast()).cast() }
719    }
720
721    unsafe fn dd_copy_generators(poly: *mut c_void) -> *mut c_void {
722        unsafe { sys::gmprational::dd_CopyGenerators(poly.cast()).cast() }
723    }
724
725    unsafe fn dd_copy_adjacency(poly: *mut c_void) -> *mut c_void {
726        unsafe { sys::gmprational::dd_CopyAdjacency(poly.cast()).cast() }
727    }
728
729    unsafe fn dd_copy_input_adjacency(poly: *mut c_void) -> *mut c_void {
730        unsafe { sys::gmprational::dd_CopyInputAdjacency(poly.cast()).cast() }
731    }
732
733    unsafe fn dd_copy_incidence(poly: *mut c_void) -> *mut c_void {
734        unsafe { sys::gmprational::dd_CopyIncidence(poly.cast()).cast() }
735    }
736
737    unsafe fn dd_copy_input_incidence(poly: *mut c_void) -> *mut c_void {
738        unsafe { sys::gmprational::dd_CopyInputIncidence(poly.cast()).cast() }
739    }
740
741    unsafe fn dd_append_matrix2poly(poly: *mut *mut c_void, rows: *mut c_void) -> i32 {
742        unsafe { sys::gmprational::dd_AppendMatrix2Poly(poly.cast(), rows.cast()) }
743    }
744
745    unsafe fn dd_free_set_family(family: *mut c_void) {
746        unsafe {
747            sys::gmprational::dd_FreeSetFamily(family.cast());
748        }
749    }
750
751    unsafe fn dd_matrix2lp(matrix: *mut c_void, err: *mut u32) -> *mut c_void {
752        unsafe { sys::gmprational::dd_Matrix2LP(matrix.cast(), err.cast()).cast() }
753    }
754
755    unsafe fn dd_free_lp_data(lp: *mut c_void) {
756        unsafe {
757            sys::gmprational::dd_FreeLPData(lp.cast());
758        }
759    }
760
761    unsafe fn dd_lp_solve_dual_simplex(lp: *mut c_void, err: *mut u32) -> i32 {
762        unsafe {
763            sys::gmprational::dd_LPSolve(
764                lp.cast(),
765                sys::gmprational::dd_LPSolverType_dd_DualSimplex,
766                err.cast(),
767            )
768        }
769    }
770
771    unsafe fn lp_status_raw(lp: *mut c_void) -> u32 {
772        unsafe { (*lp.cast::<sys::gmprational::dd_lpdata>()).LPS }
773    }
774
775    unsafe fn dd_copy_lp_solution(lp: *mut c_void) -> *mut c_void {
776        unsafe { sys::gmprational::dd_CopyLPSolution(lp.cast()).cast() }
777    }
778
779    unsafe fn dd_free_lp_solution(sol: *mut c_void) {
780        unsafe {
781            sys::gmprational::dd_FreeLPSolution(sol.cast());
782        }
783    }
784
785    unsafe fn lp_solution_optvalue_ptr(sol: *mut c_void) -> *const c_void {
786        unsafe {
787            let sol = sol.cast::<sys::gmprational::dd_lpsolution>();
788            (&(*sol).optvalue as *const sys::gmprational::mytype).cast()
789        }
790    }
791
792    unsafe fn write_mytype_real(target: *mut c_void, value: f64) {
793        unsafe {
794            sys::gmprational::__gmpq_set_d(target.cast(), value);
795        }
796    }
797
798    unsafe fn write_mytype_int(target: *mut c_void, value: c_long) {
799        unsafe {
800            sys::gmprational::__gmpq_set_si(target.cast(), value, 1);
801        }
802    }
803
804    unsafe fn read_mytype_real(source: *const c_void) -> f64 {
805        unsafe { sys::gmprational::__gmpq_get_d(source.cast()) }
806    }
807
808    unsafe fn write_mytype(target: *mut c_void, value: &Self) {
809        unsafe {
810            sys::gmprational::__gmpq_set(target.cast(), value.inner.as_ptr());
811        }
812    }
813
814    unsafe fn read_mytype(source: *const c_void) -> Self {
815        unsafe {
816            Self::ensure_initialized();
817            let mut inner = MaybeUninit::<sys::gmprational::mytype>::uninit();
818            sys::gmprational::__gmpq_init(inner.as_mut_ptr().cast());
819            sys::gmprational::__gmpq_set(inner.as_mut_ptr().cast(), source.cast());
820            CddRational {
821                inner: inner.assume_init(),
822            }
823        }
824    }
825}
826
827#[cfg(feature = "gmp")]
828impl CddFloat {
829    pub fn to_f64(&self) -> f64 {
830        <Self as CddNumber>::ensure_initialized();
831        unsafe { sys::gmpfloat::__gmpf_get_d(self.inner.as_ptr()) }
832    }
833}
834
835#[cfg(feature = "gmp")]
836impl Clone for CddFloat {
837    fn clone(&self) -> Self {
838        <Self as CddNumber>::ensure_initialized();
839        unsafe {
840            let mut inner = MaybeUninit::<sys::gmpfloat::mytype>::uninit();
841            sys::gmpfloat::__gmpf_init(inner.as_mut_ptr().cast());
842            sys::gmpfloat::__gmpf_set(inner.as_mut_ptr().cast(), self.inner.as_ptr());
843            CddFloat {
844                inner: inner.assume_init(),
845            }
846        }
847    }
848}
849
850#[cfg(feature = "gmp")]
851impl Drop for CddFloat {
852    fn drop(&mut self) {
853        <Self as CddNumber>::ensure_initialized();
854        unsafe {
855            sys::gmpfloat::__gmpf_clear(self.inner.as_mut_ptr());
856        }
857    }
858}
859
860#[cfg(feature = "gmp")]
861impl From<f64> for CddFloat {
862    fn from(value: f64) -> Self {
863        <Self as CddNumber>::ensure_initialized();
864        unsafe {
865            let mut inner = MaybeUninit::<sys::gmpfloat::mytype>::uninit();
866            sys::gmpfloat::__gmpf_init(inner.as_mut_ptr().cast());
867            sys::gmpfloat::__gmpf_set_d(inner.as_mut_ptr().cast(), value);
868            CddFloat {
869                inner: inner.assume_init(),
870            }
871        }
872    }
873}
874
875#[cfg(feature = "gmprational")]
876impl CddRational {
877    pub fn to_f64(&self) -> f64 {
878        <Self as CddNumber>::ensure_initialized();
879        unsafe { sys::gmprational::__gmpq_get_d(self.inner.as_ptr()) }
880    }
881}
882
883#[cfg(feature = "gmprational")]
884impl std::fmt::Display for CddRational {
885    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
886        use std::ffi::CStr;
887
888        <Self as CddNumber>::ensure_initialized();
889        unsafe {
890            let ptr = sys::gmprational::__gmpq_get_str(std::ptr::null_mut(), 10, self.inner.as_ptr());
891            if ptr.is_null() {
892                return Err(std::fmt::Error);
893            }
894            let s = CStr::from_ptr(ptr)
895                .to_str()
896                .map_err(|_| std::fmt::Error)?;
897            let result = f.write_str(s);
898            libc::free(ptr.cast());
899            result
900        }
901    }
902}
903
904#[cfg(feature = "gmprational")]
905impl Clone for CddRational {
906    fn clone(&self) -> Self {
907        <Self as CddNumber>::ensure_initialized();
908        unsafe {
909            let mut inner = MaybeUninit::<sys::gmprational::mytype>::uninit();
910            sys::gmprational::__gmpq_init(inner.as_mut_ptr().cast());
911            sys::gmprational::__gmpq_set(inner.as_mut_ptr().cast(), self.inner.as_ptr());
912            CddRational {
913                inner: inner.assume_init(),
914            }
915        }
916    }
917}
918
919#[cfg(feature = "gmprational")]
920impl Drop for CddRational {
921    fn drop(&mut self) {
922        <Self as CddNumber>::ensure_initialized();
923        unsafe {
924            sys::gmprational::__gmpq_clear(self.inner.as_mut_ptr());
925        }
926    }
927}
928
929#[cfg(feature = "gmprational")]
930impl From<f64> for CddRational {
931    fn from(value: f64) -> Self {
932        <Self as CddNumber>::ensure_initialized();
933        unsafe {
934            let mut inner = MaybeUninit::<sys::gmprational::mytype>::uninit();
935            sys::gmprational::__gmpq_init(inner.as_mut_ptr().cast());
936            sys::gmprational::__gmpq_set_d(inner.as_mut_ptr().cast(), value);
937            CddRational {
938                inner: inner.assume_init(),
939            }
940        }
941    }
942}