use scirs2_core::numeric::Complex64;
use scirs2_core::numeric::NumCast;
use std::fmt::Debug;
pub(crate) fn try_as_complex<T: Copy + Debug + 'static + NumCast>(val: T) -> Option<Complex64> {
if std::any::TypeId::of::<T>() == std::any::TypeId::of::<Complex64>() {
unsafe {
let ptr = &val as *const T as *const Complex64;
return Some(*ptr);
}
}
if std::any::TypeId::of::<T>() == std::any::TypeId::of::<scirs2_core::numeric::Complex32>() {
unsafe {
let ptr = &val as *const T as *const scirs2_core::numeric::Complex32;
let complex32 = *ptr;
return Some(Complex64::new(complex32.re as f64, complex32.im as f64));
}
}
let type_name = std::any::type_name::<T>();
if type_name.contains("Complex") {
let debug_str = format!("{val:?}");
let re_im: Vec<f64> = debug_str
.split(&[',', '(', ')', '{', '}', ':', ' '][..])
.filter_map(|s| s.trim().parse::<f64>().ok())
.collect();
if re_im.len() == 2 {
return Some(Complex64::new(re_im[0], re_im[1]));
}
}
macro_rules! handle_primitive {
($type:ty) => {
if std::any::TypeId::of::<T>() == std::any::TypeId::of::<$type>() {
unsafe {
let ptr = &val as *const T as *const $type;
return Some(Complex64::new(*ptr as f64, 0.0));
}
}
};
}
handle_primitive!(f64);
handle_primitive!(f32);
handle_primitive!(i32);
handle_primitive!(i64);
handle_primitive!(u32);
handle_primitive!(u64);
handle_primitive!(i16);
handle_primitive!(u16);
handle_primitive!(i8);
handle_primitive!(u8);
let debug_str = format!("{val:?}");
if debug_str.contains("Complex") || (debug_str.contains("re") && debug_str.contains("im")) {
let re_im: Vec<f64> = debug_str
.split(&[',', '(', ')', '{', '}', ':', ' '][..])
.filter_map(|s| {
let trimmed = s.trim();
if !trimmed.is_empty() {
trimmed.parse::<f64>().ok()
} else {
None
}
})
.collect();
if re_im.len() == 2 {
return Some(Complex64::new(re_im[0], re_im[1]));
} else if debug_str.contains("re:") && debug_str.contains("im:") {
let re_str = debug_str
.split("re:")
.nth(1)
.and_then(|s| s.split(',').next());
let im_str = debug_str
.split("im:")
.nth(1)
.and_then(|s| s.split('}').next());
if let (Some(re_s), Some(im_s)) = (re_str, im_str) {
if let (Ok(re), Ok(im)) = (re_s.trim().parse::<f64>(), im_s.trim().parse::<f64>()) {
return Some(Complex64::new(re, im));
}
}
}
}
NumCast::from(val).map(|v| Complex64::new(v, 0.0))
}