#[cfg(any(
feature = "diffsl-external-dynamic",
feature = "diffsl-cranelift",
feature = "diffsl-llvm",
))]
use std::ffi::CStr;
#[cfg(any(
feature = "diffsl-external-dynamic",
feature = "diffsl-cranelift",
feature = "diffsl-llvm",
))]
use std::os::raw::c_char;
#[cfg(feature = "diffsl-external-dynamic")]
use std::path::PathBuf;
use std::ptr;
use crate::c_error;
#[cfg(any(
feature = "diffsl-external-dynamic",
feature = "diffsl-cranelift",
feature = "diffsl-llvm",
))]
use crate::c_invalid_arg;
#[cfg(any(feature = "diffsl-cranelift", feature = "diffsl-llvm"))]
use crate::jit_c::jit_backend_from_i32;
use crate::ode::OdeWrapper;
use crate::ode_c::parse_ode_new_common_args;
use crate::scalar_type::ScalarType;
#[cfg(any(feature = "external", feature = "diffsl-external-dynamic"))]
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DiffsolDepPair {
pub row: usize,
pub col: usize,
}
#[cfg(any(feature = "external", feature = "diffsl-external-dynamic"))]
unsafe fn dependency_pairs_from_raw_parts(
deps_ptr: *const DiffsolDepPair,
deps_len: usize,
) -> Vec<(usize, usize)> {
if deps_ptr.is_null() || deps_len == 0 {
Vec::new()
} else {
unsafe { std::slice::from_raw_parts(deps_ptr, deps_len) }
.iter()
.map(|pair| (pair.row, pair.col))
.collect()
}
}
#[cfg(any(feature = "diffsl-cranelift", feature = "diffsl-llvm"))]
fn parse_ode_new_jit_args(
code: *const c_char,
matrix_type: i32,
linear_solver: i32,
ode_solver: i32,
) -> Option<(
String,
crate::matrix_type::MatrixType,
crate::linear_solver_type::LinearSolverType,
crate::ode_solver_type::OdeSolverType,
)> {
if code.is_null() {
c_invalid_arg!("code is null");
return None;
}
let code = unsafe { CStr::from_ptr(code) };
let code = match code.to_str() {
Ok(value) => value.to_owned(),
Err(_) => {
c_error!("code is not valid UTF-8");
return None;
}
};
let (matrix_type, linear_solver, ode_solver) =
parse_ode_new_common_args(matrix_type, linear_solver, ode_solver)?;
Some((code, matrix_type, linear_solver, ode_solver))
}
#[cfg(feature = "diffsl-external-dynamic")]
fn parse_ode_new_external_dynamic_args(
path: *const c_char,
matrix_type: i32,
linear_solver: i32,
ode_solver: i32,
) -> Option<(
PathBuf,
crate::matrix_type::MatrixType,
crate::linear_solver_type::LinearSolverType,
crate::ode_solver_type::OdeSolverType,
)> {
if path.is_null() {
c_invalid_arg!("path is null");
return None;
}
let path = unsafe { CStr::from_ptr(path) };
let path = match path.to_str() {
Ok(value) => PathBuf::from(value),
Err(_) => {
c_error!("path is not valid UTF-8");
return None;
}
};
let (matrix_type, linear_solver, ode_solver) =
parse_ode_new_common_args(matrix_type, linear_solver, ode_solver)?;
Some((path, matrix_type, linear_solver, ode_solver))
}
#[cfg(feature = "external")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn diffsol_ode_new_external(
matrix_type: i32,
linear_solver: i32,
ode_solver: i32,
rhs_state_deps_ptr: *const DiffsolDepPair,
rhs_state_deps_len: usize,
rhs_input_deps_ptr: *const DiffsolDepPair,
rhs_input_deps_len: usize,
mass_state_deps_ptr: *const DiffsolDepPair,
mass_state_deps_len: usize,
) -> *mut OdeWrapper {
let Some((matrix_type, linear_solver, ode_solver)) =
parse_ode_new_common_args(matrix_type, linear_solver, ode_solver)
else {
return ptr::null_mut();
};
let rhs_state_deps =
unsafe { dependency_pairs_from_raw_parts(rhs_state_deps_ptr, rhs_state_deps_len) };
let rhs_input_deps =
unsafe { dependency_pairs_from_raw_parts(rhs_input_deps_ptr, rhs_input_deps_len) };
let mass_state_deps =
unsafe { dependency_pairs_from_raw_parts(mass_state_deps_ptr, mass_state_deps_len) };
let scalar_type = ScalarType::F64;
match OdeWrapper::new_external(
rhs_state_deps,
rhs_input_deps,
mass_state_deps,
scalar_type,
matrix_type,
linear_solver,
ode_solver,
) {
Ok(ode) => Box::into_raw(Box::new(ode)),
Err(err) => {
c_error!(&format!("{}", err));
ptr::null_mut()
}
}
}
#[cfg(feature = "diffsl-external-dynamic")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn diffsol_ode_new_external_dynamic(
path: *const c_char,
matrix_type: i32,
linear_solver: i32,
ode_solver: i32,
rhs_state_deps_ptr: *const DiffsolDepPair,
rhs_state_deps_len: usize,
rhs_input_deps_ptr: *const DiffsolDepPair,
rhs_input_deps_len: usize,
mass_state_deps_ptr: *const DiffsolDepPair,
mass_state_deps_len: usize,
) -> *mut OdeWrapper {
let Some((path, matrix_type, linear_solver, ode_solver)) =
parse_ode_new_external_dynamic_args(path, matrix_type, linear_solver, ode_solver)
else {
return ptr::null_mut();
};
let rhs_state_deps =
unsafe { dependency_pairs_from_raw_parts(rhs_state_deps_ptr, rhs_state_deps_len) };
let rhs_input_deps =
unsafe { dependency_pairs_from_raw_parts(rhs_input_deps_ptr, rhs_input_deps_len) };
let mass_state_deps =
unsafe { dependency_pairs_from_raw_parts(mass_state_deps_ptr, mass_state_deps_len) };
let scalar_type = ScalarType::F64;
match OdeWrapper::new_external_dynamic(
path,
rhs_state_deps,
rhs_input_deps,
mass_state_deps,
scalar_type,
matrix_type,
linear_solver,
ode_solver,
) {
Ok(ode) => Box::into_raw(Box::new(ode)),
Err(err) => {
c_error!(&format!("{}", err));
ptr::null_mut()
}
}
}
#[cfg(any(feature = "diffsl-cranelift", feature = "diffsl-llvm"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn diffsol_ode_new_jit(
code: *const c_char,
jit_backend: i32,
matrix_type: i32,
linear_solver: i32,
ode_solver: i32,
) -> *mut OdeWrapper {
let Some((code, matrix_type, linear_solver, ode_solver)) =
parse_ode_new_jit_args(code, matrix_type, linear_solver, ode_solver)
else {
return ptr::null_mut();
};
let jit_backend = match jit_backend_from_i32(jit_backend) {
Some(value) => value,
None => {
c_invalid_arg!("invalid jit_backend_type");
return ptr::null_mut();
}
};
let scalar_type = ScalarType::F64;
match OdeWrapper::new_jit(
&code,
jit_backend,
scalar_type,
matrix_type,
linear_solver,
ode_solver,
) {
Ok(ode) => Box::into_raw(Box::new(ode)),
Err(err) => {
c_error!(&format!("{}", err));
ptr::null_mut()
}
}
}