use crate::copp::copp3::opt3::topp3_lp::{
topp3_lp as rust_topp3_lp, topp3_lp_expert_with_info as rust_topp3_lp_expert,
};
use crate::ffi::c::core::status::panic_to_status;
use crate::ffi::c::solver::copp3::socp::Copp3SocpResult;
use crate::ffi::c::{CoppClarabelOptions, CoppProfile3rd, CoppStatus, Topp3Problem};
use std::panic::{AssertUnwindSafe, catch_unwind};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn topp3_lp(
problem: Topp3Problem,
options: CoppClarabelOptions,
out_profile: *mut CoppProfile3rd,
) -> CoppStatus {
crate::ffi::c::core::status::clear_last_error();
if out_profile.is_null() {
return CoppStatus::NullPointer.into_ffi_status();
}
unsafe {
out_profile.write(CoppProfile3rd::empty());
}
match catch_unwind(AssertUnwindSafe(|| {
let options = options.build();
let problem = unsafe { problem.build_rust()? };
let profile =
rust_topp3_lp(&problem, &options).map_err(|error| CoppStatus::from(&error))?;
unsafe {
out_profile.write(CoppProfile3rd::from_parts(
profile.a,
profile.b,
profile.num_stationary,
));
}
Ok(CoppStatus::Ok)
})) {
Ok(Ok(status)) | Ok(Err(status)) => status.into_ffi_status(),
Err(payload) => panic_to_status(payload).into_ffi_status(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn topp3_lp_expert(
problem: Topp3Problem,
options: CoppClarabelOptions,
out_result: *mut Copp3SocpResult,
) -> CoppStatus {
crate::ffi::c::core::status::clear_last_error();
if out_result.is_null() {
return CoppStatus::NullPointer.into_ffi_status();
}
unsafe {
out_result.write(Copp3SocpResult::empty());
}
match catch_unwind(AssertUnwindSafe(|| {
let options = options.build();
let problem = unsafe { problem.build_rust()? };
let expert =
rust_topp3_lp_expert(&problem, &options).map_err(|error| CoppStatus::from(&error))?;
let result =
Copp3SocpResult::from_solution(expert.result, expert.solution, expert.linsolver, None);
unsafe {
out_result.write(result);
}
Ok(CoppStatus::Ok)
})) {
Ok(Ok(status)) | Ok(Err(status)) => status.into_ffi_status(),
Err(payload) => panic_to_status(payload).into_ffi_status(),
}
}