#![allow(non_snake_case)]
use super::types::*;
use crate::solver::{
core::{
cones::{SupportedConeT, SupportedConeT::*},
IPSolver,
},
implementations::default::*,
SolverJSONReadWrite,
};
use num_traits::FromPrimitive;
use serde_json::*;
use std::fs::File;
use std::{
ffi::CStr,
os::raw::{c_char, c_int, c_void},
};
fn to_ptr(solver: Box<DefaultSolver<f64>>) -> *mut c_void {
Box::into_raw(solver) as *mut c_void
}
fn from_ptr(ptr: *mut c_void) -> Box<DefaultSolver<f64>> {
unsafe { Box::from_raw(ptr as *mut DefaultSolver<f64>) }
}
fn ccall_arrays_to_cones(jlcones: &VectorJLRS<ConeDataJLRS>) -> Vec<SupportedConeT<f64>> {
let mut cones: Vec<SupportedConeT<f64>> = Vec::new();
for jlcone in jlcones.to_slice() {
let cone = match FromPrimitive::from_u8(jlcone.tag) {
Some(ConeEnumJLRS::ZeroConeT) => ZeroConeT(jlcone.int),
Some(ConeEnumJLRS::NonnegativeConeT) => NonnegativeConeT(jlcone.int),
Some(ConeEnumJLRS::SecondOrderConeT) => SecondOrderConeT(jlcone.int),
Some(ConeEnumJLRS::ExponentialConeT) => ExponentialConeT(),
Some(ConeEnumJLRS::PowerConeT) => PowerConeT(jlcone.float),
Some(ConeEnumJLRS::GenPowerConeT) => {
let alpha = Vec::<f64>::from(&jlcone.vec);
GenPowerConeT(alpha, jlcone.int)
}
Some(ConeEnumJLRS::PSDTriangleConeT) => PSDTriangleConeT(jlcone.int),
None => panic!("Received unrecognized cone type"),
};
cones.push(cone)
}
cones
}
#[no_mangle]
pub(crate) extern "C" fn solver_new_jlrs(
P: &CscMatrixJLRS,
q: &VectorJLRS<f64>,
A: &CscMatrixJLRS,
b: &VectorJLRS<f64>,
jlcones: &VectorJLRS<ConeDataJLRS>,
json_settings: *const c_char,
) -> *mut c_void {
let P = P.to_CscMatrix();
let A = A.to_CscMatrix();
let q = Vec::from(q);
let b = Vec::from(b);
let cones = ccall_arrays_to_cones(jlcones);
let settings = settings_from_json(json_settings);
let solver = DefaultSolver::new(&P, &q, &A, &b, &cones, settings);
match solver {
Ok(solver) => to_ptr(Box::new(solver)),
Err(e) => {
println!("Error creating solver: {}", e);
return std::ptr::null_mut();
}
}
}
#[no_mangle]
pub(crate) extern "C" fn solver_solve_jlrs(ptr: *mut c_void) -> SolutionJLRS {
let mut solver = from_ptr(ptr);
solver.solve();
let out = SolutionJLRS::from(&solver.solution);
std::mem::forget(solver);
out
}
#[no_mangle]
pub(crate) extern "C" fn solver_get_info_jlrs(ptr: *mut c_void) -> InfoJLRS {
let solver = from_ptr(ptr);
let out = InfoJLRS::from(&solver.info);
std::mem::forget(solver);
out
}
#[no_mangle]
pub(crate) extern "C" fn solver_print_timers_jlrs(ptr: *mut c_void) {
let solver = from_ptr(ptr);
match solver.timers {
Some(ref timers) => timers.print(),
None => println!("No timer info available"),
}
std::mem::forget(solver);
}
#[no_mangle]
pub(crate) extern "C" fn solver_save_to_file_jlrs(
ptr: *mut c_void,
filename: *const std::os::raw::c_char,
) -> c_int {
let slice = unsafe { CStr::from_ptr(filename) };
let filename = match slice.to_str() {
Ok(s) => s,
Err(_) => {
return -1;
}
};
let mut file = match File::create(filename) {
Ok(f) => f,
Err(_) => {
return -1;
}
};
let solver = from_ptr(ptr);
let status = solver.save_to_file(&mut file).is_ok();
let status = if status { 0 } else { -1 } as c_int;
std::mem::forget(solver);
status
}
#[no_mangle]
pub(crate) extern "C" fn solver_load_from_file_jlrs(
filename: *const std::os::raw::c_char,
json_settings: *const std::os::raw::c_char,
) -> *const c_void {
let slice = unsafe { CStr::from_ptr(filename) };
let filename = match slice.to_str() {
Ok(s) => s,
Err(_) => {
return std::ptr::null();
}
};
let mut file = match File::open(filename) {
Ok(f) => f,
Err(_) => {
return std::ptr::null();
}
};
let settings = unsafe {
if json_settings.is_null() || CStr::from_ptr(json_settings).to_bytes().is_empty() {
None
} else {
Some(settings_from_json(json_settings))
}
};
let solver = DefaultSolver::load_from_file(&mut file, settings);
match solver {
Ok(solver) => to_ptr(Box::new(solver)),
Err(_) => std::ptr::null(),
}
}
#[no_mangle]
pub(crate) extern "C" fn solver_drop_jlrs(ptr: *mut c_void) {
drop(from_ptr(ptr));
}
pub(crate) fn settings_from_json(json: *const std::os::raw::c_char) -> DefaultSettings<f64> {
let json = unsafe {
let slice = CStr::from_ptr(json);
slice.to_str().unwrap()
};
let mut settings: DefaultSettings<f64> = from_str(json).unwrap();
if settings.time_limit > f64::MAX * 0.9999 {
settings.time_limit = f64::INFINITY;
}
settings
}
#[no_mangle]
pub(crate) extern "C" fn buildinfo_jlrs() {
crate::buildinfo();
}