use std::ffi::CStr;
use std::os::raw::c_char;
use crate::symbolic::calculus;
use crate::symbolic::core::Expr;
unsafe fn c_str_to_str<'a>(s: *const c_char) -> Option<&'a str> {
unsafe {
if s.is_null() {
None
} else {
CStr::from_ptr(s).to_str().ok()
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_differentiate(
expr: *const Expr,
var: *const c_char,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::differentiate(expr_ref, var_str)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_integrate(
expr: *const Expr,
var: *const c_char,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::integrate(expr_ref, var_str, None, None)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_check_analytic(
expr: *const Expr,
var: *const c_char,
) -> bool {
unsafe {
if expr.is_null() || var.is_null() {
return false;
}
let expr_ref = &*expr;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return false,
};
calculus::check_analytic(expr_ref, var_str)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_limit(
expr: *const Expr,
var: *const c_char,
point: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || point.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let point_ref = &*point;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::limit(expr_ref, var_str, point_ref)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_definite_integrate(
expr: *const Expr,
var: *const c_char,
lower: *const Expr,
upper: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || lower.is_null() || upper.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let lower_ref = &*lower;
let upper_ref = &*upper;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::definite_integrate(
expr_ref, var_str, lower_ref, upper_ref,
)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_evaluate_at_point(
expr: *const Expr,
var: *const c_char,
value: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || value.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let value_ref = &*value;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::evaluate_at_point(
expr_ref, var_str, value_ref,
)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_find_poles(
expr: *const Expr,
var: *const c_char,
) -> *mut Vec<Expr> {
unsafe {
if expr.is_null() || var.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::find_poles(expr_ref, var_str)))
}
}
#[unsafe(no_mangle)]
pub const unsafe extern "C" fn rssn_poles_len(poles: *const Vec<Expr>) -> usize {
unsafe {
if poles.is_null() {
0
} else {
(*poles).len()
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_poles_get(
poles: *const Vec<Expr>,
index: usize,
) -> *mut Expr {
unsafe {
if poles.is_null() {
return std::ptr::null_mut();
}
let poles_ref = &*poles;
if index >= poles_ref.len() {
return std::ptr::null_mut();
}
Box::into_raw(Box::new(poles_ref[index].clone()))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_free_poles(poles: *mut Vec<Expr>) {
unsafe {
if !poles.is_null() {
let _ = Box::from_raw(poles);
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_calculate_residue(
expr: *const Expr,
var: *const c_char,
pole: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || pole.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let pole_ref = &*pole;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::calculate_residue(
expr_ref, var_str, pole_ref,
)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_find_pole_order(
expr: *const Expr,
var: *const c_char,
pole: *const Expr,
) -> usize {
unsafe {
if expr.is_null() || var.is_null() || pole.is_null() {
return 0;
}
let expr_ref = &*expr;
let pole_ref = &*pole;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return 0,
};
calculus::find_pole_order(expr_ref, var_str, pole_ref)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_substitute(
expr: *const Expr,
var: *const c_char,
replacement: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || replacement.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let replacement_ref = &*replacement;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::substitute(
expr_ref,
var_str,
replacement_ref,
)))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_get_real_imag_parts(expr: *const Expr) -> *mut Vec<Expr> {
unsafe {
if expr.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let (re, im) = calculus::get_real_imag_parts(expr_ref);
Box::into_raw(Box::new(vec![re, im]))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_path_integrate(
expr: *const Expr,
var: *const c_char,
contour: *const Expr,
) -> *mut Expr {
unsafe {
if expr.is_null() || var.is_null() || contour.is_null() {
return std::ptr::null_mut();
}
let expr_ref = &*expr;
let contour_ref = &*contour;
let var_str = match c_str_to_str(var) {
| Some(s) => s,
| None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(calculus::path_integrate(
expr_ref,
var_str,
contour_ref,
)))
}
}