use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use serde::Deserialize;
use crate::ffi_apis::ffi_api::FfiResult;
use crate::numerical::matrix::Backend;
use crate::numerical::matrix::FaerDecompositionResult;
use crate::numerical::matrix::Matrix;
#[derive(Deserialize)]
struct MatrixOpRequest {
m1: Matrix<f64>,
m2: Option<Matrix<f64>>,
}
#[derive(Deserialize)]
struct MatrixBackendRequest {
matrix: Matrix<f64>,
backend_id: i32, }
#[derive(Deserialize)]
struct MatrixDecompositionRequest {
matrix: Matrix<f64>,
kind: crate::numerical::matrix::FaerDecompositionType,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_matrix_add_json(json_ptr: *const c_char) -> *mut c_char {
if json_ptr.is_null() {
return std::ptr::null_mut();
}
let json_str = match unsafe { CStr::from_ptr(json_ptr).to_str() } {
| Ok(s) => s,
| Err(_) => {
return std::ptr::null_mut();
},
};
let req: MatrixOpRequest = match serde_json::from_str(json_str) {
| Ok(r) => r,
| Err(e) => {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some(e.to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
let m2 = match req.m2 {
| Some(m) => m,
| None => {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some(
"Second matrix m2 \
is required"
.to_string(),
),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
if req.m1.rows() != m2.rows() || req.m1.cols() != m2.cols() {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some("Dimension mismatch".to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
}
let result = req.m1 + m2;
let ffi_res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: Some(result),
err: None,
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_matrix_mul_json(json_ptr: *const c_char) -> *mut c_char {
if json_ptr.is_null() {
return std::ptr::null_mut();
}
let json_str = match unsafe { CStr::from_ptr(json_ptr).to_str() } {
| Ok(s) => s,
| Err(_) => {
return std::ptr::null_mut();
},
};
let req: MatrixOpRequest = match serde_json::from_str(json_str) {
| Ok(r) => r,
| Err(e) => {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some(e.to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
let m2 = match req.m2 {
| Some(m) => m,
| None => {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some(
"Second matrix m2 \
is required"
.to_string(),
),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
if req.m1.cols() != m2.rows() {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some("Dimension mismatch".to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
}
let result = req.m1 * m2;
let ffi_res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: Some(result),
err: None,
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_matrix_det_json(json_ptr: *const c_char) -> *mut c_char {
if json_ptr.is_null() {
return std::ptr::null_mut();
}
let json_str = match unsafe { CStr::from_ptr(json_ptr).to_str() } {
| Ok(s) => s,
| Err(_) => {
return std::ptr::null_mut();
},
};
let matrix: Matrix<f64> = match serde_json::from_str(json_str) {
| Ok(m) => m,
| Err(e) => {
let res: FfiResult<f64, String> = FfiResult {
ok: None,
err: Some(e.to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
match matrix.determinant() {
| Ok(d) => {
let ffi_res: FfiResult<f64, String> = FfiResult {
ok: Some(d),
err: None,
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
},
| Err(e) => {
let ffi_res: FfiResult<f64, String> = FfiResult {
ok: None,
err: Some(e),
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_matrix_set_backend_json(json_ptr: *const c_char) -> *mut c_char {
if json_ptr.is_null() {
return std::ptr::null_mut();
}
let json_str = match unsafe { CStr::from_ptr(json_ptr).to_str() } {
| Ok(s) => s,
| Err(_) => {
return std::ptr::null_mut();
},
};
let req: MatrixBackendRequest = match serde_json::from_str(json_str) {
| Ok(r) => r,
| Err(e) => {
let res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: None,
err: Some(e.to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
let backend = match req.backend_id {
| 1 => Backend::Faer,
| _ => Backend::Native,
};
let m = req.matrix.with_backend(backend);
let ffi_res: FfiResult<Matrix<f64>, String> = FfiResult {
ok: Some(m),
err: None,
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rssn_num_matrix_decompose_json(json_ptr: *const c_char) -> *mut c_char {
if json_ptr.is_null() {
return std::ptr::null_mut();
}
let json_str = match unsafe { CStr::from_ptr(json_ptr).to_str() } {
| Ok(s) => s,
| Err(_) => {
return std::ptr::null_mut();
},
};
let req: MatrixDecompositionRequest = match serde_json::from_str(json_str) {
| Ok(r) => r,
| Err(e) => {
let res: FfiResult<FaerDecompositionResult<f64>, String> = FfiResult {
ok: None,
err: Some(e.to_string()),
};
return CString::new(serde_json::to_string(&res).unwrap())
.unwrap()
.into_raw();
},
};
match req.matrix.decompose(req.kind) {
| Some(result) => {
let ffi_res: FfiResult<FaerDecompositionResult<f64>, String> = FfiResult {
ok: Some(result),
err: None,
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
},
| None => {
let ffi_res: FfiResult<FaerDecompositionResult<f64>, String> = FfiResult {
ok: None,
err: Some(
"Decomposition \
failed or backend \
not supported"
.to_string(),
),
};
CString::new(serde_json::to_string(&ffi_res).unwrap())
.unwrap()
.into_raw()
},
}
}