use std::ptr;
use std::sync::Arc;
use crate::ffi_apis::ffi_api::update_last_error;
use crate::numerical::interpolate;
use crate::numerical::polynomial::Polynomial;
pub type CubicSplineHandle = Arc<dyn Fn(f64) -> f64>;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_lagrange_interpolation(
x_coords: *const f64,
y_coords: *const f64,
len: usize,
) -> *mut Polynomial {
unsafe {
if x_coords.is_null() || y_coords.is_null() {
update_last_error("Null pointer passed to rssn_num_lagrange_interpolation".to_string());
return ptr::null_mut();
}
let x_slice = { std::slice::from_raw_parts(x_coords, len) };
let y_slice = { std::slice::from_raw_parts(y_coords, len) };
let points: Vec<(f64, f64)> = x_slice
.iter()
.zip(y_slice.iter())
.map(|(&x, &y)| (x, y))
.collect();
match interpolate::lagrange_interpolation(&points) {
| Ok(poly) => Box::into_raw(Box::new(poly)),
| Err(e) => {
update_last_error(e);
ptr::null_mut()
},
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_cubic_spline_interpolation(
x_coords: *const f64,
y_coords: *const f64,
len: usize,
) -> *mut CubicSplineHandle {
unsafe {
if x_coords.is_null() || y_coords.is_null() {
update_last_error(
"Null pointer passed to rssn_num_cubic_spline_interpolation".to_string(),
);
return ptr::null_mut();
}
let x_slice = { std::slice::from_raw_parts(x_coords, len) };
let y_slice = { std::slice::from_raw_parts(y_coords, len) };
let points: Vec<(f64, f64)> = x_slice
.iter()
.zip(y_slice.iter())
.map(|(&x, &y)| (x, y))
.collect();
match interpolate::cubic_spline_interpolation(&points) {
| Ok(spline) => Box::into_raw(Box::new(spline)),
| Err(e) => {
update_last_error(e);
ptr::null_mut()
},
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_cubic_spline_evaluate(
handle: *const CubicSplineHandle,
x: f64,
) -> f64 {
unsafe {
if handle.is_null() {
update_last_error("Null pointer passed to rssn_num_cubic_spline_evaluate".to_string());
return f64::NAN;
}
let spline = { &*handle };
spline(x)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_cubic_spline_free(handle: *mut CubicSplineHandle) {
if !handle.is_null() {
unsafe {
let _ = Box::from_raw(handle);
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_bezier_curve(
control_points: *const f64,
n_points: usize,
dim: usize,
t: f64,
out_point: *mut f64,
) -> i32 {
if control_points.is_null() || out_point.is_null() {
return -1;
}
let data = unsafe { std::slice::from_raw_parts(control_points, n_points * dim) };
let mut cp_vecs = Vec::with_capacity(n_points);
for i in 0..n_points {
cp_vecs.push(data[i * dim..(i + 1) * dim].to_vec());
}
let result = interpolate::bezier_curve(&cp_vecs, t);
unsafe {
std::ptr::copy_nonoverlapping(result.as_ptr(), out_point, dim);
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_b_spline(
control_points: *const f64,
n_points: usize,
dim: usize,
degree: usize,
knots: *const f64,
n_knots: usize,
t: f64,
out_point: *mut f64,
) -> i32 {
if control_points.is_null() || knots.is_null() || out_point.is_null() {
return -1;
}
let data = unsafe { std::slice::from_raw_parts(control_points, n_points * dim) };
let mut cp_vecs = Vec::with_capacity(n_points);
for i in 0..n_points {
cp_vecs.push(data[i * dim..(i + 1) * dim].to_vec());
}
let knot_slice = unsafe { std::slice::from_raw_parts(knots, n_knots) };
match interpolate::b_spline(&cp_vecs, degree, knot_slice, t) {
| Some(result) => {
unsafe {
std::ptr::copy_nonoverlapping(result.as_ptr(), out_point, dim);
}
0
},
| None => -1,
}
}