use std::collections::HashMap;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;
use crate::symbolic::core::Expr;
use crate::symbolic::optimize::CriticalPoint;
use crate::symbolic::optimize::find_constrained_extrema;
use crate::symbolic::optimize::find_extrema;
use crate::symbolic::optimize::hessian_matrix;
unsafe fn parse_c_str_array(
arr: *const *const c_char,
len: usize,
) -> Option<Vec<String>> {
unsafe {
if arr.is_null() {
return None;
}
let mut vars = Vec::with_capacity(len);
for i in 0..len {
let ptr = *arr.add(i);
if ptr.is_null() {
return None;
}
let c_str = CStr::from_ptr(ptr);
match c_str.to_str() {
| Ok(s) => {
vars.push(s.to_string());
},
| Err(_) => {
return None;
},
}
}
Some(vars)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_find_extrema_handle(
expr_ptr: *const Expr,
vars_ptr: *const *const c_char,
vars_len: c_int,
) -> *mut Vec<CriticalPoint> {
if expr_ptr.is_null() {
return std::ptr::null_mut();
}
unsafe {
let expr = &*expr_ptr;
let vars_strings =
match parse_c_str_array(vars_ptr, i64::from(vars_len).try_into().unwrap_or(0)) {
| Some(v) => v,
| None => return std::ptr::null_mut(),
};
let vars_refs: Vec<&str> = vars_strings
.iter()
.map(std::string::String::as_str)
.collect();
match find_extrema(expr, &vars_refs) {
| Ok(points) => Box::into_raw(Box::new(points)),
| Err(_) => std::ptr::null_mut(),
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_hessian_matrix_handle(
expr_ptr: *const Expr,
vars_ptr: *const *const c_char,
vars_len: c_int,
) -> *mut Expr {
if expr_ptr.is_null() {
return std::ptr::null_mut();
}
unsafe {
let expr = &*expr_ptr;
let vars_strings =
match parse_c_str_array(vars_ptr, i64::from(vars_len).try_into().unwrap_or(0)) {
| Some(v) => v,
| None => return std::ptr::null_mut(),
};
let vars_refs: Vec<&str> = vars_strings
.iter()
.map(std::string::String::as_str)
.collect();
let hessian = hessian_matrix(expr, &vars_refs);
Box::into_raw(Box::new(hessian))
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_find_constrained_extrema_handle(
expr_ptr: *const Expr,
constraints_ptr: *const Vec<Expr>,
vars_ptr: *const *const c_char,
vars_len: c_int,
) -> *mut Vec<HashMap<Expr, Expr>> {
if expr_ptr.is_null() || constraints_ptr.is_null() {
return std::ptr::null_mut();
}
unsafe {
let expr = &*expr_ptr;
let constraints = &*constraints_ptr;
let vars_strings =
match parse_c_str_array(vars_ptr, i64::from(vars_len).try_into().unwrap_or(0)) {
| Some(v) => v,
| None => return std::ptr::null_mut(),
};
let vars_refs: Vec<&str> = vars_strings
.iter()
.map(std::string::String::as_str)
.collect();
match find_constrained_extrema(expr, constraints, &vars_refs) {
| Ok(solutions) => Box::into_raw(Box::new(solutions)),
| Err(_) => std::ptr::null_mut(),
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rssn_free_critical_point_vec_handle(ptr: *mut Vec<CriticalPoint>) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr);
}
}
}
#[unsafe(no_mangle)]
#[allow(clippy::implicit_hasher)]
pub extern "C" fn rssn_free_solution_vec_handle(ptr: *mut Vec<HashMap<Expr, Expr>>) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr);
}
}
}