diff --git a/src/ffi.rs b/src/ffi.rs deleted file mode 100644 index 050e0498..00000000 --- a/src/ffi.rs +++ /dev/null @@ -1,307 +0,0 @@ -use std::os::raw::c_char; -use std::{collections::HashMap, ffi::CStr}; - -use crate::repr::DDNNFPtr; -use crate::util::semirings::{RealSemiring, Semiring}; -use crate::{ - builder::{bdd::RobddBuilder, cache::AllIteTable, BottomUpBuilder}, - constants::primes, - repr::{BddPtr, Cnf, VarLabel, VarOrder, WmcParams}, - util::semirings::FiniteField, -}; - -#[no_mangle] -pub extern "C" fn var_order_linear(num_vars: usize) -> *const VarOrder { - Box::into_raw(Box::new(VarOrder::linear_order(num_vars))) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn cnf_from_dimacs(dimacs_str: *const c_char) -> *const Cnf { - let cstr = CStr::from_ptr(dimacs_str); - - Box::into_raw(Box::new(Cnf::from_dimacs(&String::from_utf8_lossy( - cstr.to_bytes(), - )))) -} - -// directly inspired by https://users.rust-lang.org/t/how-to-deal-with-lifetime-when-need-to-expose-through-ffi/39583 -// and the follow-up at https://users.rust-lang.org/t/can-someone-explain-why-this-is-working/82324/6 -#[repr(C)] -pub struct RsddBddBuilder { - _priv: [u8; 0], -} - -unsafe fn robdd_builder_from_ptr<'_0>( - ptr: *mut RsddBddBuilder, -) -> &'_0 mut RobddBuilder<'static, AllIteTable>> { - if ptr.is_null() { - eprintln!("Fatal error, got NULL `Context` pointer"); - ::std::process::abort(); - } - &mut *(ptr.cast()) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn robdd_builder_all_table(order: *mut VarOrder) -> *mut RsddBddBuilder { - if order.is_null() { - eprintln!("Fatal error, got NULL `order` pointer"); - std::process::abort(); - } - - let order = *Box::from_raw(order); - Box::into_raw(Box::new(RobddBuilder::>::new(order))).cast() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn robdd_builder_compile_cnf( - builder: *mut RsddBddBuilder, - cnf: *mut Cnf, -) -> *mut BddPtr<'static> { - if cnf.is_null() { - eprintln!("Fatal error, got NULL `cnf` pointer"); - std::process::abort(); - } - - let builder = robdd_builder_from_ptr(builder); - let cnf = *Box::from_raw(cnf); - let ptr = builder.compile_cnf(&cnf); - Box::into_raw(Box::new(ptr)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn robdd_model_count( - builder: *mut RsddBddBuilder, - bdd: *mut BddPtr<'static>, -) -> u64 { - let builder = robdd_builder_from_ptr(builder); - let num_vars = builder.num_vars(); - let smoothed = builder.smooth(*bdd, num_vars); - let unweighted_params: WmcParams> = - WmcParams::new(HashMap::from_iter( - (0..num_vars as u64) - .map(|v| (VarLabel::new(v), (FiniteField::one(), FiniteField::one()))), - )); - - let mc = smoothed.unsmoothed_wmc(&unweighted_params).value(); - mc as u64 -} - -// implementing the disc interface - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn mk_bdd_manager_default_order(num_vars: u64) -> *mut RsddBddBuilder { - Box::into_raw(Box::new(RobddBuilder::>::new( - VarOrder::linear_order(num_vars as usize), - ))) - .cast() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_new_label(builder: *mut RsddBddBuilder) -> u64 { - let builder = robdd_builder_from_ptr(builder); - builder.new_label().value() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_var( - builder: *mut RsddBddBuilder, - label: u64, - polarity: bool, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let ptr = builder.var(VarLabel::new(label), polarity); - Box::into_raw(Box::new(ptr)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_new_var( - builder: *mut RsddBddBuilder, - polarity: bool, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let (_, ptr) = builder.new_var(polarity); - Box::into_raw(Box::new(ptr)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_ite( - builder: *mut RsddBddBuilder, - f: *mut BddPtr<'static>, - g: *mut BddPtr<'static>, - h: *mut BddPtr<'static>, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let and = builder.ite(*f, *g, *h); - Box::into_raw(Box::new(and)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_and( - builder: *mut RsddBddBuilder, - left: *mut BddPtr<'static>, - right: *mut BddPtr<'static>, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let and = builder.and(*left, *right); - Box::into_raw(Box::new(and)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_or( - builder: *mut RsddBddBuilder, - left: *mut BddPtr<'static>, - right: *mut BddPtr<'static>, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let or = builder.or(*left, *right); - Box::into_raw(Box::new(or)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_negate( - builder: *mut RsddBddBuilder, - bdd: *mut BddPtr<'static>, -) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let negate = builder.negate(*bdd); - Box::into_raw(Box::new(negate)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_is_true(bdd: *mut BddPtr<'static>) -> bool { - (*bdd).is_true() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_is_false(bdd: *mut BddPtr<'static>) -> bool { - (*bdd).is_false() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_is_const(bdd: *mut BddPtr<'static>) -> bool { - (*bdd).is_const() -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_true(builder: *mut RsddBddBuilder) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let bdd = builder.true_ptr(); - Box::into_raw(Box::new(bdd)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_false(builder: *mut RsddBddBuilder) -> *mut BddPtr<'static> { - let builder = robdd_builder_from_ptr(builder); - let bdd = builder.false_ptr(); - Box::into_raw(Box::new(bdd)) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_eq( - builder: *mut RsddBddBuilder, - left: *mut BddPtr<'static>, - right: *mut BddPtr<'static>, -) -> bool { - let builder = robdd_builder_from_ptr(builder); - builder.eq(*left, *right) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_topvar(bdd: *mut BddPtr<'static>) -> u64 { - match (*bdd).var_safe() { - Some(x) => x.value(), - None => 0, // TODO: fix this - } -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_low(bdd: *mut BddPtr<'static>) -> *mut BddPtr<'static> { - Box::into_raw(Box::new((*bdd).low())) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_high(bdd: *mut BddPtr<'static>) -> *mut BddPtr<'static> { - Box::into_raw(Box::new((*bdd).high())) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn print_bdd(bdd: *mut BddPtr<'static>) -> *const c_char { - let s = std::ffi::CString::new((*bdd).print_bdd()).unwrap(); - let p = s.as_ptr(); - std::mem::forget(s); - p -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn bdd_wmc( - bdd: *mut BddPtr<'static>, - wmc: *mut WmcParams, -) -> f64 { - DDNNFPtr::unsmoothed_wmc(&(*bdd), &(*wmc)).0 -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn new_wmc_params_f64() -> *mut WmcParams { - Box::into_raw(Box::new(WmcParams::new(HashMap::from([])))) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn wmc_param_f64_set_weight( - weights: *mut WmcParams, - var: u64, - low: f64, - high: f64, -) { - (*weights).set_weight(VarLabel::new(var), RealSemiring(low), RealSemiring(high)) -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct WeightF64(pub f64, pub f64); - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn wmc_param_f64_var_weight( - weights: *mut WmcParams, - var: u64, -) -> WeightF64 { - let (l, h) = (*weights).var_weight(VarLabel::new(var)); - WeightF64(l.0, h.0) -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn weight_f64_lo(w: WeightF64) -> f64 { - w.0 -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn weight_f64_hi(w: WeightF64) -> f64 { - w.1 -} diff --git a/src/ffi/bdd.rs b/src/ffi/bdd.rs new file mode 100644 index 00000000..44fc2f43 --- /dev/null +++ b/src/ffi/bdd.rs @@ -0,0 +1,227 @@ +use crate::{ + builder::{bdd::RobddBuilder, cache::AllIteTable, BottomUpBuilder}, + constants::primes, + repr::{self, Cnf, DDNNFPtr, VarLabel, VarOrder, WmcParams}, + util::semirings::{FiniteField, RealSemiring, Semiring}, +}; +use std::{collections::HashMap, ffi::CStr, os::raw::c_char}; + +pub(super) type BddPtr = repr::BddPtr<'static>; + +#[no_mangle] +extern "C" fn var_order_linear(num_vars: usize) -> *const VarOrder { + Box::into_raw(Box::new(VarOrder::linear_order(num_vars))) +} + +#[no_mangle] +unsafe extern "C" fn cnf_from_dimacs(dimacs_str: *const c_char) -> *const Cnf { + let cstr = CStr::from_ptr(dimacs_str); + + Box::into_raw(Box::new(Cnf::from_dimacs(&String::from_utf8_lossy( + cstr.to_bytes(), + )))) +} + +// directly inspired by https://users.rust-lang.org/t/how-to-deal-with-lifetime-when-need-to-expose-through-ffi/39583 +// and the follow-up at https://users.rust-lang.org/t/can-someone-explain-why-this-is-working/82324/6 +#[repr(C)] +struct RsddBddBuilder { + _priv: [u8; 0], +} + +unsafe fn robdd_builder_from_ptr<'_0>( + ptr: *mut RsddBddBuilder, +) -> &'_0 mut RobddBuilder<'static, AllIteTable> { + if ptr.is_null() { + eprintln!("Fatal error, got NULL `Context` pointer"); + ::std::process::abort(); + } + &mut *(ptr.cast()) +} + +#[no_mangle] +unsafe extern "C" fn robdd_builder_all_table(order: *mut VarOrder) -> *mut RsddBddBuilder { + if order.is_null() { + eprintln!("Fatal error, got NULL `order` pointer"); + std::process::abort(); + } + + let order = *Box::from_raw(order); + Box::into_raw(Box::new(RobddBuilder::>::new(order))).cast() +} + +#[no_mangle] +unsafe extern "C" fn robdd_builder_compile_cnf( + builder: *mut RsddBddBuilder, + cnf: *mut Cnf, +) -> *mut BddPtr { + if cnf.is_null() { + eprintln!("Fatal error, got NULL `cnf` pointer"); + std::process::abort(); + } + + let builder = robdd_builder_from_ptr(builder); + let cnf = *Box::from_raw(cnf); + let ptr = builder.compile_cnf(&cnf); + Box::into_raw(Box::new(ptr)) +} + +#[no_mangle] +unsafe extern "C" fn robdd_model_count(builder: *mut RsddBddBuilder, bdd: *mut BddPtr) -> u64 { + let builder = robdd_builder_from_ptr(builder); + let num_vars = builder.num_vars(); + let smoothed = builder.smooth(*bdd, num_vars); + let unweighted_params: WmcParams> = + WmcParams::new(HashMap::from_iter( + (0..num_vars as u64) + .map(|v| (VarLabel::new(v), (FiniteField::one(), FiniteField::one()))), + )); + + let mc = smoothed.unsmoothed_wmc(&unweighted_params).value(); + mc as u64 +} + +// implementing the disc interface + +#[no_mangle] +unsafe extern "C" fn mk_bdd_manager_default_order(num_vars: u64) -> *mut RsddBddBuilder { + Box::into_raw(Box::new(RobddBuilder::>::new( + VarOrder::linear_order(num_vars as usize), + ))) + .cast() +} + +#[no_mangle] +unsafe extern "C" fn bdd_new_label(builder: *mut RsddBddBuilder) -> u64 { + let builder = robdd_builder_from_ptr(builder); + builder.new_label().value() +} + +#[no_mangle] +unsafe extern "C" fn bdd_var( + builder: *mut RsddBddBuilder, + label: u64, + polarity: bool, +) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let ptr = builder.var(VarLabel::new(label), polarity); + Box::into_raw(Box::new(ptr)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_new_var(builder: *mut RsddBddBuilder, polarity: bool) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let (_, ptr) = builder.new_var(polarity); + Box::into_raw(Box::new(ptr)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_ite( + builder: *mut RsddBddBuilder, + f: *mut BddPtr, + g: *mut BddPtr, + h: *mut BddPtr, +) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let and = builder.ite(*f, *g, *h); + Box::into_raw(Box::new(and)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_and( + builder: *mut RsddBddBuilder, + left: *mut BddPtr, + right: *mut BddPtr, +) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let and = builder.and(*left, *right); + Box::into_raw(Box::new(and)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_or( + builder: *mut RsddBddBuilder, + left: *mut BddPtr, + right: *mut BddPtr, +) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let or = builder.or(*left, *right); + Box::into_raw(Box::new(or)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_negate(builder: *mut RsddBddBuilder, bdd: *mut BddPtr) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let negate = builder.negate(*bdd); + Box::into_raw(Box::new(negate)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_is_true(bdd: *mut BddPtr) -> bool { + (*bdd).is_true() +} + +#[no_mangle] +unsafe extern "C" fn bdd_is_false(bdd: *mut BddPtr) -> bool { + (*bdd).is_false() +} + +#[no_mangle] +unsafe extern "C" fn bdd_is_const(bdd: *mut BddPtr) -> bool { + (*bdd).is_const() +} + +#[no_mangle] +unsafe extern "C" fn bdd_true(builder: *mut RsddBddBuilder) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let bdd = builder.true_ptr(); + Box::into_raw(Box::new(bdd)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_false(builder: *mut RsddBddBuilder) -> *mut BddPtr { + let builder = robdd_builder_from_ptr(builder); + let bdd = builder.false_ptr(); + Box::into_raw(Box::new(bdd)) +} + +#[no_mangle] +unsafe extern "C" fn bdd_eq( + builder: *mut RsddBddBuilder, + left: *mut BddPtr, + right: *mut BddPtr, +) -> bool { + let builder = robdd_builder_from_ptr(builder); + builder.eq(*left, *right) +} + +#[no_mangle] +unsafe extern "C" fn bdd_topvar(bdd: *mut BddPtr) -> u64 { + match (*bdd).var_safe() { + Some(x) => x.value(), + None => 0, // TODO: fix this + } +} + +#[no_mangle] +unsafe extern "C" fn bdd_low(bdd: *mut BddPtr) -> *mut BddPtr { + Box::into_raw(Box::new((*bdd).low())) +} + +#[no_mangle] +unsafe extern "C" fn bdd_high(bdd: *mut BddPtr) -> *mut BddPtr { + Box::into_raw(Box::new((*bdd).high())) +} + +#[no_mangle] +unsafe extern "C" fn print_bdd(bdd: *mut BddPtr) -> *const c_char { + let s = std::ffi::CString::new((*bdd).print_bdd()).unwrap(); + let p = s.as_ptr(); + std::mem::forget(s); + p +} + +#[no_mangle] +unsafe extern "C" fn bdd_wmc(bdd: *mut BddPtr, wmc: *mut WmcParams) -> f64 { + DDNNFPtr::unsmoothed_wmc(&(*bdd), &(*wmc)).0 +} diff --git a/src/ffi/cnf.rs b/src/ffi/cnf.rs new file mode 100644 index 00000000..269dbd01 --- /dev/null +++ b/src/ffi/cnf.rs @@ -0,0 +1,22 @@ +use crate::repr::{Cnf, Literal, VarOrder}; +use core::slice; + +#[repr(C)] +struct Clause { + pub vars: *mut Literal, + pub len: usize, +} + +#[no_mangle] +unsafe extern "C" fn cnf_new(clauses: *const Clause, len: usize) -> *mut Cnf { + let clauses = slice::from_raw_parts(clauses, len) + .iter() + .map(|c| slice::from_raw_parts(c.vars, c.len).to_vec()) + .collect::>(); + Box::into_raw(Box::new(Cnf::new(&clauses))) +} + +#[no_mangle] +unsafe extern "C" fn cnf_min_fill_order(cnf: *mut Cnf) -> *mut VarOrder { + Box::into_raw(Box::new((*cnf).min_fill_order())) +} diff --git a/src/ffi/ddnnf.rs b/src/ffi/ddnnf.rs new file mode 100644 index 00000000..140bff87 --- /dev/null +++ b/src/ffi/ddnnf.rs @@ -0,0 +1,20 @@ +use crate::{ + builder::decision_nnf::{DecisionNNFBuilder, StandardDecisionNNFBuilder}, + ffi::bdd::BddPtr, + repr::{Cnf, VarOrder}, +}; + +type DDNNFBuilder = StandardDecisionNNFBuilder<'static>; + +#[no_mangle] +unsafe extern "C" fn ddnnf_builder_new(order: *mut VarOrder) -> *mut DDNNFBuilder { + Box::into_raw(Box::new(DDNNFBuilder::new(*Box::from_raw(order)))) +} + +#[no_mangle] +unsafe extern "C" fn ddnnf_builder_compile_cnf_topdown( + builder: *const DDNNFBuilder, + cnf: *const Cnf, +) -> *mut BddPtr { + Box::into_raw(Box::new((*builder).compile_cnf_topdown(&*cnf))) +} diff --git a/src/ffi/dtree.rs b/src/ffi/dtree.rs new file mode 100644 index 00000000..8d9497d8 --- /dev/null +++ b/src/ffi/dtree.rs @@ -0,0 +1,6 @@ +use crate::repr::{Cnf, DTree, VarOrder}; + +#[no_mangle] +unsafe extern "C" fn dtree_from_cnf(cnf: *const Cnf, elim_order: *const VarOrder) -> *mut DTree { + Box::into_raw(Box::new(DTree::from_cnf(&*cnf, &*elim_order))) +} diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs new file mode 100644 index 00000000..fd56f00c --- /dev/null +++ b/src/ffi/mod.rs @@ -0,0 +1,8 @@ +mod bdd; +mod cnf; +mod ddnnf; +mod dtree; +mod sdd; +mod var; +mod vtree; +mod wmc; diff --git a/src/ffi/sdd.rs b/src/ffi/sdd.rs new file mode 100644 index 00000000..caa172ec --- /dev/null +++ b/src/ffi/sdd.rs @@ -0,0 +1,27 @@ +use crate::{ + builder::{sdd::CompressionSddBuilder, BottomUpBuilder}, + repr::{self, Cnf, DDNNFPtr, VTree, WmcParams}, + util::semirings::RealSemiring, +}; + +type SddBuilder = CompressionSddBuilder<'static>; +type SddPtr = repr::SddPtr<'static>; + +#[no_mangle] +unsafe extern "C" fn sdd_builder_new(vtree: *mut VTree) -> *mut SddBuilder { + let vtree = Box::from_raw(vtree); + Box::into_raw(Box::new(CompressionSddBuilder::new(*vtree))) +} + +#[no_mangle] +unsafe extern "C" fn sdd_builder_compile_cnf( + builder: *const SddBuilder, + cnf: *const Cnf, +) -> *mut SddPtr { + Box::into_raw(Box::new((*builder).compile_cnf(&*cnf))) +} + +#[no_mangle] +unsafe extern "C" fn sdd_wmc(sdd: *const SddPtr, wmc: *const WmcParams) -> f64 { + DDNNFPtr::unsmoothed_wmc(&*sdd, &*wmc).0 +} diff --git a/src/ffi/var.rs b/src/ffi/var.rs new file mode 100644 index 00000000..e937b661 --- /dev/null +++ b/src/ffi/var.rs @@ -0,0 +1,13 @@ +use crate::repr::{Literal, VarLabel, VarOrder}; +use core::slice; + +#[no_mangle] +extern "C" fn literal_new(label: VarLabel, polarity: bool) -> Literal { + Literal::new(label, polarity) +} + +#[no_mangle] +unsafe extern "C" fn var_order_new(order: *const VarLabel, len: usize) -> *mut VarOrder { + let order = slice::from_raw_parts(order, len); + Box::into_raw(Box::new(VarOrder::new(order))) +} diff --git a/src/ffi/vtree.rs b/src/ffi/vtree.rs new file mode 100644 index 00000000..50830989 --- /dev/null +++ b/src/ffi/vtree.rs @@ -0,0 +1,7 @@ +use crate::repr::{DTree, VTree}; +use std::ptr; + +#[no_mangle] +unsafe extern "C" fn vtree_from_dtree(dtree: *const DTree) -> *mut VTree { + VTree::from_dtree(&*dtree).map_or(ptr::null_mut(), |v| Box::into_raw(Box::new(v))) +} diff --git a/src/ffi/wmc.rs b/src/ffi/wmc.rs new file mode 100644 index 00000000..97c2c287 --- /dev/null +++ b/src/ffi/wmc.rs @@ -0,0 +1,43 @@ +use crate::{ + repr::{VarLabel, WmcParams}, + util::semirings::RealSemiring, +}; +use std::collections::HashMap; + +#[no_mangle] +unsafe extern "C" fn new_wmc_params_f64() -> *mut WmcParams { + Box::into_raw(Box::new(WmcParams::new(HashMap::from([])))) +} + +#[no_mangle] +unsafe extern "C" fn wmc_param_f64_set_weight( + weights: *mut WmcParams, + var: u64, + low: f64, + high: f64, +) { + (*weights).set_weight(VarLabel::new(var), RealSemiring(low), RealSemiring(high)) +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct WeightF64(pub f64, pub f64); + +#[no_mangle] +unsafe extern "C" fn wmc_param_f64_var_weight( + weights: *mut WmcParams, + var: u64, +) -> WeightF64 { + let (l, h) = (*weights).var_weight(VarLabel::new(var)); + WeightF64(l.0, h.0) +} + +#[no_mangle] +unsafe extern "C" fn weight_f64_lo(w: WeightF64) -> f64 { + w.0 +} + +#[no_mangle] +unsafe extern "C" fn weight_f64_hi(w: WeightF64) -> f64 { + w.1 +} diff --git a/src/lib.rs b/src/lib.rs index 54fc8e71..b8fab4de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,5 +29,3 @@ pub mod wasm; // when using rsdd-ocaml #[cfg(feature = "ffi")] mod ffi; -#[cfg(feature = "ffi")] -pub use self::ffi::*; diff --git a/src/repr/var_label.rs b/src/repr/var_label.rs index 6e637558..4d814352 100644 --- a/src/repr/var_label.rs +++ b/src/repr/var_label.rs @@ -6,6 +6,7 @@ use std::fmt::{self, Display}; /// a label for each distinct variable in the BDD #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)] +#[repr(transparent)] pub struct VarLabel(u64); impl VarLabel { @@ -31,6 +32,7 @@ impl VarLabel { /// Literal, a variable label and its corresponding truth assignment #[derive(Clone, PartialEq, Eq, Hash, Copy, Serialize, Deserialize, PartialOrd, Ord)] +#[repr(transparent)] pub struct Literal { data: u64, }